feat: 完成源晶权限与经验系统并优化 me/admin 交互

这个提交包含在:
cryptocommuniums-afk
2026-02-23 20:02:46 +08:00
父节点 2b6def2560
当前提交 43cbd38bac
修改 104 个文件,包含 13348 行新增776 行删除

查看文件

@@ -6,10 +6,35 @@
## 通用约定
- 鉴权头:`Authorization: Bearer <token>`
- 鉴权头(二选一)
- `Authorization: Bearer <token>`(推荐)
- `Authorization: Basic <base64(username:password)>`(第三方直连更方便)
- 成功响应:`{ "ok": true, "data": ... }`Auth 接口除外)
- 失败响应:`{ "ok": false, "error": "..." }`
### 第三方接入快速示例
1) 登录拿 tokenBearer 方式)
```bash
curl -X POST 'https://csp.hao.work/admin139/api/v1/auth/login' \
-H 'Content-Type: application/json' \
-d '{"username":"alice","password":"password123"}'
```
2) Bearer 调用
```bash
curl 'https://csp.hao.work/admin139/api/v1/me' \
-H 'Authorization: Bearer <token>'
```
3) Basic 直接调用
```bash
curl 'https://csp.hao.work/admin139/api/v1/me' \
-H 'Authorization: Basic YWxpY2U6cGFzc3dvcmQxMjM='
```
> `YWxpY2U6cGFzc3dvcmQxMjM=` 是 `alice:password123` 的 Base64。
---
## 1) Auth
@@ -65,7 +90,7 @@
```
- `contest_id` 可选;若提交到比赛,需已报名且比赛进行中。
### `GET /submissions?user_id=&problem_id=&contest_id=&page=&page_size=`
### `GET /submissions?user_id=&problem_id=&contest_id=&created_from=&created_to=&page=&page_size=`
返回提交列表。
### `GET /submissions/:id`
@@ -120,6 +145,24 @@
### `GET /kb/articles/:slug`
返回文章详情与关联题目。
### `GET /kb/articles/:slug/claims`(需鉴权)
返回当前用户在该文章下已领取知识点和累计积分。
### `POST /kb/articles/:slug/claim`(需鉴权)
请求:
```json
{ "knowledge_key": "cpp14-io-01" }
```
说明:
- 有前置依赖的知识点,若前置未完成会返回 400。
- 同一知识点不可重复领取积分。
### `GET /kb/weekly-plan`(需鉴权)
返回本周自动生成的学习任务(含完成度、奖励汇总)。
### `POST /kb/weekly-bonus/claim`(需鉴权)
领取本周任务 100% 完成奖励;未达 100% 返回 400。
---
## 8) 题库导入任务PDF + LLM
@@ -157,3 +200,53 @@
### `GET /backend/logs?limit=100`
返回最近题解生成任务日志(按任务 ID 倒序),并包含当前排队任务数 `pending_jobs`
### `GET /backend/db-lock-guard/status`(需管理员鉴权)
返回 SQLite 锁守护运行状态,字段包含:
- `enabled` / `started`:守护是否启用、是否已启动
- `interval_sec` / `probe_busy_timeout_ms`:探测间隔与超时
- `busy_streak` / `busy_streak_trigger`:当前连续锁冲突计数与触发阈值
- `last_probe_at` / `last_probe_rc` / `last_probe_error`:最近探测结果
- `last_repair_at` / `repair_count`:最近一次自愈时间与累计自愈次数
---
## 10) 网站爬虫列表(管理员)
### `GET /admin/crawlers?status=&limit=`
返回爬虫目标列表(按最新倒序)。
### `POST /admin/crawlers`
手动新增爬虫目标。请求体示例:
```json
{ "url": "https://example.com" }
```
### `POST /admin/crawlers/:id/queue`
将目标重新入队,触发“规则生成 -> 自动测试 -> 自动运行”流程。
### `GET /admin/crawlers/:id/runs?limit=20`
查看指定目标的运行记录。
### `GET /backend/crawler-guard/status`(需管理员鉴权)
返回爬虫守护进程状态(是否启用、是否运行、处理统计、最近错误等)。
- `active_requeue_interval_sec` 表示活跃目标的周期重跑间隔(秒,默认 43200 即 12 小时)。
> 飞书群内 `@机器人` 文本如果包含 URL,也会自动写入爬虫目标列表并触发守护流程。
---
## 11) Lark 机器人事件回调
### `POST /lark/events`
用于飞书Lark事件订阅回调,支持
- URL 验证:请求体带 `challenge` 时回传 `{ "challenge": "..." }`
- 消息事件:处理 `im.message.receive_v1` 文本消息并异步回复
环境变量(后端):
- `CSP_LARK_BOT_ENABLED=true`:是否启用机器人
- `CSP_LARK_VERIFICATION_TOKEN=...`:事件回调 token可选,建议配置
- `CSP_LARK_APP_ID=...` / `CSP_LARK_APP_SECRET=...`:飞书应用凭据
- `CSP_LARK_OPEN_BASE_URL=https://open.feishu.cn`:飞书 OpenAPI 域名
- `CSP_LARK_LLM_API_URL=...` / `CSP_LARK_LLM_API_KEY=...` / `CSP_LARK_LLM_MODEL=...`:对话模型配置
- 可选:`CSP_LARK_LLM_SYSTEM_PROMPT``CSP_LARK_MEMORY_TURNS``CSP_LARK_MAX_REPLY_CHARS`

