Переглянути джерело

sync: merge E2E test stash from cfclub branch (AGENTS.md, package-lock, test report)

Sisyphus Agent 2 місяців тому
батько
коміт
22081f1f02
5 змінених файлів з 1013 додано та 65 видалено
  1. 145 1
      AGENTS.md
  2. 816 25
      cfc-frontend/package-lock.json
  3. 14 2
      cfc-frontend/package.json
  4. 0 4
      opencode.jsonc
  5. 38 33
      tests/TEST-RESULTS-v3.md

+ 145 - 1
AGENTS.md

@@ -36,7 +36,151 @@
 | `cfc-web/` | Vue 2 + Element UI 管理端 | 8082 |
 | `dan/danshop/` | 独立商城 Spring Boot | 8888 |
 
-## 常用命令
+- **接口:** 统一 `@PostMapping`,禁止 `@GetMapping/@PutMapping/@DeleteMapping`
+- **ORM:** MyBatis-Plus `@TableName` + `@TableId(type = IdType.AUTO)`
+- **响应:** 统一 `Result<T>` (code/message/data)
+- **认证:** JWT Bearer Token,`Authorization` Header;`JwtInterceptor` 拦截 `/api/**`(8个公开路径除外)
+- **DI:** `@Resource` 替代 `@Autowired`,字段名匹配默认 Bean Name
+- **角色控制:** 控制器内手动检查 `@RequestAttribute("role")`
+- **小程序限制:** 禁止可选链 `?.`(用 `&&` 替代)、禁止 CSS Grid(用 flexbox)
+- **新增Controller/Service:** 检查类名是否与其他包重名(Spring Bean Name 冲突)
+- **新增路由:** 运行 `grep -rn '@Mapping' cfc-backend/src/.../controller/ | grep -oP '@\w+Mapping\("\K[^"]*' | sort -u` 检查重复
+
+## UNIQUE STYLES
+
+- **双角色:** 家长端可切换查看孩子视角;直接登录的孩子端不能切换到家长端
+- **成长规划师:** `role=teacher`,可登录规划师端,也可切换回家长视角
+- **五维能量:** 身/心/智/行/富维度体系,能量按比例分配
+- **测评订单:** 家长申请 → 选择规划师 → 孩子快照 → 支付 → 规划师录入结果
+- **四级地址:** 省市区街道,区域回退匹配
+- **多数据源:** cfc 主库 + sfms 只读源(`SfmsDataSourceConfig`)
+- **环境自适应:** 小程序 `config.js` 通过 `uni.getAccountInfoSync()` 自动切换 develop/trial/release 的 API 地址
+- **测试模式:** `wechat.test-mode: true` 跳过微信 API,使用模拟数据
+
+## cfclub 新特性
+
+- 家庭邀请二维码(小程序码+令牌+落地页)
+- 健康报告 PDF 上传与解析
+- 文章发布-审核系统
+- 饮食推荐系统(前端+后端)
+- 维度配置与知识库管理(Web管理端)
+- 家庭关系图重设计
+- 成长记录重构
+- Dify AI 对话集成
+- 家庭成员关系编辑(前端:RelationshipPicker + family-members 编辑弹窗)
+- 关系类型 CRUD 管理(Web管理端 RelationshipTypes.vue)
+- 联系人管理(ContactCard, ContactImport, contact-detail)
+
+## 微信公众号文章发布
+
+稳定发布脚本: `C:\code\cfc\publish_v11_stable.py`
+
+**发布流程**:
+1. `GET /cgi-bin/token` 获取 access_token
+2. `POST /cgi-bin/material/add_material type=thumb` 上传封面 → thumb_media_id
+3. `POST /cgi-bin/media/uploadimg` 上传内容图片 → URL
+4. `POST /cgi-bin/draft/add` 创建草稿(content字段填完整HTML)
+
+**API关键参数**:
+| 字段 | 限制 |
+|------|------|
+| title | ≤32字符,建议≤30字节(约10个中文)|
+| content | <1MB,<2万字符,HTML标签 |
+| thumb_media_id | 必须来自 material/add_material type=thumb |
+| content内图片URL | 必须来自 media/uploadimg,外部URL被过滤 |
+
+**HTML注意事项**:
+- 单引号属性: `<img src='url' style='width:100%' />`
+- 不支持: JS, 复杂div/CSS, 双引号属性
+- WeChat会用自己的样式渲染,基本CSS会被保留
+
+**封面图片生成**:
+- 模型: `agnes-image-2.0-flash`(通过 Agnes AI API: `https://apihub.agnes-ai.com/v1/images/generations`)
+- 认证: Bearer token(见 `opencode.json` 配置)
+- 尺寸: `1024x1024`
+- 出图后下载至 `C:\Users\Administrator\Documents\双培强基工程\images\cover_33_v11_case_study.png`
+- 封面风格要求: 温暖、简约、留白充足(右侧/下方供文字叠加)、无需文字、适合家庭教育主题
+  - 示例 prompt: `"A warm summer scene with a mother and child silhouette sitting together on a bench under a tree, soft golden sunlight filtering through leaves, warm orange and gold tones, peaceful and emotional atmosphere. Minimalist composition with lots of negative space on the right and bottom for text overlay. Chinese parenting theme. No text in image. 1024x1024 pixels."`
+- 调用方式: POST 请求,model=`agnes-image-2.0-flash`,返回 JSON 中含 `data[0].url`
+
+**稳定脚本用法**:
+```bash
+python C:\code\cfc\publish_v11_stable.py
+```
+
+脚本会输出media_id,登录 `mp.weixin.qq.com` → 草稿箱查看和发布。
+
+## 公众号内容编写规范(案例研究型内容)
+
+### 核心观点:案例研究 > 纯干货
+
+纯干货内容难以转化客户,因为缺乏说服力。**案例研究**通过"证明能力"大幅提升转化率:
+- 基于**社会认同心理**:相似问题被解决 → 信任建立 → 成交
+- 客户质量高、成交率高
+- 代价:初始流量可能低于泛内容
+
+### 常见误区(必须避免)
+
+| 误区 | 问题 | 后果 |
+|------|------|------|
+| 用别人的案例(名人/网红) | 不是你的真实客户 | 无法证明你的能力 |
+| 只写结果不写过程 | 缺乏"从零到一"的路径 | 读者无法复制 |
+| 成功不是在你帮助下达成 | 无代入感 | 转化失败 |
+
+### 三步法:高转化案例研究
+
+**第一步:聚焦真实成果**
+- 必须是你**亲自完成**或**在你的帮助下**客户取得的成果
+- 禁止使用名人案例(只适合引流,不适合转化)
+- 数据来源:报告、截图、真实反馈
+
+**第二步:鲜明的前后对比**
+- 合作前状态(如:自驱力评分 4.07/10)
+- 合作后具体结果(如:自驱力提升至 5.30/10)
+- 真实描述转变过程,避免夸大
+
+**第三步:拆解问题解决过程**
+按以下框架叙述:
+1. **核心问题**:客户当时面临什么挑战?
+2. **解决方案**:你采取了什么具体行动?
+3. **经验提炼**:可供读者借鉴的教训或行动指南
+
+### 文章结构模板
+
+```
+开头:描述一个典型场景/痛点(让读者代入)
+↓
+案例引入:用真实数据/截图展示结果
+↓
+问题分析:解释为什么这个问题值得解决
+↓
+解决方案:描述你的具体方法
+↓
+经验总结:提炼可复制的规律
+↓
+结尾:呼吁行动(咨询/购买/关注)
+```
+
+### 数据与截图要求
+
+- **脱敏**:姓名→化名(如"小李"),日期→模糊(如"三个月前"),学校→不提及
+- **截图**:报告中关键数据页面,敏感信息打码
+- **数据引用**:注明来源(如"A2核心素养评估报告")
+
+### 案例库与素材库
+
+- 案例库:`C:\Users\Administrator\Documents\双培强基工程\`
+- 报告截图:`temp_images\{学生姓名}\desensitized\`
+- 文章素材:`articles\v11_case_study.md`
+
+### 禁忌清单
+
+- ❌ 使用非客户案例(名人、竞争对手)
+- ❌ 虚构或夸大成果数据
+- ❌ 暴露客户隐私(姓名/学校/家庭住址)
+- ❌ 缺少具体转变过程的描述
+
+## COMMANDS
 
 ```bash
 # 后端

