14 KiB
自动找工作系统 - 功能实施总结
更新时间: 2025-12-27
已完成功能概览
本文档总结了最近完成的两个主要功能模块:
- 价格套餐管理系统
- 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(新增映射) - 组件注册
数据库表结构
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个价格套餐:
- 体验套餐 - 7天 - ¥28
- 月度套餐 - 30天 - ¥99(推荐)
- 季度套餐 - 90天 - ¥269
- 终生套餐 - 永久 - ¥888
菜单位置
用户管理 → 价格套餐管理
关键实现细节
前端接口向后兼容
GET /api/config/pricing-plans 接口保持原有响应格式:
[
{
"id": 1,
"name": "体验套餐",
"duration": "7天",
"days": 7,
"price": 28,
"originalPrice": 28,
"unit": "元",
"features": ["7天使用权限", "全功能体验", "技术支持"],
"featured": false
}
]
状态控制逻辑
- 前端API仅返回
is_active = 1且is_delete = 0的套餐 - 按照
sort_orderASC,idASC 排序 - Features字段从JSON字符串自动解析为数组
表单组件修复
修复了单选按钮组件使用方式(重要):
// ❌ 错误写法
{
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(新增映射) - 组件注册
数据库表结构
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。
关键配置:
// 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 文件中配置:
AI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxx
AI_MODEL=qwen-turbo # 可选:qwen-turbo, qwen-plus, qwen-max, qwen-long
详细配置说明见:docs/ai_service_config.md
Token记录集成
AI服务的 callAPI() 方法自动记录所有调用:
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模型定价:
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 中注册:
// 导入组件
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 字段:
// 单选按钮
{ com: 'Radio', options: [...] }
// 文本输入框
{ com: 'Input' }
// 文本域
{ com: 'TextArea' }
// 数字输入框
{ com: 'InputNumber' }
// 下拉选择
{ com: 'Select', options: [...] }
3. 数据库软删除模式
所有查询必须包含 is_delete = 0 条件:
const list = await model.findAll({
where: {
is_delete: 0,
// ... 其他条件
}
});
4. 时间戳管理
使用手动管理而非Sequelize自动管理:
// 模型定义
{
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序列化:
// 保存时
const data = {
features: JSON.stringify(['功能1', '功能2'])
};
// 读取时
const features = JSON.parse(record.features || '[]');
6. 异步记录模式
日志/记录类操作使用异步非阻塞模式:
// 使用 .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。
必须配置正确的环境变量:
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.jsapi/controller_admin/pricing_plans.jsapi/controller_front/config.js(修改第90-136行)
前端
admin/src/api/system/pricing_plans_server.jsadmin/src/views/system/pricing_plans.vue
AI调用记录系统
数据库
_sql/create_ai_call_records_table.sql
后端
api/model/ai_call_records.jsapi/services/ai_call_recorder.jsapi/services/ai_service.js(完全重写)api/controller_admin/ai_call_records.js
前端
admin/src/api/system/ai_call_records_server.jsadmin/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(本文档)
七、维护建议
日常维护
-
监控Token使用量
- 定期查看AI调用记录统计
- 关注异常高额调用
- 优化高频调用场景
-
价格套餐调整
- 根据市场情况调整价格
- 通过后台界面快速上下架套餐
- 使用排序功能控制显示顺序
-
数据清理
- 定期归档或删除历史AI调用记录
- 清理已删除的套餐数据(物理删除)
性能优化
-
数据库索引
- AI调用记录表按需添加索引(user_id, sn_code, create_time)
- 定期分析查询性能
-
缓存策略
- 考虑对前端API
/config/pricing-plans添加缓存 - 缓存有效期建议5-10分钟
- 考虑对前端API
-
日志归档
- 建立AI调用记录的归档机制
- 超过一定时间的数据转移到历史表
文档版本: 1.0 最后更新: 2025-12-27 维护者: 开发团队