chore: 工作台产品化进行中的改动

把工作区里其余在制品一并入库,主要是工作台产品化的推进:

  后端:新增 capability_definition / project / my_app_center / office_skill
        接口与 action_definition / skill_definition / project / user_app_center
        模型,config 加路由健康上报。
  前端:新增 frontend/src/skills(Office 技能与 workbuddy 复刻)、
        项目管理、应用中心、能力目录页,以及配套 api / store / config;
        聊天侧新增 SpecialistChip / SpecialistPanel / SkillStrip / AppChatRail
        等组件。
  清理:移除旧 views/tools 下的单页工具(已并入工作台)、_frozen 冻结组件、
        cmd/inspect_oa_debug 调试入口,以及两份调试笔记。
  其它:文档与启动脚本同步。

(这批改动与上一提交的 SY23 工作并行进行,此前已在同一工作区内交织。)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
eaiadmin
2026-09-17 21:32:35 +08:00
co-authored by Claude Code
parent 8b136d4a10
commit 16d63de4e1
180 changed files with 22283 additions and 13850 deletions
+53 -59
View File
@@ -1,6 +1,7 @@
# BE02 — 考试模块设计
> **版本:V1.1 | 参考:pj006-zhilianyuan2 exam/routes.py + exam/service.py**
> **版本:V2.0 | 框架:Go + Gin + GORM + SQLite**
> **参考:`backend-go/internal/api/exam.go`**
---
@@ -33,72 +34,65 @@ question(题库)← exam_paper(考试配置,通过 domain+question_count
## 4. 题库 API
```python
# 管理员 — 题目 CRUD
GET /api/exam/questions?domain=company&status=active # 题目列表
POST /api/exam/questions # 新增题目
PUT /api/exam/questions/{id} # 编辑题目
DELETE /api/exam/questions/{id} # 停用题目
```go
// backend-go/internal/api/exam.go
# 管理员 — 考试配置
GET /api/exam/papers # 考试配置列表
POST /api/exam/papers # 创建考试
PUT /api/exam/papers/{id} # 编辑考试
DELETE /api/exam/papers/{id} # 停用考试
// GET /api/exam/questions?domain=company&status=active # 题目列表
func ListQuestions(c *gin.Context)
// POST /api/exam/questions # 新增题目
func CreateQuestion(c *gin.Context)
// PUT /api/exam/questions/{id} # 编辑题目
func UpdateQuestion(c *gin.Context)
// DELETE /api/exam/questions/{id} # 停用题目
func DeleteQuestion(c *gin.Context)
// GET /api/exam/papers # 考试配置列表
func ListPapers(c *gin.Context)
// POST /api/exam/papers # 创建考试
func CreatePaper(c *gin.Context)
// PUT /api/exam/papers/{id} # 编辑考试
func UpdatePaper(c *gin.Context)
// DELETE /api/exam/papers/{id} # 停用考试
func DeletePaper(c *gin.Context)
```
## 5. 学员端考试 API
```python
GET /api/exam/list # 我的考试列表
GET /api/exam/cover?id={paperId} # 考试封面/说明
POST /api/exam/start # 开始考试 → 下发题目
POST /api/exam/submit # 交卷判分
GET /api/exam/record # 我的考试记录
GET /api/exam/record/{recordId} # 考试记录详情
```go
// GET /api/exam/list # 我的考试列表
func ExamList(c *gin.Context)
// GET /api/exam/cover?id={paperId} # 考试封面/说明
func ExamCover(c *gin.Context)
// POST /api/exam/start # 开始考试 → 下发题目
func ExamStart(c *gin.Context)
// POST /api/exam/submit # 交卷判分
func ExamSubmit(c *gin.Context)
// GET /api/exam/record # 我的考试记录
func ExamRecordList(c *gin.Context)
// GET /api/exam/record/{recordId} # 考试记录详情
func ExamRecordDetail(c *gin.Context)
```
## 6. 判分逻辑(参考 zhilianyuan2 _is_correct)
## 6. 判分逻辑(`exam.go` 内 `isCorrect` 函数)
```python
# services/exam_service.py
```go
// backend-go/internal/api/exam.go
def _is_correct(qtype: str, correct: list, user: any) -> bool:
"""确定性判分"""
if qtype == "multiple": # 多选题:集合相等
return sorted(correct) == sorted(user) if user else False
elif qtype == "judge": # 判断题:值相等
return str(correct).lower() == str(user).lower()
else: # 单选题:值相等
return correct == user
def grade_paper(questions: list, answers: dict) -> dict:
"""批卷:逐题比对 → 统计得分/正确数"""
correct_count = 0
total = len(questions)
score_per_question = 100 / total if total else 0
details = []
for q in questions:
user_ans = answers.get(str(q["id"]))
is_correct = _is_correct(q["type"], q["answer"], user_ans)
if is_correct:
correct_count += 1
details.append({
"question_id": q["id"],
"is_correct": is_correct,
"user_answer": user_ans,
"correct_answer": q["answer"],
})
score = round(score_per_question * correct_count)
return {
"score": score,
"correct_count": correct_count,
"wrong_count": total - correct_count,
"passed": score >= paper.pass_score,
"details": details,
func isCorrect(qtype string, correct []string, user any) bool {
switch qtype {
case "multiple": // 多选题:集合相等
return sortedEqual(correct, us)
case "judge": // 判断题:值相等
return strings.EqualFold(correct[0], us)
default: // 单选题:值相等
return correct[0] == us
}
}
func ExamSubmit(c *gin.Context) {
// 逐题比对 → 统计得分/正确数
// 简答题(essay)走 LLM 评分,其余题型确定性判分
}
```
## 7. 自测 vs 正式考区别
@@ -113,7 +107,7 @@ def grade_paper(questions: list, answers: dict) -> dict:
## 8. 考试记录设计
```json
// exam_record.detail_json 示例
// exam_record.detail_json 示例(SQLite TEXT 列)
{
"questions": [
{
@@ -133,4 +127,4 @@ def grade_paper(questions: list, answers: dict) -> dict:
## 9. 权限
- **员工:** 仅查看自己的考试记录
- **管理员:** 查看全部考试记录(`/api/system/exam-records`)
- **管理员:** 查看全部考试记录(`/api/system/exam-records`)