diff --git a/CONTEXT.md b/CONTEXT.md index 9ba46bd..c6f42fa 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1,164 +1,164 @@ -# 项目上下文 - -> AI启动时必读此文件,快速了解项目全貌 - -## 一、项目信息 - -| 项目 | 内容 | -|------|------| -| **项目编号** | 012-考培练系统-2601 | -| **项目路径** | `projects/012-考培练系统-2601/` | -| **当前阶段** | 开发阶段 | -| **项目状态** | 🟢 活跃 | -| **启动日期** | 2026-01-24 | -| **技术栈** | Vue3 + TypeScript + FastAPI + MySQL | - -## 二、AI启动指令 - -请依次阅读以下文件: - -1. **框架层**(了解规则) - - `../../_framework/agents/00-框架总览.md` - - 检查 `agents/` 是否有项目覆盖 - -2. **项目文档**(了解当前状态) - - `docs/同步清单.md` - - `docs/项目状态快照.md` - - `docs/规划/系统架构.md` - -3. **技术文档** - - `docs/README.md` - 项目总览 - - `backend/README.md` - 后端开发指南 - -## 三、项目简介 - -考培练系统是一个革命性的员工能力提升平台,专为轻医美连锁品牌瑞小美打造。通过集成 Coze 和 Dify 双 AI 平台,实现智能化的培训、考核和陪练功能。 - -### 核心功能 - -- **智能考试系统**:动态题目生成(千人千卷)、三轮考试机制 -- **AI陪练中心**:模拟客户对话、语音交互支持 -- **课程管理**:知识点自动提取、分岗位内容推送 -- **数据分析**:能力雷达图、学习进度追踪 - -### 技术架构 - -| 层级 | 技术栈 | -|------|--------| -| 前端 | Vue3 + TypeScript + Element Plus + Vite | -| 后端 | Python 3.9+ + FastAPI + SQLAlchemy | -| 数据库 | MySQL 8.0 + Redis | -| AI平台 | Dify(动态考试)+ Coze(AI陪练) | -| 部署 | Docker 容器化 | - -## 四、项目结构 - -``` -012-考培练系统-2601/ -├── backend/ # 后端 (FastAPI) -│ ├── app/ # 应用主目录 -│ │ ├── api/ # API路由 -│ │ ├── models/ # 数据模型 -│ │ ├── schemas/ # Pydantic schemas -│ │ └── services/ # 业务逻辑 -│ └── requirements.txt -├── frontend/ # 用户端前端 (Vue3) -│ └── src/ -│ ├── api/ # API调用 -│ ├── views/ # 页面视图 -│ └── components/ # 组件 -├── admin-frontend/ # 管理端前端 (Vue3) -├── deploy/ # 部署配置 -│ ├── docker/ # Docker compose 文件 -│ ├── nginx/ # Nginx 配置 -│ └── scripts/ # 启动/部署脚本 -├── docs/ # 文档 -│ └── 规划/ # 系统规划文档 -├── tests/ # 测试文件 -├── 知识库/ # 开发记录、问题修复 -└── .env.* # 环境配置 -``` - -## 五、关键配置 - -### 服务端口 - -| 服务 | 端口 | -|------|------| -| 前端 | 3001 | -| 后端 API | 8000 | -| MySQL | 3306 | -| Redis | 6379 | - -### 系统账户 - -| 角色 | 用户名 | 密码 | -|------|--------|------| -| 超级管理员 | superadmin | Superadmin123! | -| 系统管理员 | admin | Admin123! | -| 测试学员 | testuser | TestPass123! | - -### 数据库连接 - -- **服务器**: 120.79.247.16 -- **端口**: 3306 -- **数据库**: kaopeilian - -### Git 仓库配置 - -| Remote | 地址 | 用途 | -|--------|------|------| -| `origin` | github.com/nongjun/ai-development-workspace | 源代码主仓库 | -| `cicd` | git.ai.ireborn.com.cn/admin/012-kaopeilian | CI/CD 触发仓库 | - -**服务器路径**: `/root/aiedu` - -**使用方式**: -```bash -# 常规开发(推送到 GitHub) -git push origin main - -# 触发 CI/CD 部署 -git push cicd main # 生产环境(6个租户) -git push cicd test # 测试环境(kpl.ireborn.com.cn) -``` - -### CI/CD 配置 - -| 分支 | 环境 | 域名 | 动作 | -|------|------|------|------| -| `test` | 测试环境 | https://kpl.ireborn.com.cn | 重建 dev 容器 | -| `main` | 生产环境 | 6个租户域名 | 前端编译 + 后端重建 | - -**生产租户**: hua, yy, hl, xy, fw, ex, cxw - -### 租户端口分配 - -| 租户 | 名称 | 域名 | 前端端口 | 后端端口 | Redis端口 | -|------|------|------|----------|----------|-----------| -| hua | 华尔倍丽 | hua.ireborn.com.cn | 3010 | 8010 | 6390 | -| yy | 杨扬宠物 | yy.ireborn.com.cn | 3011 | 8011 | 6391 | -| hl | 武汉禾丽 | hl.ireborn.com.cn | 3012 | 8012 | 6392 | -| xy | 芯颜定制 | xy.ireborn.com.cn | 3013 | 8013 | 6393 | -| fw | 飞沃 | fw.ireborn.com.cn | 3014 | 8014 | 6394 | -| ex | 恩喜成都总院 | ex.ireborn.com.cn | 3015 | 8015 | 6395 | -| cxw | 崔曦文 | cxw.ireborn.com.cn | 3016 | 8016 | 6396 | - -## 六、文件访问边界 - -| 区域 | 读取 | 写入 | -|------|------|------| -| ✅ 本项目目录 | 允许 | 允许 | -| ✅ `_framework/` | 允许 | ⚠️ 需确认 | -| ⚠️ `_private/` | 需许可 | ❌ **绝对禁止** | -| ❌ 其他项目 | 禁止 | 禁止 | - -## 七、注意事项 - -- 多租户架构:支持多个机构独立部署(.env.fw, .env.hl 等) -- AI集成:需配置 Coze 和 Dify API 密钥 -- 文件上传:使用 LibreOffice 转换 Office 文档 - ---- - -> 最后更新:2026-01-24 +# 项目上下文 + +> AI启动时必读此文件,快速了解项目全貌 + +## 一、项目信息 + +| 项目 | 内容 | +|------|------| +| **项目编号** | 012-考培练系统-2601 | +| **项目路径** | `projects/012-考培练系统-2601/` | +| **当前阶段** | 开发阶段 | +| **项目状态** | 🟢 活跃 | +| **启动日期** | 2026-01-24 | +| **技术栈** | Vue3 + TypeScript + FastAPI + MySQL | + +## 二、AI启动指令 + +请依次阅读以下文件: + +1. **框架层**(了解规则) + - `../../_framework/agents/00-框架总览.md` + - 检查 `agents/` 是否有项目覆盖 + +2. **项目文档**(了解当前状态) + - `docs/同步清单.md` + - `docs/项目状态快照.md` + - `docs/规划/系统架构.md` + +3. **技术文档** + - `docs/README.md` - 项目总览 + - `backend/README.md` - 后端开发指南 + +## 三、项目简介 + +考培练系统是一个革命性的员工能力提升平台,专为轻医美连锁品牌瑞小美打造。通过集成 Coze 和 Dify 双 AI 平台,实现智能化的培训、考核和陪练功能。 + +### 核心功能 + +- **智能考试系统**:动态题目生成(千人千卷)、三轮考试机制 +- **AI陪练中心**:模拟客户对话、语音交互支持 +- **课程管理**:知识点自动提取、分岗位内容推送 +- **数据分析**:能力雷达图、学习进度追踪 + +### 技术架构 + +| 层级 | 技术栈 | +|------|--------| +| 前端 | Vue3 + TypeScript + Element Plus + Vite | +| 后端 | Python 3.9+ + FastAPI + SQLAlchemy | +| 数据库 | MySQL 8.0 + Redis | +| AI平台 | Dify(动态考试)+ Coze(AI陪练) | +| 部署 | Docker 容器化 | + +## 四、项目结构 + +``` +012-考培练系统-2601/ +├── backend/ # 后端 (FastAPI) +│ ├── app/ # 应用主目录 +│ │ ├── api/ # API路由 +│ │ ├── models/ # 数据模型 +│ │ ├── schemas/ # Pydantic schemas +│ │ └── services/ # 业务逻辑 +│ └── requirements.txt +├── frontend/ # 用户端前端 (Vue3) +│ └── src/ +│ ├── api/ # API调用 +│ ├── views/ # 页面视图 +│ └── components/ # 组件 +├── admin-frontend/ # 管理端前端 (Vue3) +├── deploy/ # 部署配置 +│ ├── docker/ # Docker compose 文件 +│ ├── nginx/ # Nginx 配置 +│ └── scripts/ # 启动/部署脚本 +├── docs/ # 文档 +│ └── 规划/ # 系统规划文档 +├── tests/ # 测试文件 +├── 知识库/ # 开发记录、问题修复 +└── .env.* # 环境配置 +``` + +## 五、关键配置 + +### 服务端口 + +| 服务 | 端口 | +|------|------| +| 前端 | 3001 | +| 后端 API | 8000 | +| MySQL | 3306 | +| Redis | 6379 | + +### 系统账户 + +| 角色 | 用户名 | 密码 | +|------|--------|------| +| 超级管理员 | superadmin | Superadmin123! | +| 系统管理员 | admin | Admin123! | +| 测试学员 | testuser | TestPass123! | + +### 数据库连接 + +- **服务器**: 120.79.247.16 +- **端口**: 3306 +- **数据库**: kaopeilian + +### Git 仓库配置 + +| Remote | 地址 | 用途 | +|--------|------|------| +| `origin` | github.com/nongjun/ai-development-workspace | 源代码主仓库 | +| `cicd` | git.ai.ireborn.com.cn/admin/012-kaopeilian | CI/CD 触发仓库 | + +**服务器路径**: `/root/aiedu` + +**使用方式**: +```bash +# 常规开发(推送到 GitHub) +git push origin main + +# 触发 CI/CD 部署 +git push cicd main # 生产环境(6个租户) +git push cicd test # 测试环境(kpl.ireborn.com.cn) +``` + +### CI/CD 配置 + +| 分支 | 环境 | 域名 | 动作 | +|------|------|------|------| +| `test` | 测试环境 | https://kpl.ireborn.com.cn | 重建 dev 容器 | +| `main` | 生产环境 | 6个租户域名 | 前端编译 + 后端重建 | + +**生产租户**: hua, yy, hl, xy, fw, ex, cxw + +### 租户端口分配 + +| 租户 | 名称 | 域名 | 前端端口 | 后端端口 | Redis端口 | +|------|------|------|----------|----------|-----------| +| hua | 华尔倍丽 | hua.ireborn.com.cn | 3010 | 8010 | 6390 | +| yy | 杨扬宠物 | yy.ireborn.com.cn | 3011 | 8011 | 6391 | +| hl | 武汉禾丽 | hl.ireborn.com.cn | 3012 | 8012 | 6392 | +| xy | 芯颜定制 | xy.ireborn.com.cn | 3013 | 8013 | 6393 | +| fw | 飞沃 | fw.ireborn.com.cn | 3014 | 8014 | 6394 | +| ex | 恩喜成都总院 | ex.ireborn.com.cn | 3015 | 8015 | 6395 | +| cxw | 崔曦文 | cxw.ireborn.com.cn | 3016 | 8016 | 6396 | + +## 六、文件访问边界 + +| 区域 | 读取 | 写入 | +|------|------|------| +| ✅ 本项目目录 | 允许 | 允许 | +| ✅ `_framework/` | 允许 | ⚠️ 需确认 | +| ⚠️ `_private/` | 需许可 | ❌ **绝对禁止** | +| ❌ 其他项目 | 禁止 | 禁止 | + +## 七、注意事项 + +- 多租户架构:支持多个机构独立部署(.env.fw, .env.hl 等) +- AI集成:需配置 Coze 和 Dify API 密钥 +- 文件上传:使用 LibreOffice 转换 Office 文档 + +--- + +> 最后更新:2026-01-24 diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6d72f34..b118363 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "kaopeilian-frontend", "version": "1.0.0", + "hasInstallScript": true, "dependencies": { "@coze/api": "^1.3.7", "@element-plus/icons-vue": "^2.3.1", @@ -1056,129 +1057,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@napi-rs/canvas": { "version": "0.1.82", "resolved": "https://registry.npmmirror.com/@napi-rs/canvas/-/canvas-0.1.82.tgz", @@ -2989,32 +2867,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -3281,24 +3133,6 @@ ], "license": "CC-BY-4.0" }, - "node_modules/canvas": { - "version": "2.11.2", - "resolved": "https://registry.npmmirror.com/canvas/-/canvas-2.11.2.tgz", - "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "nan": "^2.17.0", - "simple-get": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/chai": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", @@ -3364,18 +3198,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "engines": { - "node": ">=10" - } - }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -3474,18 +3296,6 @@ "dev": true, "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -3564,15 +3374,6 @@ "dev": true, "license": "MIT" }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -3852,21 +3653,6 @@ "dev": true, "license": "MIT" }, - "node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "mimic-response": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -3906,15 +3692,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -4903,36 +4680,6 @@ "node": ">= 10.0.0" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4964,65 +4711,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -5243,15 +4931,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -6197,21 +5876,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -6238,52 +5902,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mlly": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", @@ -6327,15 +5945,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nan": { - "version": "2.23.1", - "resolved": "https://registry.npmmirror.com/nan/-/nan-2.23.1.tgz", - "integrity": "sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -6594,22 +6203,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -6630,18 +6223,6 @@ "dev": true, "license": "MIT" }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -7586,23 +7167,6 @@ "dev": true, "license": "MIT" }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -7930,15 +7494,6 @@ "node": ">=10" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -7982,43 +7537,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/simple-get": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-3.1.1.tgz", - "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "node_modules/sirv": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", @@ -8098,18 +7616,6 @@ "dev": true, "license": "MIT" }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -8335,38 +7841,6 @@ "url": "https://opencollective.com/synckit" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/terser": { "version": "5.44.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", @@ -9172,44 +8646,6 @@ "node": ">=8" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmmirror.com/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -9376,15 +8812,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/frontend/src/views/exam/practice.vue b/frontend/src/views/exam/practice.vue index d3e7f61..a70ace4 100644 --- a/frontend/src/views/exam/practice.vue +++ b/frontend/src/views/exam/practice.vue @@ -349,21 +349,21 @@ const transformDifyQuestions = (difyQuestions: any[]): any[] => { // 更精确地提取正确答案字母(避免误提取选项内容中的字母) let correctLetters: string[] = [] - // 情况1:纯选项字母格式(如 "A", "B", "A,B", "A、B", "A,B,C") - const pureLetterMatch = correctAnswerStr.match(/^[A-Da-d]([,、\s]+[A-Da-d])*$/) + // 情况1:纯选项字母格式(如 "A", "B", "A,B", "A、B", "A,B,C,D,E") + const pureLetterMatch = correctAnswerStr.match(/^[A-Za-z]([,、\s]+[A-Za-z])*$/) if (pureLetterMatch) { - correctLetters = correctAnswerStr.match(/[A-Da-d]/g)?.map(l => l.toUpperCase()) || [] + correctLetters = correctAnswerStr.match(/[A-Za-z]/g)?.map(l => l.toUpperCase()) || [] console.log(` ✓ 匹配情况1(纯字母): correctLetters=[${correctLetters.join(',')}]`) } else { // 情况2:多选项带内容格式(如 "A:分组列,B:聚合函数,C:常量") // 匹配所有 "X:" 或 "X:" 格式,提取字母 - const multiOptionMatch = correctAnswerStr.match(/[A-Da-d](?=[::])/g) + const multiOptionMatch = correctAnswerStr.match(/[A-Za-z](?=[::])/g) if (multiOptionMatch && multiOptionMatch.length > 0) { correctLetters = multiOptionMatch.map(l => l.toUpperCase()) console.log(` ✓ 匹配情况2(多选项带内容): correctLetters=[${correctLetters.join(',')}]`) } else { // 情况3:只有开头字母(如 "A" 后面直接跟非字母内容) - const firstLetterMatch = correctAnswerStr.match(/^([A-Da-d])(?![A-Za-z])/) + const firstLetterMatch = correctAnswerStr.match(/^([A-Za-z])(?![A-Za-z])/) if (firstLetterMatch) { correctLetters = [firstLetterMatch[1].toUpperCase()] console.log(` ✓ 匹配情况3(开头字母): correctLetters=[${correctLetters.join(',')}]`) @@ -410,8 +410,8 @@ const transformDifyQuestions = (difyQuestions: any[]): any[] => { // 提取选项内容(去掉 "A:" 或 "A:" 前缀) let content = optStr - // 匹配 "A:xxx" 或 "A:xxx" 格式(支持中英文冒号) - const contentPrefixMatch = optStr.match(/^[A-Da-d]\s*[::]\s*(.*)$/) + // 匹配 "A:xxx" 或 "A:xxx" 格式(支持中英文冒号,支持A-Z所有字母) + const contentPrefixMatch = optStr.match(/^[A-Za-z]\s*[::]\s*(.*)$/) if (contentPrefixMatch) { content = contentPrefixMatch[1].trim() } @@ -422,13 +422,13 @@ const transformDifyQuestions = (difyQuestions: any[]): any[] => { let letterSource = '' // 1. 尝试从选项内容前缀提取(如 "A:xxx" 或 "A:xxx") - const prefixMatch = optStr.match(/^([A-Da-d])\s*[::]/) + const prefixMatch = optStr.match(/^([A-Za-z])\s*[::]/) if (prefixMatch) { optionLetter = prefixMatch[1].toUpperCase() letterSource = '内容前缀' } - // 2. 尝试从 key 提取(如果 key 是单个字母 A-D) - else if (key.match(/^[A-Da-d]$/)) { + // 2. 尝试从 key 提取(如果 key 是单个字母 A-Z) + else if (key.match(/^[A-Za-z]$/)) { optionLetter = key.toUpperCase() letterSource = 'key字母' }