Різницю між файлами не показано, бо вона завелика
+ 816 - 25
cfc-frontend/package-lock.json


+ 14 - 2
cfc-frontend/package.json

@@ -7,14 +7,26 @@
   "scripts": {
     "test": "jest",
     "test:coverage": "jest --coverage",
-    "dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-dev:h5",
-    "build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build:h5",
+    "dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 UNI_INPUT_DIR=. UNI_CLI_CONTEXT=. vue-cli-service uni-serve",
+    "build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 UNI_INPUT_DIR=. UNI_CLI_CONTEXT=. vue-cli-service uni-build",
     "postbuild": "node -e \"try{require('fs').unlinkSync('dist/dev/mp-weixin/custom-tab-bar/index.vue')}catch(e){};try{const c=require('./dist/dev/mp-weixin/project.config.json');c.setting=c.setting||{};c.setting.lazyCodeLoading='requiredComponents';require('fs').writeFileSync('./dist/dev/mp-weixin/project.config.json',JSON.stringify(c,null,2))}catch(e){}\""
   },
   "devDependencies": {
     "@babel/core": "^7.29.7",
     "@babel/preset-env": "^7.29.7",
+    "@dcloudio/uni-app": "^2.0.2-5010420260703001",
+    "@dcloudio/uni-cli-i18n": "^2.0.2-5010420260703001",
+    "@dcloudio/uni-cli-shared": "^2.0.2-5010420260703001",
+    "@dcloudio/uni-h5": "^2.0.2-5010420260703001",
+    "@dcloudio/uni-i18n": "^2.0.2-5010420260703001",
+    "@dcloudio/uni-migration": "^2.0.2-5010420260703001",
+    "@dcloudio/uni-mp-weixin": "^2.0.2-5010420260703001",
+    "@dcloudio/uni-template-compiler": "^2.0.2-5010420260703001",
+    "@dcloudio/webpack-uni-pages-loader": "^2.0.2-5010420260703001",
+    "@vue/cli-plugin-babel": "^5.0.9",
+    "@vue/cli-service": "^5.0.9",
     "babel-jest": "^26.6.3",
+    "copy-webpack-plugin": "^14.0.0",
     "jest": "^26.6.3",
     "vue": "^2.7.16",
     "vuex": "^3.6.2"

+ 0 - 4
opencode.jsonc

@@ -1,4 +0,0 @@
-{
-  "$schema": "https://opencode.ai/config.json",
-  "lsp": true
-}

+ 38 - 33
tests/TEST-RESULTS-v3.md

@@ -1,45 +1,50 @@
-# API 测试报告 v3 — 2026/7/3 08:02:37
+# API 测试报告 v3 — 2026/7/3 09:52:48
 
 | 结果 | 数量 |
 |------|------|
-| ✅ PASS | 0 |
-| ❌ FAIL | 3 |
-| ⏭️ SKIP | 9 |
-| 总计 | 12 |
+| ✅ PASS | 13 |
+| ❌ FAIL | 10 |
+| ⏭️ SKIP | 1 |
+| 总计 | 24 |
 
 ## FAIL 明细
 
-- **Admin登录**: raw: <html>
-<head><title>502 Bad Gateway</title></head>
-<body>
-<center><h1>502 Bad Gateway</h1></center>
-<hr><center>openresty</center>
-</body>
-</html>
-
-- **文章列表(公开)**: code=undefined
-- **活动列表(公开)**: status=502
+- **NEW-01 创建能量规则**: code=undefined msg=
+- **NEW-02 SKU列表**: code=undefined msg=
+- **创建测试活动**: code=undefined msg=
+- **ISSUE-001 供应商下架商品**: code=401 msg=????
+- **ISSUE-002 文章发布**: code=undefined msg=
+- **energy.grantEnergy**: code=undefined msg=
+- **energy.deductForWish**: code=undefined msg=
+- **points.checkAndGrantReward**: code=undefined msg=
+- **points.deductForWish**: code=undefined msg=
+- **growth.getRecordsByChild**: code=undefined msg=
 
 ## 完整结果
 
 | 用例 | 结果 | 详情 |
 |------|------|------|
-| Admin登录 | FAIL | raw: <html>
-<head><title>502 Bad Gateway</title></head>
-<body>
-<center><h1>502 Bad Gateway</h1></center>
-<hr><center>openresty</center>
-</body>
-</html>
- |
+| Admin登录 | PASS | userId=7 |
 | Parent登录(手机验证码) | SKIP | 测试环境无法发短信,parent端需手动测试 |
-| 文章列表(公开) | FAIL | code=undefined |
-| 活动列表(公开) | FAIL | status=502 |
-| NEW-01 能量规则创建 | SKIP | 无admin token |
-| NEW-02 SKU列表 | SKIP | 无admin token |
-| NEW-03 活动发布 | SKIP | 无admin token |
-| ISSUE-001 供应商下架 | SKIP | 无admin token |
-| ISSUE-002/003 | SKIP | 无admin token |
-| 能量规则维度查询 | SKIP | 无admin token |
-| 后台管理核心接口 | SKIP | 无admin token |
-| 新增API测试 | SKIP | 无admin token |
+| 文章列表(公开) | PASS | ok |
+| 活动列表(公开) | PASS | ok |
+| 能量维度列表 | PASS | count=5 |
+| NEW-01 创建能量规则 | FAIL | code=undefined msg= |
+| NEW-02 SKU列表 | FAIL | code=undefined msg= |
+| 创建测试活动 | FAIL | code=undefined msg= |
+| 审核供应商81069 | PASS | approved |
+| 审核商品7 | PASS | approved |
+| 上架商品7 | PASS | on_shelf |
+| ISSUE-001 供应商下架商品 | FAIL | code=401 msg=???? |
+| ISSUE-003 创建用户 | PASS | userId=81186 ✅ ISSUE-003稳定 |
+| ISSUE-002 文章发布 | FAIL | code=undefined msg= |
+| 能量规则维度列表 | PASS | count=5 |
+| 用户列表 | PASS | ok |
+| 供应商列表 | PASS | ok |
+| 规划师申请列表 | PASS | pending=0 |
+| energy.grantEnergy | FAIL | code=undefined msg= |
+| energy.deductForWish | FAIL | code=undefined msg= |
+| points.checkAndGrantReward | FAIL | code=undefined msg= |
+| points.deductForWish | FAIL | code=undefined msg= |
+| growth.getRecordsByChild | FAIL | code=undefined msg= |
+| activity.end | PASS | ok |

Деякі файли не було показано, через те що забагато файлів було змінено