查看文件

@@ -76,8 +76,55 @@ OI_IMPORT_WORKERS=3
OI_IMPORT_CLEAR_EXISTING=true
OI_IMPORT_CLEAR_SOURCE_PREFIX=winterant/oi
OI_IMPORT_CLEAR_ALL_PROBLEMS=false
# SQLite 锁守护(定时探测 + 自愈)
CSP_SQLITE_BUSY_TIMEOUT_MS=15000
CSP_DB_LOCK_GUARD_ENABLED=true
CSP_DB_LOCK_GUARD_INTERVAL_SEC=20
CSP_DB_LOCK_GUARD_PROBE_TIMEOUT_MS=2000
CSP_DB_LOCK_GUARD_BUSY_STREAK=3
# Lark 机器人(事件回调 + 对话)
CSP_LARK_BOT_ENABLED=false
CSP_LARK_VERIFICATION_TOKEN=
CSP_LARK_APP_ID=
CSP_LARK_APP_SECRET=
CSP_LARK_OPEN_BASE_URL=https://open.feishu.cn
CSP_LARK_LLM_API_URL=
CSP_LARK_LLM_API_KEY=
CSP_LARK_LLM_MODEL=qwen3-max
CSP_LARK_LLM_SYSTEM_PROMPT=你是 CSP Quest World 的编程助教。请用简洁中文回答,先给结论,再给步骤。
CSP_LARK_LLM_TIMEOUT_SEC=30
CSP_LARK_API_TIMEOUT_SEC=15
CSP_LARK_MEMORY_TURNS=6
CSP_LARK_MAX_REPLY_CHARS=1200
# 网站爬虫守护URL 入库后自动:生成规则 -> 测试 -> 运行)
CSP_CRAWLER_ENABLED=true
CSP_CRAWLER_INTERVAL_SEC=15
CSP_CRAWLER_REQUEUE_INTERVAL_SEC=43200
CSP_CRAWLER_FETCH_TIMEOUT_SEC=20
CSP_CRAWLER_SCRIPT_DIR=/data/crawlers
CSP_CRAWLER_LLM_API_URL=https://one.hao.work/v1/chat/completions
CSP_CRAWLER_LLM_API_KEY=替换为你的Key
CSP_CRAWLER_LLM_MODEL=qwen3-max
CSP_CRAWLER_LLM_TIMEOUT_SEC=30
```
说明:
- `CSP_SQLITE_BUSY_TIMEOUT_MS`:主连接遇到锁时的等待时间(毫秒)。
- `CSP_DB_LOCK_GUARD_ENABLED`:是否启用定时守护。
- `CSP_DB_LOCK_GUARD_INTERVAL_SEC`:守护探测间隔(秒)。
- `CSP_DB_LOCK_GUARD_PROBE_TIMEOUT_MS`:守护探测连接的 busy timeout毫秒
- `CSP_DB_LOCK_GUARD_BUSY_STREAK`:连续探测到 busy/locked 达到阈值后触发一次自愈WAL checkpoint + optimize
- `CSP_LARK_BOT_ENABLED`:是否启用 Lark 对话机器人回调处理。
- `CSP_LARK_VERIFICATION_TOKEN`Lark 事件回调 token建议配置
- `CSP_LARK_APP_ID/CSP_LARK_APP_SECRET`Lark 应用凭据。
- `CSP_LARK_LLM_*`:机器人对话调用的模型配置。
- `CSP_CRAWLER_*`网站爬虫守护配置URL 入库后自动生成规则/测试/运行)。
- `CSP_CRAWLER_REQUEUE_INTERVAL_SEC`:已激活目标再次入队执行的周期(秒,`43200`=12小时,`0`=关闭周期重跑)。
## 5. 故障排查
### 5.1 无法访问 7888

查看文件

@@ -0,0 +1,97 @@
# 知识库重塑与游戏化规划CSP 平台)
## 1. 重塑目标
- 建立“可学习、可打卡、可成长”的知识库系统,不再只是文章列表。
- 形成四条核心技能线:
- C++14 技能树(竞赛编码主线)
- GitHub 协作技能树(团队工程主线)
- Linux 服务器技能树(部署运维主线)
- 计算机基础技能树(底层认知主线)
- 将“知识点学习”直接转化为积分成长,形成闭环:学习 -> 打卡 -> 得分 -> 排行与成长反馈。
## 2. 内容架构
### 2.1 主线知识文章(已落地)
- `cpp14-skill-tree`
- `github-collaboration-basics`
- `linux-server-basics`
- `computer-fundamentals-for-oi`
### 2.2 每篇文章的知识点模型
- 每篇文章附带一组 `skill_points`
- `key`: 唯一知识点 ID
- `title`: 知识点标题
- `description`: 可执行的学习目标
- `difficulty`: bronze/silver/gold
- `reward`: 领取奖励分值
### 2.3 文章与题目联动
- 保留 `kb_article_links`,把知识点和题目联起来。
- 在 KB 列表中提供“做相关任务”跳转到题库搜索。
## 3. 游戏化机制
### 3.1 积分获取
- 用户可对每个知识点打卡领取奖励。
- 领取规则:`user + article + knowledge_key` 唯一,不可重复刷分。
- 奖励实时写入用户 `rating`
### 3.2 数据表设计
- 新增表:`kb_knowledge_claims`
- `user_id`
- `article_id`
- `knowledge_key`
- `reward`
- `created_at`
- 唯一约束:`UNIQUE(user_id, article_id, knowledge_key)`
### 3.3 成长展示
- 文章详情页展示:
- 技能点清单
- 已领取数量
- 已领取总积分
- 单点“领取奖励”按钮与状态
- 积分流水新增 `kb_skill` 类型,进入个人成长历史。
## 4. 交互设计
### 4.1 KB 列表页
- 支持关键词搜索。
- 增加快捷筛选按钮:`C++14``GitHub``Linux``计算机基础`
- 分类分组路线图、C++、CSP-J、CSP-S、GitHub、Linux、计算机基础、其他。
### 4.2 KB 详情页
- 文章内容区
- 技能打卡区(奖励领取)
- 关联题目区(学练结合)
## 5. 版本规划(建议)
### Phase A当前已实现
- 重构四条核心文章
- 技能点打卡与积分领取
- 积分流水接入
- KB 列表筛选与分类增强
### Phase B下一步
- 技能点前置依赖(先修解锁)
- 每周学习任务(自动生成)
- 学习路径推荐(根据已领取点与错题)
- 章节徽章(铜/银/金)
### Phase C进阶
- 班级/战队学习排行
- 学习挑战赛(限时技能闯关)
- 知识点掌握度雷达图
- AI 学习教练(按薄弱点推送下一步)
## 6. 运营指标(建议)
- 日活学习人数
- 人均领取知识点数
- 文章完成率(领取数 / 可领取数)
- 学完知识后去做题转化率
- 学习后 AC 提升率
## 7. 风险与控制
- 风险:刷接口刷分。
- 控制:唯一约束 + 服务端验证技能点 key。
- 风险:内容过长难消化。
- 控制:拆分为技能点任务和周计划。
- 风险:学习与做题割裂。
- 控制:每篇文章都提供相关题目入口。

查看文件

@@ -0,0 +1,101 @@
# CSP Quest World 第三方 REST 接入指南
本文档用于第三方系统(脚本、自动化平台、企业内部系统)快速接入 CSP Quest World 的 REST API。
## 1. 基础信息
- 线上基础地址:`https://csp.hao.work/admin139/api/v1`
- 文档入口Swagger`https://csp.hao.work/api-docs`
- OpenAPI JSON`https://csp.hao.work/admin139/api/openapi.json`
- 数据格式:`application/json`
## 2. 鉴权方式
受保护接口支持两种方式,任选其一:
1. Bearer Token推荐
- 先调用 `/auth/login` 获取 `token`
- 请求头带上:`Authorization: Bearer <token>`
2. Basic 账号密码(适合第三方直连)
- 请求头带上:`Authorization: Basic <base64(username:password)>`
- 示例:`alice:password123` -> `YWxpY2U6cGFzc3dvcmQxMjM=`
说明:
- 两种方式都可访问全部 REST 接口。
- 管理员接口仍需管理员账号(如 `admin`)才能通过权限校验。
## 3. 快速调用示例
### 3.1 登录获取 Token
```bash
curl -X POST 'https://csp.hao.work/admin139/api/v1/auth/login' \
-H 'Content-Type: application/json' \
-d '{"username":"alice","password":"password123"}'
```
### 3.2 使用 Bearer 调用
```bash
curl 'https://csp.hao.work/admin139/api/v1/me' \
-H 'Authorization: Bearer <token>'
```
### 3.3 使用 Basic 调用
```bash
curl 'https://csp.hao.work/admin139/api/v1/me' \
-H 'Authorization: Basic YWxpY2U6cGFzc3dvcmQxMjM='
```
## 4. Python 示例requests
```python
import base64
import requests
BASE = "https://csp.hao.work/admin139/api/v1"
username = "alice"
password = "password123"
basic = base64.b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8")
headers = {"Authorization": f"Basic {basic}"}
resp = requests.get(f"{BASE}/me", headers=headers, timeout=15)
resp.raise_for_status()
print(resp.json())
```
## 5. 响应约定
- 成功:`{ "ok": true, "data": ... }`Auth 接口除外)
- 失败:`{ "ok": false, "error": "..." }`
常见状态码:
- `200`:成功
- `400`:请求参数错误
- `401`:未登录或鉴权失败
- `403`:有登录身份但权限不足(如非管理员访问管理员接口)
- `404`:资源不存在
- `409`:状态冲突(例如任务已在运行)
## 6. 安全建议
1. 生产环境优先用 HTTPS。
2. 若可控,优先使用 Bearer Token,减少明文密码在网关/代理日志出现的风险。
3. 使用 Basic 时建议为第三方集成准备专用账号,并定期更换密码。
4. 管理员账号只用于管理员接口,不建议用于普通业务拉取。
## 7. 爬虫自动化接口(管理员)
- 爬虫列表:`GET /admin/crawlers?status=&limit=`
- 新增目标:`POST /admin/crawlers`,Body`{ "url": "https://example.com" }`
- 重新入队:`POST /admin/crawlers/{id}/queue`
- 运行记录:`GET /admin/crawlers/{id}/runs?limit=20`
- 守护状态:`GET /backend/crawler-guard/status`
说明:
- 新地址入库后,后端守护会自动执行规则生成LLM→ 自动测试 → 自动运行。
- `crawler-guard/status` 返回 `active_requeue_interval_sec`,用于确认周期重跑间隔(默认 43200 秒,即 12 小时)。
- 飞书群内 `@机器人` 的文本消息若含 URL,也会自动入库到爬虫列表。