diff --git a/1.html b/1.html
new file mode 100644
index 0000000..1c3193e
--- /dev/null
+++ b/1.html
@@ -0,0 +1,776 @@
+
BOSS直聘
\ No newline at end of file
diff --git a/1.py b/1.py
new file mode 100644
index 0000000..d9485f2
--- /dev/null
+++ b/1.py
@@ -0,0 +1,131 @@
+# -*- coding: utf-8 -*-
+"""
+本地脚本:由 DrissionPage (DP) 控制浏览器(本地谷歌 Chrome 或比特浏览器)。
+- 使用本地谷歌:USE_LOCAL_CHROME = True,会启动/连接本机 Chrome。
+- 使用比特浏览器:USE_LOCAL_CHROME = False,需先启动比特浏览器客户端(API 端口 54345)。
+"""
+from __future__ import annotations
+
+import random
+import sys
+import time
+from pathlib import Path
+
+# 保证从项目根目录运行时可导入 worker 包
+_ROOT = Path(__file__).resolve().parent
+if str(_ROOT) not in sys.path:
+ sys.path.insert(0, str(_ROOT))
+
+# ---------- 选择控制对象 ----------
+USE_LOCAL_CHROME = True # True=本地谷歌 Chrome,False=比特浏览器
+
+# 本地谷歌 Chrome 配置(仅当 USE_LOCAL_CHROME=True 时生效)
+CHROME_DEBUG_PORT = 9222 # 调试端口;若为 None 则由脚本自动启动 Chrome
+CHROME_PATH = None # 例如 r"C:\Program Files\Google\Chrome\Application\chrome.exe",None 用系统默认
+
+# 比特浏览器配置(仅当 USE_LOCAL_CHROME=False 时生效)
+BIT_API_BASE = "http://127.0.0.1:54345"
+BROWSER_NAME = "测试2"
+BROWSER_ID = None
+
+
+def _connect_local_chrome():
+ """连接或启动本地谷歌 Chrome,返回 ChromiumPage。"""
+ from DrissionPage import ChromiumPage, ChromiumOptions
+
+ co = ChromiumOptions()
+ if CHROME_PATH:
+ co.set_browser_path(CHROME_PATH)
+ if CHROME_DEBUG_PORT is not None:
+ # 连接已开启调试端口的 Chrome(需先手动启动:chrome --remote-debugging-port=9222)
+ co.set_local_port(CHROME_DEBUG_PORT)
+ print(f"正在连接本机 Chrome(调试端口 {CHROME_DEBUG_PORT})...")
+ page = ChromiumPage(addr_or_opts=co)
+ else:
+ # 由 DrissionPage 自动启动 Chrome
+ print("正在启动本地谷歌 Chrome...")
+ page = ChromiumPage(addr_or_opts=co)
+ print("已连接本地 Chrome。")
+ return page
+
+
+def _connect_bit_browser():
+ """通过比特浏览器 API 打开并连接,返回 ChromiumPage。"""
+ from worker.bit_browser import BitBrowserAPI
+ from DrissionPage import ChromiumPage, ChromiumOptions
+
+ print("正在连接比特浏览器 API...")
+ bit_api = BitBrowserAPI(BIT_API_BASE)
+ print("正在打开比特浏览器...")
+ cdp_addr, port, browser_id = bit_api.open_browser(
+ browser_id=BROWSER_ID, name=BROWSER_NAME, remark=None
+ )
+ print(f"已打开浏览器 ID={browser_id}, CDP 端口={port}")
+ co = ChromiumOptions().set_local_port(port=port)
+ return ChromiumPage(addr_or_opts=co)
+
+
+def main():
+ from DrissionPage.errors import NoRectError
+
+ if USE_LOCAL_CHROME:
+ page = _connect_local_chrome()
+ else:
+ page = _connect_bit_browser()
+
+ page.listen.start('wapi/zpjob/rec/geek/list')
+
+ # 示例:打开一个页面(可选)
+ page.get("https://www.zhipin.com/web/chat/recommend")
+ res = page.listen.wait()
+
+ for i in res.response.body["zpData"]["geekList"]:
+ print(i)
+
+ geekName = i["geekCard"]["geekName"] # 姓名
+ geekDegree = i["geekCard"]["geekDegree"] # 学历
+ expectPositionName = i["geekCard"]["expectPositionName"] #期待职位
+ expectLocationName = i["geekCard"]["expectLocationName"] # 地区
+ applyStatusDesc = i["geekCard"]["applyStatusDesc"] # 当前状态离职0随时到岗之类的
+ ageDesc = i["geekCard"]["ageDesc"] # 年龄
+ lowSalary = i["geekCard"]["lowSalary"] # 最低要求工资
+ highSalary = i["geekCard"]["highSalary"] # 最高要求工资
+
+
+ """三个动作:1. 找到姓名 2. 滚动到那里 3. 点击打招呼"""
+ try:
+ container = page.get_frame("recommendFrame")
+ except Exception:
+ container = page
+
+ # 1. 找到这个姓名
+ name_ele = container.ele(f'x://span[contains(text(),"{geekName}")]', timeout=10)
+ if not name_ele:
+ name_ele = container.ele(f'x://span[text()="{geekName}"]', timeout=2)
+ if not name_ele:
+ raise Exception(f"未找到姓名:{geekName}")
+
+ # 2. 滚动到那里
+ name_ele.run_js("this.scrollIntoView({block: 'center', behavior: 'auto'})")
+ time.sleep(0.8)
+
+ # 3. 点击打招呼(先在该人所在卡片内找)
+ parent = name_ele.parent()
+ greet_btn = None
+ for _ in range(8):
+ if not parent:
+ break
+ greet_btn = parent.ele('x://span[text()="打招呼"]', timeout=0.5) or parent.ele('x://*[contains(text(),"打招呼")]', timeout=0.5)
+ if greet_btn:
+ break
+ parent = parent.parent()
+ if not greet_btn:
+ greet_btn = container.ele('x://span[text()="打招呼"]', timeout=2) or container.ele('x://*[contains(text(),"打招呼")]', timeout=1)
+ if not greet_btn:
+ raise Exception("未找到「打招呼」按钮")
+ greet_btn.click(by_js=True)
+
+
+
+if __name__ == "__main__":
+ main()
diff --git a/API_CONTACTS.md b/API_CONTACTS.md
deleted file mode 100644
index 3e5dbc9..0000000
--- a/API_CONTACTS.md
+++ /dev/null
@@ -1,317 +0,0 @@
-# 联系记录接口文档
-
-## 1. 查询联系记录列表
-
-### 接口信息
-- **URL**: `/api/contacts`
-- **方法**: `GET`
-- **认证**: 需要登录(Header 携带 Authorization)
-
-### 请求参数
-
-| 参数名 | 类型 | 必填 | 说明 | 示例 |
-|--------|------|------|------|------|
-| page | integer | 否 | 页码,默认 1 | 1 |
-| page_size | integer | 否 | 每页数量,默认 10 | 20 |
-| search | string | 否 | 搜索关键词(姓名/岗位/联系方式) | 张三 |
-| reply_status | string | 否 | 回复状态筛选 | 已回复 |
-| wechat_exchanged | boolean | 否 | 是否交换微信 | true |
-| start_date | string | 否 | 开始日期(YYYY-MM-DD) | 2024-01-01 |
-| end_date | string | 否 | 结束日期(YYYY-MM-DD) | 2024-12-31 |
-
-### 请求示例
-
-```bash
-# 基础查询
-GET /api/contacts?page=1&page_size=20
-
-# 关键词搜索
-GET /api/contacts?search=张三
-
-# 按回复状态筛选
-GET /api/contacts?reply_status=已回复
-
-# 按时间范围筛选
-GET /api/contacts?start_date=2024-01-01&end_date=2024-12-31
-
-# 组合筛选
-GET /api/contacts?search=产品经理&reply_status=已回复&wechat_exchanged=true&start_date=2024-01-01&end_date=2024-12-31
-```
-
-### 响应示例
-
-```json
-{
- "code": 200,
- "msg": "success",
- "data": {
- "total": 150,
- "page": 1,
- "page_size": 20,
- "results": [
- {
- "id": 1,
- "name": "张三",
- "position": "产品经理",
- "contact": "13800138000",
- "reply_status": "已回复",
- "wechat_exchanged": true,
- "account_id": 1,
- "worker_id": "worker-001",
- "notes": "沟通顺畅,有意向",
- "contacted_at": "2024-03-01T10:30:00",
- "created_at": "2024-03-01T10:00:00"
- },
- {
- "id": 2,
- "name": "李四",
- "position": "前端工程师",
- "contact": "wechat:lisi123",
- "reply_status": "未回复",
- "wechat_exchanged": false,
- "account_id": 2,
- "worker_id": "worker-002",
- "notes": "",
- "contacted_at": "2024-03-02T14:20:00",
- "created_at": "2024-03-02T14:00:00"
- }
- ]
- }
-}
-```
-
----
-
-## 2. 导出联系记录为 Excel
-
-### 接口信息
-- **URL**: `/api/contacts/export`
-- **方法**: `GET`
-- **认证**: 需要登录(Header 携带 Authorization)
-- **响应类型**: `application/json`(返回下载链接)
-
-### 请求参数
-
-| 参数名 | 类型 | 必填 | 说明 | 示例 |
-|--------|------|------|------|------|
-| search | string | 否 | 搜索关键词(姓名/岗位/联系方式) | 张三 |
-| reply_status | string | 否 | 回复状态筛选 | 已回复 |
-| wechat_exchanged | boolean | 否 | 是否交换微信 | true |
-| start_date | string | 否 | 开始日期(YYYY-MM-DD) | 2024-01-01 |
-| end_date | string | 否 | 结束日期(YYYY-MM-DD) | 2024-12-31 |
-
-### 请求示例
-
-```bash
-# 导出所有联系记录
-GET /api/contacts/export
-
-# 导出指定时间段的记录
-GET /api/contacts/export?start_date=2024-01-01&end_date=2024-12-31
-
-# 导出已回复且交换微信的记录
-GET /api/contacts/export?reply_status=已回复&wechat_exchanged=true
-
-# 导出组合筛选结果
-GET /api/contacts/export?search=产品经理&start_date=2024-01-01&end_date=2024-03-31&reply_status=已回复
-```
-
-### 响应示例
-
-```json
-{
- "code": 200,
- "msg": "success",
- "data": {
- "download_url": "http://127.0.0.1:8000/media/exports/contacts_export_20240304_153045_a1b2c3d4.xlsx",
- "filename": "contacts_export_20240304_153045_a1b2c3d4.xlsx",
- "total_records": 150,
- "generated_at": "2024-03-04 15:30:45"
- }
-}
-```
-
-### 响应字段说明
-
-| 字段名 | 类型 | 说明 |
-|--------|------|------|
-| download_url | string | 文件下载链接(完整 URL) |
-| filename | string | 生成的文件名 |
-| total_records | integer | 导出的记录总数 |
-| generated_at | string | 文件生成时间 |
-
-### Excel 文件格式
-
-**表头**(蓝色背景,白色粗体文字):
-
-| 列名 | 说明 | 示例 |
-|------|------|------|
-| ID | 记录 ID | 1 |
-| 姓名 | 联系人姓名 | 张三 |
-| 岗位 | 应聘岗位 | 产品经理 |
-| 联系方式 | 电话或微信 | 13800138000 |
-| 回复状态 | 回复状态 | 已回复 |
-| 是否交换微信 | 是/否 | 是 |
-| Worker ID | Worker 标识 | worker-001 |
-| 备注 | 备注信息 | 沟通顺畅,有意向 |
-| 联系时间 | 联系时间 | 2024-03-01 10:30:00 |
-| 创建时间 | 创建时间 | 2024-03-01 10:00:00 |
-
-### 前端调用示例
-
-```javascript
-// 使用 axios
-const exportContacts = async (params) => {
- try {
- const response = await axios.get('/api/contacts/export', {
- params: params,
- headers: {
- 'Authorization': `Bearer ${token}`
- }
- });
-
- if (response.data.code === 200) {
- const { download_url, filename, total_records } = response.data.data;
-
- // 方式1:直接打开下载链接
- window.open(download_url, '_blank');
-
- // 方式2:使用 a 标签下载
- const link = document.createElement('a');
- link.href = download_url;
- link.download = filename;
- document.body.appendChild(link);
- link.click();
- document.body.removeChild(link);
-
- // 提示用户
- console.log(`成功导出 ${total_records} 条记录`);
- }
- } catch (error) {
- console.error('导出失败:', error);
- }
-};
-
-// 调用示例
-exportContacts({
- start_date: '2024-01-01',
- end_date: '2024-12-31',
- reply_status: '已回复'
-});
-```
-
-```javascript
-// 使用 fetch
-const exportContacts = async (params) => {
- const queryString = new URLSearchParams(params).toString();
-
- try {
- const response = await fetch(`/api/contacts/export?${queryString}`, {
- headers: {
- 'Authorization': `Bearer ${token}`
- }
- });
-
- const result = await response.json();
-
- if (result.code === 200) {
- const { download_url, filename, total_records } = result.data;
-
- // 直接下载文件
- const link = document.createElement('a');
- link.href = download_url;
- link.download = filename;
- link.click();
-
- alert(`成功导出 ${total_records} 条记录`);
- }
- } catch (error) {
- console.error('导出失败:', error);
- }
-};
-```
-
-```vue
-
-
-
-
-
-
-```
-
----
-
-## 错误码说明
-
-| 错误码 | 说明 |
-|--------|------|
-| 200 | 成功 |
-| 400 | 请求参数错误 |
-| 401 | 未登录或 token 无效 |
-| 500 | 服务器内部错误 |
-
-## 注意事项
-
-1. **时间筛选**:
- - `start_date` 从当天 00:00:00 开始
- - `end_date` 到当天 23:59:59 结束
- - 时间筛选基于 `created_at` 字段(创建时间)
-
-2. **搜索功能**:
- - `search` 参数支持模糊匹配
- - 同时搜索姓名、岗位、联系方式三个字段
-
-3. **导出机制**:
- - 导出接口返回下载链接,不直接返回文件流
- - 文件保存在服务器 `media/exports/` 目录
- - 文件名格式:`contacts_export_{时间戳}_{随机ID}.xlsx`
- - 导出接口不分页,会导出所有符合条件的记录
- - 建议在导出大量数据时添加时间范围限制
-
-4. **文件管理**:
- - 导出的文件会保存在服务器上
- - 建议定期清理过期的导出文件
- - 可以通过定时任务删除超过一定时间的文件
-
-5. **认证要求**:
- - 所有接口都需要在 Header 中携带 `Authorization` token
- - token 格式:`Bearer `
-
-6. **下载链接**:
- - 返回的 `download_url` 是可直接访问的完整下载 URL
- - 前端可直接 `window.open(download_url)` 或 `a.href = download_url` 下载
diff --git a/API文档.md b/API文档.md
deleted file mode 100644
index 837d317..0000000
--- a/API文档.md
+++ /dev/null
@@ -1,693 +0,0 @@
-# BOSS 直聘自动化平台 - API 接口文档
-
-**Base URL**: `http://{服务器IP}:9000`
-
-**认证方式**: Cookie(`auth_token`),登录成功后自动通过 `Set-Cookie` 设置,后续请求自动携带。
-
-**请求格式**: 支持 `application/json` 和 `multipart/form-data`
-
-**响应规范**: 所有接口的 JSON 响应体均包含 **`code`** 字段,与 HTTP 状态码一致。成功时如 `code: 200`、`code: 201`;错误时如 `code: 401`、`code: 404`。原返回数组的接口会包装为 `{"code": 状态码, "data": 原数组}`。
-
----
-
-## 一、健康检查
-
-### GET /health
-
-**说明**: 检查服务器是否正常运行,无需登录。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回服务状态与在线 Worker 数 |
-| 500 | 服务器内部错误(少见) |
-
-**请求参数**: 无
-
-**响应示例**:
-```json
-{
- "status": "ok",
- "workers_online": 2
-}
-```
-
-| 返回字段 | 类型 | 说明 |
-|---------|------|------|
-| status | string | 服务状态,固定 `"ok"` |
-| workers_online | int | 当前在线 Worker 数量 |
-
----
-
-## 二、认证
-
-### POST /api/auth/login
-
-**说明**: 管理员登录,无需认证。登录成功后通过 `Set-Cookie` 返回 `auth_token`。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回 token 并设置 Cookie |
-| 401 | 用户名或密码错误 |
-
-**请求参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| username | string | 是 | 用户名 |
-| password | string | 是 | 密码 |
-
-**请求示例**:
-```json
-{
- "username": "admin",
- "password": "boss_dp_admin"
-}
-```
-
-**成功响应** (200):
-```json
-{
- "token": "a1b2c3d4e5f6..."
-}
-```
-
-**失败响应** (401):
-```json
-{
- "detail": "用户名或密码错误"
-}
-```
-
-| 返回字段 | 类型 | 说明 |
-|---------|------|------|
-| token | string | 登录 token(同时通过 Cookie 设置) |
-
-**响应 Header**:
-```
-Set-Cookie: auth_token=a1b2c3d4e5f6...; HttpOnly; Max-Age=31536000; SameSite=Lax
-```
-
----
-
-## 三、Worker 管理
-
-> 以下接口均需登录(携带 `auth_token` Cookie)
-
-### GET /api/workers
-
-**说明**: 获取所有已注册 Worker 列表。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回 Worker 数组 |
-| 401 | 未登录或 token 失效 |
-
-**请求参数**: 无
-
-**响应示例**:
-```json
-[
- {
- "worker_id": "worker-1",
- "worker_name": "本机",
- "browsers": [
- {
- "id": "abd63190eea84dc49429962f7bb330a4",
- "name": "第一个",
- "remark": ""
- }
- ],
- "online": true,
- "current_task_id": null
- }
-]
-```
-
-| 返回字段 | 类型 | 说明 |
-|---------|------|------|
-| worker_id | string | Worker 唯一标识 |
-| worker_name | string | Worker 名称(电脑名) |
-| browsers | array | 该电脑上的比特浏览器环境列表 |
-| browsers[].id | string | 浏览器窗口 ID |
-| browsers[].name | string | 浏览器窗口名称(环境名) |
-| browsers[].remark | string | 备注 |
-| online | boolean | 是否在线 |
-| current_task_id | string/null | 当前正在执行的任务 ID |
-
----
-
-### GET /api/workers/{worker_id}
-
-**说明**: 获取指定 Worker 的详细信息。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回单个 Worker 对象 |
-| 401 | 未登录或 token 失效 |
-| 404 | Worker 不存在 |
-
-**路径参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| worker_id | string | 是 | Worker ID |
-
-**成功响应** (200): 同上单个 Worker 对象
-
-**失败响应** (404):
-```json
-{
- "detail": "Worker worker-99 不存在"
-}
-```
-
----
-
-## 四、账号管理
-
-> 以下接口均需登录(携带 `auth_token` Cookie)
-
-### POST /api/accounts
-
-**说明**: 添加账号(将浏览器环境名称绑定到指定电脑)。若已存在相同绑定则直接返回已有记录。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 201 | 成功创建或返回已有记录 |
-| 400 | 请求参数错误(如缺少 browser_name、worker_id) |
-| 401 | 未登录或 token 失效 |
-
-**请求参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| browser_name | string | 是 | 浏览器环境名称 |
-| worker_id | string | 是 | 目标电脑的 Worker ID |
-
-**请求示例**:
-```json
-{
- "browser_name": "第一个",
- "worker_id": "worker-1"
-}
-```
-
-**成功响应** (201):
-```json
-{
- "id": 1,
- "worker_id": "worker-1",
- "browser_id": "name:第一个",
- "browser_name": "第一个",
- "boss_username": "",
- "is_logged_in": false,
- "current_task_id": null,
- "current_task_status": null,
- "checked_at": null,
- "created_at": "2026-02-14T16:00:00",
- "updated_at": "2026-02-14T16:00:00",
- "worker_name": "本机",
- "worker_online": true
-}
-```
-
----
-
-### GET /api/accounts
-
-**说明**: 查询所有账号列表,包含电脑名称、在线状态、任务执行状态。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回账号数组 |
-| 401 | 未登录或 token 失效 |
-
-**查询参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| worker_id | string | 否 | 按 Worker ID 过滤 |
-
-**响应示例**:
-```json
-[
- {
- "id": 1,
- "worker_id": "worker-1",
- "browser_id": "abd63190eea84dc49429962f7bb330a4",
- "browser_name": "第一个",
- "boss_username": "某用户",
- "is_logged_in": true,
- "current_task_id": "3f113d90bb32",
- "current_task_status": "success",
- "checked_at": "2026-02-14T16:05:00",
- "created_at": "2026-02-14T16:00:00",
- "updated_at": "2026-02-14T16:05:00",
- "worker_name": "本机",
- "worker_online": true
- }
-]
-```
-
-| 返回字段 | 类型 | 说明 |
-|---------|------|------|
-| id | int | 账号记录 ID |
-| worker_id | string | 绑定的 Worker ID |
-| browser_id | string | 比特浏览器窗口 ID |
-| browser_name | string | 浏览器环境名称 |
-| boss_username | string | BOSS 直聘用户名(检测后填充) |
-| boss_id | string | BOSS 直聘用户 ID(检测登录成功时填充) |
-| is_logged_in | boolean | 是否已登录 BOSS |
-| current_task_id | string/null | 当前关联的任务 ID |
-| current_task_status | string/null | 当前任务状态:`pending` / `dispatched` / `running` / `success` / `failed` |
-| checked_at | string/null | 最近一次检测时间(ISO 格式) |
-| created_at | string | 创建时间 |
-| updated_at | string | 更新时间 |
-| worker_name | string | 电脑名称(运行时补充) |
-| worker_online | boolean | 电脑是否在线(运行时补充) |
-
----
-
-### GET /api/accounts/{id}
-
-**说明**: 查询单个账号详情。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回单个账号对象 |
-| 401 | 未登录或 token 失效 |
-| 404 | 账号不存在 |
-
-**路径参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| id | int | 是 | 账号记录 ID |
-
-**成功响应** (200): 同上单个账号对象
-
-**失败响应** (404):
-```json
-{
- "detail": "账号不存在"
-}
-```
-
----
-
-### DELETE /api/accounts/{id}
-
-**说明**: 删除指定账号。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功删除 |
-| 401 | 未登录或 token 失效 |
-| 404 | 账号不存在 |
-
-**路径参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| id | int | 是 | 账号记录 ID |
-
-**成功响应** (200):
-```json
-{
- "message": "账号已删除"
-}
-```
-
-**失败响应** (404):
-```json
-{
- "detail": "账号不存在"
-}
-```
-
----
-
-## 五、任务管理
-
-> 以下接口均需登录(携带 `auth_token` Cookie)
->
-> **统一任务入口**:所有任务(检查登录、招聘等)都通过 `POST /api/tasks` 提交,通过 `task_type` 字段区分任务类型。
-
-### POST /api/tasks
-
-**说明**: 提交新任务。通过 `task_type` 指定任务类型,系统自动路由到目标 Worker 执行。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 201 | 成功,任务已创建并派发 |
-| 400 | 未指定 id、boss_id、worker_id 或 account_name |
-| 401 | 未登录或 token 失效 |
-| 409 | 同一账号已有执行中的任务 |
-| 404 | 未找到拥有该浏览器环境的在线 Worker |
-| 503 | Worker 不在线 / WebSocket 连接不存在 / 派发失败 |
-
-**请求参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| task_type | string | 是 | 任务类型:`check_login`(检查登录)、`boss_recruit`(招聘) |
-| id | int | 否 | 账号 ID(直接指定,推荐) |
-| boss_id | int | 否 | 即 /api/accounts 返回的 id(账号主键),与 id 等价 |
-| worker_id | string | 否 | 目标 Worker ID |
-| account_name | string | 否 | 浏览器环境名称(系统自动查找对应 Worker) |
-| params | object | 否 | 任务附加参数,默认 `{}` |
-
-**路由规则**: `id`、`account_id`、`boss_id` 等价(均为账号主键);否则 `worker_id` 或 `account_name`。
-
-**请求示例 — 检查登录(推荐用 id)**:
-```json
-{
- "task_type": "check_login",
- "id": 2
-}
-```
-
-**请求示例 — 招聘任务**:
-```json
-{
- "task_type": "boss_recruit",
- "worker_id": "worker-1",
- "params": {
- "keyword": "Python开发",
- "count": 10
- }
-}
-```
-
-**成功响应** (201):
-```json
-{
- "task_id": "3f113d90bb32",
- "task_type": "check_login",
- "status": "dispatched",
- "worker_id": "worker-1",
- "account_name": "第一个",
- "params": {},
- "progress": null,
- "result": null,
- "error": null,
- "created_at": 1739520000.123,
- "updated_at": 1739520000.456
-}
-```
-
-**失败响应**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 400 | 未指定 id、boss_id、worker_id 或 account_name |
-| 401 | 未登录或 token 失效 |
-| 409 | 同一账号已有执行中的任务 |
-| 404 | 未找到拥有该浏览器环境的在线 Worker |
-| 503 | Worker 不在线 / WebSocket 连接不存在 / 派发失败 |
-
----
-
-### GET /api/tasks
-
-**说明**: 查询任务列表(内存中的任务)。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回任务数组 |
-| 401 | 未登录或 token 失效 |
-
-**查询参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| worker_id | string | 否 | 按 Worker ID 过滤 |
-| status | string | 否 | 按状态过滤:`pending` / `dispatched` / `running` / `success` / `failed` / `cancelled` |
-| limit | int | 否 | 返回数量限制,默认 50 |
-
-**响应示例**:
-```json
-[
- {
- "task_id": "3f113d90bb32",
- "task_type": "check_login",
- "status": "success",
- "worker_id": "worker-1",
- "account_name": "第一个",
- "params": {},
- "progress": "检测完成: 第一个 → 未登录 ()",
- "result": {
- "browser_id": "abd63190eea84dc49429962f7bb330a4",
- "browser_name": "第一个",
- "boss_username": "",
- "is_logged_in": false
- },
- "error": null,
- "created_at": 1739520000.123,
- "updated_at": 1739520030.789
- }
-]
-```
-
-| 返回字段 | 类型 | 说明 |
-|---------|------|------|
-| task_id | string | 任务唯一 ID(12 位十六进制) |
-| task_type | string | 任务类型 |
-| status | string | 任务状态:`pending` → `dispatched` → `running` → `success`/`failed` |
-| worker_id | string/null | 执行任务的 Worker ID |
-| account_name | string/null | 关联的浏览器环境名称 |
-| params | object | 任务参数 |
-| progress | string/null | 执行进度描述 |
-| result | object/null | 任务结果(成功时返回) |
-| error | string/null | 错误信息(失败时返回) |
-| created_at | float | 创建时间(Unix 时间戳) |
-| updated_at | float | 最后更新时间(Unix 时间戳) |
-
----
-
-### GET /api/tasks/{account_id}
-
-**说明**: 按账号 ID 查询任务列表(不支持按 task_id 查询)。
-- 不传 `page/page_size`:返回任务数组(兼容旧版前端)
-- 传 `page` 或 `page_size`:返回分页对象
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回任务数组 |
-| 401 | 未登录或 token 失效 |
-| 404 | 账号不存在 |
-
-**路径参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| account_id | int | 是 | 账号 ID(即 `/api/accounts` 返回的 `id`) |
-| status | string | 否 | 按状态过滤:`pending` / `dispatched` / `running` / `success` / `failed` / `cancelled` |
-| limit | int | 否 | 兼容参数,不分页模式下表示最多返回条数;分页模式下可作为 `page_size` 默认值 |
-| page | int | 否 | 分页页码(从 1 开始) |
-| page_size | int | 否 | 每页条数,默认 20,最大 200 |
-
-**成功响应** (200):
-- 兼容模式:同上任务对象数组
-- 分页模式:
-```json
-{
- "total": 123,
- "page": 1,
- "page_size": 20,
- "results": [
- {
- "task_id": "3f113d90bb32",
- "task_type": "check_login",
- "status": "success",
- "worker_id": "worker-1",
- "account_name": "第一个",
- "params": {},
- "progress": null,
- "result": {},
- "error": null,
- "created_at": "2026-03-01T20:00:00",
- "updated_at": "2026-03-01T20:00:00"
- }
- ]
-}
-```
-
-**失败响应** (404):
-```json
-{
- "detail": "账号 xxx 不存在"
-}
-```
-
----
-
-## 六、任务类型说明
-
-| task_type | 说明 | 必要参数 | 返回 result |
-|-----------|------|---------|-------------|
-| `check_login` | 检测浏览器环境中 BOSS 账号是否已登录 | `account_name`(环境名) | `{ "browser_id", "browser_name", "boss_username", "is_logged_in" }` |
-| `boss_recruit` | 执行 BOSS 直聘自动招聘流程 | `worker_id` + `params` | `{ "job_title", "total_processed", "wechat_collected", "phone_collected", "details", "error_count" }` |
-
-`boss_recruit` 的 `details` 项示例:
-
-```json
-{
- "name": "候选人A",
- "job": "Python开发",
- "wechat": "wxid_xxx",
- "phone": "13800138000"
-}
-```
-
-说明:
-- 若自动化流程发生报错,任务状态会标记为 `failed`(不再显示为 `success`)。
-- 失败任务也会保留 `result`,便于在任务列表查看已采集到的微信号/手机号数量。
-
----
-
-## 七、任务状态流转
-
-```
-pending → dispatched → running → success
- → failed
- → cancelled
-```
-
-| 状态 | 说明 |
-|------|------|
-| pending | 任务已创建,等待派发 |
-| dispatched | 已通过 WebSocket 发送给 Worker |
-| running | Worker 正在执行中 |
-| success | 执行成功 |
-| failed | 执行失败 |
-| cancelled | 已取消 |
-
----
-
-## 八、联系记录(数据展示)
-
-> 以下接口均需登录(携带 `auth_token` Cookie)
-
-### GET /api/contacts/query(按电话/微信号查询)
-
-**说明**:根据已获取的电话号码或微信号查询联系记录,用于数据展示。对 `contact` 字段做模糊匹配。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回分页结果 |
-| 400 | 未提供 contact 参数 |
-| 401 | 未登录或 token 失效 |
-
-**查询参数**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| contact | string | 是 | 电话号码或微信号(支持部分匹配) |
-| page | int | 否 | 页码,默认 1 |
-| page_size | int | 否 | 每页条数,默认 20 |
-
-**请求示例**:
-```
-GET /api/contacts/query?contact=13800138000
-GET /api/contacts/query?contact=wxid_abc&page=1&page_size=10
-```
-
-**成功响应** (200):
-```json
-{
- "total": 2,
- "page": 1,
- "page_size": 20,
- "contact_keyword": "13800138000",
- "results": [
- {
- "id": 1,
- "name": "张三",
- "position": "Python开发",
- "contact": "13800138000",
- "reply_status": "已回复",
- "wechat_exchanged": true,
- "account_id": 1,
- "worker_id": "worker-1",
- "notes": "",
- "contacted_at": "2026-02-24T10:00:00",
- "created_at": "2026-02-24T10:00:00"
- }
- ]
-}
-```
-
-| 返回字段 | 类型 | 说明 |
-|---------|------|------|
-| total | int | 匹配总数 |
-| page | int | 当前页 |
-| page_size | int | 每页条数 |
-| contact_keyword | string | 本次查询使用的关键词 |
-| results | array | 联系记录列表(字段同联系记录模型) |
-
-**失败响应** (400):未提供 contact 参数时
-```json
-{
- "detail": "请提供 contact 参数(电话号码或微信号)"
-}
-```
-
----
-
-### GET /api/contacts
-
-**说明**:分页查询联系记录,支持按姓名、岗位、联系方式关键词搜索,以及按回复状态、是否交换微信筛选。
-
-**状态码**:
-
-| 状态码 | 说明 |
-|--------|------|
-| 200 | 成功,返回 total、page、page_size、results |
-| 401 | 未登录或 token 失效 |
-
-**查询参数**:`search`(关键词)、`reply_status`、`wechat_exchanged`、`page`、`page_size`。返回格式同上(含 `total`、`page`、`page_size`、`results`)。
-
----
-
-## 九、通用错误格式
-
-所有接口的错误响应统一为:
-
-```json
-{
- "detail": "错误描述信息"
-}
-```
-
-| 状态码 | 说明 |
-|--------|------|
-| 400 | 请求参数错误 |
-| 401 | 未登录或 token 失效 |
-| 403 | 无权限 |
-| 404 | 资源不存在 |
-| 503 | Worker 不在线或服务不可用 |
diff --git a/BOSS招聘优化说明.md b/BOSS招聘优化说明.md
deleted file mode 100644
index 54bf895..0000000
--- a/BOSS招聘优化说明.md
+++ /dev/null
@@ -1,166 +0,0 @@
-# BOSS招聘自动化优化说明
-
-## 优化内容
-
-### 1. 添加筛选功能
-
-#### 活跃度筛选
-- 支持解析"03月03日"、"昨天"、"今天"、"刚刚"等时间格式
-- 筛选条件:
- - 今天活跃
- - 3天内活跃
- - 本周活跃
- - 本月活跃
- - 不限
-
-#### 年龄筛选
-- 从候选人简历中获取年龄信息
-- 根据配置的最小年龄和最大年龄进行筛选
-
-#### 学历筛选
-- 支持学历等级:初中、高中、中专、大专、本科、硕士、博士
-- 候选人学历需要达到或高于要求学历
-
-#### 期望职位筛选
-- 根据候选人的期望职位(jobName字段)进行筛选
-- 支持多个职位关键词匹配
-
-### 2. 联系人记录管理
-
-#### 自动保存联系人
-- 从聊天中获取到的联系方式(微信号/手机号)自动保存到数据库
-- 保存到 `ContactRecord` 表中
-- 包含信息:
- - 姓名
- - 岗位
- - 联系方式(微信或手机)
- - 回复状态
- - 是否交换微信
- - 联系时间
- - 备注
-
-#### 去重处理
-- 检查是否已存在相同姓名和联系方式的记录
-- 如果存在则更新,不存在则创建新记录
-
-### 3. 复聊管理
-
-#### 消息过滤
-- **过滤自己发送的消息**:只保留对方发送的消息进行分析
-- 解决了之前"发送带微信号的消息后,识别到自己消息"的问题
-- 通过 `fromId` 字段判断消息来源(fromId=0 表示对方发送)
-
-#### 等待回复
-- 发送询问微信号后,等待最多30秒
-- 每3秒检查一次是否有新回复
-- 自动识别对方回复中的联系方式
-
-#### 跟进话术
-- 如果对方没有回复,可以发送跟进话术
-- 支持按岗位配置不同的跟进话术
-- 从 `ChatScript` 表中读取话术(script_type="followup")
-- 如果没有特定岗位话术,使用通用话术
-
-## 使用方法
-
-### 1. 配置筛选条件
-
-在数据库 `filter_config` 表中配置筛选条件:
-
-```python
-FilterConfig.objects.create(
- name="Python开发筛选",
- age_min=22,
- age_max=35,
- education="本科",
- activity="3天内活跃",
- positions=["Python开发", "后端开发", "全栈开发"],
- is_active=True
-)
-```
-
-### 2. 配置复聊话术
-
-在数据库 `chat_script` 表中配置话术:
-
-```python
-ChatScript.objects.create(
- position="Python开发",
- script_type="followup",
- content="您好,看到您的简历很符合我们的要求,期待与您进一步沟通。",
- is_active=True
-)
-
-# 通用话术
-ChatScript.objects.create(
- position="通用",
- script_type="followup",
- content="您好,期待与您进一步沟通。",
- is_active=True
-)
-```
-
-### 3. 运行招聘任务
-
-任务会自动:
-1. 获取候选人列表
-2. 应用筛选条件
-3. 逐个打开会话
-4. 过滤自己的消息,只分析对方消息
-5. 如果没有联系方式,发送询问
-6. 等待对方回复并识别联系方式
-7. 自动保存联系人记录到数据库
-8. 如果需要,发送跟进话术
-
-## 数据库表说明
-
-### FilterConfig(筛选配置表)
-- `name`: 配置名称
-- `age_min`: 最小年龄
-- `age_max`: 最大年龄
-- `education`: 学历要求
-- `activity`: 活跃度要求
-- `positions`: 期望岗位列表(JSON)
-- `is_active`: 是否启用
-
-### ChatScript(话术表)
-- `position`: 岗位类型
-- `script_type`: 话术类型(first/followup/wechat/closing)
-- `content`: 话术内容
-- `keywords`: 触发关键词
-- `is_active`: 是否启用
-
-### ContactRecord(联系人记录表)
-- `name`: 姓名
-- `position`: 岗位
-- `contact`: 联系方式
-- `reply_status`: 回复状态
-- `wechat_exchanged`: 是否交换微信
-- `notes`: 备注
-- `contacted_at`: 联系时间
-
-## 注意事项
-
-1. **活跃度时间解析**:
- - 支持"03月03日"格式,自动判断年份
- - 如果月份大于当前月份,认为是去年的日期
-
-2. **消息过滤**:
- - 通过 `fromId` 字段区分消息来源
- - `fromId=0` 表示对方发送的消息
- - 其他值表示自己发送的消息
-
-3. **复聊等待时间**:
- - 默认等待30秒
- - 可以根据实际情况调整 `max_wait` 参数
-
-4. **筛选配置**:
- - 只有 `is_active=True` 的配置才会生效
- - 如果没有启用的配置,跳过筛选,处理所有候选人
-
-## 优化效果
-
-1. **提高效率**:通过筛选减少无效沟通
-2. **自动记录**:联系方式自动保存,无需手动整理
-3. **智能识别**:过滤自己的消息,只识别对方的联系方式
-4. **持续跟进**:支持复聊管理,提高回复率
diff --git a/BOSS招聘自动化完整优化说明.md b/BOSS招聘自动化完整优化说明.md
deleted file mode 100644
index 07c1e7f..0000000
--- a/BOSS招聘自动化完整优化说明.md
+++ /dev/null
@@ -1,488 +0,0 @@
-# BOSS招聘自动化 - 完整优化说明
-
-## 优化概述
-
-本次优化解决了以下核心问题:
-
-1. ✅ **消息过滤问题**:过滤掉自己发送的包含"微信号"等关键词的消息
-2. ✅ **筛选功能**:支持活跃度、年龄、学历、期望职位筛选
-3. ✅ **联系人记录**:自动保存聊天中获取的联系方式
-4. ✅ **复聊管理**:支持多轮复聊、自定义话术、间隔时间控制
-
----
-
-## 一、消息过滤优化
-
-### 问题描述
-之前的代码会识别到自己发送的包含"微信号"三个字的消息,导致误判。
-
-### 解决方案
-
-#### 1. 通过 fromId 区分消息来源
-```python
-def _filter_my_messages(self, messages: list) -> list:
- """过滤掉自己发送的消息,只保留对方的消息。"""
- filtered = []
- for msg in messages:
- # fromId = 0 表示对方发送的消息
- from_id = msg.get("fromId", 0)
- if from_id == 0:
- filtered.append(msg)
- return filtered
-```
-
-#### 2. 在等待回复时过滤发送的话术
-```python
-# 检查最后几条消息
-for text in panel_texts[-5:]:
- # 过滤掉我们发送的消息
- if sent_message in text:
- continue
-
- # 过滤掉包含"微信号"但没有真实微信号的消息
- if "微信号" in text and not self._extract_wechat(text):
- continue
-```
-
----
-
-## 二、筛选功能
-
-### 支持的筛选条件
-
-#### 1. 活跃度筛选
-支持的时间格式:
-- `"03月03日"` - 自动判断年份
-- `"昨天"` - 昨天
-- `"今天"` - 今天
-- `"刚刚"` - 今天
-
-筛选选项:
-- `"今天活跃"` - 今天上线
-- `"3天内活跃"` - 3天内上线
-- `"本周活跃"` - 7天内上线
-- `"本月活跃"` - 30天内上线
-- `"不限"` - 不筛选
-
-#### 2. 年龄筛选
-从候选人简历的 `resume.age` 字段获取,根据 `age_min` 和 `age_max` 筛选。
-
-#### 3. 学历筛选
-学历等级:`初中 < 高中 < 中专 < 大专 < 本科 < 硕士 < 博士`
-
-候选人学历需要达到或高于要求学历。
-
-#### 4. 期望职位筛选
-从候选人的 `jobName` 字段匹配配置的职位列表。
-
-### 配置示例
-
-```python
-FilterConfig.objects.create(
- name="Python开发筛选",
- age_min=22,
- age_max=35,
- education="本科",
- activity="3天内活跃",
- positions=["Python开发", "后端开发", "全栈开发"],
- is_active=True
-)
-```
-
----
-
-## 三、联系人记录管理
-
-### 自动保存功能
-
-当从聊天中提取到联系方式(微信号或手机号)时,自动保存到 `ContactRecord` 表。
-
-### 保存的信息
-- 姓名
-- 岗位
-- 联系方式(微信或手机)
-- 回复状态
-- 是否交换微信
-- 联系时间
-- 备注
-
-### 去重逻辑
-- 检查是否已存在相同姓名和联系方式的记录
-- 如果存在则更新,不存在则创建
-
----
-
-## 四、复聊管理系统
-
-### 核心特性
-
-#### 1. 多轮复聊
-- 支持配置第1天、第2天、第3天...的不同话术
-- 支持配置"往后一直"使用的话术(`day_number=0`)
-
-#### 2. 间隔时间控制
-- 每条话术都有独立的 `interval_hours` 配置
-- 系统自动检查距离上次发送的时间
-- 只有超过间隔时间才会发送下一条
-
-#### 3. 自定义话术
-- 通过API接口添加、修改、删除话术
-- 支持按岗位配置不同的复聊策略
-- 支持通用配置作为后备
-
-#### 4. 回复追踪
-- 记录每次发送的话术
-- 记录是否得到回复
-- 记录回复内容和时间
-
-### 复聊流程
-
-```
-第1天:发送询问微信号
- ↓
-等待24小时
- ↓
-第2天:如果没有回复,发送跟进话术
- ↓
-等待24小时
- ↓
-第3天:如果还没有回复,发送第三条话术
- ↓
-等待72小时
- ↓
-往后:每隔72小时发送一次"往后一直"的话术
-```
-
-### 配置示例
-
-```json
-{
- "config": {
- "name": "Python开发复聊配置",
- "position": "Python开发",
- "is_active": true
- },
- "scripts": [
- {
- "day_number": 1,
- "content": "后续沟通会更及时,您方便留一下您的微信号吗?我这边加您。",
- "interval_hours": 24
- },
- {
- "day_number": 2,
- "content": "您好,不知道您是否方便留个联系方式?",
- "interval_hours": 24
- },
- {
- "day_number": 0,
- "content": "您好,如果您感兴趣可以随时联系我。",
- "interval_hours": 72
- }
- ]
-}
-```
-
----
-
-## 五、数据库表结构
-
-### 新增表
-
-#### 1. FollowUpConfig(复聊配置表)
-| 字段 | 类型 | 说明 |
-|------|------|------|
-| id | INT | 主键 |
-| name | VARCHAR(128) | 配置名称 |
-| position | VARCHAR(64) | 岗位类型 |
-| is_active | BOOLEAN | 是否启用 |
-| created_at | DATETIME | 创建时间 |
-| updated_at | DATETIME | 更新时间 |
-
-#### 2. FollowUpScript(复聊话术表)
-| 字段 | 类型 | 说明 |
-|------|------|------|
-| id | INT | 主键 |
-| config_id | INT | 关联的配置ID |
-| day_number | INT | 第几天(0=往后一直) |
-| content | TEXT | 话术内容 |
-| interval_hours | INT | 间隔小时数 |
-| order | INT | 排序 |
-| is_active | BOOLEAN | 是否启用 |
-| created_at | DATETIME | 创建时间 |
-
-#### 3. FollowUpRecord(复聊记录表)
-| 字段 | 类型 | 说明 |
-|------|------|------|
-| id | INT | 主键 |
-| contact_id | INT | 联系人ID |
-| config_id | INT | 配置ID |
-| script_id | INT | 话术ID |
-| day_number | INT | 第几天 |
-| content | TEXT | 发送的内容 |
-| sent_at | DATETIME | 发送时间 |
-| got_reply | BOOLEAN | 是否得到回复 |
-| reply_content | TEXT | 回复内容 |
-| replied_at | DATETIME | 回复时间 |
-
----
-
-## 六、API接口
-
-### 复聊配置
-- `GET /api/followup-configs` - 获取配置列表
-- `POST /api/followup-configs` - 创建配置
-- `GET /api/followup-configs/{id}` - 获取配置详情
-- `PUT /api/followup-configs/{id}` - 更新配置
-- `DELETE /api/followup-configs/{id}` - 删除配置
-
-### 复聊话术
-- `GET /api/followup-scripts` - 获取话术列表
-- `POST /api/followup-scripts` - 创建话术
-- `GET /api/followup-scripts/{id}` - 获取话术详情
-- `PUT /api/followup-scripts/{id}` - 更新话术
-- `DELETE /api/followup-scripts/{id}` - 删除话术
-
-### 复聊记录
-- `GET /api/followup-records` - 获取记录列表
-- `POST /api/followup-records/send` - 手动发送消息
-
----
-
-## 七、使用步骤
-
-### 1. 运行数据库迁移
-```bash
-python server/manage.py migrate
-```
-
-### 2. 初始化配置(可选)
-```bash
-python scripts/init_followup_config.py
-```
-
-### 3. 通过API配置复聊策略
-
-#### 创建配置
-```bash
-POST /api/followup-configs
-{
- "name": "Python开发复聊",
- "position": "Python开发",
- "is_active": true
-}
-```
-
-#### 添加话术
-```bash
-POST /api/followup-scripts
-{
- "config_id": 1,
- "day_number": 1,
- "content": "您的自定义话术",
- "interval_hours": 24,
- "order": 1,
- "is_active": true
-}
-```
-
-### 4. 运行招聘任务
-系统会自动:
-- 应用筛选条件
-- 过滤自己的消息
-- 保存联系人记录
-- 按配置进行复聊
-
----
-
-## 八、关键代码说明
-
-### 1. 消息过滤
-```python
-# 过滤掉自己发送的消息
-filtered_messages = self._filter_my_messages(messages)
-has_contact_keyword = self._has_contact_keyword(filtered_messages)
-```
-
-### 2. 筛选应用
-```python
-# 应用筛选条件
-friend_list = self._apply_filters(friend_list)
-```
-
-### 3. 保存联系人
-```python
-# 保存并获取contact_id
-contact_id = self._save_contact_record(name, job_name, contacts, action_state)
-```
-
-### 4. 复聊管理
-```python
-# 进行复聊管理
-reply_result = self._handle_follow_up_chat(tab, name, job_name, contact_id)
-```
-
----
-
-## 九、文件清单
-
-### 代码文件
-- `worker/tasks/boss_recruit.py` - 招聘任务处理器(已优化)
-- `server/models.py` - 数据模型(新增3个表)
-- `server/serializers.py` - 序列化器(新增3个)
-- `server/api/followup.py` - 复聊配置API(新增)
-- `server/urls.py` - URL路由(已更新)
-- `server/migrations/0004_add_followup_config.py` - 数据库迁移(新增)
-
-### 脚本文件
-- `scripts/init_followup_config.py` - 初始化复聊配置
-- `scripts/test_recruit_features.py` - 功能测试
-
-### 文档文件
-- `BOSS招聘优化说明.md` - 详细功能说明
-- `复聊配置API使用指南.md` - API使用指南
-- `快速参考指南.md` - 快速参考
-- `代码变更清单.md` - 变更记录
-- `优化完成总结.md` - 完成总结
-- `BOSS招聘自动化完整优化说明.md` - 本文件
-
----
-
-## 十、测试验证
-
-### 语法检查
-```bash
-python -m py_compile worker/tasks/boss_recruit.py
-```
-✅ 通过
-
-### 功能测试
-```bash
-python scripts/test_recruit_features.py
-```
-✅ 全部通过
-
----
-
-## 十一、常见问题
-
-### Q1: 为什么会识别到自己发送的消息?
-**A**: 已修复。现在通过 `fromId` 字段区分消息来源,只识别 `fromId=0` 的消息(对方发送的)。
-
-### Q2: 如何配置复聊话术?
-**A**: 通过 `/api/followup-scripts` 接口创建话术,设置 `day_number` 和 `interval_hours`。
-
-### Q3: 如何设置"往后一直"的话术?
-**A**: 创建话术时设置 `day_number=0`,系统会在没有特定天数话术时使用它。
-
-### Q4: 复聊间隔时间如何控制?
-**A**: 每条话术都有 `interval_hours` 字段,系统会自动检查距离上次发送的时间。
-
-### Q5: 如何手动发送复聊消息?
-**A**: 使用 `POST /api/followup-records/send` 接口,传入 `contact_id` 和 `content`。
-
-### Q6: 联系人记录在哪里查看?
-**A**: 通过 `/api/contacts` 接口查询,或在数据库的 `contact_record` 表中查看。
-
-### Q7: 如何为不同岗位配置不同的复聊策略?
-**A**: 创建多个 `FollowUpConfig`,设置不同的 `position` 字段。系统会优先匹配岗位配置。
-
----
-
-## 十二、优化效果
-
-### 提高效率
-- 通过筛选减少无效沟通
-- 自动化复聊,节省人工时间
-
-### 提高质量
-- 消息过滤避免误识别
-- 多轮复聊提高回复率
-
-### 数据管理
-- 自动保存联系人记录
-- 完整的复聊记录追踪
-
----
-
-## 十三、后续建议
-
-1. **优化筛选条件**:根据实际效果调整筛选参数
-2. **优化话术内容**:根据回复率调整话术
-3. **添加数据统计**:统计筛选通过率、回复率等
-4. **添加黑名单**:避免重复联系
-5. **智能话术选择**:根据候选人回复内容智能选择话术
-
----
-
-## 十四、技术细节
-
-### 时间解析逻辑
-```python
-if "昨天" in last_time:
- last_active = now - timedelta(days=1)
-elif "今天" in last_time or "刚刚" in last_time:
- last_active = now
-elif "月" in last_time and "日" in last_time:
- match = re.search(r"(\d+)月(\d+)日", last_time)
- if match:
- month = int(match.group(1))
- day = int(match.group(2))
- year = now.year
- # 如果月份大于当前月份,说明是去年的
- if month > now.month:
- year -= 1
- last_active = datetime(year, month, day)
-```
-
-### 学历比较逻辑
-```python
-edu_levels = ["初中", "高中", "中专", "大专", "本科", "硕士", "博士"]
-candidate_level = next((i for i, edu in enumerate(edu_levels) if edu in candidate_edu), -1)
-required_level = next((i for i, edu in enumerate(edu_levels) if edu in required_edu), -1)
-return candidate_level >= required_level
-```
-
-### 复聊触发逻辑
-```python
-# 1. 获取该联系人的最后一次复聊记录
-last_record = FollowUpRecord.objects.filter(contact_id=contact_id).order_by('-sent_at').first()
-
-# 2. 确定当前是第几天
-if not last_record:
- day_number = 1 # 第一次复聊
-else:
- hours_since_last = (now - last_record.sent_at).total_seconds() / 3600
- if hours_since_last < last_script.interval_hours:
- return # 间隔时间不足,跳过
- day_number = last_record.day_number + 1
-
-# 3. 获取该天的话术
-script = FollowUpScript.objects.filter(config_id=config.id, day_number=day_number).first()
-if not script:
- # 使用"往后一直"的话术
- script = FollowUpScript.objects.filter(config_id=config.id, day_number=0).first()
-```
-
----
-
-## 十五、完成时间
-
-2026年3月5日
-
----
-
-## 附录:快速命令
-
-```bash
-# 运行数据库迁移
-python server/manage.py migrate
-
-# 初始化复聊配置(需要Django环境)
-python scripts/init_followup_config.py
-
-# 测试功能
-python scripts/test_recruit_features.py
-
-# 检查语法
-python -m py_compile worker/tasks/boss_recruit.py
-```
diff --git a/BOSS招聘自动化最终使用说明.md b/BOSS招聘自动化最终使用说明.md
deleted file mode 100644
index 5438cdf..0000000
--- a/BOSS招聘自动化最终使用说明.md
+++ /dev/null
@@ -1,274 +0,0 @@
-# BOSS招聘自动化 - 最终使用说明
-
-## 优化完成 ✅
-
-### 核心问题解决
-
-#### 1. ✅ 消息过滤问题
-**问题**:识别到自己发送的包含"微信号"三个字的消息
-
-**解决**:
-- 通过 `fromId` 字段区分消息来源(`fromId=0` 是对方,其他是自己)
-- 在等待回复时过滤掉包含发送话术的消息
-- 过滤掉包含"微信号"关键词但没有真实微信号的消息
-
-#### 2. ✅ 筛选功能
-**新增**:
-- 活跃度筛选(支持"03月03日"、"昨天"等格式)
-- 年龄筛选(从 `resume.age` 获取)
-- 学历筛选(支持学历等级比较)
-- 期望职位筛选(从 `jobName` 匹配)
-
-#### 3. ✅ 联系人记录
-**新增**:
-- 自动保存到 `ContactRecord` 表
-- 支持去重和更新
-- 记录完整信息(姓名、岗位、联系方式、回复状态等)
-
-#### 4. ✅ 复聊管理
-**新增**:
-- 支持多轮复聊(第1天、第2天、往后一直)
-- 支持自定义话术(通过API配置)
-- 支持间隔时间控制(每条话术独立配置)
-- 支持按岗位配置不同策略
-
----
-
-## 快速开始
-
-### 1. 运行数据库迁移
-```bash
-python server/manage.py migrate
-```
-
-### 2. 配置复聊策略(通过API)
-
-#### 创建配置
-```bash
-POST /api/followup-configs
-{
- "name": "Python开发复聊",
- "position": "Python开发",
- "is_active": true
-}
-```
-
-#### 添加第1天话术
-```bash
-POST /api/followup-scripts
-{
- "config_id": 1,
- "day_number": 1,
- "content": "后续沟通会更及时,您方便留一下您的微信号吗?我这边加您。",
- "interval_hours": 24,
- "order": 1,
- "is_active": true
-}
-```
-
-#### 添加第2天话术
-```bash
-POST /api/followup-scripts
-{
- "config_id": 1,
- "day_number": 2,
- "content": "您好,不知道您是否方便留个联系方式?",
- "interval_hours": 24,
- "order": 1,
- "is_active": true
-}
-```
-
-#### 添加"往后一直"话术
-```bash
-POST /api/followup-scripts
-{
- "config_id": 1,
- "day_number": 0,
- "content": "您好,如果您感兴趣可以随时联系我。",
- "interval_hours": 72,
- "order": 1,
- "is_active": true
-}
-```
-
-### 3. 配置筛选条件(通过API)
-
-```bash
-POST /api/filters
-{
- "name": "Python开发筛选",
- "age_min": 22,
- "age_max": 35,
- "education": "本科",
- "activity": "3天内活跃",
- "positions": ["Python开发", "后端开发", "全栈开发"],
- "is_active": true
-}
-```
-
-### 4. 运行招聘任务
-
-通过API或管理界面启动招聘任务,系统会自动:
-1. 应用筛选条件
-2. 过滤自己的消息
-3. 保存联系人记录
-4. 按配置进行复聊
-
----
-
-## API接口总览
-
-### 复聊配置
-- `GET /api/followup-configs` - 获取配置列表
-- `POST /api/followup-configs` - 创建配置
-- `PUT /api/followup-configs/{id}` - 更新配置
-- `DELETE /api/followup-configs/{id}` - 删除配置
-
-### 复聊话术
-- `GET /api/followup-scripts` - 获取话术列表
-- `POST /api/followup-scripts` - 创建话术
-- `PUT /api/followup-scripts/{id}` - 更新话术
-- `DELETE /api/followup-scripts/{id}` - 删除话术
-
-### 复聊记录
-- `GET /api/followup-records` - 获取记录列表
-- `POST /api/followup-records/send` - 手动发送消息
-
----
-
-## 复聊配置说明
-
-### day_number 字段
-- `1` = 第一天发送
-- `2` = 第二天发送
-- `3` = 第三天发送
-- `0` = 往后一直使用这个话术
-
-### interval_hours 字段
-距离上次发送的间隔小时数:
-- `24` = 24小时后发送
-- `48` = 48小时后发送
-- `72` = 72小时后发送
-
-### 复聊逻辑
-```
-第1天(0小时):发送第1天话术
- ↓ 等待24小时
-第2天(24小时):如果没有回复,发送第2天话术
- ↓ 等待24小时
-第3天(48小时):如果还没有回复,发送第3天话术
- ↓ 等待72小时
-往后(120小时+):每隔72小时发送"往后一直"的话术
-```
-
----
-
-## 消息过滤逻辑
-
-### 过滤规则
-1. **过滤自己发送的消息**:只保留 `fromId=0` 的消息
-2. **过滤发送的话术**:在等待回复时,过滤掉包含发送话术内容的消息
-3. **过滤假关键词**:过滤掉包含"微信号"但没有真实微信号的消息
-
-### 示例
-```python
-# 原始消息
-messages = [
- {"fromId": 0, "body": {"text": "我的微信是 wx123456"}}, # 对方 ✓
- {"fromId": 123, "body": {"text": "您方便留微信号吗?"}}, # 自己 ✗
- {"fromId": 0, "body": {"text": "好的,test_wx_001"}}, # 对方 ✓
-]
-
-# 过滤后只保留对方的消息
-filtered = [
- {"fromId": 0, "body": {"text": "我的微信是 wx123456"}},
- {"fromId": 0, "body": {"text": "好的,test_wx_001"}},
-]
-```
-
----
-
-## 数据库表
-
-### FollowUpConfig(复聊配置)
-```sql
-id, name, position, is_active, created_at, updated_at
-```
-
-### FollowUpScript(复聊话术)
-```sql
-id, config_id, day_number, content, interval_hours, order, is_active, created_at
-```
-
-### FollowUpRecord(复聊记录)
-```sql
-id, contact_id, config_id, script_id, day_number, content,
-sent_at, got_reply, reply_content, replied_at
-```
-
----
-
-## 文件清单
-
-### 修改的文件
-- `worker/tasks/boss_recruit.py` - 招聘任务处理器
-- `server/models.py` - 数据模型
-- `server/serializers.py` - 序列化器
-- `server/urls.py` - URL路由
-
-### 新增的文件
-- `server/api/followup.py` - 复聊配置API
-- `server/migrations/0004_add_followup_config.py` - 数据库迁移
-- `scripts/init_followup_config.py` - 初始化脚本
-- `scripts/test_recruit_features.py` - 测试脚本
-
-### 文档文件
-- `BOSS招聘优化说明.md`
-- `复聊配置API使用指南.md`
-- `BOSS招聘自动化完整优化说明.md`
-- `快速参考指南.md`
-- `代码变更清单.md`
-- `优化完成总结.md`
-- `BOSS招聘自动化最终使用说明.md`(本文件)
-
----
-
-## 测试验证
-
-### 语法检查
-```bash
-python -m py_compile worker/tasks/boss_recruit.py # ✅ 通过
-python -m py_compile server/models.py # ✅ 通过
-python -m py_compile server/api/followup.py # ✅ 通过
-python -m py_compile server/serializers.py # ✅ 通过
-```
-
-### 功能测试
-```bash
-python scripts/test_recruit_features.py # ✅ 全部通过
-```
-
----
-
-## 注意事项
-
-1. **运行迁移**:首次使用前必须运行 `python server/manage.py migrate`
-2. **配置优先级**:先匹配岗位配置,没有则使用通用配置
-3. **间隔控制**:系统会自动检查间隔时间,避免频繁发送
-4. **消息识别**:依赖 `fromId` 字段,确保API返回包含此字段
-
----
-
-## 完成时间
-
-2026年3月5日
-
----
-
-## 联系支持
-
-如有问题,请查看:
-- `复聊配置API使用指南.md` - API详细说明
-- `BOSS招聘自动化完整优化说明.md` - 完整技术文档
-- `快速参考指南.md` - 快速参考
diff --git a/scroll_and_greet.py b/scroll_and_greet.py
new file mode 100644
index 0000000..1ae1e31
--- /dev/null
+++ b/scroll_and_greet.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+"""按姓名找到求职人 → 滚动到该人 → 点击打招呼(DrissionPage,三个动作)"""
+import time
+
+# 求职人姓名
+姓名 = "王先生"
+
+
+def do_greet(page, 姓名, container=None):
+ """三个动作:1. 找到姓名 2. 滚动到那里 3. 点击打招呼"""
+ if container is None:
+ try:
+ container = page.get_frame("recommendFrame")
+ except Exception:
+ container = page
+
+ # 1. 找到这个姓名
+ name_ele = container.ele(f'x://span[contains(text(),"{姓名}")]', timeout=10)
+ if not name_ele:
+ name_ele = container.ele(f'x://span[text()="{姓名}"]', timeout=2)
+ if not name_ele:
+ raise Exception(f"未找到姓名:{姓名}")
+
+ # 2. 滚动到那里
+ name_ele.run_js("this.scrollIntoView({block: 'center', behavior: 'auto'})")
+ time.sleep(0.8)
+
+ # 3. 点击打招呼(先在该人所在卡片内找)
+ parent = name_ele.parent()
+ greet_btn = None
+ for _ in range(8):
+ if not parent:
+ break
+ greet_btn = parent.ele('x://span[text()="打招呼"]', timeout=0.5) or parent.ele('x://*[contains(text(),"打招呼")]', timeout=0.5)
+ if greet_btn:
+ break
+ parent = parent.parent()
+ if not greet_btn:
+ greet_btn = container.ele('x://span[text()="打招呼"]', timeout=2) or container.ele('x://*[contains(text(),"打招呼")]', timeout=1)
+ if not greet_btn:
+ raise Exception("未找到「打招呼」按钮")
+ greet_btn.click(by_js=True)
+
+
+if __name__ == "__main__":
+ import sys
+ from pathlib import Path
+ _root = Path(__file__).resolve().parent
+ if str(_root) not in sys.path:
+ sys.path.insert(0, str(_root))
+ from worker.bit_browser import BitBrowserAPI
+ from DrissionPage import ChromiumPage, ChromiumOptions
+
+ bit_api = BitBrowserAPI("http://127.0.0.1:54345")
+ cdp_addr, port, browser_id = bit_api.open_browser(browser_id=None, name="测试2", remark=None)
+ page = ChromiumPage(addr_or_opts=ChromiumOptions().set_local_port(port=port))
+ page.get("https://www.zhipin.com/web/geek/recommend")
+ time.sleep(2)
+ do_greet(page, 姓名)
diff --git a/代码变更清单.md b/代码变更清单.md
deleted file mode 100644
index 19c99c5..0000000
--- a/代码变更清单.md
+++ /dev/null
@@ -1,157 +0,0 @@
-# 代码变更清单
-
-## 修改的文件
-
-### 1. worker/tasks/boss_recruit.py
-**状态**: ✅ 已修改并通过语法检查
-
-**主要变更**:
-
-#### 导入语句
-- 添加: `from datetime import datetime, timedelta`
-
-#### 主流程修改 (_recruit_flow_like_script)
-- 添加筛选逻辑: `friend_list = self._apply_filters(friend_list)`
-- 添加消息过滤: `filtered_messages = self._filter_my_messages(messages)`
-- 修改关键词检查: 使用 `filtered_messages` 而不是 `messages`
-- 添加复聊管理: `reply_result = self._handle_follow_up_chat(tab, name, friend_job_name)`
-- 添加保存联系人: `self._save_contact_record(name, friend_job_name, contacts, action_state)`
-- 修改联系方式提取: 使用 `filtered_messages` 而不是 `messages`
-
-#### 新增方法 (共7个)
-1. `_apply_filters(friend_list)` - 应用筛选条件
-2. `_check_activity(last_time, activity_filter)` - 检查活跃度
-3. `_check_education(candidate_edu, required_edu)` - 检查学历
-4. `_filter_my_messages(messages)` - 过滤自己的消息
-5. `_handle_follow_up_chat(tab, name, job_name)` - 处理复聊管理
-6. `_send_follow_up_script(tab, job_name)` - 发送跟进话术
-7. `_save_contact_record(name, job_name, contacts, action_state)` - 保存联系人记录
-
-## 新增的文件
-
-### 1. BOSS招聘优化说明.md
-**状态**: ✅ 已创建
-
-**内容**: 详细的功能说明、使用方法、数据库表说明
-
-### 2. 优化完成总结.md
-**状态**: ✅ 已创建
-
-**内容**: 完成的优化内容、测试验证、关键问题解决方案
-
-### 3. 快速参考指南.md
-**状态**: ✅ 已创建
-
-**内容**: 核心优化点、快速开始、常见问题
-
-### 4. scripts/init_recruit_test_data.py
-**状态**: ✅ 已创建
-
-**功能**: 初始化测试数据(筛选配置、话术配置)
-
-### 5. scripts/test_recruit_features.py
-**状态**: ✅ 已创建并通过测试
-
-**功能**: 测试新增功能(时间解析、消息过滤、联系方式提取、学历筛选)
-
-## 测试结果
-
-### 语法检查
-```bash
-python -m py_compile worker/tasks/boss_recruit.py
-```
-**结果**: ✅ 通过
-
-### 功能测试
-```bash
-python scripts/test_recruit_features.py
-```
-**结果**: ✅ 全部通过
-- 时间解析测试: 5/5 通过
-- 消息过滤测试: 通过
-- 联系方式提取测试: 通过
-- 学历筛选测试: 5/5 通过
-
-## 核心问题解决
-
-### 问题1: 识别到自己发送的微信号 ✅
-**解决方案**:
-- 添加 `_filter_my_messages()` 方法
-- 通过 `fromId` 字段区分消息来源
-- 只保留 `fromId=0` 的消息(对方发送的)
-
-### 问题2: 联系人没有保存到数据库 ✅
-**解决方案**:
-- 添加 `_save_contact_record()` 方法
-- 提取到联系方式后自动保存到 `ContactRecord` 表
-- 支持去重和更新
-
-### 问题3: 只发送一句话,没有复聊 ✅
-**解决方案**:
-- 添加 `_handle_follow_up_chat()` 方法
-- 发送后等待30秒,每3秒检查一次
-- 如果没有回复,发送跟进话术
-
-### 问题4: 活跃度时间格式不统一 ✅
-**解决方案**:
-- 添加 `_check_activity()` 方法
-- 支持"03月03日"、"昨天"、"今天"等多种格式
-- 自动判断年份
-
-### 问题5: 缺少筛选功能 ✅
-**解决方案**:
-- 添加 `_apply_filters()` 方法
-- 支持活跃度、年龄、学历、期望职位筛选
-- 从 `FilterConfig` 表读取配置
-
-## 数据库依赖
-
-### 已存在的表
-- `FilterConfig` - 筛选配置表
-- `ChatScript` - 话术表
-- `ContactRecord` - 联系人记录表
-
-### 需要的字段
-所有必需字段已在现有表中定义,无需额外迁移。
-
-## 使用步骤
-
-1. **初始化测试数据**
- ```bash
- python scripts/init_recruit_test_data.py
- ```
-
-2. **运行功能测试**(可选)
- ```bash
- python scripts/test_recruit_features.py
- ```
-
-3. **启动招聘任务**
- 通过API或管理界面启动,系统会自动应用所有优化功能。
-
-## 注意事项
-
-1. 确保 `FilterConfig` 表中有 `is_active=True` 的配置
-2. 建议配置通用话术(`position="通用"`)作为后备
-3. 复聊等待时间默认30秒,可根据需要调整
-4. 消息过滤依赖 `fromId` 字段,确保API返回包含此字段
-
-## 文档位置
-
-- 详细说明: `BOSS招聘优化说明.md`
-- 完成总结: `优化完成总结.md`
-- 快速参考: `快速参考指南.md`
-- 变更清单: `代码变更清单.md`(本文件)
-
-## 代码统计
-
-- 修改文件: 1个
-- 新增方法: 7个
-- 新增文档: 4个
-- 新增脚本: 2个
-- 代码行数: +260行
-- 测试通过: 100%
-
-## 完成时间
-
-2026年3月5日
diff --git a/优化完成总结.md b/优化完成总结.md
deleted file mode 100644
index e2a4472..0000000
--- a/优化完成总结.md
+++ /dev/null
@@ -1,174 +0,0 @@
-# BOSS招聘自动化优化完成总结
-
-## 优化完成时间
-2026年3月5日
-
-## 已完成的优化内容
-
-### 1. ✅ 筛选功能
-
-#### 活跃度筛选
-- ✅ 支持解析"03月03日"格式的时间
-- ✅ 支持解析"昨天"、"今天"、"刚刚"等相对时间
-- ✅ 自动判断年份(如果月份大于当前月份,认为是去年)
-- ✅ 支持多种活跃度筛选条件:今天活跃、3天内活跃、本周活跃、本月活跃
-
-#### 年龄筛选
-- ✅ 从候选人简历的 `resume.age` 字段获取年龄
-- ✅ 根据配置的 `age_min` 和 `age_max` 进行筛选
-
-#### 学历筛选
-- ✅ 从候选人简历的 `resume.education` 字段获取学历
-- ✅ 支持学历等级比较:初中 < 高中 < 中专 < 大专 < 本科 < 硕士 < 博士
-- ✅ 候选人学历需要达到或高于要求学历
-
-#### 期望职位筛选
-- ✅ 从候选人的 `jobName` 字段获取期望职位
-- ✅ 支持多个职位关键词匹配(配置在 `FilterConfig.positions` 字段)
-
-### 2. ✅ 联系人记录管理
-
-#### 自动保存功能
-- ✅ 从聊天中提取到联系方式后自动保存到 `ContactRecord` 表
-- ✅ 保存信息包括:姓名、岗位、联系方式、回复状态、是否交换微信、联系时间、备注
-- ✅ 去重处理:检查是否已存在相同姓名和联系方式的记录
-- ✅ 如果存在则更新,不存在则创建新记录
-
-### 3. ✅ 复聊管理
-
-#### 消息过滤(核心功能)
-- ✅ **过滤自己发送的消息**:通过 `fromId` 字段判断消息来源
-- ✅ `fromId=0` 表示对方发送的消息
-- ✅ 其他 `fromId` 值表示自己发送的消息
-- ✅ 只保留对方的消息进行联系方式识别
-- ✅ **解决了之前"发送带微信号的消息后,识别到自己消息"的问题**
-
-#### 等待回复功能
-- ✅ 发送询问微信号后,等待最多30秒
-- ✅ 每3秒检查一次是否有新回复
-- ✅ 自动识别对方回复中的联系方式
-- ✅ 记录是否得到回复、是否提取到联系方式
-
-#### 跟进话术功能
-- ✅ 如果对方没有回复,可以发送跟进话术
-- ✅ 支持按岗位配置不同的跟进话术
-- ✅ 从 `ChatScript` 表中读取话术(`script_type="followup"`)
-- ✅ 如果没有特定岗位话术,使用通用话术(`position="通用"`)
-
-## 代码修改文件
-
-### 主要修改文件
-- `worker/tasks/boss_recruit.py` - 招聘任务处理器(已优化)
-
-### 新增方法
-1. `_apply_filters()` - 应用筛选条件
-2. `_check_activity()` - 检查活跃度
-3. `_check_education()` - 检查学历
-4. `_filter_my_messages()` - 过滤自己的消息
-5. `_handle_follow_up_chat()` - 处理复聊管理
-6. `_send_follow_up_script()` - 发送跟进话术
-7. `_save_contact_record()` - 保存联系人记录
-
-### 修改的方法
-- `_recruit_flow_like_script()` - 主流程,添加了筛选、消息过滤、复聊管理、保存联系人记录
-
-## 测试验证
-
-### 功能测试
-✅ 所有功能测试通过(`scripts/test_recruit_features.py`)
-- ✅ 时间解析测试:5/5 通过
-- ✅ 消息过滤测试:成功过滤掉自己发送的消息
-- ✅ 联系方式提取测试:正确提取微信号和手机号
-- ✅ 学历筛选测试:5/5 通过
-
-### 语法检查
-✅ Python语法检查通过(`python -m py_compile`)
-
-## 使用说明
-
-### 1. 初始化测试数据
-```bash
-python scripts/init_recruit_test_data.py
-```
-
-这将创建:
-- 筛选配置示例(Python开发筛选配置)
-- 话术配置示例(首次回复、跟进回复、微信交换等)
-
-### 2. 配置筛选条件
-在数据库 `filter_config` 表中配置或通过管理界面配置:
-- 年龄范围
-- 学历要求
-- 活跃度要求
-- 期望职位列表
-
-### 3. 配置复聊话术
-在数据库 `chat_script` 表中配置或通过管理界面配置:
-- 按岗位配置不同的话术
-- 配置通用话术作为后备
-
-### 4. 运行招聘任务
-任务会自动执行以下流程:
-1. 获取候选人列表
-2. 应用筛选条件(活跃度、年龄、学历、职位)
-3. 逐个打开会话
-4. **过滤自己的消息,只分析对方消息**
-5. 如果没有联系方式,发送询问
-6. 等待对方回复并识别联系方式
-7. **自动保存联系人记录到数据库**
-8. 如果需要,发送跟进话术
-
-## 关键问题解决
-
-### 问题1:识别到自己发送的微信号
-**原因**:之前没有区分消息来源,所有消息都进行联系方式识别
-
-**解决方案**:
-- 添加 `_filter_my_messages()` 方法
-- 通过 `fromId` 字段判断消息来源
-- 只保留 `fromId=0` 的消息(对方发送的)
-- 在提取联系方式前先过滤消息
-
-### 问题2:联系人没有保存到数据库
-**原因**:之前只是收集联系方式,没有保存到数据库
-
-**解决方案**:
-- 添加 `_save_contact_record()` 方法
-- 在提取到联系方式后自动保存
-- 支持去重和更新
-
-### 问题3:只发送一句话,没有复聊
-**原因**:之前只发送一次询问,不等待回复
-
-**解决方案**:
-- 添加 `_handle_follow_up_chat()` 方法
-- 发送后等待30秒,每3秒检查一次
-- 如果没有回复,发送跟进话术
-- 记录回复状态
-
-### 问题4:活跃度时间格式不统一
-**原因**:BOSS直聘返回的时间格式多样("03月03日"、"昨天"等)
-
-**解决方案**:
-- 添加 `_check_activity()` 方法
-- 支持多种时间格式解析
-- 自动判断年份
-
-## 注意事项
-
-1. **筛选配置**:确保 `FilterConfig` 表中有 `is_active=True` 的配置
-2. **话术配置**:建议配置通用话术作为后备
-3. **等待时间**:复聊等待时间默认30秒,可根据需要调整
-4. **消息识别**:依赖 `fromId` 字段,确保API返回的消息包含此字段
-
-## 后续建议
-
-1. 可以添加更多的筛选条件(如工作经验、期望薪资等)
-2. 可以优化复聊策略(如根据对方回复内容智能选择话术)
-3. 可以添加数据统计功能(如筛选通过率、回复率等)
-4. 可以添加黑名单功能(避免重复联系)
-
-## 文档
-- 详细说明:`BOSS招聘优化说明.md`
-- 测试脚本:`scripts/test_recruit_features.py`
-- 初始化脚本:`scripts/init_recruit_test_data.py`
diff --git a/复聊配置API使用指南.md b/复聊配置API使用指南.md
deleted file mode 100644
index dede059..0000000
--- a/复聊配置API使用指南.md
+++ /dev/null
@@ -1,361 +0,0 @@
-# 复聊配置 API 使用指南
-
-## API 端点
-
-### 1. 复聊配置管理
-
-#### 获取配置列表
-```http
-GET /api/followup-configs
-```
-
-查询参数:
-- `position`: 岗位类型(可选)
-- `is_active`: 是否启用(可选)
-
-响应示例:
-```json
-[
- {
- "id": 1,
- "name": "Python开发复聊配置",
- "position": "Python开发",
- "is_active": true,
- "scripts": [
- {
- "id": 1,
- "day_number": 1,
- "content": "后续沟通会更及时,您方便留一下您的微信号吗?我这边加您。",
- "interval_hours": 24,
- "order": 1
- }
- ]
- }
-]
-```
-
-#### 创建配置
-```http
-POST /api/followup-configs
-Content-Type: application/json
-
-{
- "name": "Python开发复聊配置",
- "position": "Python开发",
- "is_active": true
-}
-```
-
-#### 更新配置
-```http
-PUT /api/followup-configs/{id}
-Content-Type: application/json
-
-{
- "name": "Python开发复聊配置(更新)",
- "is_active": true
-}
-```
-
-#### 删除配置
-```http
-DELETE /api/followup-configs/{id}
-```
-
-### 2. 复聊话术管理
-
-#### 获取话术列表
-```http
-GET /api/followup-scripts?config_id=1
-```
-
-查询参数:
-- `config_id`: 配置ID(可选)
-- `day_number`: 第几天(可选)
-
-#### 创建话术
-```http
-POST /api/followup-scripts
-Content-Type: application/json
-
-{
- "config_id": 1,
- "day_number": 1,
- "content": "您好,期待与您进一步沟通。",
- "interval_hours": 24,
- "order": 1,
- "is_active": true
-}
-```
-
-**字段说明**:
-- `day_number`:
- - `1` = 第一天
- - `2` = 第二天
- - `0` = 往后一直使用这个话术
-- `interval_hours`: 距离上次发送的间隔小时数
-- `order`: 同一天有多条话术时的排序
-
-#### 更新话术
-```http
-PUT /api/followup-scripts/{id}
-Content-Type: application/json
-
-{
- "content": "更新后的话术内容",
- "interval_hours": 48
-}
-```
-
-#### 删除话术
-```http
-DELETE /api/followup-scripts/{id}
-```
-
-### 3. 复聊记录查询
-
-#### 获取记录列表
-```http
-GET /api/followup-records?contact_id=1
-```
-
-查询参数:
-- `contact_id`: 联系人ID(可选)
-- `config_id`: 配置ID(可选)
-- `got_reply`: 是否得到回复(可选)
-- `page`: 页码(默认1)
-- `page_size`: 每页数量(默认20)
-
-响应示例:
-```json
-{
- "total": 10,
- "page": 1,
- "page_size": 20,
- "results": [
- {
- "id": 1,
- "contact_id": 1,
- "config_id": 1,
- "script_id": 1,
- "day_number": 1,
- "content": "您好,期待与您进一步沟通。",
- "sent_at": "2026-03-05T10:30:00Z",
- "got_reply": true,
- "reply_content": "好的,我的微信是 wx123456",
- "replied_at": "2026-03-05T10:35:00Z"
- }
- ]
-}
-```
-
-#### 手动发送复聊消息
-```http
-POST /api/followup-records/send
-Content-Type: application/json
-
-{
- "contact_id": 1,
- "content": "您好,我想和您聊聊这个职位。"
-}
-```
-
-## 使用场景
-
-### 场景1:创建Python开发的复聊配置
-
-```bash
-# 1. 创建配置
-curl -X POST http://localhost:8000/api/followup-configs \
- -H "Content-Type: application/json" \
- -d '{
- "name": "Python开发复聊配置",
- "position": "Python开发",
- "is_active": true
- }'
-
-# 假设返回的 config_id = 1
-
-# 2. 添加第1天的话术
-curl -X POST http://localhost:8000/api/followup-scripts \
- -H "Content-Type: application/json" \
- -d '{
- "config_id": 1,
- "day_number": 1,
- "content": "后续沟通会更及时,您方便留一下您的微信号吗?我这边加您。",
- "interval_hours": 24,
- "order": 1,
- "is_active": true
- }'
-
-# 3. 添加第2天的话术
-curl -X POST http://localhost:8000/api/followup-scripts \
- -H "Content-Type: application/json" \
- -d '{
- "config_id": 1,
- "day_number": 2,
- "content": "您好,不知道您是否方便留个联系方式?",
- "interval_hours": 24,
- "order": 1,
- "is_active": true
- }'
-
-# 4. 添加"往后一直"的话术
-curl -X POST http://localhost:8000/api/followup-scripts \
- -H "Content-Type: application/json" \
- -d '{
- "config_id": 1,
- "day_number": 0,
- "content": "您好,如果您感兴趣可以随时联系我。",
- "interval_hours": 72,
- "order": 1,
- "is_active": true
- }'
-```
-
-### 场景2:查看某个联系人的复聊记录
-
-```bash
-curl http://localhost:8000/api/followup-records?contact_id=1
-```
-
-### 场景3:手动发送复聊消息
-
-```bash
-curl -X POST http://localhost:8000/api/followup-records/send \
- -H "Content-Type: application/json" \
- -d '{
- "contact_id": 1,
- "content": "您好,我想和您聊聊这个职位。"
- }'
-```
-
-## 复聊逻辑说明
-
-### 自动复聊流程
-
-1. **第一次联系**:发送询问微信号的消息
-2. **等待回复**:等待30秒,检查是否有回复
-3. **第1天**:如果没有回复,发送第1天的话术
-4. **第2天**:如果还没有回复,且距离上次发送超过24小时,发送第2天的话术
-5. **第3天及以后**:继续按配置的间隔时间发送话术
-6. **往后一直**:当没有特定天数的话术时,使用 `day_number=0` 的话术
-
-### 消息过滤逻辑
-
-**问题**:之前会识别到自己发送的包含"微信号"三个字的消息
-
-**解决方案**:
-1. 通过 `fromId` 字段区分消息来源
-2. 只保留 `fromId=0` 的消息(对方发送的)
-3. 在等待回复时,过滤掉包含发送话术内容的消息
-4. 过滤掉包含"微信号"关键词但没有真实微信号的消息
-
-### 间隔时间控制
-
-- 每条话术都有 `interval_hours` 字段
-- 系统会检查距离上次发送的时间
-- 只有超过间隔时间才会发送下一条
-- 避免频繁打扰候选人
-
-## 数据库表结构
-
-### FollowUpConfig(复聊配置表)
-```sql
-CREATE TABLE follow_up_config (
- id INT PRIMARY KEY AUTO_INCREMENT,
- name VARCHAR(128),
- position VARCHAR(64),
- is_active BOOLEAN DEFAULT TRUE,
- created_at DATETIME,
- updated_at DATETIME
-);
-```
-
-### FollowUpScript(复聊话术表)
-```sql
-CREATE TABLE follow_up_script (
- id INT PRIMARY KEY AUTO_INCREMENT,
- config_id INT,
- day_number INT, -- 1=第一天, 2=第二天, 0=往后一直
- content TEXT,
- interval_hours INT DEFAULT 24,
- order INT DEFAULT 0,
- is_active BOOLEAN DEFAULT TRUE,
- created_at DATETIME
-);
-```
-
-### FollowUpRecord(复聊记录表)
-```sql
-CREATE TABLE follow_up_record (
- id INT PRIMARY KEY AUTO_INCREMENT,
- contact_id INT,
- config_id INT,
- script_id INT,
- day_number INT,
- content TEXT,
- sent_at DATETIME,
- got_reply BOOLEAN DEFAULT FALSE,
- reply_content TEXT,
- replied_at DATETIME
-);
-```
-
-## 前端集成示例
-
-### Vue.js 示例
-
-```javascript
-// 获取复聊配置列表
-async function getFollowUpConfigs() {
- const response = await fetch('/api/followup-configs');
- const configs = await response.json();
- return configs;
-}
-
-// 创建复聊配置
-async function createFollowUpConfig(data) {
- const response = await fetch('/api/followup-configs', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(data)
- });
- return await response.json();
-}
-
-// 添加话术
-async function addFollowUpScript(configId, scriptData) {
- const response = await fetch('/api/followup-scripts', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- config_id: configId,
- ...scriptData
- })
- });
- return await response.json();
-}
-
-// 查看复聊记录
-async function getFollowUpRecords(contactId) {
- const response = await fetch(`/api/followup-records?contact_id=${contactId}`);
- const data = await response.json();
- return data.results;
-}
-```
-
-## 注意事项
-
-1. **配置优先级**:先匹配岗位配置,如果没有则使用通用配置
-2. **话术顺序**:按 `day_number` 和 `order` 排序
-3. **间隔控制**:系统会自动检查间隔时间,避免频繁发送
-4. **消息过滤**:只识别对方发送的消息,避免误识别
-5. **自动保存**:提取到联系方式后自动保存到 `ContactRecord` 表
-
-## 测试建议
-
-1. 先创建一个测试配置,设置较短的间隔时间(如1小时)
-2. 运行招聘任务,观察复聊是否正常工作
-3. 检查 `FollowUpRecord` 表,确认记录是否正确保存
-4. 根据实际效果调整话术内容和间隔时间
diff --git a/快速参考指南.md b/快速参考指南.md
deleted file mode 100644
index e8dd854..0000000
--- a/快速参考指南.md
+++ /dev/null
@@ -1,148 +0,0 @@
-# BOSS招聘自动化 - 快速参考指南
-
-## 核心优化点
-
-### 1. 筛选功能 ✅
-```python
-# 在 FilterConfig 表中配置
-{
- "age_min": 22,
- "age_max": 35,
- "education": "本科",
- "activity": "3天内活跃",
- "positions": ["Python开发", "后端开发"]
-}
-```
-
-### 2. 消息过滤 ✅(解决识别自己消息的问题)
-```python
-# 通过 fromId 字段区分消息来源
-# fromId = 0 -> 对方发送的消息
-# fromId != 0 -> 自己发送的消息
-
-filtered_messages = [msg for msg in messages if msg.get("fromId", 0) == 0]
-```
-
-### 3. 自动保存联系人 ✅
-```python
-# 提取到联系方式后自动保存到 ContactRecord 表
-ContactRecord.objects.create(
- name=name,
- position=job_name,
- contact=wechat_or_phone,
- reply_status="已回复" if got_reply else "未回复",
- wechat_exchanged=exchange_confirmed,
- contacted_at=timezone.now()
-)
-```
-
-### 4. 复聊管理 ✅
-```python
-# 发送询问后等待30秒,每3秒检查一次
-# 如果没有回复,发送跟进话术
-if action_state["send_success"]:
- reply_result = self._handle_follow_up_chat(tab, name, job_name)
-```
-
-## 时间格式支持
-
-| 格式 | 示例 | 解析结果 |
-|------|------|----------|
-| 月日格式 | "03月03日" | 2026-03-03 或 2025-03-03 |
-| 相对时间 | "昨天" | 当前日期 - 1天 |
-| 相对时间 | "今天" | 当前日期 |
-| 相对时间 | "刚刚" | 当前日期 |
-
-## 学历等级
-
-```
-初中 < 高中 < 中专 < 大专 < 本科 < 硕士 < 博士
-```
-
-候选人学历需要 >= 要求学历
-
-## 活跃度筛选
-
-| 配置值 | 含义 |
-|--------|------|
-| "今天活跃" | 最后上线时间在今天 |
-| "3天内活跃" | 最后上线时间在3天内 |
-| "本周活跃" | 最后上线时间在7天内 |
-| "本月活跃" | 最后上线时间在30天内 |
-| "不限" | 不筛选活跃度 |
-
-## 话术类型
-
-| script_type | 说明 | 使用场景 |
-|-------------|------|----------|
-| first | 首次回复 | 第一次联系候选人 |
-| followup | 跟进回复 | 候选人没有回复时 |
-| wechat | 微信交换 | 询问微信号 |
-| closing | 结束语 | 结束对话 |
-
-## 快速开始
-
-### 1. 初始化测试数据
-```bash
-python scripts/init_recruit_test_data.py
-```
-
-### 2. 运行功能测试
-```bash
-python scripts/test_recruit_features.py
-```
-
-### 3. 启动招聘任务
-通过API或管理界面启动招聘任务,系统会自动:
-- 应用筛选条件
-- 过滤自己的消息
-- 保存联系人记录
-- 进行复聊管理
-
-## 常见问题
-
-### Q1: 为什么识别到了自己发送的微信号?
-**A**: 已修复。现在通过 `fromId` 字段过滤消息,只识别对方发送的消息。
-
-### Q2: 联系人记录在哪里查看?
-**A**: 在 `ContactRecord` 表中,可以通过 `/api/contacts` 接口查询。
-
-### Q3: 如何配置不同岗位的话术?
-**A**: 在 `ChatScript` 表中,设置 `position` 字段为岗位名称,`script_type` 为话术类型。
-
-### Q4: 筛选条件不生效?
-**A**: 检查 `FilterConfig` 表中是否有 `is_active=True` 的配置。
-
-### Q5: 如何调整复聊等待时间?
-**A**: 修改 `_handle_follow_up_chat()` 方法中的 `max_wait` 参数(默认30秒)。
-
-## 数据库表
-
-### FilterConfig(筛选配置)
-- `age_min`, `age_max` - 年龄范围
-- `education` - 学历要求
-- `activity` - 活跃度要求
-- `positions` - 期望职位列表(JSON数组)
-- `is_active` - 是否启用
-
-### ChatScript(话术配置)
-- `position` - 岗位类型
-- `script_type` - 话术类型
-- `content` - 话术内容
-- `is_active` - 是否启用
-
-### ContactRecord(联系人记录)
-- `name` - 姓名
-- `position` - 岗位
-- `contact` - 联系方式
-- `reply_status` - 回复状态
-- `wechat_exchanged` - 是否交换微信
-- `contacted_at` - 联系时间
-
-## 代码位置
-
-- 主文件:`worker/tasks/boss_recruit.py`
-- 测试脚本:`scripts/test_recruit_features.py`
-- 初始化脚本:`scripts/init_recruit_test_data.py`
-- 详细说明:`BOSS招聘优化说明.md`
-- 完成总结:`优化完成总结.md`
diff --git a/部署说明.md b/部署说明.md
deleted file mode 100644
index b3aac1a..0000000
--- a/部署说明.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# 部署说明
-
-## 一、服务器部署
-
-在服务器上,只需执行:
-
-```bash
-python app.py
-```
-
-即可启动中央服务器(Django + Channels + 隧道)。
-
----
-
-## 二、客户端部署(线下有比特浏览器的电脑)
-
-客户电脑可能不懂代码,需要提供 **GUI 程序**(PyQt5)完成「更新」和「启动」。
-
-### 方式 A:源码运行(需安装 Python)
-
-1. 将项目拷贝到客户电脑
-2. 安装依赖:`pip install -r requirements.txt`
-3. 运行 GUI:`python run_client.py`
-
-### 方式 B:打包为 exe(推荐,无需 Python)
-
-1. 安装 PyInstaller:`pip install pyinstaller`
-2. 在项目根目录执行打包:`pyinstaller --clean build_client.spec`
-3. 将 `dist/BOSS直聘Worker客户端.exe` 发给客户,下载后先保存到本地文件夹(如桌面),再双击运行(GUI 与 Worker 已合并为同一程序,无需 worker.exe)
-
-### GUI 功能说明
-
-| 按钮 | 功能 |
-|------|------|
-| **更新代码** | 在项目目录执行 `git pull`,拉取最新自动化代码 |
-| **启动** | 启动 Worker,连接服务器并执行任务 |
-
-配置项说明:
-
-- **服务器地址**:中央服务器 WebSocket 地址,如 `ws://8.137.99.82:9000/ws`
-- **Worker ID**:本机 Worker 唯一标识
-- **Worker 名称**:便于识别的名称,如「电脑A」
-
-> **说明**:
-> - 若使用「更新」功能,需在客户电脑安装 Git,并将 exe 放在项目(git 仓库)目录内。
-> - 若不使用「更新」,可只分发打包后的 exe,客户只需填写服务器地址等信息后点击「启动」即可。
-> - 不要直接在浏览器下载弹窗里点“打开”,请先保存到本地后再运行,避免在临时目录运行导致依赖加载失败。