no message
This commit is contained in:
@@ -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,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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user