562 lines
14 KiB
Markdown
562 lines
14 KiB
Markdown
# 自动找工作系统 - 功能实施总结
|
||
|
||
**更新时间**: 2025-12-27
|
||
|
||
---
|
||
|
||
## 已完成功能概览
|
||
|
||
本文档总结了最近完成的两个主要功能模块:
|
||
|
||
1. **价格套餐管理系统**
|
||
2. **AI调用记录与Token追踪系统**
|
||
|
||
---
|
||
|
||
## 一、价格套餐管理系统
|
||
|
||
### 功能描述
|
||
|
||
将原本硬编码在 `api/controller_front/config.js` 中的价格套餐数据迁移到数据库,并提供完整的后台管理界面。
|
||
|
||
### 实施文件清单
|
||
|
||
#### 数据库层
|
||
- ✅ `_sql/create_pricing_plans_table.sql` - 数据表创建脚本
|
||
- ✅ `_sql/insert_pricing_plans_data.sql` - 初始数据插入脚本
|
||
- ✅ `api/model/pricing_plans.js` - Sequelize 数据模型
|
||
|
||
#### 后端API层
|
||
- ✅ `api/controller_admin/pricing_plans.js` - 后台管理API(5个端点)
|
||
- `POST /pricing_plans/list` - 分页查询
|
||
- `GET /pricing_plans/detail` - 获取详情
|
||
- `POST /pricing_plans/create` - 创建套餐
|
||
- `POST /pricing_plans/update` - 更新套餐
|
||
- `POST /pricing_plans/delete` - 删除套餐(软删除)
|
||
- ✅ `api/controller_front/config.js` (修改第90-136行) - 前端API改为数据库查询
|
||
|
||
#### 前端层
|
||
- ✅ `admin/src/api/system/pricing_plans_server.js` - API服务层
|
||
- ✅ `admin/src/views/system/pricing_plans.vue` - 管理界面组件
|
||
- ✅ `admin/src/router/component-map.js` (新增映射) - 组件注册
|
||
|
||
### 数据库表结构
|
||
|
||
```sql
|
||
CREATE TABLE `pricing_plans` (
|
||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||
`name` VARCHAR(100) NOT NULL COMMENT '套餐名称',
|
||
`duration` VARCHAR(50) NOT NULL COMMENT '时长描述',
|
||
`days` INT(11) NOT NULL COMMENT '天数(-1表示永久)',
|
||
`price` DECIMAL(10,2) NOT NULL COMMENT '价格',
|
||
`original_price` DECIMAL(10,2) NULL COMMENT '原价',
|
||
`unit` VARCHAR(20) NOT NULL DEFAULT '元',
|
||
`discount` VARCHAR(50) NULL COMMENT '折扣描述',
|
||
`features` TEXT NOT NULL COMMENT '功能列表(JSON格式)',
|
||
`featured` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否推荐',
|
||
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
|
||
`sort_order` INT(11) NOT NULL DEFAULT 0 COMMENT '排序顺序',
|
||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
`last_modify_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
`is_delete` TINYINT(1) NOT NULL DEFAULT 0,
|
||
PRIMARY KEY (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
```
|
||
|
||
### 初始数据
|
||
|
||
系统预置了4个价格套餐:
|
||
|
||
1. **体验套餐** - 7天 - ¥28
|
||
2. **月度套餐** - 30天 - ¥99(推荐)
|
||
3. **季度套餐** - 90天 - ¥269
|
||
4. **终生套餐** - 永久 - ¥888
|
||
|
||
### 菜单位置
|
||
|
||
**用户管理** → **价格套餐管理**
|
||
|
||
### 关键实现细节
|
||
|
||
#### 前端接口向后兼容
|
||
|
||
`GET /api/config/pricing-plans` 接口保持原有响应格式:
|
||
|
||
```javascript
|
||
[
|
||
{
|
||
"id": 1,
|
||
"name": "体验套餐",
|
||
"duration": "7天",
|
||
"days": 7,
|
||
"price": 28,
|
||
"originalPrice": 28,
|
||
"unit": "元",
|
||
"features": ["7天使用权限", "全功能体验", "技术支持"],
|
||
"featured": false
|
||
}
|
||
]
|
||
```
|
||
|
||
#### 状态控制逻辑
|
||
|
||
- 前端API仅返回 `is_active = 1` 且 `is_delete = 0` 的套餐
|
||
- 按照 `sort_order` ASC, `id` ASC 排序
|
||
- Features字段从JSON字符串自动解析为数组
|
||
|
||
#### 表单组件修复
|
||
|
||
修复了单选按钮组件使用方式(重要):
|
||
|
||
```javascript
|
||
// ❌ 错误写法
|
||
{
|
||
title: '是否推荐',
|
||
key: 'featured',
|
||
type: 'radio', // 错误
|
||
options: [...]
|
||
}
|
||
|
||
// ✅ 正确写法
|
||
{
|
||
title: '是否推荐',
|
||
key: 'featured',
|
||
com: 'Radio', // 正确
|
||
options: [
|
||
{ value: 1, label: '推荐' },
|
||
{ value: 0, label: '普通' }
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 二、AI调用记录与Token追踪系统
|
||
|
||
### 功能描述
|
||
|
||
为所有AI调用添加自动记录功能,追踪Token使用量、调用成本、响应时间等关键指标,并提供后台管理和统计分析界面。
|
||
|
||
### 实施文件清单
|
||
|
||
#### 数据库层
|
||
- ✅ `_sql/create_ai_call_records_table.sql` - 数据表创建脚本
|
||
- ✅ `api/model/ai_call_records.js` - Sequelize 数据模型
|
||
|
||
#### 服务层
|
||
- ✅ `api/services/ai_call_recorder.js` - AI调用记录服务
|
||
- ✅ `api/services/ai_service.js` - AI服务(集成Token记录)
|
||
|
||
#### 后端API层
|
||
- ✅ `api/controller_admin/ai_call_records.js` - 后台管理API(5个端点)
|
||
- `POST /ai_call_records/list` - 分页查询
|
||
- `GET /ai_call_records/detail` - 获取详情
|
||
- `GET /ai_call_records/stats` - 统计分析
|
||
- `POST /ai_call_records/delete` - 删除记录
|
||
- `POST /ai_call_records/batch_delete` - 批量删除
|
||
|
||
#### 前端层
|
||
- ✅ `admin/src/api/system/ai_call_records_server.js` - API服务层
|
||
- ✅ `admin/src/views/system/ai_call_records.vue` - 管理界面组件
|
||
- ✅ `admin/src/router/component-map.js` (新增映射) - 组件注册
|
||
|
||
### 数据库表结构
|
||
|
||
```sql
|
||
CREATE TABLE `ai_call_records` (
|
||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||
`user_id` INT(11) NULL COMMENT '用户ID',
|
||
`sn_code` VARCHAR(100) NULL COMMENT '设备SN码',
|
||
`service_type` VARCHAR(50) NOT NULL COMMENT '服务类型:chat/completion/embedding',
|
||
`model_name` VARCHAR(100) NOT NULL COMMENT '模型名称',
|
||
`prompt_tokens` INT(11) NOT NULL DEFAULT 0 COMMENT '输入Token数',
|
||
`completion_tokens` INT(11) NOT NULL DEFAULT 0 COMMENT '输出Token数',
|
||
`total_tokens` INT(11) NOT NULL DEFAULT 0 COMMENT '总Token数',
|
||
`request_content` TEXT NULL COMMENT '请求内容',
|
||
`response_content` TEXT NULL COMMENT '响应内容',
|
||
`cost_amount` DECIMAL(10,4) NULL COMMENT '费用(元)',
|
||
`status` VARCHAR(20) NOT NULL DEFAULT 'success' COMMENT '状态:success/failed',
|
||
`error_message` TEXT NULL COMMENT '错误信息',
|
||
`response_time` INT(11) NULL COMMENT '响应时间(毫秒)',
|
||
`api_provider` VARCHAR(50) NULL DEFAULT 'qwen' COMMENT 'API提供商',
|
||
`business_type` VARCHAR(50) NULL COMMENT '业务类型',
|
||
`reference_id` VARCHAR(100) NULL COMMENT '关联业务ID',
|
||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
`last_modify_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
`is_delete` TINYINT(1) NOT NULL DEFAULT 0,
|
||
PRIMARY KEY (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
```
|
||
|
||
### AI服务集成
|
||
|
||
#### 使用的AI服务
|
||
|
||
系统使用 **阿里云DashScope API (Qwen 2.5)**,而非DeepSeek。
|
||
|
||
**关键配置:**
|
||
|
||
```javascript
|
||
// api/services/ai_service.js
|
||
class aiService {
|
||
constructor() {
|
||
this.apiKey = config.ai?.apiKey || process.env.DASHSCOPE_API_KEY;
|
||
this.apiUrl = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions';
|
||
this.model = config.ai?.model || 'qwen-turbo';
|
||
this.maxRetries = 3;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 环境变量配置
|
||
|
||
在 `.env` 文件中配置:
|
||
|
||
```bash
|
||
AI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxx
|
||
AI_MODEL=qwen-turbo # 可选:qwen-turbo, qwen-plus, qwen-max, qwen-long
|
||
```
|
||
|
||
详细配置说明见:[docs/ai_service_config.md](ai_service_config.md:1)
|
||
|
||
#### Token记录集成
|
||
|
||
AI服务的 `callAPI()` 方法自动记录所有调用:
|
||
|
||
```javascript
|
||
async callAPI(prompt, options = {}) {
|
||
const startTime = Date.now();
|
||
// ... 调用API ...
|
||
|
||
// 成功时自动记录Token使用量
|
||
this.recordAiCall({
|
||
user_id: options.user_id,
|
||
sn_code: options.sn_code,
|
||
service_type: options.service_type || 'completion',
|
||
model_name: this.model,
|
||
prompt_tokens: usage.prompt_tokens || 0,
|
||
completion_tokens: usage.completion_tokens || 0,
|
||
total_tokens: usage.total_tokens || 0,
|
||
cost_amount: this.calculateCost(usage.total_tokens || 0),
|
||
status: 'success',
|
||
response_time: responseTime,
|
||
api_provider: 'qwen',
|
||
business_type: options.business_type,
|
||
reference_id: options.reference_id
|
||
}).catch(err => {
|
||
console.warn('记录AI调用失败(不影响主流程):', err.message);
|
||
});
|
||
}
|
||
```
|
||
|
||
#### 业务类型分类
|
||
|
||
系统中的AI调用按业务类型分类:
|
||
|
||
| 业务类型 | 说明 | 调用方法 |
|
||
|---------|------|---------|
|
||
| `job_analysis` | 岗位分析 | `analyzeJob()` |
|
||
| `chat_generation` | 聊天内容生成 | `generateChatContent()` |
|
||
| `resume_analysis` | 简历分析 | `analyzeResume()` |
|
||
| `interview_invitation` | 面试邀约 | `generateInterviewInvitation()` |
|
||
| `outsourcing_detection` | 外包检测 | `identifyOutsourcingJob()` |
|
||
|
||
#### 成本计算
|
||
|
||
基于Qwen模型定价:
|
||
|
||
```javascript
|
||
calculateCost(totalTokens) {
|
||
// qwen-turbo: ¥0.003/1000 tokens
|
||
// qwen-plus: ¥0.004/1000 tokens
|
||
// qwen-max: ¥0.12/1000 tokens
|
||
const pricePerThousand = 0.003;
|
||
return (totalTokens / 1000) * pricePerThousand;
|
||
}
|
||
```
|
||
|
||
### 管理界面功能
|
||
|
||
#### 筛选功能
|
||
- 按用户ID搜索
|
||
- 按设备SN码搜索
|
||
- 按业务类型筛选
|
||
- 按服务类型筛选
|
||
- 按状态筛选
|
||
- 按时间范围筛选
|
||
|
||
#### 统计功能
|
||
- 总调用次数
|
||
- Token总使用量(输入/输出/总计)
|
||
- 总费用统计
|
||
- 平均响应时间
|
||
- 成功率统计
|
||
|
||
#### 操作功能
|
||
- 查看详情(完整请求/响应内容)
|
||
- 单条删除
|
||
- 批量删除
|
||
|
||
### 菜单位置
|
||
|
||
**系统设置** → **AI调用记录**
|
||
|
||
---
|
||
|
||
## 三、关键技术点总结
|
||
|
||
### 1. 组件注册规范
|
||
|
||
前端Vue组件必须在 `admin/src/router/component-map.js` 中注册:
|
||
|
||
```javascript
|
||
// 导入组件
|
||
import PricingPlans from '@/views/system/pricing_plans.vue'
|
||
import AiCallRecords from '@/views/system/ai_call_records.vue'
|
||
|
||
// 注册映射
|
||
const componentMap = {
|
||
'system/pricing_plans': PricingPlans,
|
||
'system/ai_call_records': AiCallRecords,
|
||
}
|
||
```
|
||
|
||
### 2. 表单控件使用规范
|
||
|
||
使用 `com` 字段而非 `type` 字段:
|
||
|
||
```javascript
|
||
// 单选按钮
|
||
{ com: 'Radio', options: [...] }
|
||
|
||
// 文本输入框
|
||
{ com: 'Input' }
|
||
|
||
// 文本域
|
||
{ com: 'TextArea' }
|
||
|
||
// 数字输入框
|
||
{ com: 'InputNumber' }
|
||
|
||
// 下拉选择
|
||
{ com: 'Select', options: [...] }
|
||
```
|
||
|
||
### 3. 数据库软删除模式
|
||
|
||
所有查询必须包含 `is_delete = 0` 条件:
|
||
|
||
```javascript
|
||
const list = await model.findAll({
|
||
where: {
|
||
is_delete: 0,
|
||
// ... 其他条件
|
||
}
|
||
});
|
||
```
|
||
|
||
### 4. 时间戳管理
|
||
|
||
使用手动管理而非Sequelize自动管理:
|
||
|
||
```javascript
|
||
// 模型定义
|
||
{
|
||
timestamps: false, // 禁用自动时间戳
|
||
// 手动定义时间字段
|
||
create_time: { type: DataTypes.DATE },
|
||
last_modify_time: { type: DataTypes.DATE }
|
||
}
|
||
|
||
// 创建时手动设置
|
||
const now = new Date();
|
||
await model.create({
|
||
// ... 其他字段
|
||
create_time: now,
|
||
last_modify_time: now
|
||
});
|
||
```
|
||
|
||
### 5. JSON字段处理
|
||
|
||
数据库存储为TEXT类型,应用层处理JSON序列化:
|
||
|
||
```javascript
|
||
// 保存时
|
||
const data = {
|
||
features: JSON.stringify(['功能1', '功能2'])
|
||
};
|
||
|
||
// 读取时
|
||
const features = JSON.parse(record.features || '[]');
|
||
```
|
||
|
||
### 6. 异步记录模式
|
||
|
||
日志/记录类操作使用异步非阻塞模式:
|
||
|
||
```javascript
|
||
// 使用 .catch() 而非 try-catch,避免阻塞主流程
|
||
this.recordAiCall(params).catch(err => {
|
||
console.warn('记录失败(不影响主流程):', err.message);
|
||
});
|
||
|
||
// 主流程继续执行
|
||
return result;
|
||
```
|
||
|
||
---
|
||
|
||
## 四、部署检查清单
|
||
|
||
### 数据库层
|
||
- [ ] 执行 `create_pricing_plans_table.sql`
|
||
- [ ] 执行 `insert_pricing_plans_data.sql`
|
||
- [ ] 执行 `create_ai_call_records_table.sql`
|
||
- [ ] 验证表创建成功
|
||
|
||
### 后端层
|
||
- [ ] 重启Node.js服务以加载新模型
|
||
- [ ] 验证模型加载:`Framework.getModels()`
|
||
- [ ] 配置环境变量 `AI_API_KEY` 和 `AI_MODEL`
|
||
- [ ] 测试后台API端点
|
||
|
||
### 前端层
|
||
- [ ] 重新编译前端代码
|
||
- [ ] 验证组件注册成功
|
||
- [ ] 刷新浏览器缓存
|
||
- [ ] 测试管理界面功能
|
||
|
||
### 菜单系统
|
||
- [ ] 验证"价格套餐管理"菜单显示
|
||
- [ ] 验证"AI调用记录"菜单显示
|
||
- [ ] 测试菜单跳转功能
|
||
|
||
### 功能测试
|
||
- [ ] 价格套餐CRUD操作
|
||
- [ ] 前端API `/config/pricing-plans` 返回数据库数据
|
||
- [ ] AI调用自动记录Token
|
||
- [ ] AI调用记录管理界面
|
||
- [ ] 统计功能准确性
|
||
|
||
---
|
||
|
||
## 五、已知问题与注意事项
|
||
|
||
### 1. 组件热更新
|
||
|
||
修改组件映射后需要:
|
||
- 重启前端开发服务器
|
||
- 清除浏览器缓存
|
||
- 刷新页面
|
||
|
||
### 2. AI服务配置
|
||
|
||
**重要**:系统使用阿里云DashScope API,不是DeepSeek。
|
||
|
||
必须配置正确的环境变量:
|
||
```bash
|
||
AI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxx # 阿里云API Key
|
||
AI_MODEL=qwen-turbo # Qwen模型
|
||
```
|
||
|
||
### 3. Token记录异步
|
||
|
||
Token记录失败不会影响AI调用主流程,但会打印警告日志。如果需要确保记录成功,应检查数据库连接和表结构。
|
||
|
||
### 4. 成本计算
|
||
|
||
当前成本计算使用固定价格(qwen-turbo: ¥0.003/1000 tokens),如果切换到其他模型,需要修改 `calculateCost()` 方法。
|
||
|
||
### 5. 数据备份
|
||
|
||
AI调用记录表会快速增长,建议:
|
||
- 定期归档历史数据
|
||
- 设置数据保留策略(如只保留最近90天)
|
||
- 建立定期备份机制
|
||
|
||
---
|
||
|
||
## 六、文件路径索引
|
||
|
||
### 价格套餐系统
|
||
|
||
**数据库**
|
||
- `_sql/create_pricing_plans_table.sql`
|
||
- `_sql/insert_pricing_plans_data.sql`
|
||
|
||
**后端**
|
||
- `api/model/pricing_plans.js`
|
||
- `api/controller_admin/pricing_plans.js`
|
||
- `api/controller_front/config.js` (修改第90-136行)
|
||
|
||
**前端**
|
||
- `admin/src/api/system/pricing_plans_server.js`
|
||
- `admin/src/views/system/pricing_plans.vue`
|
||
|
||
### AI调用记录系统
|
||
|
||
**数据库**
|
||
- `_sql/create_ai_call_records_table.sql`
|
||
|
||
**后端**
|
||
- `api/model/ai_call_records.js`
|
||
- `api/services/ai_call_recorder.js`
|
||
- `api/services/ai_service.js` (完全重写)
|
||
- `api/controller_admin/ai_call_records.js`
|
||
|
||
**前端**
|
||
- `admin/src/api/system/ai_call_records_server.js`
|
||
- `admin/src/views/system/ai_call_records.vue`
|
||
|
||
### 公共配置
|
||
|
||
- `admin/src/router/component-map.js` (新增两个组件映射)
|
||
- `config/config.js` (AI配置项)
|
||
- `.env` (环境变量)
|
||
|
||
### 文档
|
||
|
||
- `docs/ai_service_config.md` (AI服务配置说明)
|
||
- `docs/implementation_summary.md` (本文档)
|
||
|
||
---
|
||
|
||
## 七、维护建议
|
||
|
||
### 日常维护
|
||
|
||
1. **监控Token使用量**
|
||
- 定期查看AI调用记录统计
|
||
- 关注异常高额调用
|
||
- 优化高频调用场景
|
||
|
||
2. **价格套餐调整**
|
||
- 根据市场情况调整价格
|
||
- 通过后台界面快速上下架套餐
|
||
- 使用排序功能控制显示顺序
|
||
|
||
3. **数据清理**
|
||
- 定期归档或删除历史AI调用记录
|
||
- 清理已删除的套餐数据(物理删除)
|
||
|
||
### 性能优化
|
||
|
||
1. **数据库索引**
|
||
- AI调用记录表按需添加索引(user_id, sn_code, create_time)
|
||
- 定期分析查询性能
|
||
|
||
2. **缓存策略**
|
||
- 考虑对前端API `/config/pricing-plans` 添加缓存
|
||
- 缓存有效期建议5-10分钟
|
||
|
||
3. **日志归档**
|
||
- 建立AI调用记录的归档机制
|
||
- 超过一定时间的数据转移到历史表
|
||
|
||
---
|
||
|
||
**文档版本**: 1.0
|
||
**最后更新**: 2025-12-27
|
||
**维护者**: 开发团队
|