# 简历存储功能 - 前置条件和使用说明

## ⚠️ 重要前置条件

在使用简历存储功能之前，必须确保以下条件已满足：

### 1. 数据库表已创建

#### ✅ `pla_account` 表（平台账户表）

此表存储设备与平台账户的绑定关系，**必须先有记录**才能存储简历。

**表结构**:
```sql
CREATE TABLE `pla_account` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `name` varchar(50) NOT NULL DEFAULT '' COMMENT '账户名',
  `sn_code` varchar(50) NOT NULL DEFAULT '' COMMENT '设备SN码',
  `platform_type` varchar(50) NOT NULL DEFAULT '' COMMENT '平台类型(boss/liepin)',
  `login_name` varchar(50) NOT NULL DEFAULT '' COMMENT '登录名',
  `pwd` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
  `keyword` varchar(50) NOT NULL DEFAULT '' COMMENT '关键词',
  `search_url` varchar(50) NOT NULL DEFAULT '' COMMENT '搜索页网址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```

**示例数据**:
```sql
INSERT INTO `pla_account` (`name`, `sn_code`, `platform_type`, `login_name`, `pwd`) 
VALUES ('张三的Boss账号', 'GHJU', 'boss', '13800138000', 'password123');
```

#### ✅ `resume_info` 表（简历信息表）

此表存储简历详细信息，会自动创建（通过 Sequelize sync）。

**关键字段**:
- `id` - 简历UUID（主键）
- `sn_code` - 设备SN码（关联设备）
- `account_id` - 账户ID（**关联 pla_account.id**）
- `platform` - 平台类型（boss/liepin）

### 2. 数据关联关系

```
┌─────────────────┐         ┌──────────────────┐
│  pla_account    │         │   resume_info    │
├─────────────────┤         ├──────────────────┤
│ id (自增)       │◄────────│ account_id       │
│ sn_code         │         │ sn_code          │
│ platform_type   │         │ platform         │
│ login_name      │         │ fullName         │
│ pwd             │         │ ...              │
└─────────────────┘         └──────────────────┘
```

**查询逻辑**:
1. 通过 `sn_code` + `platform` 查询 `pla_account` 表
2. 获取 `pla_account.id` 作为 `account_id`
3. 将 `account_id` 存入 `resume_info` 表

### 3. 环境配置

#### 数据库连接
确保数据库连接配置正确（`config/config.js`）

#### AI服务配置（可选）
如需AI分析功能，需配置 DeepSeek API：

```env
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxx
DEEPSEEK_API_URL=https://api.deepseek.com/v1/chat/completions
DEEPSEEK_MODEL=deepseek-chat
```

## 🚀 使用流程

### 步骤1: 创建平台账户记录

在调用简历存储功能之前，必须先在 `pla_account` 表中创建账户记录：

```javascript
const db = require('./api/middleware/dbProxy');
const pla_account = db.getModel('pla_account');

// 创建账户记录
await pla_account.create({
    name: '张三的Boss账号',
    sn_code: 'GHJU',
    platform_type: 'boss',
    login_name: '13800138000',
    pwd: 'password123',
    keyword: '前端工程师',
    search_url: 'https://www.zhipin.com/web/geek/job'
});
```

### 步骤2: 同步数据库表结构

运行同步脚本确保表结构正确：

```bash
node scripts/sync_resume_table.js
```

### 步骤3: 调用简历存储功能

```javascript
const jobManager = require('./api/middleware/job/jobManager');

// 获取在线简历（自动存储）
const resumeData = await jobManager.get_online_resume(
    'GHJU',              // 设备SN码（必须在 pla_account 中存在）
    mqttClient,          // MQTT客户端
    { platform: 'boss' } // 平台类型（必须与 pla_account.platform_type 匹配）
);
```

## ❌ 常见错误

### 错误1: "未找到设备 GHJU 在平台 boss 的账户信息"

**原因**: `pla_account` 表中没有对应的记录

**解决方案**:
```javascript
// 检查是否存在账户记录
const account = await pla_account.findOne({
    where: { sn_code: 'GHJU', platform_type: 'boss' }
});

if (!account) {
    // 创建账户记录
    await pla_account.create({
        name: '账户名称',
        sn_code: 'GHJU',
        platform_type: 'boss',
        login_name: '登录名',
        pwd: '密码'
    });
}
```

### 错误2: "Unknown column 'sn_code' in 'field list'"

**原因**: 数据库表结构未同步

**解决方案**:
```bash
# 运行同步脚本
node scripts/sync_resume_table.js

# 或手动执行SQL
ALTER TABLE `resume_info` 
ADD COLUMN `sn_code` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '设备SN码',
ADD COLUMN `account_id` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '用户ID';
```

### 错误3: "account_id 不能为空"

**原因**: `pla_account` 查询失败或返回 null

**解决方案**:
1. 确认 `sn_code` 和 `platform_type` 匹配
2. 检查 `pla_account` 表中是否有对应记录
3. 确认 `platform` 参数正确（'boss' 不是 'Boss'）

## ✅ 验证清单

使用简历存储功能前，请确认：

- [ ] `pla_account` 表已创建
- [ ] `pla_account` 表中有对应设备的记录
- [ ] `sn_code` 和 `platform_type` 匹配
- [ ] `resume_info` 表已创建
- [ ] `resume_info` 表包含 `sn_code` 和 `account_id` 字段
- [ ] 数据库连接正常
- [ ] MQTT 客户端可用
- [ ] （可选）DeepSeek API 配置正确

## 📝 完整示例

```javascript
const db = require('./api/middleware/dbProxy');
const jobManager = require('./api/middleware/job/jobManager');

async function setupAndGetResume() {
    const pla_account = db.getModel('pla_account');
    
    // 1. 检查或创建账户记录
    let account = await pla_account.findOne({
        where: { sn_code: 'GHJU', platform_type: 'boss' }
    });
    
    if (!account) {
        console.log('创建账户记录...');
        account = await pla_account.create({
            name: '测试账号',
            sn_code: 'GHJU',
            platform_type: 'boss',
            login_name: '13800138000',
            pwd: 'password123'
        });
        console.log('账户创建成功，ID:', account.id);
    } else {
        console.log('账户已存在，ID:', account.id);
    }
    
    // 2. 获取简历（自动存储）
    console.log('获取在线简历...');
    const resumeData = await jobManager.get_online_resume(
        'GHJU',
        mqttClient,
        { platform: 'boss' }
    );
    
    console.log('简历获取成功！');
    console.log('姓名:', resumeData.baseInfo?.name);
    
    // 3. 验证存储结果
    const resume_info = db.getModel('resume_info');
    const savedResume = await resume_info.findOne({
        where: { sn_code: 'GHJU', platform: 'boss', isActive: true }
    });
    
    console.log('简历已保存，ID:', savedResume.id);
    console.log('关联账户ID:', savedResume.account_id);
    console.log('竞争力评分:', savedResume.aiCompetitiveness);
}
```

## 🔗 相关文档

- 详细功能说明: `_doc/简历存储和分析功能说明.md`
- 数据库同步指南: `_doc/数据库表同步指南.md`
- 快速参考: `_doc/简历功能快速参考.md`
- 示例代码: `examples/resume_storage_example.js`

