first commit

This commit is contained in:
2026-04-17 13:23:50 +08:00
commit d985b56ac6
46 changed files with 8171 additions and 0 deletions

104
README.md Normal file
View File

@@ -0,0 +1,104 @@
# Resume Parse API
一个简单的 Node.js/Express 接口:上传简历文档(支持 `.docx` / `.pdf`),提取文本后返回结构化信息和面试评估内容。
## 运行
1. 安装依赖
- `npm install`
2. 启动开发模式
- `npm run dev`
3. 服务启动后默认地址
- `http://localhost:3000`
## 健康检查
- `GET /health`
返回示例:`{ "ok": true, "mysql": { "ok": true, "skipped": false, "database": "Resume" } }`
- 未配置 `MYSQL_HOST` 时:`mysql.skipped === true`
- 连接失败时:`mysql.ok === false` 且带 `mysql.error`
## MySQL远程库 Resume
`.env` 中配置(勿提交到 Git仓库已忽略 `.env`
- `MYSQL_HOST`:服务器 IP 或域名(必填)
- `MYSQL_PORT`:默认 `3306`
- `MYSQL_USER`:默认 `root`(按你服务器实际账号修改)
- `MYSQL_PASSWORD`
- `MYSQL_DATABASE`:默认 `Resume`
启动时会在控制台打印 `[mysql] 已连接``[mysql] 连接失败`。代码里通过 `require("./mysql").getMysqlPool()` 获取连接池。
### 入库说明
- 连接成功后会自动维护表 **`resume_submissions`**。
- **列结构**:与解析结果对齐,**姓名、城市、年龄、期望薪资、教育经历、学历、能力、工作经历、项目经历、技术栈**各占一列(便于查询、统计、以后查重);**不再写入**整段 `extracted_text`
- **JSON 列**`interview_report`AI 面试题与整块评估)、`pdf_meta`PDF/OCR 元信息)、`warnings_json`(解析告警列表)。
- 若检测到**旧版表**(曾含 `extracted_text` 列),启动时会 **DROP 后重建**,旧数据会清空,请注意备份。
- 接口响应里仍有 **`db`**`{ "saved": true, "id": 1 }` 等含义不变。
## 解析接口
### 推荐流程(前端默认)
1. **`POST /api/resume/step1`**`multipart/form-data`,字段 `file`
- 抽取文本、计算 `file_sha256`、与库比对是否重复(同哈希且已有 `interview_report`)。
- **不调 AI**。返回 `parsedPreview`(规则)、`text``fileSha256``uploadId`(非重复时用于第二步)、`isDuplicate` 等。
2. **`POST /api/resume/consult-ai`**`application/json`
- Body`{ "fileSha256": "...", "uploadId": "..." }`(重复时可省略 `uploadId`)。
- 若重复:直接返回库内 `interview_report` 与列字段还原的 `parsed`**不请求模型**。
- 若不重复:用 `uploadId` 取内存会话,调用 AI写入 `resume_submissions`,并清除会话。
### 兼容接口
- `POST /api/parse-word`:一步完成「抽取 + AI + 入库」(脚本或旧客户端可用)。
- 请求类型:`multipart/form-data`
- 文件字段名:`file`
### curl 示例
```bash
curl -X POST "http://localhost:3000/api/parse-word" ^
-F "file=@D:\test\demo.docx"
```
```bash
curl -X POST "http://localhost:3000/api/parse-word" ^
-F "file=@D:\test\demo.pdf"
```
### 返回
```json
{
"filename": "demo.pdf",
"mimeType": "application/pdf",
"sourceType": "pdf",
"text": "解析出的内容(纯文本)",
"parsed": {
"姓名": "张三"
},
"interviewReport": {
"interviewQuestions": []
},
"warnings": []
}
```
## 说明
- 当前使用 `mammoth` 解析 `.docx`,使用 `pdf-parse` 解析 `.pdf`
- **扫描版 PDF几乎无文本层**:当文本层有效字符数低于阈值时,可启用 OCR使用 `pdfjs-dist` + `@napi-rs/canvas` 将页面渲染为图片,再用 `tesseract.js` 识别文字。
- **`PDF_OCR_ENABLED=1` 才会执行 OCR**(默认不开启,避免首次下载模型时请求长时间无响应)。
- `PDF_OCR_MIN_CHARS`:低于该有效字符数才尝试 OCR默认 `80`
- `PDF_OCR_MAX_PAGES`:最多 OCR 的页数,默认 `5`
- `PDF_OCR_SCALE`:渲染缩放(越大越清晰但更慢),默认 `2`
- `PDF_OCR_DISABLED`:设为 `1` 可强制关闭 OCR优先级高于 `PDF_OCR_ENABLED`
- `PDF_OCR_LANG`Tesseract 语言,默认 `chi_sim`。可设为 `eng``chi_sim+eng`
- `PDF_OCR_INIT_TIMEOUT_MS`:初始化 Tesseract含首次下载超时默认 `120000`
- `PDF_OCR_PAGE_TIMEOUT_MS`:单页识别超时,默认 `120000`
- 项目将 `pdfjs-dist` 固定为 `5.4.296`,与 `pdf-parse` 内置版本一致,避免 Worker 与 API 版本不一致。
- 如果你需要支持 `.doc`(旧版 Word告诉我你的文档来源/格式,我可以再加转换或抽取方案。