e519d1804b62defc304c01ca45dfc5b814a78053
Root cause: sync_account_priorities_for_upstream() was doing a global priority re-rank across ALL imported accounts on a website whenever any upstream rate changed, triggering spurious account_priority_changed notifications for accounts in different target groups with no competition. Fix: - Add imported_target_group_id / imported_target_group_name to UpstreamGeneratedKey (nullable; old data falls back to group_id) - Writ imported_target_group_id on account import in websites.py - Rewrite sync_account_priorities_for_upstream(): * bucket accounts by competition_group = imported_target_group_id or group_id * only process buckets with count > 1 (genuine competition) * each competitive bucket independently sorted by rate; priority starts at 1 * single-account groups: completely skipped (no update_account, no notification) * no competitive groups at all: early return, no log, no notification - Remove auto priority update in re-import idempotency path (was also incorrect; now fully delegated to sync_account_priorities_for_upstream) - Fix Sub2ApiWebsiteClient local import in sync fn → use module-level name so monkeypatch works correctly in tests Tests: rewrite test_priority_sync.py - REMOVED: test_priority_sync_full_website_update (was asserting the buggy behavior) - NEW: test_no_update_when_different_groups_single_account_each - NEW: test_same_target_group_two_accounts_updated - NEW: test_two_target_groups_independent_priority - NEW: test_old_data_null_target_group_fallback - NEW: test_single_account_in_mixed_website - UPDATED: test_priority_sync_log_structure (now requires competitive group) - KEPT: test_priority_sync_cross_upstream_group, test_import_auto_priority_by_rate All 25 tests pass (8 priority_sync + 17 existing upstream tests).
SmartUp — API 上游管理与 Webhook 通知系统
SmartUp 是一个独立的 Web 后台,用于管理多个 API 上游的分组倍率监听,并通过 Webhook(通用 JSON / 钉钉机器人)发送变更通知。
功能
- 上游管理:支持 none / bearer / api_key / 邮箱密码 四种认证方式
- 定时检测:每个上游独立配置检测间隔,APScheduler 后台运行
- 倍率快照:检测变化后保存快照,diff 比对历史
- Webhook 通知:支持通用 JSON 和钉钉机器人(带签名)
- 通知日志:记录每次发送结果,支持筛选查看
- 自定义页面:支持直接嵌入、代理模式、远程浏览器模式
技术栈
- 后端:FastAPI + SQLite + APScheduler
- 前端:Vue 3 + Element Plus + Vite
- 部署:Docker Compose 单容器
快速部署
1. 准备配置文件
cp .env.example .env
# 编辑 .env,至少填写 ADMIN_PASSWORD 和 JWT_SECRET
2. 启动
docker compose up -d --build
首次启动时自动:
- 创建 SQLite 数据库(
./data/app.db) - 初始化管理员账号
3. 访问
打开浏览器:http://localhost:8899
默认账号:.env 中配置的 ADMIN_EMAIL / ADMIN_PASSWORD
本地开发
后端
cd backend
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
playwright install chromium
# 创建 .env(可复制根目录的 .env.example)
cat > .env << 'EOF'
ADMIN_EMAIL=admin@smartup.local
ADMIN_PASSWORD=dev123
JWT_SECRET=dev-secret
DATABASE_URL=sqlite:///./data/app.db
EOF
mkdir -p data
uvicorn app.main:app --reload --port 8000
前端
cd frontend
npm install
npm run dev # 代理到 localhost:8000
数据备份
SQLite 数据库位于 ./data/app.db,直接复制即可备份:
WAL 模式说明:启用 WAL 后,备份前请先执行 checkpoint 将 WAL 合并入主库:
sqlite3 ./data/app.db "PRAGMA wal_checkpoint(TRUNCATE);"
cp ./data/app.db ./data/app.db.$(date +%Y%m%d)
环境变量
| 变量 | 说明 | 默认值 |
|---|---|---|
ADMIN_EMAIL |
管理员邮箱 | admin@smartup.local |
ADMIN_PASSWORD |
管理员密码(必填) | — |
JWT_SECRET |
JWT 签名密钥 | change-me-in-production |
SERVER_PORT |
宿主机端口 | 8899 |
TZ |
时区 | Asia/Shanghai |
UNHEALTHY_THRESHOLD |
连续失败多少次标记为异常 | 3 |
BROWSER_PROFILES_DIR |
远程浏览器登录态/profile 存储目录 | /app/data/browser-profiles |
BROWSER_HEADLESS |
远程浏览器是否无头运行 | true |
目录结构
SmartUp/
├── backend/ # FastAPI 应用
│ └── app/
│ ├── models/ # SQLAlchemy ORM
│ ├── schemas/ # Pydantic schemas
│ ├── routers/ # API 路由
│ ├── services/ # 业务逻辑(client/scheduler/webhook)
│ └── utils/ # JWT / 钉钉签名
├── frontend/ # Vue 3 前端
│ └── src/
│ ├── views/ # 页面组件
│ ├── api/ # Axios 封装
│ └── stores/ # Pinia 状态
├── data/ # SQLite 数据目录(Docker volume)
├── Dockerfile # 多阶段构建
├── docker-compose.yml
└── .env.example
Description
Languages
Python
64.3%
Vue
28.2%
TypeScript
3.3%
CSS
2.1%
JavaScript
1.1%
Other
1%