no message

This commit is contained in:
hajimi
2026-06-13 10:47:34 +08:00
parent 186521392d
commit 50f0b6aff5
4 changed files with 183 additions and 18 deletions
+11
View File
@@ -106,6 +106,17 @@
| 7 | 幂等性 | SQL 初始化必须可重复执行 |
| 8 | 文档同步 | 功能完成后更新 `业务进度管理.md` |
## 代码变更后部署
- 只要本项目有代码变更,完成必要验证后,必须执行以下命令,将最新代码更新到测试服运行环境:
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /www/wwwroot/test-server.sbnews.net
```
- 默认将这条部署命令视为 Sport Era 项目代码变更后的必做步骤,除非用户在当前任务中明确说明“不需要部署”。
## 设计稿映射
设计稿与页面/组件映射统一维护在:
+14 -7
View File
@@ -14,11 +14,15 @@ Docker 只负责运行 Python 爬虫和容器内 cron。MySQL、Redis、Nginx
配置源:
- Docker Compose`docker/docker-compose.crawler.yml`
- Compose 路径变量示例:`docker/.env.example`
- 环境变量示例:`docker/.env.docker.example`
- 任务清单:`server/public/dongqiudi-crawler/config/crawler_tasks.yaml`
- 爬虫源码:`docker/crawler`
- 任务清单:`docker/crawler/config/crawler_tasks.yaml`
- 任务日志:管理后台 `系统设置 -> 系统维护 -> 爬虫任务日志`
- 错误日志:管理后台 `系统设置 -> 系统维护 -> 爬虫错误日志`
`docker/docker-compose.crawler.yml` 默认使用 `./crawler` 作为构建上下文和 `logs/data` 挂载目录。如果服务器上的 `docker/.env` 已存在,需要确认里面是 `CRAWLER_DIR=./crawler`,或者删除该变量让 Compose 使用默认值。
禁用的定时任务不要放进 Docker 执行清单;如需临时停用某个 Docker 爬虫任务,将 `crawler_tasks.yaml` 对应任务的 `active` 改为 `false`,然后重建或重启 crawler 容器。
### 当前 Docker 定时任务列表
@@ -137,12 +141,13 @@ cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net
```
全量模式默认以仓库根目录为源,只打包以下个子目录:
全量模式默认以仓库根目录为源,只打包以下个子目录:
```text
server/
uniapp/
admin/
docker/
```
也就是说,远端 `RemoteDir` 下最终会形成:
@@ -151,9 +156,11 @@ admin/
<RemoteDir>/server
<RemoteDir>/uniapp
<RemoteDir>/admin
<RemoteDir>/docker
<RemoteDir>/docker/crawler
```
默认会排除运行态或较大目录,例如 `server/.env``server/vendor``server/runtime``server/public/uploads``server/public/admin``server/public/mobile`、爬虫 `data/logs/venv`,以及 `uniapp/node_modules``uniapp/dist``admin/node_modules``admin/dist`。如确实需要包含,可追加参数:
默认会排除运行态、密钥或较大目录,例如 `server/.env``docker/.env``docker/.env.docker``server/vendor``server/runtime``server/public/uploads``server/public/admin``server/public/mobile`、爬虫 `data/logs/venv`,以及 `uniapp/node_modules``uniapp/dist``admin/node_modules``admin/dist`。如确实需要包含,可追加参数:
```bash
--include-env
@@ -203,11 +210,11 @@ cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncremental -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun
```
脚本会在打包和上传前先检查默认打包范围(`server` + `uniapp` + `admin`);如果这些目录内存在未提交、删除或未跟踪文件,会先自动提交这些变更,再继续计算增量范围。可以通过 `-AutoCommitMessage "提交说明"` 自定义这次自动提交的说明。若存在合并冲突,需要先手动解决。
脚本会在打包和上传前先检查默认打包范围(`server` + `uniapp` + `admin` + `docker`);如果这些目录内存在未提交、删除或未跟踪文件,会先自动提交这些变更,再继续计算增量范围。可以通过 `-AutoCommitMessage "提交说明"` 自定义这次自动提交的说明。若存在合并冲突,需要先手动解决。
注意:自动增量只包含指定提交范围内已经提交到 Git 的差异,不会包含工作区未提交文件。需要指定任意起止提交时,继续使用 `-From <old_commit> -To <new_commit>`
如果当前根目录 Git 只把 `server``uniapp``admin` 记录为 gitlink/submodule,脚本无法拿到对应目录内部的文件级差异;此时会把该目录从当前工作区按源码目录补进增量包,保证可以继续发布。
如果当前根目录 Git 只把 `server``uniapp``admin` 记录为 gitlink/submodule,脚本无法拿到对应目录内部的文件级差异;此时会跳过该 gitlink 的自动提交,并把该目录从当前工作区按源码目录补进增量包,保证可以继续发布。
### 只演练不上传
@@ -233,7 +240,7 @@ powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -Remo
### 发布 uniapp 源码到服务器并在服务器构建
默认发布命令会把 `server/``uniapp/``admin/` 一起同步到远端根目录;如果需要在服务器端构建 `uniapp`,建议在远端根目录执行构建,再把 H5 产物写回同一套代码下的 `server/public/mobile`
默认发布命令会把 `server/``uniapp/``admin/``docker/` 一起同步到远端根目录;如果需要在服务器端构建 `uniapp`,建议在远端根目录执行构建,再把 H5 产物写回同一套代码下的 `server/public/mobile`
```powershell
cd D:\www\sport-era
@@ -246,7 +253,7 @@ powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 `
说明:
- `-RemoteDir` 指向服务器上的项目根目录,解压后里面会同时有 `server/``uniapp/``admin/`
- `-RemoteDir` 指向服务器上的项目根目录,解压后里面会同时有 `server/``uniapp/``admin/``docker/`
- `-UniappReleasePath` 会通过环境变量 `UNIAPP_RELEASE_PATH` 传给 `uniapp/scripts/release.mjs`;这里传 `../server/public/mobile`,是因为构建命令会先 `cd uniapp`,再把 H5 产物回写到兄弟目录 `server/public/mobile`
- 服务器需要预先安装 `node >= 18.19.0``npm`,否则 `npm install` / `npm run build:h5` 无法执行。
+69 -11
View File
@@ -257,7 +257,11 @@ function Get-ArchiveExcludePatterns {
"." {
$patterns += @("uniapp/node_modules", "uniapp/dist", "admin/node_modules", "admin/dist")
if (-not $IncludeEnv) {
$patterns += "server/.env"
$patterns += @(
"server/.env",
"docker/.env",
"docker/.env.docker"
)
}
if (-not $IncludeVendor) {
$patterns += "server/vendor"
@@ -276,7 +280,13 @@ function Get-ArchiveExcludePatterns {
"server/public/dongqiudi-crawler/data",
"server/public/dongqiudi-crawler/logs",
"server/public/dongqiudi-crawler/venv",
"server/public/dongqiudi-crawler/__pycache__"
"server/public/dongqiudi-crawler/__pycache__",
"docker/crawler/data",
"docker/crawler/logs",
"docker/crawler/venv",
"docker/crawler/__pycache__",
"docker/crawler/test_output.txt",
"docker/crawler/tmp_*"
)
}
}
@@ -315,6 +325,45 @@ function Get-ArchiveExcludePatterns {
return @($patterns)
}
function Test-ArchiveExcludedPath {
param([string]$RelativePath)
$path = ($RelativePath -replace "\\", "/").TrimStart("./")
foreach ($rawPattern in (Get-ArchiveExcludePatterns)) {
if ([string]::IsNullOrWhiteSpace($rawPattern)) {
continue
}
$pattern = ($rawPattern -replace "\\", "/").TrimStart("./").TrimEnd("/")
if ([string]::IsNullOrWhiteSpace($pattern)) {
continue
}
if ($pattern.Contains("/")) {
if ($pattern -match "[*?\[]") {
if ($path -like $pattern -or $path -like "$pattern/*") {
return $true
}
} elseif ($path -eq $pattern -or $path.StartsWith("$pattern/")) {
return $true
}
continue
}
foreach ($segment in @($path -split "/")) {
if ($pattern -match "[*?\[]") {
if ($segment -like $pattern) {
return $true
}
} elseif ($segment -eq $pattern) {
return $true
}
}
}
return $false
}
function Commit-SourceChangesIfNeeded {
param(
[string]$Repository,
@@ -559,8 +608,9 @@ function Build-IncrementalPayload {
$status = $parts[0]
if ($status -eq "D") {
$path1 = $parts[1]
if (Test-UnderSourceDir $path1) {
$script:DeletedDisplayPaths += (Strip-SourcePrefix $path1)
$displayPath = Strip-SourcePrefix $path1
if ((Test-UnderSourceDir $path1) -and -not (Test-ArchiveExcludedPath $displayPath)) {
$script:DeletedDisplayPaths += $displayPath
}
} elseif ($status -like "R*" -or $status -like "C*") {
if ($parts.Count -lt 3) {
@@ -568,18 +618,21 @@ function Build-IncrementalPayload {
}
$path1 = $parts[1]
$path2 = $parts[2]
if (Test-UnderSourceDir $path2) {
$displayPath2 = Strip-SourcePrefix $path2
if ((Test-UnderSourceDir $path2) -and -not (Test-ArchiveExcludedPath $displayPath2)) {
[void]$changedGitPaths.Add($path2)
$script:ChangedDisplayPaths += (Strip-SourcePrefix $path2)
if ($status -like "R*" -and (Test-UnderSourceDir $path1)) {
$script:DeletedDisplayPaths += (Strip-SourcePrefix $path1)
$script:ChangedDisplayPaths += $displayPath2
$displayPath1 = Strip-SourcePrefix $path1
if ($status -like "R*" -and (Test-UnderSourceDir $path1) -and -not (Test-ArchiveExcludedPath $displayPath1)) {
$script:DeletedDisplayPaths += $displayPath1
}
}
} else {
$path1 = $parts[1]
if (Test-UnderSourceDir $path1) {
$displayPath = Strip-SourcePrefix $path1
if ((Test-UnderSourceDir $path1) -and -not (Test-ArchiveExcludedPath $displayPath)) {
[void]$changedGitPaths.Add($path1)
$script:ChangedDisplayPaths += (Strip-SourcePrefix $path1)
$script:ChangedDisplayPaths += $displayPath
}
}
}
@@ -694,7 +747,12 @@ $RootGitLinkIncludePaths = @(Get-RootGitLinkIncludePaths)
if ($RootGitLinkIncludePaths.Count -gt 0) {
Write-DeployLog "root gitlink include paths will be copied from working tree: $($RootGitLinkIncludePaths -join ' ')"
}
Commit-SourceChangesIfNeeded -Repository $GitCwd -Pathspec $DeployPathspec
$CommitPathspec = @($DeployPathspec | Where-Object { $RootGitLinkIncludePaths -notcontains $_ })
if ($CommitPathspec.Count -gt 0) {
Commit-SourceChangesIfNeeded -Repository $GitCwd -Pathspec $CommitPathspec
} else {
Write-DeployLog "all deploy paths are root gitlinks; skip auto commit and use working tree payload"
}
if ($Mode -eq "incremental") {
& git -C $GitCwd rev-parse --verify "$FromCommit^{commit}" *> $null
+89
View File
@@ -13,6 +13,95 @@
## 一、已完成事项
### 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