Files
sbnews/AGENTS.md
T

255 lines
16 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 项目说明
## 思考语言
思考过程请使用中文。
## 项目信息
- 基于 likeadmin 的体育资讯 AI 分析 App / 流量平台
- 后端:PHP 8.x + ThinkPHP / likeadmin
- 管理后台:Vue 3 + Vite + Element Plus + TypeScript
- 手机端:uni-app + Vue 3
- PC 前台:Nuxt 3 + Vue 3
- 数据库:MySQL`sbnews`,表前缀 `la_`
- 缓存:RedisThinkPHP Cache facade
## 子项目开发规范
修改到哪个子项目,则需要遵循对应子项目的 Agent 说明:
| 模块 | Agent 文件 | 职责 |
| --- | --- | --- |
| 后端 | `server/AGENTS.md` | API 接口、数据库建模、业务逻辑、定时任务 |
| 管理后台 | `admin/AGENTS.md` | 消费 adminapi 接口,构建管理页面 |
| 手机端 | `uniapp/AGENTS.md` | 消费 api 接口,构建 H5/App/小程序页面 |
| PC 前台 | `pc/AGENTS.md` | 消费 api 接口,构建 Nuxt PC 页面 |
| 测试 | `qa/AGENTS.md` | 后端 API 验证与前端页面验证 |
---
## 编程准则
1. 做新功能之前必须先检查现有代码是否已有相关功能,避免重复开发。
2. 创建新数据表时,用到的字典、枚举值、状态码等必须配置在现有的数据表或配置表内统一管理,不能硬编码。
3. 相同或相似的功能必须封装为可复用的方法,避免重复代码。
4. 查询字段、路由、菜单、配置前,优先以当前项目代码和 `sbnews.sql` / `docs/sql/` 中结构为准;如需线上核对,再按用户要求使用可用 MCP 或指定连接方式。
5. 不通过 WSL sshpass/scp 上传代码到服务器;项目代码更新由用户自行通过 SFTP 等方式处理。
6. 新增项目级文档(如协作规范、业务进度、设计稿映射、产品方案、实现流程、爬虫说明等)统一存放在 `docs/`;根目录仅保留 `README.md``AGENTS.md``文档索引.md` 等入口文件。仅子项目专属的 README / AGENTS 等说明可放在对应子目录。
---
## 常用命令速查
| 模块 | 开发命令 | 构建命令 |
| --- | --- | --- |
| server | `php think run` | — |
| admin | `npm run dev` | `npm run build` |
| uniapp | `npm run dev:h5` | `npm run build:h5` |
| pc | `npm run dev` | `npm run generate` / `npm run build` |
## 自动化执行边界
- 除非用户在当前任务中明确要求,否则不要自动执行构建或测试。
- **持续授权:每次修改真实源码或运行配置后都必须创建 Git commit,无须再次询问。**说明文档及 `server/public/admin``server/public/mobile` 等生成产物不属于该触发范围。
- **`server/` 例外:**本次修改 `server/` 下的真实运行源码或运行配置时,除提交外还必须同步测试服;无需用户重复要求。
- `admin/``uniapp/``pc/``docker/``python/``qa/``scripts/` 等非 `server/` 源码改动只提交 commit,不自动同步测试站点;用户明确要求时除外。
- 用户明确要求“构建”“测试”“部署”“上线”“发布”等操作时,才执行对应命令;但 `server/` 源码变更适用上述持续授权同步例外。
- 对已经由用户给出的命令,可按用户原命令执行;不要额外扩展到未要求的构建、测试、提交或部署步骤。
## 数据库结构基准
- 数据库表前缀:`la_`
- 配置存储在 `la_config` 表,通过 `ConfigService::get/set` 读写。
- 菜单存储在 `la_system_menu` 表,type: M=目录、C=页面、A=按钮权限。
- 定时任务注册在 `la_dev_crontab`,通过 `php think crontab` 统一调度。
- MySQL 保留字如 `system``order``group``key` 等写原生 SQL 时必须用反引号包裹。
### 数据库连接方式
测试数据库连接信息位于 `server/.env`(不入库)。连接参数:
| 配置项 | 值 |
| --- | --- |
| Host | `95.40.220.223` |
| Port | `3300` |
| Database | `sbnews` |
| User | `sbnews` |
| Password | 见 `server/.env``PASSWORD` 字段 |
> ⚠️ 安全提醒:密码禁止硬编码到代码或文档中,统一从 `.env` 读取。命令行查询时避免 `-p"密码"` 方式(会暴露在进程列表),改用交互式输入:
>
> ```bash
> mysql -h 95.40.220.223 -P 3300 -u sbnews -p sbnews -e "SELECT ..."
> # 回车后输入密码
> ```
## 代码修改后验证与评审
仅在用户明确要求验证、测试或构建时,代码修改完成后按改动类型选择验证方式;未明确要求时只列出建议命令,不自动执行:
### 后端接口修改
1. PHP 语法检查:`php -l <modified_file.php>`
2. 涉及接口时确认控制器、逻辑层、验证器、列表类、模型字段一致。
3. 涉及数据库字段时确认表结构、索引、字典或配置存在。
4. 检查前端调用方是否需要同步更新。
### 前端页面修改
1. 检查接口请求模块、页面路由、组件引用是否一致。
2. 新增 uniapp 页面必须检查 `pages.json`
3. 涉及条件编译时确认 H5/App/小程序差异。
4. 检查控制台、网络请求和页面渲染问题。
### 通用代码评审清单
| 序号 | 检查项 | 说明 |
| --- | --- | --- |
| 1 | 改动范围 | 确认改动文件列表,是否有遗漏或多余文件 |
| 2 | 跨文件依赖 | 修改 model/controller/API 后,检查引用方是否同步 |
| 3 | 硬编码检查 | 业务枚举、分类、状态优先走字典或配置 |
| 4 | 未使用引入 | 检查多余 import/use |
| 5 | 命名一致性 | 字段、方法、路由命名与现有风格一致 |
| 6 | 安全性 | SQL 拼接、用户输入、权限校验是否安全 |
| 7 | 幂等性 | SQL 初始化必须可重复执行 |
| 8 | 文档同步 | 功能完成后更新 `docs/业务进度管理.md` |
## 服务器源码变更后必须同步
- 每次修改 `server/` 下的真实运行源码或运行配置后,完成必要的静态检查后必须先创建 Git commit,再将代码同步到测试服;这是一项持续授权,不需要用户重复要求。
- 使用项目部署脚本并保留 `-Sudo` 参数,目标目录固定为 `/www/wwwroot/test-server.sbnews.net`,避免 Docker 创建的 root 权限文件中断更新。
- 默认使用以下命令将最新代码更新到测试服运行环境:
```powershell
Set-Location D:\www\gs-sport-era; powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /www/wwwroot/test-server.sbnews.net
```
- `admin/``uniapp/``pc/``docker/``python/``qa/``scripts/` 等非 `server/` 源码改动必须提交 commit,但不要因此自动同步服务器。`docs/` 等说明文档不触发自动提交或服务器同步。
## 测试环境命令与 Docker 运行清单
### Git 同步
在服务器以 `ubuntu` 用户执行日常 Git 操作;只有 Docker 命令使用 `sudo`
```bash
cd /www/wwwroot/test-server.sbnews.net
git remote -v
git fetch origin dev.1.0.0
git pull --ff-only
```
如果 `.git/objects` 权限异常,只修复 Git 元数据,不要递归修改整个项目:
```bash
sudo chown -R ubuntu:ubuntu .git
sudo chmod -R u+rwX .git
```
如果 `.playwright-mcp/*` 等未跟踪生成文件阻塞拉取,先移动到临时目录,再执行 `git pull --ff-only`
```bash
backup="/tmp/sport-era-playwright-$(date +%Y%m%d%H%M%S)"
mv .playwright-mcp "$backup"
git pull --ff-only
```
工作区存在历史改动时,可只同步指定运行文件,避免覆盖其它现场文件:
```bash
git fetch origin dev.1.0.0
git checkout -f origin/dev.1.0.0 -- docker/docker-compose.dev.yml docker/docker-compose.crawler.yml docker/crawler
```
### Compose 操作
```bash
cd /www/wwwroot/test-server.sbnews.net/docker
# 检查配置,不启动服务
sudo docker compose -f docker-compose.dev.yml config -q
sudo docker compose -f docker-compose.crawler.yml config -q
# PHP/前端/开发 crawler 环境
sudo docker compose -f docker-compose.dev.yml ps
sudo docker compose -f docker-compose.dev.yml build crawler
sudo docker compose -f docker-compose.dev.yml up -d --no-build --force-recreate --no-deps crawler
# 知识库 worker:依赖、Dockerfile 或 kb_worker.py 变化后必须重建
sudo docker compose -f docker-compose.crawler.yml build kb-worker
sudo docker compose -f docker-compose.crawler.yml up -d --no-build --force-recreate --no-deps kb-worker
sudo docker compose -f docker-compose.crawler.yml ps kb-worker
sudo docker logs --tail 100 sport-era-kb-worker
```
### 当前容器职责
| 容器/服务 | 作用 | 网络与端口 |
| --- | --- | --- |
| `sport-era-dev-server-1` | PHP ThinkPHP API | host networkDocker Nginx 对外 `8000` |
| `sport-era-dev-scheduler-1` | 每分钟执行 `php think crontab` | host network |
| `sport-era-crawler` | Python 爬虫与容器 cron | host network,共用 crawler `logs/data` |
| `sport-era-kb-worker` | 消费 Redis Stream,生成 Embedding,写入 AI 知识库 | host networkRedis Stream `ai:kb:sync:stream` |
| `sport-era-dev-nginx-1` | Docker 内 Nginx/PHP-FPM 反代 | host network,监听 `8000` |
| `sport-era-dev-admin-1` | Admin Vite 开发服务器 | `5176` |
| `sport-era-dev-uniapp-h5-1` | uni-app H5 Vite 开发服务器 | `5177` |
当前 Compose 不启动 MySQL/Redis 容器,使用测试服外部 MySQL `3300` 和 Redis `6377`;私有连接参数只放在 `docker/.env.server``docker/.env.docker`
### 宿主机 Nginx 与访问验证
修改三个测试域名反代后执行:
```bash
sudo nginx -t
sudo systemctl reload nginx
curl -kI https://test-admin.sbnews.net/
curl -kI https://testh5.sbnews.net/
curl -kI https://test-server.sbnews.net/api/index/config
```
域名映射为:Admin → `5176`H5 → `5177`Server/API → `8000`。Admin/H5 当前是 Vite 开发模式,首屏慢时优先检查 Vite 模块转换;需要稳定快速访问时改用生产构建并由 Nginx 托管静态资源。
## 设计稿映射
设计稿与页面/组件映射统一维护在:
- [设计稿映射.md](./docs/设计稿映射.md)
开发或还原视觉前,先确认设计稿名称、页面路径、实现状态与备注。
## 业务进度管理
当前业务进度、待办事项、避坑记录统一维护在:
- [业务进度管理.md](./docs/业务进度管理.md)
开发或接手任务前,先查看该文档确认已完成事项、进行中事项、待办事项与避坑记录。
## 近期交接总结
- 当前真实开发目录以 `D:\www\gs-sport-era` 为准;Codex worktree(如 `C:\Users\Administrator\.codex\worktrees\...\gs-sport-era`)中的改动不会自动进入真实仓库、`git log` 或服务器运行目录。涉及可部署代码时,先确认改动已经同步到真实目录并形成清晰提交。
- 正确的服务器运行目录是 `/www/wwwroot/test-server.sbnews.net``/www/wwwroot/api.sbnews.net` 不是当前项目的有效同步目录,不要再部署到该路径。排查“代码已更新但服务器没生效”时,本地真实仓库看 `git log`,服务器侧看文件内容、修改时间、容器内 `/app` 文件与定时任务日志。
- Docker crawler 任务真实执行入口是 `sport-era-crawler` 容器。更新 `docker/crawler` 源码或 `config/crawler_tasks.yaml` 后,必须在服务器 `docker` 目录执行 `sudo docker compose -f docker-compose.crawler.yml build crawler``sudo docker compose -f docker-compose.crawler.yml up -d --no-deps crawler`;仅重启旧容器不能保证镜像内代码更新,必要时使用 `--no-cache` 重建。
- 重启 crawler 后必须核验容器内代码和 cron,而不是只看宿主机源码:例如检查 `/app/match_live_stream.py``/app/config/crawler_tasks.yaml`,以及 `cat /etc/cron.d/* | grep match_live_stream`
- 雨燕直播间任务 `match_live_stream` 当前应直接同步 `all_live_rooms.json`,写入主播 `anchor_id``anchor_name``anchor_avatar``anchor_level` 以及直播间观看/关注/公告/简介字段;对应 SQL 为 `docs/sql/alter_match_live_anchor_fields.sql``docs/sql/insert_crontab_match_live_stream.sql`。上线后用 `la_match_live` 主播字段统计和 `la_crawler_task_log` 最近任务状态共同确认是否生效。
- 测试服当前使用 Git 分支 `dev.1.0.0`,真实目录为 `/www/wwwroot/test-server.sbnews.net`。同步前先确认远端 `origin`、分支和工作区状态;不要在服务器上用 root 执行日常 `git pull`,否则可能让 `.git/objects` 出现 root/www/ubuntu 混合权限。
- 测试环境域名反代关系:`test-admin.sbnews.net` → 宿主机 `5176`Admin Vite)、`testh5.sbnews.net``5177`uni-app H5 Vite)、`test-server.sbnews.net``8000`Docker Nginx/PHP API)。宿主机 Nginx 配置位于 `/www/server/panel/vhost/nginx/` 和对应 `rewrite/` 目录,修改后必须执行 `sudo nginx -t && sudo systemctl reload nginx`
- `docker/docker-compose.dev.yml` 当前包含 `crawler` 服务;PHP、scheduler、crawler、Docker Nginx 使用 host network 访问测试服 MySQL/Redis。测试服私有 `docker/.env.server``docker/.env.docker` 不入库,数据库/Redis 密码不得写入 Git。
- `sport-era-kb-worker` 使用 `docker/docker-compose.crawler.yml`,通过 Redis Stream `ai:kb:sync:stream` 消费知识库任务并生成 Embedding,写入 `la_ai_kb_document`/`la_ai_kb_chunk`。测试账号仅授权 `127.0.0.1` 时,worker 必须使用 host networkcrawler 镜像需要 `cryptography` 才能连接 MySQL `caching_sha2_password` 认证。
## 近期踩坑
- `Validate::only()` 只限制校验字段范围,不会自动过滤请求参数;新增字段落库前,要同时检查 validate、logic、model、保存白名单和数据库列是否同步。
- `adminapi/match.match/edit` 写入失败时,先查测试库或线上库表结构,确认 `la_match` 已补齐对应字段,不要只盯业务代码。
- 世界杯专题页、比赛详情页这类前后端联动改动,要统一入口显示规则和跳转目标,避免只改一处导致入口不一致。
- 构建产生的 `server/public/admin``server/public/mobile` 等产物不要混进提交,提交前先清理临时截图和生成文件。
- **uni-app iOS 端 scroll-view+JS 计算高度 间隙问题**:在 iOSAPP-PLUS/MP)端,通过 `uni.createSelectorQuery()` 计算 `windowHeight - topBar - inputBar` 然后设置 `scroll-view` 的 inline `height` 会因安全区域、设备像素比等因素产生几像素偏差,导致 `scroll-view` 底部与固定输入栏之间出现间隙。**正确做法**:页面使用 `height: 100vh; display: flex; flex-direction: column`topbar 和 input-bar 设 `flex-shrink: 0`scroll-view 设 `flex: 1; min-height: 0` 自然填满剩余空间,不再用 JS 计算高度。
- **Vue3 `<script setup>``defineEmits``defineProps` 返回值必须赋值**`defineEmits(...)` 的返回值才是可调用的 emit 函数,直接写 `defineEmits([...])` 不赋值会导致 "Can't find variable: emit"`defineProps` 的返回值才能通过 `props.xxx` 访问属性,模板中自动解包但脚本中必须用 `props.xxx`
- **服务器 Git 权限**:如果 `git pull``insufficient permission for adding an object to repository database .git/objects`,通常是之前用 `sudo git` 造成 `.git` 混合所有者。只修复 Git 元数据:`sudo chown -R ubuntu:ubuntu .git && sudo chmod -R u+rwX .git`,不要对整个项目目录递归改所有者。
- **服务器 Git 拉取被未跟踪文件阻塞**:如果提示 `.playwright-mcp/* would be overwritten by merge`,这些是浏览器检查生成物。先把明确目录移到 `/tmp` 备份或删除,再执行 `git pull --ff-only`;不要使用无范围的 `git clean -fd`
- **测试域名首屏慢的根因**Admin/H5 当前是 Vite 开发服务器,首轮按需转换大量模块,浏览器首屏可能需要 20–40 秒;宿主机 Nginx 反代本身约几百毫秒。需要快速访问时应构建生产静态资源并由 Nginx 直接托管,但这会改变频繁改代码的即时生效方式。
- **uni-app H5 API 地址**H5 浏览器不能请求 `http://127.0.0.1:8000`,这会被浏览器当作用户本机回环地址并触发 CORS/Private Network 拦截。测试域名应使用 `https://test-server.sbnews.net/` 或同域反代路径;修改后需重启/刷新 H5 Vite 服务。