Files
sbnews/业务进度管理.md
T
2026-06-22 01:31:20 +08:00

1531 lines
117 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 业务进度管理
> 本文档用于跟踪 Sport Era 项目所有功能模块的开发状态、待办事项与避坑记录。每完成一个功能或发现一个坑,及时在对应章节追加。
## 目录
- [一、已完成事项](#一已完成事项)
- [二、进行中事项](#二进行中事项)
- [三、待办事项](#三待办事项)
- [四、避坑记录](#四避坑记录)
---
## 一、已完成事项
### 74. 赛事直播流定时抓取恢复与 Docker 调度优化
- 状态:已完成 - 时间:2026-06-21
完成内容:
- 排查赛事直播线路新增后长期停留在待抓取,确认 `la_dev_crontab` 中的 `crawler match_live_stream` 仅用于管理态记录;服务端 `php think crontab` 对已迁移的 crawler 任务会直接跳过,真实执行入口是测试服 `sport-era-crawler` 容器内由 `docker_task_runner.py` 渲染出的 `/etc/cron.d/sport-era-crawler`
- 确认测试服 `sport-era-crawler` 容器已连续运行 8 天且镜像未重建,旧容器内缺少 `/app/match_live_stream.py`,也没有渲染 `match_live_stream` 的 cron 任务,导致服务器目录虽然已同步源码,但新增线路不会被定时抓取。
- 已在测试服重建并重启 `sport-era-crawler` 容器,确认容器内 `config/crawler_tasks.yaml``/etc/cron.d/sport-era-crawler` 都已包含 `match_live_stream` 每分钟调度。
- 继续排查发现 `docker/crawler/scripts/docker_task_runner.py` 外层已对动作加锁,而 `docker/crawler/match_live_stream.py` 内部再次抢同名 `match_live_stream.lock`,任务会把自己判定成“已在执行中”并直接跳过,表现为 `la_crawler_task_log` 连续成功但 `la_match_live` 数据不更新。
- 优化 `docker_task_runner.py` 在子进程执行时注入 `DQD_RUNNING_UNDER_TASK_RUNNER=1`,并让 `match_live_stream.py` 在该上下文下跳过内部同名锁,保留脚本独立执行时的文件锁能力,避免双重加锁导致的假成功。
- 已补充 `match_live_stream` 回归测试,并在测试服手动触发一轮任务,确认 `la_match_live.play_url_m3u8` 成功写入,`fetch_status=1`,已抓到播放地址的线路会按 10 分钟规则刷新。
涉及模块:
- `docker/crawler/match_live_stream.py`
- `docker/crawler/scripts/docker_task_runner.py`
- `docker/crawler/tests/test_match_live_stream.py`
- `docs/sql/insert_crontab_match_live_stream.sql`
验证记录:
- 已执行 `C:\Python311\python.exe -m unittest docker.crawler.tests.test_match_live_stream.MatchLiveStreamTest.test_run_does_not_skip_due_rows_when_invoked_by_docker_task_runner`,确认修复前红灯场景已被回归测试覆盖。
- 已执行 `C:\Python311\python.exe -m unittest docker.crawler.tests.test_match_live_stream`10 个直播流抓取单测通过。
- 已在测试服执行 `sudo docker compose -f docker-compose.crawler.yml build crawler && sudo docker compose -f docker-compose.crawler.yml up -d --no-deps crawler`,确认新容器已加载 `match_live_stream.py` 与对应 cron。
- 已在测试库补齐 `la_dev_crontab` 中的 `crawler / match_live_stream` 记录,并手动执行 `python /app/scripts/docker_task_runner.py run match_live_stream ...`,确认 `la_match_live``play_url_m3u8` 已成功落库。
### 73. 彩票帖子 AI 分析图片先本地化再识别
- 状态:已完成 - 时间:2026-06-13
完成内容:
- 进入六合彩帖子 AI 分析前,后端会先把远程图片下载到 `server/public/uploads/ai_lottery_posts/YYYYMMDD/`,生成站内可访问图片 URL。
- 下载成功后会同步替换 `la_community_post.images` 中的图片链接,并重建 `la_community_post_image` 明细表,避免帖子展示图片与 AI 输入图片不一致。
- `AiService::analyzeLotteryPostImages()` 不再把图片转成 `data:image/...;base64,...` 传给模型,而是直接把本地化后的站内图片 URL 发给视觉模型分析。
- 彩票帖子图片识别和后续二段 JSON 分析都显式限制为 25 秒、`reasoning_effort=low`、关闭同步重试,降低首屏请求被网关切断后一直无结果的概率。
涉及模块:
- `server/app/api/controller/CommunityController.php`
- `server/app/common/service/ai/AiService.php`
- `server/app/common/service/ai/KbRagService.php`
- `qa/backend/test_lottery_post_ai_fast_options_static.php`
验证记录:
- 已先运行 `php qa/backend/test_lottery_post_ai_fast_options_static.php`,修改前因缺少 25 秒快速参数失败,确认旧链路仍可能等待到网关超时。
- 修改后已执行 `php qa/backend/test_lottery_post_ai_fast_options_static.php`,静态检查通过,覆盖图片本地化、数据库图片链接回写、明细表同步、不再转 base64、快速参数等约束。
- 已执行 `php -l server/app/api/controller/CommunityController.php``php -l server/app/common/service/ai/AiService.php``php -l server/app/common/service/ai/KbRagService.php`,语法检查通过。
- 已执行 `php qa/backend/test_deepseek_client_invalid_response.php``php qa/backend/test_deepseek_client_transient_retry.php`DeepSeekClient 相关回归测试通过。
### 72. Docker AI 评论账号昵称改为以用户表为准
- 状态:已完成 - 时间:2026-06-13
完成内容:
- `docker/crawler` 的 AI 评论调度在补齐虚拟评论账号时,已有 `ai_comment_*` 用户不再按账号序号生成昵称并覆盖 `la_user.nickname`
- 虚拟评论账号返回给 LLM 的昵称现在直接读取 `la_user.nickname`;仅新建账号或数据库昵称为空时才使用 `_build_bot_nickname()` 作为初始化/兜底。
- 这样管理端或数据库中维护的正常网名会成为唯一展示来源,避免定时任务再次把昵称改回固定生成值。
涉及模块:
- `docker/crawler/ai_comment_dispatch.py`
- `docker/crawler/tests/test_ai_comment_dispatch.py`
验证记录:
- 已先新增回归测试 `test_existing_virtual_user_nickname_comes_from_user_table`,修改前失败,确认旧逻辑会把数据库昵称 `赛点阿泽已手动改名` 改成生成昵称。
- 修改后已执行 `C:\Python311\python.exe -m unittest docker.crawler.tests.test_ai_comment_dispatch.AiCommentDispatchTest.test_existing_virtual_user_nickname_comes_from_user_table`,测试通过。
- 已执行 `C:\Python311\python.exe -m unittest docker.crawler.tests.test_ai_comment_dispatch`,8 个 AI 评论调度单测全部通过。
- 已执行 `C:\Python311\python.exe -m py_compile docker\crawler\ai_comment_dispatch.py docker\crawler\tests\test_ai_comment_dispatch.py`,语法编译通过。
### 71. 社区帖子 AI 分析 502 网关兜底
- 状态:已完成 - 时间:2026-06-13
完成内容:
- `/api/community/aiAnalysis?post_id=6254` 这条链路实际会走 `uniapp/src/api/community.ts` -> `uniapp/src/pages/ai_analysis/ai_analysis.vue` -> `server/app/api/controller/CommunityController.php::aiAnalysis()` -> `AiService::analyzeLotteryPostImages()` / `AiService::analyzePost()` -> `KbRagService::analyzePost()`,其中六合彩帖子会先做图片识别,再做结构化 JSON 分析,属于同步长链路。
- 前端 AI 分析页已补充 502/503/504、`Bad Gateway``Gateway Timeout``网关` 等兜底判断;当首个请求被网关切断或直接返回空分析时,会转入已有的 `aiAnalysisResult` 轮询逻辑,而不是直接抛“AI分析结果为空”。
- 兜底提示已统一为“AI分析服务正在排队或网关暂时断开,请稍后重新进入分析页查看结果”,让用户能继续等缓存结果,而不是被一次性失败打断。
涉及模块:
- `uniapp/src/pages/ai_analysis/ai_analysis.vue`
- `uniapp/src/api/community.ts`
- `server/app/api/controller/CommunityController.php`
- `server/app/common/service/ai/AiService.php`
- `server/app/common/service/ai/KbRagService.php`
验证记录:
- 已执行临时静态检查,确认前端兜底判断已覆盖 502/503/504 和网关错误;临时检查脚本已清理,避免混入仓库。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 构建生成的 `server/public/mobile` 哈希产物已清理回构建前状态,避免混入源码修复。
- 本次未执行测试服部署命令:当前仓库已有多处与本任务无关的未提交改动,且 `scripts/deploy-server.ps1` 会对发布范围内未提交内容自动 `git add`/`git commit`,为避免卷入他人改动,暂不触发自动部署。
### 70. 彩票 AI 预测页移除生肖分析模块
- 状态:已完成 - 时间:2026-06-12
完成内容:
- `packages_lottery/pages/ai_predict` 当前用于通用彩票 AI 预测,不再按 `template=HK6` 自动展示六合彩专属“波色 & 生肖分析”模块。
- 已移除该页面对 `/lottery/aiColorZodiac` 的请求、`isHK6/colorZodiac` 页面状态、缓存恢复逻辑和相关样式,避免非六合彩彩种误显示生肖分析。
- 保留历史开奖、热冷号、趋势推荐、统计数据四个通用分析模块,现有入口参数和其它彩票接口不变。
涉及模块:
- `uniapp/src/packages_lottery/pages/ai_predict.vue`
验证记录:
- 已先用临时静态检查确认修改前会命中 `getLotteryAiColorZodiac` 引用,修改后确认页面不再包含 `colorZodiac``isHK6``getLotteryAiColorZodiac``生肖分析` 等残留。
- 已执行 `npm run build:h5`H5 构建通过;构建生成的 `server/public/mobile` 哈希产物已清理回构建前状态,避免混入源码修复。
- 本次未执行测试服部署命令:当前仓库已有多处与本任务无关的未提交改动,且 `scripts/deploy-server.ps1` 会对发布范围内未提交内容自动 `git add`/`git commit`,为避免卷入他人改动,暂不触发自动部署。
### 69. Docker 爬虫源码迁移到 docker/crawler 并稳定部署路径
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 懂球帝爬虫源码已迁移到 `docker/crawler`Docker Compose 默认构建上下文和 `logs/data` 挂载路径统一改为 `${CRAWLER_DIR:-./crawler}`,避免继续依赖 `server/public/dongqiudi-crawler`
- 新增 `docker/.env.example`,服务器如保留 `docker/.env`,需要设置 `CRAWLER_DIR=./crawler`,否则可删除该变量使用 Compose 默认值。
- 根目录部署默认范围继续包含 `server/``uniapp/``admin/``docker/`,并默认排除 `docker/.env``docker/.env.docker``docker/crawler/venv``docker/crawler/logs``docker/crawler/data``test_output.txt` 与临时脚本,避免密钥、日志、缓存和样例输出进入发布包。
- 默认发布范围内如仍存在 `admin` 这类 root gitlink,部署脚本会跳过该 gitlink 的自动提交 pathspec,但仍从当前工作区把源码补进发布包,避免自动提交阶段被 gitlink 卡住。
- `docker/crawler/Dockerfile` 在镜像构建时会把 `/app/docker/entrypoint.sh` 的 CRLF 换行归一为 LF,避免 Windows 上传后入口脚本报 `/usr/bin/env: 'bash\r': No such file or directory`
- `.vscode/sftp.json` 新增 `docker` 上传配置,远端目录为 `/www/wwwroot/test-server.sbnews.net/docker`,并忽略 Docker 密钥与 crawler 运行态目录。
- `README.md` 已同步 Docker 爬虫源码目录、任务清单路径、默认发布目录结构和服务器 `CRAWLER_DIR` 注意事项。
涉及模块:
- `docker/docker-compose.crawler.yml`
- `docker/.env.example`
- `docker/.gitignore`
- `docker/crawler/Dockerfile`
- `docker/crawler/.dockerignore`
- `docker/crawler/.gitignore`
- `.vscode/sftp.json`
- `scripts/deploy-server.ps1`
- `README.md`
验证记录:
- 已执行 `git diff --check -- docker/docker-compose.crawler.yml docker/.env.example docker/.gitignore docker/crawler/.dockerignore docker/crawler/.gitignore scripts/deploy-server.ps1 README.md 业务进度管理.md`,未发现空白错误。
- 已执行 `deploy-server.ps1` PowerShell 语法解析检查,通过。
- 已在临时 Git 克隆中执行 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun`,确认全量包默认包含 `server``uniapp``admin``docker`,且未上传到服务器。
- 已在临时 Git 克隆中执行 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun`,确认迁移提交范围会上传 `docker/crawler` 源码并跳过 `docker/crawler/data``logs``venv``test_output.txt` 等运行态/输出文件。
- 本机未安装 `docker` 命令,因此未在本机执行 `docker compose -f docker-compose.crawler.yml config`;该项需要在服务器或已安装 Docker 的环境验证。
### 68. 默认部署切换为根目录同时上传 server、uniapp 与 admin
- 状态:已完成 - 时间:2026-06-12
完成内容:
- `scripts/deploy-server.ps1` 默认 `SourceDir` 改为仓库根目录 `.`,不再先发 `server` 再补发前端目录,而是直接以根目录为源打一个包。
- 根目录默认只包含 `server/``uniapp/``admin/` 三个子目录,因此远端 `RemoteDir` 下会直接形成三套源码目录,方便后续按 `server/public``uniapp``admin` 分别配置 Nginx 和构建流程。
- 根目录模式下,排除规则已同步切到子目录路径:会继续默认排除 `server/.env``server/vendor``server/runtime``server/public/uploads``server/public/admin``server/public/mobile`、crawler 大文件目录,以及 `uniapp/node_modules``uniapp/dist``admin/node_modules``admin/dist`
- 默认增量发布也切到根目录范围,`-AutoIncremental` / `-AutoIncrementalCommits` / `-From` / `-To` 会同时跟踪 `server``uniapp``admin` 的 Git 变更和删除文件。
- 若根仓库里某个默认目录仍是 gitlink/submodule 记录,脚本会把该目录从当前工作区按源码目录补进增量包,避免 `admin` 这类目录在转换期间漏传。
- `README.md` 已同步更新根目录发布、远端目录结构以及在远端根目录内执行 `cd uniapp && npm install && npm run build:h5` 的示例。
涉及模块:
- `scripts/deploy-server.ps1`
- `README.md`
验证记录:
- 已在临时最小 Git 仓库执行默认 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -DryRun -RemoteDir /tmp/test`,修改前日志只出现 `server` 打包,确认红灯。
- 修改后已在临时最小 Git 仓库执行默认 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -DryRun -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /tmp/test`,日志已同时出现 `server/app/ok.txt``uniapp/src/App.vue``admin/src/main.ts` 的增量变更,确认根目录模式能同时覆盖三套源码。
- 已补跑 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -SourceDir server -DryRun -RemoteDir /tmp/test`,确认显式单独发布 `server` 的老用法仍可继续使用。
- 已在真实仓库执行 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -DryRun -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /www/wwwroot/test-server.sbnews.net`,日志出现 `root gitlink include paths will be copied from working tree: admin``+ admin/`,确认 `admin` 仍是 gitlink 记录时也会被补进增量包。
- 已在真实仓库执行默认全量 DryRun,日志显示 `working tree include paths: server uniapp admin`,确认全量包也会同时包含三套源码。
### 67. 部署脚本支持发布 uniapp 源码到服务器
- 状态:已完成 - 时间:2026-06-12
完成内容:
- `scripts/deploy-server.ps1` 现在支持 `-SourceDir uniapp`,可将 `uniapp` 源码按独立目录发布到服务器,不再只支持 `server` 后端目录。
- `uniapp` 全量打包默认改为包含整个源码目录,并排除 `node_modules``dist``.hbuilderx` 等不应上传的本地构建/IDE 目录;增量发布也可正确识别 `uniapp` 目录下的 Git 变更与删除文件。
- 部署脚本新增 `-UniappReleasePath`,会在远端执行 `-PostInstall` 时通过环境变量 `UNIAPP_RELEASE_PATH` 传给 `uniapp/scripts/release.mjs`,让服务器构建 `npm run build:h5` 后可把 H5 产物直接写入指定站点的 `public/mobile`
- `uniapp/scripts/release.mjs` 新增 `UNIAPP_RELEASE_PATH` 覆盖能力,本地构建仍默认输出到 `../server/public/mobile`,服务端构建时则可改写到测试站真实目录。
- `README.md` 已补充“发布 uniapp 源码到服务器并在服务器构建”的标准命令示例与 Node.js 版本要求。
涉及模块:
- `scripts/deploy-server.ps1`
- `uniapp/scripts/release.mjs`
- `README.md`
验证记录:
- 已先执行 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -SourceDir uniapp -RemoteDir /tmp/sport-era-uniapp -DryRun`,修改前失败,确认原脚本不支持 `uniapp` 目录打包。
- 修改后已执行 `powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -SourceDir uniapp -RemoteDir /tmp/sport-era-uniapp -DryRun`,全量打包演练通过。
- 已执行 `git diff --check -- scripts/deploy-server.ps1 uniapp/scripts/release.mjs README.md 业务进度管理.md`,未发现空白错误。
- 已通过 SSH 检查测试服当前缺少 `node` / `npm`,因此本次仅验证到“源码可发布 + 远端构建命令已就绪”,尚未在测试服实际执行 `npm install` / `npm run build:h5`
### 66. 管理端评论账号列表与统一评论列表
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 管理端新增“评论账号”后台契约与页面,后端 `community.commentAccount/lists` 仅筛选 `ai_comment_*` 虚拟评论账号,返回账号、昵称、人设标签、禁用状态、资讯评论数、社区评论数和总评论数。
- 现有“社区评论管理”升级为统一评论列表,不再只看社区帖子评论;现在同一页面可同时查看资讯评论与社区评论,并按评论类型、虚拟/真实评论、状态、目标 ID、关键词筛选。
- 统一评论列表后端通过合并 `la_article_comment``la_community_comment` 输出统一字段:`comment_type``source_type_desc``target_id``target_title``target_summary``target_owner_nickname``account``is_virtual``user_type_desc``status` 等。
- 评论审核与删除逻辑已扩展到两类评论:资讯评论操作 `la_article_comment.is_show``la_article.comment_count`,社区评论操作 `la_community_comment.status``la_community_post.comment_count`
- 新增菜单 SQL `docs/sql/insert_menu_comment_account.sql`,用于把“评论账号”挂到现有“社区管理”菜单下;统一评论列表继续复用原有 `community.communityComment/lists` 菜单入口。
涉及模块:
- `server/app/adminapi/controller/community/CommunityCommentController.php`
- `server/app/adminapi/lists/community/CommunityCommentLists.php`
- `server/app/adminapi/logic/community/CommunityCommentLogic.php`
- `server/app/adminapi/validate/community/CommunityCommentValidate.php`
- `server/app/adminapi/controller/community/CommentAccountController.php`
- `server/app/adminapi/lists/community/CommentAccountLists.php`
- `admin/src/api/community.ts`
- `admin/src/views/community/comment/index.vue`
- `admin/src/views/community/account/index.vue`
- `docs/sql/insert_menu_comment_account.sql`
- `qa/backend/test_comment_admin_static.php`
验证记录:
- 已先执行 `php qa/backend/test_comment_admin_static.php`,新增文件前失败,提示缺少 `admin/src/views/community/account/index.vue`
- 修改后已执行 `php qa/backend/test_comment_admin_static.php`,静态检查通过。
- 已执行 `php -l` 检查 `CommunityCommentController.php``CommunityCommentLogic.php``CommunityCommentLists.php``CommunityCommentValidate.php``CommentAccountController.php``CommentAccountLists.php`,语法检查通过。
- 已在 `admin` 目录执行 `npm run build`,构建通过并刷新 `server/public/admin` 产物。
### 65. Docker AI评论调度接入帖子与资讯
- 状态:已完成 - 时间:2026-06-12
完成内容:
-`server/public/dongqiudi-crawler` 新增 `ai_comment_dispatch.py`,由 Docker crawler 直接执行 AI 评论调度,不再复用旧的 PHP `article_ai_comment` 运行链。
- 评论任务新增统一任务表方案 `la_ai_comment_task`,记录 `target_type/target_id/virtual_user_id/persona_key/selection_sources/comment_content/status/error_msg`,并补充幂等 SQL `docs/sql/create_ai_comment_task.sql`
- 新增幂等 SQL `docs/sql/insert_ai_comment_config.sql`,初始化 `auto_comment_enabled``auto_comment_user_pool_size``auto_comment_per_run``auto_comment_daily_cap``auto_comment_concurrency``auto_comment_request_timeout``auto_comment_article_prompt``auto_comment_post_prompt` 等配置;Python 侧直接复用 `la_ai_config` 中的 `openai_* / max_tokens / temperature`
- AI 评论调度会自动把 `ai_comment_` 虚拟账号池补足到 100 个,并按稳定 persona 映射分配昵称与发言角色。
- 资讯候选池按现有前台口径实现:每个可见分类最新 100 条、`is_recommend=1` 视为置顶 10 条、今天创建且当前总浏览最高 20 条;帖子候选池按现有 `community_tag` 口径实现:每个标签最新 100 条、`is_top=1` 置顶 10 条、今天创建且 `view_count` 最高 20 条。
- 各候选池会先按内容 ID 去重并合并来源标签,再过滤已存在机器人成功评论或已有待执行任务的内容;单轮默认按 25 条资讯 + 25 条帖子配额取数,某一侧不足时由另一侧补满。
- 评论生成支持多 persona 的角色、语气、场景和关注点,并在模型失败时回退到兜底短评;成功后直接写入 `la_article_comment` / `la_community_comment` 并同步递增文章或帖子评论数。
- `main.py` 新增 `ai_comment_dispatch` 动作注册与 1800 秒超时,`config/crawler_tasks.yaml` 新增 `*/10 * * * *` 的 Docker 定时任务;另补充 `docs/sql/disable_article_ai_comment_crontab.sql` 用于停用旧 `article_ai_comment` 定时任务。
涉及模块:
- `server/public/dongqiudi-crawler/ai_comment_dispatch.py`
- `server/public/dongqiudi-crawler/main.py`
- `server/public/dongqiudi-crawler/config/crawler_tasks.yaml`
- `server/public/dongqiudi-crawler/tests/test_ai_comment_dispatch.py`
- `qa/backend/test_ai_comment_dispatch_static.py`
- `docs/sql/create_ai_comment_task.sql`
- `docs/sql/insert_ai_comment_config.sql`
- `docs/sql/disable_article_ai_comment_crontab.sql`
验证记录:
- 已先新增并执行 `python -m unittest server/public/dongqiudi-crawler/tests/test_ai_comment_dispatch.py`,在实现前因缺少 `ai_comment_dispatch` 模块失败。
- 修改后已执行 `C:\Python311\python.exe -m unittest server/public/dongqiudi-crawler/tests/test_ai_comment_dispatch.py server/public/dongqiudi-crawler/tests/test_docker_task_runner.py server/public/dongqiudi-crawler/tests/test_runtime_guard.py`15 个测试全部通过。
- 已执行 `C:\Python311\python.exe qa/backend/test_ai_comment_dispatch_static.py`,静态检查通过。
- 已执行 `C:\Python311\python.exe -m py_compile server/public/dongqiudi-crawler/ai_comment_dispatch.py server/public/dongqiudi-crawler/main.py server/public/dongqiudi-crawler/scripts/docker_task_runner.py qa/backend/test_ai_comment_dispatch_static.py`Python 语法检查通过。
- 已在测试库执行 `docs/sql/create_ai_comment_task.sql``docs/sql/insert_ai_comment_config.sql``docs/sql/disable_article_ai_comment_crontab.sql`,确认 `la_ai_comment_task` 建表成功、`auto_comment_*` 配置写入成功,旧 `article_ai_comment` 定时任务已停用。
- 已用远端测试库配置手动执行一轮 `ai_comment_dispatch` 最小联调,临时将单轮条数压到 2,实际成功创建 2 条任务:`article_id=2044144``post_id=5924`,均已写入对应评论表并将文章/帖子 `comment_count` 回写为 `1`
- 已在测试服 `/www/wwwroot/test-server.sbnews.net/docker` 执行 `sudo docker compose -f docker-compose.crawler.yml build crawler` 并强制删除旧 `sport-era-crawler` 容器后重新 `up -d --no-deps crawler`,当前 `sport-era-crawler` 已切到新容器并正常运行。
- 已确认运行中容器内 `/etc/cron.d/sport-era-crawler` 已渲染 `ai_comment_dispatch``*/10 * * * *` 任务,且容器内可直接 `import ai_comment_dispatch`
### 64. AI助手资讯类联网检索接入
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 在 AI 助手固定四阶段编排链的 `Retriever` 阶段新增 `AiAssistantWebNewsRetriever`,对资讯/新闻/消息/转会类问题触发 OpenAI `responses``web_search` 工具,补充外网最新资讯,不再只依赖站内向量库和知识库。
- `DeepSeekClient``responses` payload 新增 `tools``tool_choice``include` 透传能力,支持联网检索器强制执行 `web_search` 并请求返回官方 sources 元信息。
- `AiAssistantContextService::composePayload()` 新增 `web_news_context`,回答阶段会同时看到“站内资料、联网资讯与实时上下文”;外网资讯来源统一归一为 `web_news`,并跳转到 `/pages/webview/webview?url=...`
- 修正 `AiAssistantPlanner` fallback 意图判断顺序,像“今天NBA有什么最新消息?”这类问题优先识别为 `news_search`,避免被“今天”误判成赛程类。
- AI 助手前端来源类型映射新增 `web_news => 外网资讯`,方便用户识别联网结果来源。
涉及模块:
- `server/app/common/service/ai/AiAssistantWebNewsRetriever.php`
- `server/app/common/service/ai/AiAssistantRetriever.php`
- `server/app/common/service/ai/AiAssistantContextService.php`
- `server/app/common/service/ai/AiAssistantResponder.php`
- `server/app/common/service/ai/DeepSeekClient.php`
- `server/app/common/service/ai/AiAssistantPlanner.php`
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
- `qa/backend/test_ai_assistant_web_news_static.php`
- `qa/backend/test_ai_assistant_web_news_source_behavior.php`
验证记录:
- 已先执行 `php qa/backend/test_ai_assistant_web_news_static.php``php qa/backend/test_ai_assistant_web_news_source_behavior.php`,修改前失败。
- 修改后已执行 `php qa/backend/test_ai_assistant_planner_behavior.php``php qa/backend/test_ai_assistant_web_news_static.php``php qa/backend/test_ai_assistant_web_news_source_behavior.php``php qa/backend/test_ai_assistant_orchestrator_static.php`,均通过。
- 已执行 `php -l` 检查 `AiAssistantWebNewsRetriever.php``AiAssistantRetriever.php``AiAssistantContextService.php``AiAssistantResponder.php``DeepSeekClient.php``AiAssistantPlanner.php`,语法检查通过。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 已直接使用测试服 `.env` 中的 `OPENAI_API_KEY``https://lingsuan.top/v1/responses` 发起 `web_search` 请求,确认可返回结构化联网资讯 JSON。
- 截至当前一次 `POST /api/assistant/chat` 复测,“今天NBA有什么最新消息?” 仍主要返回站内文章来源,尚未观察到 `web_news` 来源出现在测试服助手接口响应中;当前未执行测试服后端发布脚本,因为项目内 `scripts/deploy-server.ps1` 会自动提交工作区,不符合当前未请求提交的协作约束。
### 63. AI助手升级为多阶段编排链
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 将 AI 助手主链路从“直接拼上下文后回答”升级为固定四阶段编排:`Planner -> Retriever -> Ranker -> Responder`,由新增 `AiAssistantOrchestrator` 串联,`AiAssistantService` 保留会话、限流、消息落库和返回格式职责。
- 新增 `AiAssistantPlanner`,通过 LLM 先输出结构化查询规划 JSON,包含 `intent``rewritten_query``alternate_queries``domains``preferred_domain``entities``date_range``needs_realtime``answer_format``confidence`;当规划失败时自动回退到规则 fallback,保证助手不中断。
- `AiAssistantContextService` 升级为按规划结果驱动检索:知识库检索优先使用 `rewritten_query + alternate_queries` 多路召回并合并去重;赛事和加密实时上下文根据规划结果决定是否检索、提取哪些实体、是否带日期范围。
- 新增 `AiAssistantRanker` 对知识库命中做领域偏好重排,并统一拼装 `query_plan + knowledge_hits + match_context + crypto_realtime` 的回答上下文;新增 `AiAssistantResponder` 基于规划结果和证据上下文生成最终 markdown 回复。
- 新增 `AiAssistantTrace` 作为本次请求内的轻量 DTO,贯穿四阶段,先不加数据库新表,避免扩大改动面。
- 新增 QA 回归覆盖:AI 助手服务必须委托 `AiAssistantOrchestrator`,编排链必须包含 `Planner/Retriever/Ranker/Responder` 四阶段;`Planner` 的归一化输出必须稳定保留 query、domain、date_range 和 markdown 默认格式。
涉及模块:
- `server/app/common/service/ai/AiAssistantService.php`
- `server/app/common/service/ai/AiAssistantOrchestrator.php`
- `server/app/common/service/ai/AiAssistantTrace.php`
- `server/app/common/service/ai/AiAssistantPlanner.php`
- `server/app/common/service/ai/AiAssistantRetriever.php`
- `server/app/common/service/ai/AiAssistantRanker.php`
- `server/app/common/service/ai/AiAssistantResponder.php`
- `server/app/common/service/ai/AiAssistantContextService.php`
- `qa/backend/test_ai_assistant_orchestrator_static.php`
- `qa/backend/test_ai_assistant_planner_behavior.php`
验证记录:
- 已先执行 `php qa/backend/test_ai_assistant_orchestrator_static.php``php qa/backend/test_ai_assistant_planner_behavior.php`,修改前均失败。
- 修改后已执行 `php qa/backend/test_ai_assistant_orchestrator_static.php``php qa/backend/test_ai_assistant_planner_behavior.php``php qa/backend/test_ai_assistant_frontend_error_static.php``php qa/backend/test_ai_assistant_markdown_static.php``php qa/backend/test_ai_assistant_markdown_table_static.php``php qa/backend/test_ai_assistant_match_context_static.php``php qa/backend/test_ai_assistant_retry_options.php``php qa/backend/test_ai_assistant_worldcup_schedule_static.php`,均通过。
- 已执行 `php -l` 检查新增/修改的 `AiAssistant*` 服务类与相关 QA 脚本,语法检查通过。
- 已复测测试服 `POST /api/assistant/chat`
- 提问“今天的世界杯赛程”可返回 2026-06-12 的两场世界杯并附带表格;
- 提问“BTC 今天行情怎么样?”可返回实时行情摘要并附带 `BTC/USDT` 行情来源。
### 62. AI助手世界杯今日赛程与表格渲染修复
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 复测 `POST /api/assistant/chat` 提问“今天的世界杯赛程”,确认修复前助手会把 2026-07-15/18/19 的未来淘汰赛占位对阵误当成“今天赛程”,根因是赛事检索只按球队/联赛模糊匹配并默认按 `match_time desc` 取最新,不区分“今天/明天/昨天”这类日期问法。
- `AiAssistantContextService` 新增日期范围识别逻辑,对“今天/今日/明天/昨天/昨日”的赛程类问题按本地自然日过滤 `match_time`,并让赛程类问法按时间正序取当天比赛;结果类问法继续优先已完场赛事。
- 复测同一接口发现模型会用 markdown 表格输出赛程,而 `uniapp/src/utils/assistant-markdown.ts` 原先未支持表格,容易导致 AI 助手正文显示异常;现已补齐 markdown table 转 HTML table 逻辑,并在 AI 助手消息样式中补充表格排版。
- 同步更新 QA 静态回归:覆盖“世界杯今日赛程”日期筛选,以及 markdown 表格识别与转换。
涉及模块:
- `server/app/common/service/ai/AiAssistantContextService.php`
- `uniapp/src/utils/assistant-markdown.ts`
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
- `qa/backend/test_ai_assistant_worldcup_schedule_static.php`
- `qa/backend/test_ai_assistant_markdown_table_static.php`
- `qa/backend/test_ai_assistant_match_context_static.php`
验证记录:
- 已先执行 `php qa/backend/test_ai_assistant_worldcup_schedule_static.php``php qa/backend/test_ai_assistant_markdown_table_static.php`,修改前均失败。
- 修改后已执行 `php qa/backend/test_ai_assistant_markdown_static.php``php qa/backend/test_ai_assistant_frontend_error_static.php``php qa/backend/test_ai_assistant_match_context_static.php``php qa/backend/test_ai_assistant_markdown_table_static.php``php qa/backend/test_ai_assistant_worldcup_schedule_static.php`,均通过。
- 已执行 `php -l server/app/common/service/ai/AiAssistantContextService.php``php -l qa/backend/test_ai_assistant_match_context_static.php``php -l qa/backend/test_ai_assistant_markdown_table_static.php``php -l qa/backend/test_ai_assistant_worldcup_schedule_static.php`,语法检查通过。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 已复测测试服 `POST /api/assistant/chat` 提问“今天的世界杯赛程”,回复改为列出 2026-06-12 的两场世界杯:`韩国 vs 捷克``加拿大 vs 波黑`,并返回 markdown 表格正文与对应赛事来源。
### 61. AI助手回复 markdown 渲染适配
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 排查 `uniapp/src/pages/ai_assistant/ai_assistant.vue`,确认当前助手消息直接通过纯文本节点输出,导致 `##``**`、列表等 markdown 语法原样展示。
- 复用项目已全局注册的 `u-parse` 组件,新增 `uniapp/src/utils/assistant-markdown.ts`,将助手回复中的标题、加粗、列表、引用、分割线、代码块和链接转换为安全 HTML 后渲染。
- AI 助手消息区分用户文本与助手回复:用户消息继续走纯文本展示,助手消息走 markdown 渲染链路,并补充对应的排版样式。
- 新增 QA 静态回归脚本,检查 AI 助手页面存在 markdown 转换逻辑并通过 `u-parse` 渲染助手回复。
涉及模块:
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
- `uniapp/src/utils/assistant-markdown.ts`
- `qa/backend/test_ai_assistant_markdown_static.php`
验证记录:
- 已先执行 `php qa/backend/test_ai_assistant_markdown_static.php`,修改前失败,提示缺少 markdown 转换逻辑。
- 修改后已执行 `php qa/backend/test_ai_assistant_markdown_static.php`,通过。
- 已执行 `php -l qa/backend/test_ai_assistant_markdown_static.php`,语法检查通过。
- 已执行 `php qa/backend/test_ai_assistant_frontend_error_static.php`,通过。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 已确认本地页面 `http://localhost:8991/pages/ai_assistant/ai_assistant` 可返回 HTTP 200;当前线程未提供可用浏览器/Playwright 依赖,未做自动化截图验收。
### 60. AI助手马刺最新赛果上下文修复
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 核查 `pages/match_detail/match_detail?id=3567442` 对应赛事,确认测试库 `la_match.id=3567442` 为 NBA 纽约尼克斯 vs 圣安东尼奥马刺,比分 107-106,已完场。
- 确认该赛事已进入 AI 知识库:`la_ai_kb_document.id=948``domain=match``subtype=event``source_id=3567442`6 个 chunk 均已有 1024 维 embedding,最近同步任务 `la_ai_kb_sync_job.id=25444` 成功。
- 定位 AI 助手未优先回答该场的原因:`马刺最新比赛结果` 这类中文连写问题没有从 `queryTerms()` 中拆出“马刺”,而知识库向量召回本身没有时间排序语义;同时实时赛事兜底原先按 `match_time desc` 优先拿未来 0-0 赛程。
- `AiAssistantContextService` 已补充赛事查询词停用词剥离,将“马刺最新比赛结果”归一出“马刺”;对“最新/最近/结果/比分/赛果/成绩/战绩”等问法优先查询已完场比赛,再补充其他赛程。
- 新增 QA 静态回归脚本,防止中文连写球队词无法提取、最新赛果不优先完场赛事的问题回退。
涉及模块:
- `server/app/common/service/ai/AiAssistantContextService.php`
- `qa/backend/test_ai_assistant_match_context_static.php`
- `la_match`
- `la_ai_kb_document`
- `la_ai_kb_chunk`
- `la_ai_kb_sync_job`
验证记录:
- 已查询测试库,确认 `source_id=3567442` 的 match/event 知识库文档存在且有 6 个有效向量 chunk。
- 已查询 `la_ai_kb_query_log`,确认修复前 `马刺最新比赛结果` 的 hit docs 不包含 `3567442`
- 已执行 `php qa/backend/test_ai_assistant_match_context_static.php`,修改前失败、修改后通过。
- 已执行 `php -l server/app/common/service/ai/AiAssistantContextService.php``php -l qa/backend/test_ai_assistant_match_context_static.php`,语法检查通过。
- 已请求测试服 `POST /api/assistant/chat` 提问“马刺最新比赛结果”,返回答案包含“圣安东尼奥马刺客场 106-107 不敌纽约尼克斯”,sources 包含 `/pages/match_detail/match_detail?id=3567442`
### 59. 赛事时间按当前时区显示
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 排查赛事时间展示链路,确认普通赛事卡和详情主时间已基本使用本地 `Date`,偏差集中在世界杯专题页固定叠加北京时间、以及比赛详情文字直播时间固定转北京时间。
- 新增 `uniapp/src/utils/match-time.ts`,统一将赛事 Unix 秒转换为设备当前时区的 `Date`;世界杯源字段按 UTC 时间保存但历史入库为服务器本地 Unix 秒,先在工具层归一到真实时间点再本地化展示。
- `match-card``match_detail``WorldCupPanel` 已统一接入 `getLocalMatchDate`,世界杯赛程分组、赛程卡时间、对阵图日期/时间和比赛详情主时间不再固定显示北京时间。
- 比赛详情文字直播时间移除 `+8 * 3600``getUTC*`,数字时间戳直接按设备当前时区显示。
- 新增 QA 静态回归脚本,检查赛事时间展示必须走统一本地时区工具,并阻止世界杯面板/详情页再次写入北京时间硬编码。
涉及模块:
- `uniapp/src/utils/match-time.ts`
- `uniapp/src/components/match-card/match-card.vue`
- `uniapp/src/pages/match_detail/match_detail.vue`
- `uniapp/src/packages_match/components/WorldCupPanel.vue`
- `qa/backend/test_match_timezone_display_static.php`
验证记录:
- 已先执行 `php qa/backend/test_match_timezone_display_static.php`,修改前因缺少统一赛事时间工具失败。
- 修改后已执行 `php qa/backend/test_match_timezone_display_static.php`,通过。
- 已执行 `php -l qa/backend/test_match_timezone_display_static.php`,语法检查通过。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
### 58. AI助手知识库检索 fallback 修复
- 状态:已完成 - 时间:2026-06-12
完成内容:
- 排查 `/api/assistant/chat` 提问“旧澳六合最近有什么分析线索?”返回 `sources=[]`,确认测试库向量库已有彩票内容:`lottery/draw_result` 4698 条文档、`post/post``旧澳六合` 相关文档 207+ 条,问题不在向量入库。
- 查询 `la_ai_kb_query_log`,确认当前 59+ 条知识库检索日志均为 `status=2``hit_docs_json=[]`,AI 助手在知识库检索异常后静默退化为“站内资料不足”。
- 定位根因:`KbService::loadCandidates()` fallback 使用了 ThinkPHP 不支持的 `whereOrLike()` 魔术方法,会被解析成字段名 `like` 并导致 SQL 异常;同时中文长句只保留整句作为 LIKE 词,无法拆出“旧澳六合”等核心召回词。
- 修复 fallback:改为显式 `whereOr('字段', 'like', $like)`,多关键词按 OR 召回;补充“旧澳六合 -> 老澳门六合彩”“新澳六合 -> 新澳门六合彩”别名,避免依赖 MySQL 中文全文分词。
涉及模块:
- `server/app/common/service/ai/KbService.php`
- `qa/backend/test_kb_retrieve_fallback_static.php`
验证记录:
- 已执行 `php qa/backend/test_kb_retrieve_fallback_static.php`,通过。
- 已执行 `php -l server/app/common/service/ai/KbService.php``php -l qa/backend/test_kb_retrieve_fallback_static.php`,语法检查通过。
- 已执行 `php qa/backend/test_kb_sync_pipeline_static.php``php qa/backend/test_kb_redis_enqueue_static.php`,通过。
- 已用测试库 SQL 复刻修复后的 fallback 条件,确认“旧澳六合最近有什么分析线索?”可召回 `post/post` 211 条和 `lottery/draw_result` 2 条,样本包含“老澳门六合彩 第2026162期开奖”。
- 已通过 `scripts/deploy-server.ps1 -AutoIncremental` 发布 server 修复到测试服,并执行 `php think clear` 清理缓存;复测 `/api/assistant/chat` 提问“旧澳六合最近有什么分析线索?”返回 `sources` 6 条,`la_ai_kb_query_log` session 29 记录 `status=1``hit_len=6`
### 57. AI助手前端网络失败兜底增强
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 排查用户端仍展示“AI助手请求失败,请检查网络后重试。”,确认该文案来自前端 `request:fail/network/网络` 分支;测试库最近 30 分钟无新的助手失败记录,说明该类报错多发生在前端未拿到后端响应时。
- AI 助手发送失败时新增历史恢复逻辑:若请求已到后端并生成会话/回复,但前端网络层未收到响应,则通过 `client_id + last_message` 拉取最新会话消息并回填当前对话。
- 网络失败提示保留原始 `errMsg/message`,展示为“错误详情:xxx”,避免继续只显示泛化网络文案。
- 已重新执行 `npm run build:h5` 并使用 `-IncludePublicBuilds` 发布到测试服,确认远端 `public/mobile` 新产物包含恢复逻辑与“错误详情”文案。
涉及模块:
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
- `qa/backend/test_ai_assistant_frontend_error_static.php`
- `server/public/mobile`
验证记录:
- 已执行 `php qa/backend/test_ai_assistant_frontend_error_static.php`,通过。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 已请求测试服 `/api/assistant/chat``马刺最近比赛` 返回 `code=1`
- 已发布测试服并执行 `php think clear`;远端构建产物可检索到“错误详情”和恢复逻辑。
### 56. AI助手上游502重试增强
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 排查用户端返回 `OpenAI: OpenAI 返回异常: 响应不是有效JSON(HTTP 502),已重试1次`,确认配置与 API Key 正常,`https://lingsuan.top/v1/responses` 最小请求可返回 200。
- 查询测试库 `la_ai_chat_message`,确认失败集中在 `马刺最近比赛` 等完整助手请求,模型为 `gpt-5.5`,错误为上游中转偶发 `HTTP 502 + 非 JSON`
- AI 助手模型调用单独提高瞬时故障重试能力:`retry_times=3``retry_sleep_ms=1200`,不影响其他 AI 分析链路的默认重试配置。
- 新增 QA 脚本检查 AI 助手默认重试参数,避免后续退回到只重试 1 次。
- 已发布 server 到测试服并执行 `php think clear`;复测 `马刺最近比赛``马刺 最近比赛``马刺最新的比赛` 均返回 `code=1`
涉及模块:
- `server/app/common/service/ai/AiAssistantService.php`
- `qa/backend/test_ai_assistant_retry_options.php`
- `la_ai_chat_message`
验证记录:
- 已执行 `php qa/backend/test_ai_assistant_retry_options.php`,通过。
- 已执行 `php qa/backend/test_deepseek_client_transient_retry.php`,通过。
- 已执行 `php -l server/app/common/service/ai/AiAssistantService.php``php -l server/app/common/service/ai/DeepSeekClient.php``php -l qa/backend/test_ai_assistant_retry_options.php`,语法检查通过。
### 55. 世界杯专题页赛程时间校正
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 修复 `/packages_match/pages/worldcup` 世界杯赛程时间显示偏差:源赛程时间戳比预期北京时间少 8 小时,页面增加世界杯专用时间规范化后再按北京时间展示。
- 统一修正赛程日期分组、赛程卡中间时间、对阵图时间和对阵图日期,避免出现 `19:00` 应为次日 `03:00` 的情况。
验证记录:
- 已用 `match_time=1781175600` 静态验证,页面新逻辑输出 `2026-06-12 03:00`
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
### 54. AI知识库Redis队列测试服启用与消费修复
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 在测试库执行并确认 `kb:enqueue-recent` 每分钟定时任务注册成功,补齐近期扫描索引:`idx_kb_recent_article``idx_kb_recent_match``idx_kb_recent_post``idx_kb_recent_draw``idx_kb_recent_ai_history`
- 发布 server 代码到测试服并执行 `php think clear`,解决测试服 `Command "kb:enqueue-recent" is not defined` 导致定时任务失败的问题。
- 同步远端 `docker/docker-compose.crawler.yml`,补充并启动 `sport-era-kb-worker` 服务;从应用 `.env` 安全同步 embedding key 到 `docker/.env.docker`
- 修复 PHP `KbService``source_updated_at/source_created_at` 直接 `(int)` 转换日期字符串导致写成 `2026` 的问题,统一解析为 Unix 时间戳。
- 修复 Python worker 对 DashScope embedding 单次批量超过 10 条时报错的问题,改为按 `EMBEDDING_BATCH_SIZE` 分批请求;`vector_norm` 写库前保留 8 位小数,减少 MySQL decimal 截断告警。
- 清理 Redis consumer group 中旧 worker 遗留 pending 消息,重新写回 Stream 后由新 worker 消费。
- 追加 worker Redis 读取超时保护,设置连接/读取超时与健康检查;遇到临时 `TimeoutError/ConnectionError` 时记录 warning 并继续轮询,避免容器因 Redis 短暂抖动重启。
验证记录:
- 已执行测试服 `php think kb:enqueue-recent --limit=10 --minutes=30`,成功写入 Redis Stream。
- Redis DB4 `ai:kb:sync:stream` 已存在,consumer group `ai_kb_workers` 已创建,`ai:kb:sync:dead` 死信长度为 0。
- `sport-era-kb-worker` 已启动并持续输出 `kb upsert ok` 日志,`la_ai_kb_document``la_ai_kb_chunk` 持续增量更新。
- 截至 2026-06-11 13:10 左右,Redis lag 已从 648 降至 398,今日赛事过期文档数从 27 降至 20,队列仍在继续追赶。
- 截至 2026-06-11 13:51 左右,Redis `pending=0``lag=0`、死信长度为 0,worker 持续消费并写入知识库。
### 53. AI知识库Redis队列与Python异步向量Worker
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 新增 `kb:enqueue-recent` 后端命令,每分钟扫描最近 30 分钟更新的资讯、加密资讯、彩票开奖结果、彩票 AI 历史、赛事和社区帖子,并写入 Redis Stream `ai:kb:sync:stream`
- 新增 `KbRedisQueueService`,按源表更新时间筛选缺失、失效或过期的知识库文档,入队前使用 `ai:kb:sync:dedupe:{domain}:{subtype}:{source_id}` 做 30 分钟去重。
- 新增 Python 常驻 worker `scripts/kb_worker.py`,通过 Redis consumer group `ai_kb_workers` 消费队列,直接写入 `la_ai_kb_document``la_ai_kb_chunk`;成功 `XACK`,失败重试,超过阈值写入 `ai:kb:sync:dead` 死信队列。
- `docker/docker-compose.crawler.yml` 新增 `kb-worker` 服务,复用 crawler 镜像并支持 `EMBEDDING_API_KEY/BASE_URL/MODEL/DIM` 环境变量;crawler entrypoint 支持传入命令时直接执行,避免 worker 被固定 cron entrypoint 拦截。
- 新增幂等 SQL 注册每分钟 `kb:enqueue-recent` 定时任务,并为近实时扫描补充 `update_time` 相关索引 SQL。
- 新增 QA 静态检查和 Python worker 队列行为单测,覆盖 Redis Stream 名称、去重、五类扫描、consumer group、ack、死信和 Docker worker 配置。
涉及模块:
- `server/app/common/command/KbEnqueueRecent.php`
- `server/app/common/service/ai/KbRedisQueueService.php`
- `server/public/dongqiudi-crawler/scripts/kb_worker.py`
- `server/public/dongqiudi-crawler/docker/entrypoint.sh`
- `docker/docker-compose.crawler.yml`
- `docker/.env.docker.example`
- `docs/sql/insert_ai_kb_enqueue_recent_crontab.sql`
- `docs/sql/add_ai_kb_recent_source_indexes.sql`
- `qa/backend/test_kb_redis_enqueue_static.php`
- `qa/backend/test_kb_worker_static.py`
- `server/public/dongqiudi-crawler/tests/test_kb_worker.py`
- `la_ai_kb_document`
- `la_ai_kb_chunk`
- Redis Stream `ai:kb:sync:stream`
验证记录:
- 已执行 `php qa/backend/test_kb_redis_enqueue_static.php`,静态检查通过。
- 已执行 `C:\Python311\python.exe qa/backend/test_kb_worker_static.py`,静态检查通过。
- 已执行 `C:\Python311\python.exe -m unittest discover -s server/public/dongqiudi-crawler/tests -p test_kb_worker.py`worker 队列行为单测通过。
- 已执行 `C:\Python311\python.exe -m py_compile server/public/dongqiudi-crawler/scripts/kb_worker.py server/public/dongqiudi-crawler/tests/test_kb_worker.py qa/backend/test_kb_worker_static.py`Python 语法检查通过。
- 已执行 `php -l server/app/common/service/ai/KbRedisQueueService.php``php -l server/app/common/command/KbEnqueueRecent.php``php -l qa/backend/test_kb_redis_enqueue_static.php`PHP 语法检查通过。
- 本机未安装 Docker CLI,无法执行 `docker compose config`;本机 PHP CLI 仍因 Redis 驱动缺失报 `not support: redis`,需在测试服执行 SQL、启动 `kb-worker` 并观察 Redis Stream 与知识库表增量。
### 52. AI知识库资讯与赛事向量同步链路修复
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 核查测试库 AI 知识库状态,确认 `la_ai_kb_document``la_ai_kb_chunk` 当前无有效记录;`la_article` 可见资讯 38121 条全部缺少 article 向量文档,最近 24 小时可见资讯 999 条全部缺少向量文档;2026-06-11 当天赛事 36 场全部缺少 match/event 向量文档。
- 确认测试库 `la_dev_crontab` 原本没有 `kb:consume` 定时任务,`la_ai_kb_sync_job` 只有 article/post 待处理任务且长期未消费;爬虫直接写入 `la_article``la_match`,不会主动调用 PHP `KbSyncService::enqueue()`
- `KbSyncService` 新增资讯回填,并将回填逻辑从“只补缺失文档”升级为“补缺失或源数据更新时间晚于向量文档”的未同步数据;赛事回填优先级调高,避免今天赛事被历史资讯 backlog 压住。
- `kb:consume` 每次运行前自动补标赛事、资讯和彩票缺失/过期向量任务;`kb:rebuild` 后按重建域补标残留缺失/过期任务。
- 管理端知识库重建域校验补充 `match`,使后台可触发赛事知识库重建。
- 新增幂等 SQL `docs/sql/insert_ai_kb_consume_crontab.sql`,已在测试库执行并确认只生成 1 条启用的 `kb:consume` 定时任务,表达式为 `*/5 * * * *`,参数为 `--batch=100`
- 新增 QA 静态回归脚本,检查资讯/赛事未同步回填、消费命令补标、重建补标、管理端 match 域校验和定时任务 SQL。
涉及模块:
- `server/app/common/service/ai/KbSyncService.php`
- `server/app/common/command/KbConsume.php`
- `server/app/common/command/KbRebuild.php`
- `server/app/adminapi/validate/ai/KbSyncJobValidate.php`
- `docs/sql/insert_ai_kb_consume_crontab.sql`
- `qa/backend/test_kb_sync_pipeline_static.php`
- `la_ai_kb_document`
- `la_ai_kb_chunk`
- `la_ai_kb_sync_job`
- `la_dev_crontab`
验证记录:
- 已用 MySQL 查询测试库,确认修复前 article/match 向量覆盖率均为 0,且无 `kb:consume` 定时任务。
- 已执行 `docs/sql/insert_ai_kb_consume_crontab.sql`,重复执行后确认 `kb:consume` 仍只有 1 条启用记录,SQL 幂等。
- 已执行 `php qa/backend/test_kb_sync_pipeline_static.php`,回归检查通过。
- 已执行修改过的 PHP 文件语法检查,均通过。
- 本地 Windows CLI 执行 `php think kb:consume --batch=5` 时被当前 PHP 环境 Redis 驱动拦截,报 `not support: redis`,未进入业务消费逻辑;需由测试服 PHP 环境实际定时消费后再观察 `la_ai_kb_document` 增量。
### 51. 资讯卡片底部信息布局优化
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 调整 `feed-card__footer` 布局,将作者信息固定在左侧,阅读量和发布时间组合固定在右侧展示。
- 右侧阅读量与时间改为独立信息组,避免与作者等分宽度导致视觉分散;作者名称超长时在左侧省略,不挤压右侧信息。
涉及模块:
- `uniapp/src/components/feed-card/feed-card.vue`
验证记录:
- 已执行 `npm run build:h5`H5 构建通过。
### 50. AI 助手快捷问题单行省略
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 修复 `/pages/ai_assistant/ai_assistant``.quick-list__item` 快捷问题过长时会分行显示的问题。
- 快捷问题文本增加独立 `.quick-list__text` 包裹,容器与文本均设置单行、省略号和溢出隐藏,移除导致强制换行的 `word-break: break-all`
涉及模块:
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
验证记录:
- 已先执行静态检查,修改前确认缺少单行省略样式会失败。
- 修改后静态检查通过,确认存在 `quick-list__text``white-space: nowrap``text-overflow: ellipsis`
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
### 49. 部署脚本发布前自动提交 server 变更
- 状态:已完成 - 时间:2026-06-11
完成内容:
- `scripts/deploy-server.ps1` 新增发布前 `server` 工作区检查,在打包和上传前执行 `git status --porcelain -- server`
- 发现 `server` 下存在未提交、删除或未跟踪文件时,脚本会先 `git add -A -- server` 并自动提交,然后再继续计算增量范围。
- 新增 `-AutoCommitMessage` 参数,可自定义自动提交说明;默认提交说明为 `deploy: auto commit server changes <时间>`
-`server` 下存在合并冲突,脚本会提示先手动解决后再发布。
- README 已补充说明:包含 `-DryRun` 在内,发布脚本都会先自动提交 `server` 变更。
涉及模块:
- `scripts/deploy-server.ps1`
- `README.md`
验证记录:
- 已使用临时 Git 仓库验证:`server` 下修改和新增文件会被自动提交,随后继续自动增量 dry-run;仓库中 README/admin 的未提交变更不会被自动提交。
- 已使用临时 Git 仓库验证:`server` 下删除文件会被自动提交,随后进入增量删除清单。
- 已执行 PowerShell Parser 检查,`scripts/deploy-server.ps1` 语法解析通过。
- 已执行 `git diff --check -- scripts/deploy-server.ps1`,未发现空白错误。
### 48. AI 助手对话页跨端样式优化
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 优化 `/pages/ai_assistant/ai_assistant` 移动端聊天视觉:导航、欢迎卡片、快捷问题、AI/用户消息气泡、资料来源卡片和底部输入栏统一为更清爽的对话界面。
- AI 消息补充头像标识与加载状态脉冲条,长文本气泡提升行高和换行稳定性,来源卡片增加左侧强调线与绿色来源标签,便于阅读和点击。
- 底部输入区拆分为 `input-panel + input-bar`,补充 iOS/Android/H5 安全区、`disable-default-padding``cursor-spacing` 和隐藏 iOS confirm bar,避免输入栏贴边、默认内边距和键盘遮挡问题。
- 输入框固定为与发送按钮同高,去除 `auto-height`,输入内容增减时不再撑开底部输入栏,多行内容在输入框内部滚动。
- 修复 H5 下 `constant(safe-area-inset-bottom)` 写在 `padding` 简写中导致整条 padding 失效的问题,改为独立声明 top/left/right/bottom。
涉及模块:
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
验证记录:
- 已执行 UI 特征检查,确认安全高度、textarea 跨端属性、AI 头像、输入安全区容器和来源强调线均存在。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 已通过 Edge Headless DevTools 以 430×932 移动视口检查目标页,确认路由加载为 `pages/ai_assistant/ai_assistant`、页面宽度 430、无横向溢出,输入栏左右 padding 与底部安全区生效。
### 47. AI 助手 OpenAI 502 瞬时错误重试
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 排查 `/api/assistant/chat` 请求 `NBA 最近比赛近况` 返回 `OpenAI: OpenAI 返回异常: 响应不是有效JSON(HTTP 502)`,确认根因是上游 OpenAI 中转偶发返回 502 且响应体不是 JSON,`DeepSeekClient` 原逻辑会立即失败并透传错误。
- `DeepSeekClient` 新增可覆盖的 HTTP 发送方法,并对 cURL 错误、HTTP 429、HTTP 5xx 做有限重试,默认重试 1 次,可通过 `ai_request_retry_times``ai_request_retry_sleep_ms` 配置调整。
- 失败结果补充“已重试N次”提示,便于后续从 AI 助手错误消息和日志判断是否为持续性上游故障。
- 新增 QA 回归脚本,模拟第一次 `HTTP 502 + 非 JSON`、第二次正常 Responses JSON,确认瞬时故障可自动恢复。
涉及模块:
- `server/app/common/service/ai/DeepSeekClient.php`
- `qa/backend/test_deepseek_client_transient_retry.php`
验证记录:
- 已执行 `php qa/backend/test_deepseek_client_transient_retry.php`,回归测试通过。
- 已执行 `php qa/backend/test_deepseek_client_invalid_response.php`,原有非 JSON/null 防护测试通过。
- 已执行 `php -l server/app/common/service/ai/DeepSeekClient.php``php -l qa/backend/test_deepseek_client_transient_retry.php`,语法检查通过。
### 46. 部署脚本自动增量支持自定义提交数
- 状态:已完成 - 时间:2026-06-11
完成内容:
- `scripts/deploy-server.ps1` 新增 `-AutoIncrementalCommits <n>` 参数,配合 `-AutoIncremental` 使用时可自动对比 `HEAD~n``HEAD`,默认仍为最近 1 个提交。
- 自动增量日志补充 `auto incremental commits` 输出,部署元信息补充 `auto_incremental_commits`,便于 dry-run 和真实发布时确认范围。
- README 自动增量发布说明已同步新增最近 N 个提交的发布示例。
涉及模块:
- `scripts/deploy-server.ps1`
- `README.md`
验证记录:
- 已先执行 `powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncremental -AutoIncrementalCommits 2 -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun`,修改前因参数不存在失败,确认覆盖新行为。
- 修改后已执行自定义 2 个提交 dry-run,日志显示 `auto incremental commits: 2`,只打包不上传。
- 修改后已执行默认自动增量 dry-run,日志显示 `auto incremental commits: 1`,原命令兼容。
- 已验证单独传 `-AutoIncrementalCommits` 且不带 `-AutoIncremental` 会报错阻止误用。
### 45. AI助手请求失败提示补充真实错误
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 排查用户端显示“AI助手请求失败,请稍后重试。”,确认该文案来自 `ai_assistant.vue` 的前端 catch 兜底;测试服 `/api/assistant/chat` 直接请求当前可返回 `code=1`
- 补充 AI 助手前端错误解析,优先展示后端 `msg`、请求 `errMsg`、异常 `message`,并针对 timeout、abort、network/request:fail 给出更明确提示。
- catch 中增加 `[ai_assistant] chat failed` 控制台日志,便于后续复现时直接定位是网络层、请求取消、超时还是后端返回失败。
- 已复测测试服 AI 助手接口,最新消息入库模型为 `gpt-5.5`,确认当前服务端已走 OpenAI Responses 配置,不再走旧 `qwen3.7-plus` 链路。
- 已在测试服执行 `php think clear` 清理 runtime 缓存;当前 ThinkPHP 8.0.3 项目没有 `optimize:clear` 命令,后续清缓存使用 `clear`
- 继续排查 `{"code":0,"msg":"AI助手暂时不可用,请稍后再试"}`,确认原始失败原因是 `OpenAI: OpenAI 返回异常: Upstream rate limit exceeded, please retry later`,即上游中转限流。
- 后端失败返回改为输出脱敏后的模型原始错误,不再固定覆盖成“AI助手暂时不可用”;已同步测试服并复测失败路径,接口 `msg` 可直接返回上游限流原因。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
涉及模块:
- `server/app/common/service/ai/AiAssistantService.php`
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
- `server/public/mobile`
### 44. uniapp 启动缺失 sourcemap 修复
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 排查 H5 启动时报 `Failed to load source map ... index.js.map`,确认根因是 `vk-uview-ui` 内置 `async-validator.js` 尾部保留了 `//# sourceMappingURL=index.js.map`,但同目录没有对应 map 文件。
- 移除该第三方 vendored 文件的无效 sourcemap 注释,避免 Vite 启动或构建时继续读取不存在的 `index.js.map`
涉及模块:
- `uniapp/src/uni_modules/vk-uview-ui/libs/util/async-validator.js`
验证记录:
- 已执行 `npm run build:h5`H5 构建通过,日志中不再出现 `index.js.map` 缺失报错。
### 43. 项目 AI 统一切换 OpenAI Responses 配置
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 后端生成类 AI 统一改为通过 `DeepSeekClient::defaultModelOptions()` 读取项目 OpenAI 配置,默认模型 `gpt-5.5`、Base URL `https://lingsuan.top`、协议 `responses`
- `DeepSeekClient` 支持从 `server/.env``OPENAI_API_KEY / OPENAI_BASE_URL / OPENAI_MODEL / OPENAI_WIRE_API` 以及 `la_ai_config.openai_%` 读取配置,并默认关闭 Responses 存储。
- 帖子图片识别、彩票/赛事/资讯 RAG 分析和 AI 助手统一复用 OpenAI Responses 配置;AI 助手不再优先走 `qwen_%` 配置。
- 已向测试库 `la_ai_config` 写入 `openai_api_key``openai_base_url``openai_model``openai_wire_api``openai_provider_label``openai_reasoning_effort``openai_disable_response_storage` 配置项。
- 新增幂等 SQL `docs/sql/insert_openai_ai_config.sql`,用于初始化非密钥 OpenAI 配置;API Key 建议继续通过 `.env` 或后台配置维护。
涉及模块:
- `server/app/common/service/ai/DeepSeekClient.php`
- `server/app/common/service/ai/AiService.php`
- `server/app/common/service/ai/KbRagService.php`
- `server/app/common/service/ai/AiAssistantService.php`
- `docs/sql/insert_openai_ai_config.sql`
- `la_ai_config`
验证记录:
- 已执行 PHP 语法检查,相关 AI 服务文件均通过。
- 已查询测试库 `la_ai_config`,确认 `openai_%` 配置已写入且密钥只做脱敏检查。
### 42. 私聊语音输入与 Docker Whisper 转文字
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 私聊聊天室底部新增语音输入入口,App 端点击麦克风后可按住录音、松开发起识别;识别结果只填入文字输入框,由用户确认后再发送为普通文字消息。
- H5 端保留麦克风入口并降级提示“请在App中使用语音输入”,不尝试调用浏览器录音能力。
- 新增前台登录接口 `/api/chat/voiceToText`,接收单个音频文件并转发到本地 Docker Whisper ASR 服务,返回 `text``duration_ms`;支持开关、超时、Token、大小限制等 `whisper_asr_%` 配置。
- 新增 Docker Whisper ASR 服务目录,基于 FastAPI + `faster-whisper` 提供 `/health``/v1/transcribe`,默认仅绑定 `127.0.0.1:8791`,模型缓存使用 Docker volume。
- 关系文案统一优化为“对方还未添加你为好友”,并同步前端兜底展示。
- App 打包配置补充 Android 麦克风权限与 iOS 麦克风用途说明。
- 私聊聊天室底部输入栏补充对齐优化,麦克风、图片、输入框和发送按钮统一按同一中线排布,避免固定底栏控件高低错位。
- 私聊聊天室输入框改为固定高度,长文本在输入框内部滚动,避免内容继续撑开底部固定输入区。
- 私聊聊天室消息区补充头像和昵称展示:非本人消息左侧展示对方头像并在气泡上方展示对方昵称;本人消息右侧展示我的头像,不显示昵称。
- 私聊聊天室关系提示在当前用户未关注对方时追加蓝色下划线“添加好友”操作,点击后复用社区关注接口并更新本地关系状态。
- 私聊聊天室顶部仅显示对方头像和昵称,不再显示关系副标题;互关时聊天区不展示关系提示,单向关注时分别展示“对方未添加互关”或“对方已关注 + 添加互关”。
涉及模块:
- `server/app/api/controller/ChatController.php`
- `server/app/common/service/chat/WhisperAsrService.php`
- `server/app/common/service/chat/PrivateChatService.php`
- `server/app/adminapi/lists/ai/KbConfigLists.php`
- `server/extend/whisper-asr`
- `uniapp/src/api/chat.ts`
- `uniapp/src/pages/private_chat/room.vue`
- `uniapp/src/pages/private_chat/list.vue`
- `uniapp/src/manifest.json`
- `docs/sql/insert_whisper_asr_config.sql`
- `qa/backend/test_whisper_asr_service.php`
验证记录:
- 已执行 `php -l server/app/api/controller/ChatController.php`,语法检查通过。
- 已执行 `php -l server/app/common/service/chat/PrivateChatService.php`,语法检查通过。
- 已执行 `php -l server/app/common/service/chat/WhisperAsrService.php`,语法检查通过。
- 已执行 `php -l server/app/adminapi/lists/ai/KbConfigLists.php`,语法检查通过。
- 已执行 `php -l qa/backend/test_whisper_asr_service.php`,语法检查通过。
- 已执行 `php qa/backend/test_whisper_asr_service.php`,回归测试通过。
- 已执行 `C:\Python311\python.exe -m py_compile server/extend/whisper-asr/main.py`Python 语法检查通过。
- 已在 `server/.env` 指向的 `sbnews` 库重复执行 `docs/sql/insert_whisper_asr_config.sql`,确认 `whisper_asr_%` 5 个配置项均已写入且 SQL 可重复执行。
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 当前本机未安装 Docker CLI`docker --version``docker compose config` 无法执行;需在服务器 Docker 环境执行 `server/extend/whisper-asr` 下的 `docker compose up -d --build` 后再验证 `/health``/v1/transcribe`
### 41. Docker 化爬虫调度与任务日志管理
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 新增懂球帝爬虫 Docker 运行方案,`docker/docker-compose.crawler.yml` 构建并启动独立 `sport-era-crawler` 容器,容器内通过 cron 调度 Python crawler。
- 新增 `server/public/dongqiudi-crawler/config/crawler_tasks.yaml`,迁移当前启用的 crawler 任务清单,包括赛程、实时详情、比赛收尾、资讯、文章补全、彩票开奖、世界杯和错误报告等动作。
- 新增 `scripts/docker_task_runner.py`,负责动作级文件锁、执行超时、子进程输出采集、运行中/成功/失败/跳过状态写入 `la_crawler_task_log`
- `src/core/config.py` 支持 `DQD_DB_*``DQD_REDIS_*``DQD_LOG_*` 环境变量覆盖,Docker 镜像不需要写死数据库和 Redis 密钥。
- 新增管理端只读菜单“爬虫任务日志”,接口为 `/adminapi/crawler.taskLog/lists``/adminapi/crawler.taskLog/detail`,支持按任务、动作、状态、来源筛选并查看输出详情。
- 旧 PHP `crontab` 与手动执行入口对 `crawler``truth_social``fifa_worldcup_news` 这类 Python crawler 命令不再启动本机 Python,统一提示已迁移到 Docker 容器调度,避免 Docker 与 PHP 双跑。
- 新增幂等 SQL `docs/sql/create_crawler_task_log.sql`:创建 `la_crawler_task_log`、注册菜单权限,并在 Docker 验证上线后停用旧 `la_dev_crontab` 中的 Python crawler 任务。
涉及模块:
- `server/public/dongqiudi-crawler`
- `server/app/adminapi/controller/crawler/TaskLogController.php`
- `server/app/adminapi/lists/crawler/TaskLogLists.php`
- `server/app/common/model/CrawlerTaskLog.php`
- `admin/src/views/crawler/task_log/index.vue`
- `docs/sql/create_crawler_task_log.sql`
验证记录:
- 已新增 Python 单元测试覆盖配置环境变量覆盖、cron 渲染、成功/失败/超时/重复任务跳过。
- 已在测试服执行 `docs/sql/create_crawler_task_log.sql`,确认 `la_crawler_task_log`、菜单权限写入成功,并将旧 `la_dev_crontab` 中 active Python crawler 任务停用。
- 已在测试服安装 Docker Compose v2,并通过单服务 `crawler` 启动 `sport-era-crawler`;容器只运行 Python crawler 与 cronMySQL、Redis、Nginx 均继续使用宿主机服务。
- 已确认 `DQD_DB_HOST/DQD_REDIS_HOST` 指向 `host.docker.internal`,容器内 `scrapling``browserforge` 依赖可正常导入。
- 已确认 `nba_match``live_detail``match_finish``article_content_fetch` 等任务持续写入 `la_crawler_task_log` 成功日志,旧 `la_dev_crontab_log` 不再新增 Python crawler 日志。
- 已复测 `/api/match/detail?id=3567442`,返回纽约尼克斯 107-106 圣安东尼奥马刺,状态为已结束。
### 40. 后端部署脚本目录权限兼容修复
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 排查 `scripts/deploy-server.ps1` 全量部署测试服时报 `tar: Cannot change mode ... Operation not permitted`,确认 SSH 用户 `ubuntu` 仅通过 `www` 组拥有目标目录写权限,并不是目录 owner,GNU tar 覆盖解包目录项时会尝试 `chmod` 已有目录导致失败。
- 远端安装 payload 改为优先使用 `rsync -r --links --no-perms --no-owner --no-group`,不保留 owner/group/perms;远端无 rsync 时回退为 `find + mkdir/cp/ln` 逐文件复制,避免对已有目录执行 chmod。
- 修复通过 `ssh bash -s` 下发远端 Bash 文本时可能写入 UTF-8 BOM 的问题,改为用 `UTF8 No BOM` 字节流写入 stdin,避免 `set -euo pipefail` 失效导致部署“假成功”。
- 2026-06-12 再次排查测试服增量部署时报 `invalid option namepefail`,根因是远端 Bash 脚本 stdin 保留了 Windows `CRLF`,导致 `set -euo pipefail` 被识别成 `pipefail\r` 非法选项;现已在写入 stdin 前统一转换为 `LF`
- 保留当前全量部署包含整个 `public` 目录的变更,解决包含更多已有目录后触发的部署失败。
涉及模块:
- `scripts/deploy-server.ps1`
### 39. AI 分析 Responses 非 JSON 返回防护
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 修复 `/api/community/aiAnalysis` 在 GPT 中转 Responses API 返回空响应、HTML 或其他非 JSON 内容时,`DeepSeekClient::extractResponsesContent()` 因收到 `null` 触发 TypeError,导致前台显示“AI分析异常”的问题。
- `DeepSeekClient` 现在会先校验 `json_decode()` 结果是否为数组;非数组响应统一返回 `OpenAI(GPT中转) 返回异常: 响应不是有效JSON/响应JSON结构异常`,不再抛出 PHP fatal。
- `extractResponsesContent()` 增加 `null` 兜底,避免后续调用方再次把异常响应升级成类型错误。
- 新增 QA 回归脚本,覆盖 Responses 返回体解析遇到 `null` 的场景。
涉及模块:
- `server/app/common/service/ai/DeepSeekClient.php`
- `qa/backend/test_deepseek_client_invalid_response.php`
验证记录:
- 已执行 `php -l server/app/common/service/ai/DeepSeekClient.php`,语法检查通过。
- 已执行 `php -l qa/backend/test_deepseek_client_invalid_response.php`,语法检查通过。
- 已执行 `php qa/backend/test_deepseek_client_invalid_response.php`,回归测试通过。
- 使用测试账号请求测试服 `/api/community/aiAnalysis?post_id=5374&force=1` 时,测试服仍返回旧版 `extractResponsesContent(array $data)` 堆栈,说明测试服运行文件尚未同步或 OPcache 尚未刷新;待服务器同步最新 `DeepSeekClient.php` 后需复测。
### 38. NBA 实时比分爬虫与定时任务恢复
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 排查 `/pages/match_detail/match_detail?id=3567442` NBA 比赛比分不更新,确认前端详情页直接读取 `/api/match/detail``la_match` 数据,根因在测试服爬虫定时任务未持续写入实时比分。
- 修复懂球帝爬虫运行保护:`main.py` 新增动作级超时配置、跨进程动作锁、`writer.connect()` 连接超时、执行超时失败落日志,并将告警管理改为懒加载,避免导入阶段异常导致日志长期停留 `status=0`
- 修复 ThinkPHP 定时调度保护:`Crontab` 启动 crawler 前会按动作超时标记陈旧运行日志,并跳过超时时间内的重复 crawler 启动,避免 `nba_match` / `live_detail` / `match_finish` 堆积。
- 补齐 `crawler` 命令白名单,允许 `match_finish``live_detail` 通过统一 `php think crontab` 调度入口执行。
- 测试服重建并切换 `public/dongqiudi-crawler/venv`,旧环境备份为 `venv.bak-20260611041713`,修复 `aiohttp.http_writer.HttpVersion``pip._vendor.rich.protocol.is_renderable` 导入异常。
- 已修复目标比赛 `id=3567442 / match_id=54467991` 数据,接口返回纽约尼克斯 107-106 圣安东尼奥马刺,状态为已结束。
涉及模块:
- `server/public/dongqiudi-crawler/main.py`
- `server/public/dongqiudi-crawler/tests/test_runtime_guard.py`
- `server/app/common/command/Crontab.php`
- `server/app/common/command/CrawlerCommand.php`
- `la_match`
- `la_dev_crontab_log`
验证记录:
- 本地已覆盖爬虫动作锁与超时配置单元测试。
- 测试服 `main.py test``main.py nba_match``main.py live_detail` 均可正常完成。
- 测试服最近 `match_finish``nba_match``live_detail` 定时日志已恢复成功状态,相关任务当前无 `status=0` 遗留运行日志。
- `/api/match/detail?id=3567442` 已返回 `status=2``home_score=107``away_score=106`
### 37. 社区列表取消请求误报修复
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 复测测试服 `/api/community/postLists?page_no=1&page_size=15`,接口当前返回 `code=1`、本页 15 条、总数 5058,不是后端空响应。
- 排查社区列表页首屏生命周期与请求取消器交互:页面初始 `needRefresh=true` 时可能触发重复 `/community/postLists`,前一个请求被 `abort` 后网络面板显示无响应,页面 catch 又统一提示“加载失败,请重试”。
- `/packages_community/pages/index``/pages/empty` 初始刷新标记改为 `false`,首屏仅由 `onMounted` 拉取;新增请求序号保护,旧请求返回或取消时不覆盖最新列表状态。
- 两个页面对 `request:fail abort` 不再展示加载失败 toast,避免用户把主动取消的旧请求误判为接口失败。
- 同步补齐 `/packages_community/pages/index` 模板引用的分享弹窗状态与 `handleShare`,避免运行期未定义变量告警。
涉及模块:
- `uniapp/src/packages_community/pages/index.vue`
- `uniapp/src/pages/empty/empty.vue`
验证记录:
- 已执行 `npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 已复测测试服 `/api/community/postLists?page_no=1&page_size=15` 返回 `code=1``lists=15``count=5058`
### 36. 用户主页底部间隔优化
- 状态:已完成 - 时间:2026-06-11
完成内容:
- `/packages_community/pages/user_profile` 移除 `scroll-view` 基于 `windowHeight` 的 JS 高度计算,改为页面根容器纵向 flex 布局。
- 内容区使用 `flex: 1; height: 0; min-height: 0` 自适应剩余空间,并补充底部安全区 padding,避免 Android/iOS 端底部出现灰色间隔。
- H5 移动视口截图抽样确认底部为白色;`npm run build:h5``npm run build:app` 均已通过。
涉及模块:
- `uniapp/src/packages_community/pages/user_profile.vue`
### 35. 帖子加好友与私聊 v1
- 状态:已完成 - 时间:2026-06-11
完成内容:
- “好友”复用社区关注关系 `la_community_follow`,帖子作者区、他人主页、我的关注/粉丝列表均新增“加好友/已好友”和“私聊”入口,不新增好友申请/同意流程。
- 新增前台私聊接口 `/api/chat/sessions``/api/chat/open``/api/chat/messages``/api/chat/send`,登录后可查看会话、打开会话、轮询消息和发送文字/图片消息。
- 新增私聊数据表初始化 SQL`docs/sql/create_private_chat_tables.sql`,包含 `la_private_chat_session``la_private_chat_message`SQL 使用 `CREATE TABLE IF NOT EXISTS` 保持幂等。
- 私聊会话和消息返回关系状态 `is_followed_by_me``is_following_me``is_mutual``relationship_text`;未互关时聊天页顶部和首屏提示展示“对方还未添加你为好友”。
- uni-app 新增 `src/api/chat.ts``/pages/private_chat/list` 会话列表、`/pages/private_chat/room` 聊天室,聊天室每 3 秒通过 `after_id` 轮询新消息,页面隐藏/卸载时停止轮询。
- 个人中心新增“私聊消息”入口,并展示 `chat_unread_count` 未读数;`/api/community/userStats` 同步返回私聊未读总数。
涉及模块:
- `server/app/api/controller/ChatController.php`
- `server/app/api/controller/CommunityController.php`
- `server/app/common/model/chat/PrivateChatSession.php`
- `server/app/common/model/chat/PrivateChatMessage.php`
- `server/app/common/service/chat/PrivateChatService.php`
- `uniapp/src/api/chat.ts`
- `uniapp/src/pages/private_chat/list.vue`
- `uniapp/src/pages/private_chat/room.vue`
- `uniapp/src/packages_community/pages/post_detail.vue`
- `uniapp/src/packages_community/pages/user_profile.vue`
- `uniapp/src/pages/my_follow/my_follow.vue`
- `uniapp/src/pages/user/user.vue`
- `docs/sql/create_private_chat_tables.sql`
- `qa/backend/test_private_chat_api.py`
验证记录:
- 已执行新增/修改 PHP 文件 `php -l`,语法检查通过。
- 已执行 `uniapp``npm run build:h5`H5 构建通过并复制到 `server/public/mobile`
- 已在 `server/.env` 指向的 `sbnews` 库重复执行 `docs/sql/create_private_chat_tables.sql`,确认 `la_private_chat_session``la_private_chat_message` 均已存在且 SQL 可重复执行。
- `qa/backend/test_private_chat_api.py` 已确认可由 `C:\Python311\python.exe` 启动;当前环境缺少 `PRIVATE_CHAT_TOKEN_A``PRIVATE_CHAT_TOKEN_B``PRIVATE_CHAT_TARGET_USER_ID`,未进入真实接口请求阶段。
### 34. AI 助手等待回复读秒
- 状态:已完成 - 时间:2026-06-11
完成内容:
- `/pages/ai_assistant/ai_assistant` 在助手 pending 气泡中新增“分析用时”读秒展示,发送消息后从 `0m0s` 开始逐秒更新。
- 接口成功或失败后停止计时并替换为正式回答或失败提示;完成后的历史消息不持久化本地计时字段。
- 页面卸载时清理计时器,避免切页后 interval 继续运行。
涉及模块:
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
### 33. AI 助手测试服接口 500/403 修复
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 测试服补执行 `docs/sql/create_ai_assistant_tables.sql`,创建 `la_ai_chat_session``la_ai_chat_message` 并写入 `assistant_%` 配置,修复 `/api/assistant/sessions` 因缺表导致的 500。
- `AiAssistantService` 的助手模型调用改为优先读取 `qwen_api_key` / `qwen_base_url` / `qwen_model`,并回退 `server/.env``DASHSCOPE_API_KEY`;未配置 Qwen 时才使用现有默认客户端。
- 前台助手失败时返回通用“暂时不可用”文案,真实下游错误继续写入 `la_ai_chat_message.error_msg`,便于后台排查。
涉及模块:
- `server/app/common/service/ai/AiAssistantService.php`
- `docs/sql/create_ai_assistant_tables.sql`
### 32. 世博头条 AI 助手 v1
- 状态:已完成 - 时间:2026-06-11
完成内容:
- 新增前台 `/api/assistant/chat``/api/assistant/sessions``/api/assistant/messages``/api/assistant/clear`,支持匿名 `client_id` 与登录用户两类会话隔离。
- 新增 AI 助手会话表与消息表初始化 SQL:`docs/sql/create_ai_assistant_tables.sql`,并追加 `assistant_%` 配置项。
- 新增 `AiAssistantService``AiAssistantContextService`,复用 GPT 中转客户端、`KbService::retrieve()`、AI 调用日志和 Redis 频控。
- 知识库召回覆盖资讯、社区、彩票,并扩展 `match:event` 赛事知识库文档生成;加密行情按币种实时查询 Binance ticker 后注入上下文。
- uni-app 新增 `/pages/ai_assistant/ai_assistant` 页面、`src/api/assistant.ts`、首页入口和个人中心入口,支持快捷问题、历史会话、引用来源跳转和匿名对话。
涉及模块:
- `server/app/api/controller/AssistantController.php`
- `server/app/common/service/ai/AiAssistantService.php`
- `server/app/common/service/ai/AiAssistantContextService.php`
- `server/app/common/service/ai/KbService.php`
- `uniapp/src/pages/ai_assistant/ai_assistant.vue`
- `uniapp/src/api/assistant.ts`
- `docs/sql/create_ai_assistant_tables.sql`
### 31. AI 生成与图片识别切换到 GPT 中转
- 状态:已完成 - 时间:2026-06-10
完成内容:
- `DeepSeekClient` 保留历史类名以兼容既有引用,但默认提供商已硬编码切换为 GPT 中转,base url 为 `https://sub2.congmingai.com`,默认模型 `gpt-5.5`
- 客户端新增 OpenAI Responses API wire 支持,请求路径自动拼接 `/v1/responses`,并兼容 `output_text``output[].content[].text` 两类返回结构。
- 社区帖子 RAG 最终生成从 Qwen 固定配置改为 GPT 中转,并显式传入 `wire_api=responses`
- 旧澳/新澳六合彩图片识别链路从 DashScope Qwen 改为 GPT 中转,图片仍会先转为 data URL 后提交,降低第三方图片 URL 被模型侧拒绝的概率。
- AI 日志模型 fallback 改为 `gpt-5.5`;知识库 Embedding 暂保留原有 embedding 配置,避免用生成模型替代向量模型导致召回不可用。
涉及模块:
- `server/app/common/service/ai/DeepSeekClient.php`
- `server/app/common/service/ai/KbRagService.php`
- `server/app/common/service/ai/AiService.php`
### 30. 帖子 AI 分析页展示原图并改为看图自由分析
- 状态:已完成 - 时间:2026-06-10
完成内容:
- `/pages/ai_analysis/ai_analysis` 在帖子 AI 分析场景新增原帖图片展示,读取 `/api/community/postDetail` 返回的 `images`,支持点击预览。
- 帖子分析结果新增 `图片解读``诗句字谜` 展示区,对应后端返回的 `image_interpretation``poem_analysis` 字段。
- 旧澳/新澳六合彩帖子分析改为只依据当前帖子文案与图片识别内容自由解读,不再要求依赖知识库证据,也不会把“知识库证据不足”作为主结论。
- 后端归一化阶段新增兜底过滤:新澳六合、旧澳六合帖子如果模型仍返回“知识库”相关表述,会替换为“仅依据当前图片和帖子文案解读”的口径。
- 后端新增 `analysis_source=image_free_v1` 缓存版本标记,并要求六合彩帖子缓存命中该标记,避免继续复用旧的知识库不足缓存。
- 图片内容识别仍保留理性风险提示,但允许围绕诗句、字谜、藏宝图、生肖、波色、尾数、胆码、旺弱号码等当前图片内容进行自由分析。
- 前端补充 AI 响应安全解包,避免请求异常或旧路由返回空数据时出现 `Cannot read properties of undefined (reading 'analysis')`
- `/api/community/aiAnalysis` 新增 `force=1` 支持;前端发现旧版缓存缺少 `analysis_source=image_free_v1` 时,会自动强制刷新并重新生成看图分析。
涉及模块:
- `server/app/common/service/ai/KbRagService.php`
- `server/app/common/service/ai/AiService.php`
- `server/app/api/controller/CommunityController.php`
- `uniapp/src/api/community.ts`
- `uniapp/src/pages/ai_analysis/ai_analysis.vue`
### 29. AI 分析长请求断线后轮询结果
- 状态:已完成 - 时间:2026-06-10
完成内容:
- 社区帖子 AI 分析新增 `/api/community/aiAnalysisResult` 只读结果接口,只查询 `la_ai_analysis` 成功缓存,不触发图片识别、知识库召回或 LLM 生成。
- `/pages/ai_analysis/ai_analysis` 帖子分析主请求如果遇到 `timeout / request:fail / abort`,不再立即退出失败态,而是继续 loading 并轮询缓存结果,最多等待约 `120` 秒。
- 轮询期间如果测试服尚未同步新接口或返回异常,会低频回退查询原 `/community/aiAnalysis`,优先命中已生成缓存,避免页面直接报“网络失败”。
- AI 请求前端超时从 `3` 分钟放宽到 `5` 分钟;`docs/sql/insert_qwen_ai_config.sql``ai_request_timeout` 默认值和更新语句同步改为 `300` 秒。
- 本地尝试直连测试库更新 `la_ai_config.ai_request_timeout=300` 时被 MySQL 拒绝访问,需在有数据库权限的环境执行对应 SQL 后才算线上配置完全生效。
涉及模块:
- `server/app/api/controller/CommunityController.php`
- `uniapp/src/api/aiRequest.ts`
- `uniapp/src/api/community.ts`
- `uniapp/src/pages/ai_analysis/ai_analysis.vue`
- `docs/sql/insert_qwen_ai_config.sql`
### 28. 社区帖子 AI 分析 request:fail 稳定性优化
- 状态:已完成 - 时间:2026-06-10
完成内容:
- 复测 `/api/community/aiAnalysis?post_id=5310`,测试服当前已稳定返回 `code=1` JSON,并命中帖子 AI 分析缓存,不再返回 ThinkPHP 500 HTML。
- 针对 uni-app 端长耗时 AI 请求补充 `ignoreCancel=true`,避免 `/community/aiAnalysis` 这类相同 URL 的长请求被全局请求取消器误 abort,前端表现为 `request:fail`
- AI 分析页补充 `abort` 与通用 `request:fail` 错误文案,用户侧不再直接暴露底层错误字符串。
- 已执行 `npm run build:h5` 验证通过;构建产物复制到 `server/public/mobile`
涉及模块:
- `uniapp/src/api/aiRequest.ts`
- `uniapp/src/pages/ai_analysis/ai_analysis.vue`
### 27. 全站 AI 默认提供商切换为 DashScope Qwen
- 状态:已完成 - 时间:2026-06-10
完成内容:
- OpenAI-compatible 聊天客户端默认提供商已从 `deepseek_*` 配置切换为 DashScope Qwen,默认模型 `qwen3.7-plus`,默认 base url 为 `https://dashscope.aliyuncs.com/compatible-mode`
- `DeepSeekClient` 保留历史类名以兼容服务器同步和既有引用,但内部默认提供商已改为 DashScope Qwen。
- `DASHSCOPE_API_KEY` 作为默认密钥来源;后台 `qwen_api_key` 留空时自动回退到 `.env`,避免密钥硬编码。
- 赛事分析、资讯分析、彩票分析、帖子分析、用户可信度分析、文章评论生成等所有默认 LLM 生成链路现在统一走 Qwen;帖子图片识别原本已走 Qwen,保持一致。
- 知识库 Embedding 默认也切换为 DashScope compatible 接口,默认模型 `text-embedding-v4`、默认维度 `1024`,避免向量召回因 `embedding_*` 未配置而退化。
- 后台知识库配置列表已放开 `qwen_%` 配置项,并新增幂等 SQL `docs/sql/insert_qwen_ai_config.sql`;当前测试库已执行该 SQL。
涉及模块:
- `server/app/common/service/ai/DeepSeekClient.php`
- `server/app/common/service/ai/EmbeddingClient.php`
- `server/app/common/service/ai/AiService.php`
- `server/app/adminapi/lists/ai/KbConfigLists.php`
- `docs/sql/insert_qwen_ai_config.sql`
### 26. AI 分析页长耗时请求超时优化
- 状态:已完成 - 时间:2026-06-10
完成内容:
- `/pages/ai_analysis/ai_analysis` 使用的赛事分段分析、资讯分析和帖子分析请求已改为 AI 专属 3 分钟超时,不再受全局普通接口 `60s` 超时限制。
- 长耗时 AI GET 请求已禁用自动超时重试,避免一次模型分析尚未返回时又重复触发新的 LLM/RAG 请求。
- 请求封装已修复“禁用重试后 timeout 错误丢失”的问题,超时会继续把原始错误交给页面处理。
- AI 分析页补充字符串错误和 `errMsg` 兼容,超时时显示更明确的“耗时较长/稍后重试”提示;加载超过 60 秒时会提示正在结合知识库与模型继续推理。
- 同步给彩票 AI 分析类接口套用相同长超时策略,减少后续彩票模块 AI 请求被前端提前截断。
- 后端 OpenAI-compatible 模型客户端的固定 `60s` cURL 超时已改为可配置 `ai_request_timeout`,默认 `180s`,并增加连接超时,避免前端已延长但后端先断开。
涉及模块:
- `server/app/common/service/ai/DeepSeekClient.php`
- `uniapp/src/api/aiRequest.ts`
- `uniapp/src/api/ai.ts`
- `uniapp/src/api/community.ts`
- `uniapp/src/api/lottery.ts`
- `uniapp/src/pages/ai_analysis/ai_analysis.vue`
- `uniapp/src/utils/request/http.ts`
### 25. 社区帖子 RAG 生成模型切换到 Qwen3.7
- 状态:已完成 - 时间:2026-06-10
完成内容:
- 排查 `/api/community/aiAnalysis` 仍返回 `DeepSeek 返回异常: Insufficient Balance` 的原因,确认图片识别已走 DashScope Qwen,但帖子 RAG 最终 JSON 生成仍复用默认 DeepSeek 配置。
- 已将 `KbRagService::analyzePost()` 的最终生成阶段改为 DashScope OpenAI 兼容接口,模型固定为 `qwen3.7-plus`,使用 `server/.env``DASHSCOPE_API_KEY`
- `DeepSeekClient` 作为 OpenAI 兼容 HTTP 客户端保留,但现在会按调用方传入的 `provider_label` 返回错误提示;帖子分析失败时将显示 `DashScope(Qwen)`,不再误导为 DeepSeek。
- `AiService::saveResult()` 已改为记录下游返回的真实模型名,帖子 AI 日志会写入 `qwen3.7-plus`
涉及模块:
- `server/app/common/service/ai/KbRagService.php`
- `server/app/common/service/ai/DeepSeekClient.php`
- `server/app/common/service/ai/AiService.php`
### 24. 社区帖子 AI 分析改为统一分析页并显示分析计时
- 状态:已完成 - 时间:2026-06-10
完成内容:
- 社区列表页与首页社区流中的六合彩帖子 `AI分析` 入口已改为直接跳转统一分析页 `/pages/ai_analysis/ai_analysis?type=post&id=...`,不再先进帖子详情页再等待页内分析。
- 帖子详情页中的 `AI分析` 按钮也已切换为直接跳统一分析页;旧的 `show_ai=1` 链路改为兼容重定向,避免历史入口失效。
- 统一分析页已新增 `post` 类型支持,接入 `/api/community/aiAnalysis`,并展示帖子卡片、综合结论、下期预测、可信线索、风险提示、相似历史和知识库证据。
- AI 分析加载阶段新增“分析用时 `0m1s`”计时显示;赛事分段分析的后续阶段 loading 也会继续显示累计分析时长,避免长耗时场景下用户无感等待。
涉及模块:
- `uniapp/src/pages/ai_analysis/ai_analysis.vue`
- `uniapp/src/packages_community/pages/post_detail.vue`
- `uniapp/src/packages_community/pages/index.vue`
- `uniapp/src/pages/empty/empty.vue`
### 23. 六合图片分析升级到 Qwen3.7 并移除代码内密钥
- 状态:已完成 - 时间:2026-06-10
完成内容:
- `AiService::analyzeLotteryPostImages()` 已将 DashScope 视觉模型从旧版 `qwen-vl-max-latest` 切换为新版统一多模态模型 `qwen3.7-plus`,继续沿用 OpenAI 兼容接口 `https://dashscope.aliyuncs.com/compatible-mode`
- 移除了 `AiService` 中硬编码的 DashScope API Key,改为统一从 `server/.env``DASHSCOPE_API_KEY` 读取,避免密钥继续直接写入代码文件。
- 同步补充 `server/.example.env` 的 DashScope Key 占位配置,便于后续环境初始化和部署时对齐。
涉及模块:
- `server/app/common/service/ai/AiService.php`
- `server/.env`
- `server/.example.env`
### 22. 六合图片分析 404 链路修复
- 状态:已完成 - 时间:2026-06-09
完成内容:
- 排查 `/api/community/translatePost``旧澳六合/新澳六合` 图片分析分支返回 `HTTP 404` 的问题,确认不是帖子不存在,而是 Qwen 视觉模型请求地址被拼成了 `.../v1/v1/chat/completions`
- 已将 `AiService` 中 DashScope 兼容接口基地址收敛为 `https://dashscope.aliyuncs.com/compatible-mode`,并在 `DeepSeekClient` 中补充聊天接口地址规范化,兼容 `base_url` 传入根地址、`/v1` 地址或完整 `/chat/completions` 地址,避免后续再次重复拼接。
- 同步把多模型错误提示统一改为带 provider 名称返回,后续如果 DashScope/Qwen 鉴权或模型权限异常,接口会更容易直接看出来自哪个下游。
涉及模块:
- `server/app/common/service/ai/AiService.php`
- `server/app/common/service/ai/DeepSeekClient.php`
### 21. 六合图片分析切换到 DashScope Qwen 视觉模型
- 状态:已完成 - 时间:2026-06-09
完成内容:
- `AiService::analyzeLotteryPostImages()` 已按当前需求固定改为调用阿里云 DashScope OpenAI 兼容接口,不再读取后台 `lottery_image_analysis_*``deepseek_vision_model` 配置。
- 当前六合彩图片分析分支硬编码使用 `Qwen` 视觉模型 `qwen-vl-max-latest`,兼容接口基地址统一为 `https://dashscope.aliyuncs.com/compatible-mode`,由客户端自动补齐聊天接口路径,并使用指定的 DashScope API Key。
- 错误提示中的 provider 标识已改为 `DashScope(Qwen)`,方便后续定位图片分析失败是否来自 Qwen 视觉链路。
- 同步收紧图片分析提示词,新增“先过滤噪音再逐项分析”的规则,只保留当期号码、图表结论、推荐组合等有效信息,忽略水印、口号、装饰边框、重复标题和低置信度杂讯。
涉及模块:
- `server/app/common/service/ai/AiService.php`
### 20. 六合帖子 `translatePost` 收紧为纯图片分析
- 状态:已完成 - 时间:2026-06-09
完成内容:
- `/api/community/translatePost``新澳六合 / 旧澳六合` 已改为只走当前帖子图片分析,不再接受旧版六合彩分析缓存直接命中。
- 新增 `lottery_analysis_source=image_only``lottery_analysis_images_hash` 标记,只有明确由当前帖子图片生成的分析结果才会复用;旧缓存或图片已变更时会重新按图片分析。
- 移除了六合彩图片分析失败时写入“虚拟历史分析文案”的兜底逻辑,当前图片无法识别时接口会直接返回失败,避免返回看似真实、实则并非基于当前图片的内容。
- 同步收紧图片分析提示词,明确禁止引用往期内容、历史期数、知识库信息或模型记忆;社区列表侧也只展示 `image_only` 来源的六合彩分析结果。
涉及模块:
- `server/app/api/controller/CommunityController.php`
- `server/app/api/lists/community/CommunityPostLists.php`
- `server/app/common/service/ai/AiService.php`
### 19. 社区帖子分支链路收紧为“普通/特朗普/六合”三类
- 状态:已完成 - 时间:2026-06-09
完成内容:
- 重新梳理社区帖子链路后,已将普通帖子、特朗普帖子、`新澳六合/旧澳六合` 帖子的入口分支彻底拆开:普通帖子不再显示或触发 AI 分析;特朗普帖子只保留本地 `MTranServer` 翻译链路;六合帖子才显示 AI 入口。
- `post-card``/pages/empty/empty`、社区分包列表页、帖子详情页已统一按 `旧澳六合/新澳六合` 标签控制 `AI` 按钮和 `show_ai=1` 跳转,避免普通帖误入 `/api/community/aiAnalysis`
- 后端 `CommunityController::aiAnalysis()` 已改为只接受六合帖,并在进入知识库分析前先确保 `lottery_analysis_content` 已由视觉模型完成图片识别;`translatePost()` 的彩票图片分析分支也同步从泛 `彩票` 收紧为 `a6/xa6`
- `KbRagService::analyzePost()``AiService::analyzePost()` 已补强:当前帖子本身只要识别为 `a6/xa6` 就稳定输出 `next_prediction`,并跳过缺少预测字段的旧缓存,避免仍回落到历史错误结果。
涉及模块:
- `uniapp/src/pages/empty/empty.vue`
- `uniapp/src/packages_community/pages/index.vue`
- `uniapp/src/packages_community/components/post-card.vue`
- `uniapp/src/packages_community/pages/post_detail.vue`
- `server/app/api/controller/CommunityController.php`
- `server/app/api/lists/community/CommunityPostLists.php`
- `server/app/common/service/ai/AiService.php`
- `server/app/common/service/ai/KbRagService.php`
### 18. 世界杯资讯与特朗普帖子翻译切换 GPT-4o
- 状态:已完成 - 时间:2026-06-09
完成内容:
- 世界杯资讯翻译链路已改为按文章分类识别:当资讯属于“世界杯”分类时,`ArticleLogic::translate()``autoTranslateArticle()` 会优先走 `GPT-4o` 翻译,不影响其他资讯仍沿用原有翻译模型。
- 特朗普帖子翻译链路已改为按帖子标签识别:社区列表自动预热、帖子详情自动补翻译、`/api/community/translatePost` 手动翻译这 3 条路径,命中“特朗普”标签时统一走 `GPT-4o`
- 在 AI 配置层新增 `openai_api_key / openai_base_url / openai_translation_model` 约定,并补充幂等 SQL `docs/sql/insert_ai_translation_gpt4o_config.sql`;后台知识库配置列表已放开 `openai_%` 配置项,便于直接维护 `GPT-4o` 翻译参数。
- 同步把 OpenAI 兼容翻译调用的错误文案改成按 provider 显示,避免 `GPT-4o` 未配置时仍提示成 `DeepSeek API Key未配置`
涉及模块:
- `server/app/common/service/ai/DeepSeekClient.php`
- `server/app/common/service/ai/AiService.php`
- `server/app/api/logic/ArticleLogic.php`
- `server/app/api/controller/CommunityController.php`
- `server/app/api/lists/community/CommunityPostLists.php`
- `server/app/adminapi/lists/ai/KbConfigLists.php`
- `docs/sql/insert_ai_translation_gpt4o_config.sql`
### 17. 定时任务企业微信告警接入
- 状态:已完成 - 时间:2026-06-08
完成内容:
- 为 crawler 本地配置增加 `alert.dispatch_enabled / alert.wecom_webhook / alert.cooldown_seconds`,企业微信告警改走固定群机器人 Webhook,本地维护,不做后台配置页。
- 新增统一告警表 `la_crontab_alert`,并在 Python `Database` 与 PHP `CrontabAlertService` 中同时补上建表与读写逻辑,支持告警创建、30 分钟冷却、成功恢复后自动关闭。
- `main.py` 已增加 `TASK_ALERT_POLICY` 与标准化运行摘要;已启用的 `crawler` 任务按“采集型 saved_required / 维护型 saved_if_candidates / error_report 跳过自告警”规则统一落库告警。
- `ErrorCollector` 已扩展为记录单次运行的 `404 / 5xx / 网络异常` 统计;`error_report` 任务已改为读取 `la_crontab_alert` 并尝试分发企业微信消息。
-`crawler` 的 PHP 定时任务(如 `sms_verify``worldcup_article_translate`)已通过 `Crontab.php` 接入同一张告警表,仅在执行异常时产生 `command_exception` 告警。
- 已新增幂等 SQL `server/public/dongqiudi-crawler/update_crontab_error_report.sql`,并已把测试服现有 `error_report` 任务频率从 `*/5 * * * *` 调整为 `*/1 * * * *`
涉及模块:
- `server/public/dongqiudi-crawler/config/settings.yaml`
- `server/public/dongqiudi-crawler/main.py`
- `server/public/dongqiudi-crawler/src/core/error_collector.py`
- `server/public/dongqiudi-crawler/src/core/alert_manager.py`
- `server/public/dongqiudi-crawler/src/storage/database.py`
- `server/public/dongqiudi-crawler/src/scheduler/task_runner.py`
- `server/app/common/command/Crontab.php`
- `server/app/common/service/crontab/CrontabAlertService.php`
- `server/public/dongqiudi-crawler/update_crontab_error_report.sql`
### 16. 资讯无正文默认稿子并禁止发布
- 状态:已完成 - 时间:2026-06-07
完成内容:
- 为爬虫侧新增 `article_publish_helper.py`,统一判断资讯正文是否达到可发布标准;没有拉到正文、只有 RSS 摘要或占位文本的文章,采集入库时默认写成稿子状态(`is_show=0`)。
- `article_fetcher.py` 已调整为优先处理稿子状态或正文明显不足的资讯;抓到真实正文后会自动写回 `content`,同时将文章切回发布状态并重置 `content_retry`
- `nba_news.py``cba_news.py``crypto_news.py``lottery_news.py``hkjc_lottery_news.py``taiwan_lottery_news.py``fifa_worldcup_news.py` 已统一接入该规则,避免后续新采文章在正文未完成时直接暴露到前台。
- 后台 `ArticleLogic` / `ArticleController` 已增加发布拦截:手动新增、编辑或切换状态时,如果正文未达到发布标准,会直接返回“暂不能发布,请先保存为稿子”。
- 已在测试服先行回退当前可见的 NBA / CBA 占位稿:示例 `1903906``1915226` 的公开详情现已返回空数据,不再继续对前台暴露无正文资讯。
涉及模块:
- `server/public/dongqiudi-crawler/article_publish_helper.py`
- `server/public/dongqiudi-crawler/article_fetcher.py`
- `server/public/dongqiudi-crawler/nba_news.py`
- `server/public/dongqiudi-crawler/cba_news.py`
- `server/public/dongqiudi-crawler/crypto_news.py`
- `server/public/dongqiudi-crawler/lottery_news.py`
- `server/public/dongqiudi-crawler/hkjc_lottery_news.py`
- `server/public/dongqiudi-crawler/taiwan_lottery_news.py`
- `server/public/dongqiudi-crawler/fifa_worldcup_news.py`
- `server/app/common/model/article/Article.php`
- `server/app/adminapi/logic/article/ArticleLogic.php`
- `server/app/adminapi/controller/article/ArticleController.php`
### 15. NBA / CBA 资讯正文抓取补回退链路
- 状态:已完成 - 时间:2026-06-07
完成内容:
- 继续排查发现,NBA / CBA 资讯列表入库后,详情正文并不是完全没跑,而是由 `article_content_fetch` 每轮按分类各抓 `3` 条慢慢补;因此刚采集完的一大批文章会先以 RSS 摘要占位,随后逐轮补正文。
- 测试服执行日志确认 `article_content_fetch` 一直在跑,但部分 Google News 解码后的真实地址(如 `m.sohu.com``sports.sina.cn``sports.cctv.com`)在 `scrapling Fetcher` 路径下会返回 `HTTP 403`,导致正文抓取失败并累计 `content_retry`
- 已为 `server/public/dongqiudi-crawler/article_fetcher.py` 增加 `requests + BeautifulSoup` 回退抓取链路:当 `scrapling` 返回 `403` 或抛异常时,改用普通请求抓页面并复用同一套正文抽取规则,降低这类站点的正文缺失率。
- 同步补充 `server/public/dongqiudi-crawler/requirements.txt``beautifulsoup4` 依赖声明,避免后续环境重装时漏掉回退解析库。
涉及模块:
- `server/public/dongqiudi-crawler/article_fetcher.py`
- `server/public/dongqiudi-crawler/requirements.txt`
### 14. NBA / CBA 资讯定时任务补注册与恢复拉取
- 状态:已完成 - 时间:2026-06-07
完成内容:
- 排查发现 `server/public/dongqiudi-crawler/main.py``nba_news.py``cba_news.py` 代码入口都已存在,`article_content_fetch` 也已覆盖 `cid=17/18` 的正文补全,但测试服 `la_dev_crontab` 中缺少 `nba_news``cba_news` 两个定时任务,所以后台从未自动触发 NBA / CBA 资讯采集。
- 已补充幂等 SQL `insert_crontab_nba_news.sql``insert_crontab_cba_news.sql`,分别注册 `crawler nba_news``crawler cba_news`
- 已在测试服后台实际创建两条任务,当前执行规则分别为 `10 * * * *`NBA)和 `20 * * * *`CBA),状态均为“运行”。
- 已手动验证一次:NBA 任务成功抓取 100 条,新增 99 条;CBA 任务成功抓取 169 条,新增 152 条。
- 已继续验证正文抓取链路:`article_content_fetch` 在 2026-06-07 00:50 自动处理了新入库的 NBA / CBA 文章,成功补全 4 篇正文;另有 2 篇源站返回 HTTP 403,已按现有 `content_retry` 机制记录重试。
涉及模块:
- `server/public/dongqiudi-crawler/main.py`
- `server/public/dongqiudi-crawler/nba_news.py`
- `server/public/dongqiudi-crawler/cba_news.py`
- `server/public/dongqiudi-crawler/article_fetcher.py`
- `server/public/dongqiudi-crawler/insert_crontab_nba_news.sql`
- `server/public/dongqiudi-crawler/insert_crontab_cba_news.sql`
### 13. 赛事 AI 分段分析接入知识库召回
- 状态:已完成 - 时间:2026-06-06
完成内容:
- 排查发现 `/api/ai/matchPredictSection` 原链路只会组装 `match_info / head_to_head / home_recent / away_recent` 后直接调用 `DeepSeekClient::chatJson()`,并不会进入知识库检索层。
- 现已为赛事分析补充 `KbRagService::analyzeMatch()``analyzeMatchSection()`,先根据主队、客队、联赛名到知识库中召回相关资讯/帖子,再把召回证据与结构化交手记录、近期战绩、赔率一起交给 LLM。
- `AiService::predictMatch()``predictMatchSection()` 已切换到赛事专用 RAG 链路,返回结果增加 `evidence_list / similar_history / from_kb / retrieval_meta` 等知识库增强字段。
- 为避免旧的赛事分段缓存继续短路新链路,当前逻辑只接受带知识库字段痕迹的新缓存;老缓存会自动跳过并重新走 RAG 生成。
- 当前赛事 RAG 仍未把 `match_event / match_history / match_recent` 建成独立知识库 domain,交手记录和近期战绩继续直接从业务表读取;知识库侧主要召回相关资讯与帖子。
涉及模块:
- `server/app/common/service/ai/AiService.php`
- `server/app/common/service/ai/KbRagService.php`
- `server/app/common/service/ai/KbService.php`
- `server/app/api/controller/AiController.php`
### 12. 全站 AI 知识库与 RAG 分析底座
- 状态:已完成 - 时间:2026-06-06
完成内容:
- 新增 AI 知识库底座表设计与 SQL:`la_ai_kb_document``la_ai_kb_chunk``la_ai_kb_sync_job``la_ai_kb_query_log`,并补充知识库菜单与 Embedding / KB 配置初始化 SQL。
- 后端新增 `KbService / KbSyncService / EmbeddingClient / KbRagService`,支持资讯、帖子、彩票历史内容统一建档、切片、Embedding、全文候选、向量重排、规则混排和查询日志记录。
- 新增控制台命令 `php think kb:rebuild``php think kb:consume`,支持全量回填与增量消费;文章新增/编辑/上下架、帖子发布/删除/翻译缓存更新已接入同步任务队列,彩票历史通过消费命令补录扫描。
- 现有 `AiService` 已接入知识库增强分析:资讯分析、彩票总分析、彩票分模块分析统一增加 `from_kb / evidence_list / similar_history / retrieval_meta`;新增帖子专属接口 `GET /api/community/aiAnalysis?post_id={id}`
- 管理后台新增知识库配置、知识文档、同步任务、查询日志页面与对应 API,且扩展了 AI 分析记录 / AI 日志类型展示。
- 新增 `qa/backend/test_kb_article_analysis.py``qa/backend/test_kb_post_analysis.py` 作为知识库增强接口的最小冒烟脚本。
涉及模块:
- `server/app/common/model/ai/*`
- `server/app/common/service/ai/*`
- `server/app/common/command/KbRebuild.php`
- `server/app/common/command/KbConsume.php`
- `server/app/api/controller/CommunityController.php`
- `server/app/common/service/ai/AiService.php`
- `server/app/adminapi/controller/ai/*`
- `admin/src/views/ai/*`
- `docs/sql/create_ai_kb_tables.sql`
- `docs/sql/insert_ai_kb_config.sql`
- `docs/sql/insert_menu_ai_kb.sql`
- `qa/backend/test_kb_article_analysis.py`
- `qa/backend/test_kb_post_analysis.py`
### 11. 彩票资讯远程图片代理中转
- 状态:已完成 - 时间:2026-06-03
完成内容:
- 为前台资讯接口补充 `ArticleImageProxyService`,对白名单内的香港赛马会与台湾彩券远程图片生成站内代理地址。
- 新增公开接口 `/api/article/imageProxy`,由服务器代拉 `res.hkjc.com``cdn.taiwanlottery.com.tw` 等远程图片并回传,规避国内客户端无法直连的问题。
- `ArticleLogic::detail()``ArticleLists::lists()` 已统一接入代理改写,老文章无需重采即可让详情正文图片和列表封面图走服务器中转。
- 代理按 `ext.source` 白名单控制,仅对 `hkjc_racingnews``taiwan_lottery` 两类彩票资讯生效,降低 SSRF 风险。
涉及模块:
- `server/app/common/service/article/ArticleImageProxyService.php`
- `server/app/api/controller/ArticleController.php`
- `server/app/api/logic/ArticleLogic.php`
- `server/app/api/lists/article/ArticleLists.php`
### 1. 项目基础文档与协作协议
- 状态:已完成 - 时间:2026-05-07
完成内容:
- 创建根目录 `AGENTS.md`,记录项目技术栈、子模块分工、数据库基准与协作规范。
- 创建 `server/AGENTS.md``admin/AGENTS.md``uniapp/AGENTS.md``pc/AGENTS.md``qa/AGENTS.md`
- 创建 `业务进度管理.md``设计稿映射.md`,作为后续进度与设计稿映射维护入口。
涉及模块:
- `AGENTS.md`
- `server/AGENTS.md`
- `admin/AGENTS.md`
- `uniapp/AGENTS.md`
- `pc/AGENTS.md`
- `qa/AGENTS.md`
- `业务进度管理.md`
- `设计稿映射.md`
### 2. 新闻爬虫文章入库去重
- 状态:已完成 - 时间:2026-05-09
完成内容:
- 在懂球帝爬虫公共入库方法 `upsert_articles` 中增加同分类标题去重,阻止不同 `article_id` 的同标题文章重复写入。
- 新闻和视频采集任务按已知频道传入对应文章分类 `cid`,减少新增 `cid=0` 数据。
- 对已存在 `article_id` 且旧分类为 `cid=0` 的数据,后续带正确分类再次入库时可迁移到正确分类。
涉及模块:
- `server/public/dongqiudi-crawler/src/storage/database.py`
- `server/public/dongqiudi-crawler/src/scheduler/task_runner.py`
### 3. Truth Social 定时任务入口整理
- 状态:已完成 - 时间:2026-05-09
完成内容:
- 后台定时任务 `truth_social` 改为执行 `public/dongqiudi-crawler/main.py truth_social`
- 移除旧的 `server/public/truth-social` 独立采集目录,避免继续维护两套特朗普消息采集代码。
涉及模块:
- `server/app/adminapi/logic/crontab/CrontabLogic.php`
- `server/public/dongqiudi-crawler/truth_social.py`
### 4. 49宝典彩票社区爬虫接入
- 状态:已完成 - 时间:2026-05-11
完成内容:
- 新增 `lottery_community` 爬虫入口,拉取 49宝典首页 Astro props 数据并解析开奖与图库资料。
- 自动创建或复用社区标签 `彩票`,自动创建或复用发布用户 `lottery_publisher`
-`origin_id` 对彩票社区帖子做幂等新增/更新,并同步帖子图片和标签关联。
- 接入 ThinkPHP `crawler` 命令白名单和 Python 主入口命令映射。
- 提供幂等 SQL 注册定时任务 `crawler lottery_community`
- 修复 49宝典响应中文解码和图库图片域名规则,`prod/` 图片资源改用可直接访问的 `tk2cdn-ali.tprswe.com`
涉及模块:
- `server/public/dongqiudi-crawler/lottery_community.py`
### 10. 彩票 AI 趋势分析坏缓存容错
- 状态:已完成 - 时间:2026-06-03
完成内容:
- 排查 `/api/lottery/aiTrend?code=XOMLHC` 时发现,当前问题不是彩种不存在,也不是当前 DeepSeek key 鉴权失败,而是命中了 `la_ai_analysis` 中一条 `type=4` 的成功缓存,但该缓存 `result` 实际是 JSON 字符串 `\"\"``json_decode(..., true)` 后得到的是字符串而不是数组。
- `server/app/common/service/ai/AiService.php``analyzeLotteryModule()` 已补充防守:彩票 AI 模块缓存只有在解码后为非空数组时才视为有效;若模型返回的 `parsed` 不是数组或为空,也不再写入“成功缓存”,而是按格式异常处理。
- 这样可以避免旧的坏缓存继续让 `LotteryController::aiTrend()``aiHotCold()``aiStats()``aiColorZodiac()` 走到 `$this->data(string)` 并触发类型错误。
涉及模块:
- `server/app/common/service/ai/AiService.php`
### 9. 世界杯资讯翻译预热限制为列表前 50 条
- 状态:已完成 - 时间:2026-06-03
完成内容:
- 调整 `server/app/common/command/WorldcupArticleTranslate.php`,世界杯英文资讯翻译预热不再全量扫描全部文章。
- 预热范围改为按前台资讯列表同口径排序:`published_at desc, id desc`,仅处理用户当前最先看到的前 50 条世界杯资讯。
- 这样可以在 AI key 恢复后优先补齐前台首屏和专题页最靠前文章的翻译缓存,避免一次性处理历史文章拖慢恢复。
涉及模块:
- `server/app/common/command/WorldcupArticleTranslate.php`
### 9. 世界杯比赛详情接口默认直播链接
- 状态:已完成 - 时间:2026-06-03
完成内容:
- `server/app/api/controller/MatchController.php` 在前台 `/api/match/detail` 接口中为世界杯比赛补充默认直播链接。
- 当赛事 `league_name=世界杯``competition_id=61` 且数据库 `live_url` 为空时,接口响应中的 `live_url` 默认返回 `https://sports.cctv.com/?spm=C28340.P9mj1V5B06xk.E2XVQsMhlk44.7`
- 默认值仅在接口响应层兜底,不写回数据库;后台已维护的 `live_url` 仍优先返回,用户端继续只消费接口返回字段。
涉及模块:
- `server/app/api/controller/MatchController.php`
- `admin/src/views/match/lists/index.vue`
- `uniapp/src/pages/match_detail/match_detail.vue`
- `server/public/dongqiudi-crawler/main.py`
- `server/app/common/command/CrawlerCommand.php`
- `server/public/dongqiudi-crawler/insert_crontab_lottery_community.sql`
### 5. 项目级文档归档到根目录
- 状态:已完成 - 时间:2026-05-14
完成内容:
- 将项目级文档 `01-产品方案文档.md``02-实现流程文档.md``爬虫任务脚本文档.md``docs/` 目录移动到项目根目录统一维护。
- 在根目录 `AGENTS.md` 中补充项目级文档存放规则,明确协作类与业务类总文档默认放根目录。
- 同步修正文档引用路径,避免后续继续引用旧的 `docs/` 路径。
涉及模块:
- `AGENTS.md`
- `业务进度管理.md`
- `01-产品方案文档.md`
- `02-实现流程文档.md`
- `爬虫任务脚本文档.md`
### 6. FIFA 世界杯资讯定时采集接入
- 状态:已完成 - 时间:2026-05-15
完成内容:
- 新增 FIFA 世界杯资讯爬虫入口 `fifa_worldcup_news`,通过 FIFA CXM API 拉取世界杯页面新闻区块数据。
- 增加世界杯文章分类幂等创建/复用逻辑,默认分类名为 `世界杯`,并自动启用显示。
- 新增定时任务注册 SQL `insert_crontab_fifa_worldcup_news.sql`,采用 `crawler fifa_worldcup_news` 动作并按 10 分钟执行。
- 将后端定时任务调度链路扩展到 `fifa_worldcup_news`,沿用现有 crawler 异步执行模式。
- 已验证 FIFA API 可返回 20 条世界杯资讯;本地完整写库验证因 crawler 当前数据库配置指向 `127.0.0.1` 而 MySQL 拒绝连接,需在服务器/可用数据库环境执行。
涉及模块:
- `server/public/dongqiudi-crawler/fifa_worldcup_news.py`
- `server/public/dongqiudi-crawler/main.py`
- `server/public/dongqiudi-crawler/insert_crontab_fifa_worldcup_news.sql`
- `server/app/common/command/CrawlerCommand.php`
- `server/app/adminapi/logic/crontab/CrontabLogic.php`
### 7. 懂球帝世界杯专属采集与用户端世界杯中心
- 状态:已完成 - 时间:2026-05-15
完成内容:
- 新增 `dqd_worldcup` 专属采集任务,固定抓取懂球帝 2026 世界杯 `standing / schedule / person_ranking(goals|assists)`
- 世界杯赛程写入 `la_match`,统一使用 `league_name=世界杯``competition_id=61``sport_type=1`,并保留 `round_name``stage`
- 新增世界杯缓存表 `la_worldcup_standing``la_worldcup_person_ranking`,保留小组积分榜和球员榜结构。
- 新增幂等 SQL `insert_crontab_dqd_worldcup.sql`,自动创建并启用足球二级分类"世界杯",同时注册 `crawler dqd_worldcup` 定时任务。
- `MatchController` 新增 `worldCupStandings``worldCupRankings``worldCupSchedule` 3 个前台接口,供用户端世界杯中心使用。
- 用户端 `pages/match/match` 在"足球 > 世界杯"分类下新增"赛程对阵图"顶部入口卡,并新增 `packages_match/pages/worldcup` 世界杯专属页,提供"对阵图 / 积分榜 / 射手榜 / 助攻榜 / 赛程" 5 个 tab。
- 已在测试库执行 SQL 并手动跑通一次采集,当前写入结果为:`la_match` 104 场、`la_worldcup_standing` 48 条、`la_worldcup_person_ranking``goals/assists` 暂为空。
- 已验证测试服 `/api/match/leagues``/api/match/lists?league_name=世界杯` 可返回世界杯分类与赛程;`worldCupStandings / worldCupRankings / worldCupSchedule` 仍需等待后端自动同步到测试服后再做最终联调。
涉及模块:
- `server/public/dongqiudi-crawler/dqd_worldcup.py`
- `server/public/dongqiudi-crawler/main.py`
- `server/public/dongqiudi-crawler/insert_crontab_dqd_worldcup.sql`
- `server/app/common/command/CrawlerCommand.php`
- `server/app/common/model/match/WorldCupStanding.php`
- `server/app/common/model/match/WorldCupPersonRanking.php`
- `server/app/api/controller/MatchController.php`
- `uniapp/src/api/match.ts`
- `uniapp/src/pages/match/match.vue`
### 8. 49宝典新澳六合/旧奥六合爬取 API 格式适配修复
- 状态:已完成 - 时间:2026-06-01
完成内容:
- 发现新澳六合(xa6)和旧奥六合(a6)的 draw 类型帖子自 2026-05-29 起停止更新,根源为第三方 API 变更响应格式。
- 字段变更:开奖号码数组从 `openCode` 迁移到 `currentResult`,期号从 `issue` 迁移到 `currentCompleteIssue`/`currentIssue`
- 字段编码:五行由中文(金木水火土)变为字母编码(j/m/s/h/t),单双由中文(单双)变为字母编码(o/e),大小由中文(大小)变为字母编码(b/s),颜色新增 R/G/B 编码。
- 时间格式:开奖时间从时间戳变为 `"Y-m-d H:i:s"` 字符串格式。
- 修复 `lottery_community.py``build_draw_post` 函数,添加 `WUXING_MAP``ODD_EVEN_MAP``SIZE_MAP` 等映射表,增强 `color_text` 函数支持 R/G/B 编码,增强 `format_time` 函数支持字符串时间格式。
- 修复后的代码在 2026-05-31 18:10 的执行中成功同步:xa6 新增 92 条(含 1 条 draw + 91 条 gallery),a6 更新 101 条。
- 数据库验证:xa6 和 a6 的 draw 类型均已同步到最新 2026151 期,gallery 类型同步到最新数据。
- 注意:2026149-2026150 期因 API 格式变更期间不可回溯(API 只返回当前期),已无法补回。
涉及模块:
- `server/public/dongqiudi-crawler/lottery_community.py`
## 四、避坑记录
- **Docker crawler 新增任务后,不能只同步源码不重建容器**:像 `match_live_stream.py` 这类新增动作,即使服务器目录里已经有文件,运行中的 `sport-era-crawler` 仍可能还是旧镜像;要同时检查容器内 `/app/<task>.py``/app/config/crawler_tasks.yaml``/etc/cron.d/sport-era-crawler` 是否都已加载新任务,否则会出现“代码在服务器上、任务却永远不执行”的假象。
- **Docker 外层 runner 与任务脚本内部不要重复抢同名锁**:`docker_task_runner.py` 已经按 action 加过锁,任务脚本内部如果再对同名 action 抢文件锁,会出现“任务日志连续成功、数据库完全没更新”的假成功症状;后续新增 Docker crawler 任务时,要先确认锁只保留一层,或显式区分 runner 锁和脚本独立执行锁。