Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3addfafc0 | ||
|
|
1b4e69cd83 | ||
|
|
752ea4c54b | ||
|
|
1c0cf5204f | ||
|
|
583105e23a | ||
|
|
b39f5dfe58 | ||
|
|
cfe023aa2a | ||
|
|
2acc3acfb0 | ||
|
|
a7007916e1 | ||
|
|
c1e74d8e68 | ||
|
|
965ac7bc86 | ||
|
|
ac86ec57cf | ||
|
|
1418377b35 | ||
|
|
24f14c2841 | ||
|
|
35b6d76d50 | ||
|
|
ac696a8559 | ||
|
|
5905135258 | ||
|
|
ec56ae3286 | ||
|
|
1ad534c956 | ||
|
|
f9385cfc4c | ||
|
|
e87f96ab00 | ||
|
|
8d109cbc01 | ||
|
|
8e17762510 | ||
|
|
c84aeda062 | ||
|
|
6e5bbee71d | ||
|
|
d0cd7e4667 | ||
|
|
89af372416 | ||
|
|
451918bc73 | ||
|
|
a41e0ab0f7 | ||
|
|
c2420e7393 | ||
|
|
b5cd96f92b | ||
|
|
f9ae632f33 | ||
|
|
76ccb24679 | ||
|
|
434aa8c69d | ||
|
|
8592243d36 | ||
|
|
590eca8c22 | ||
|
|
788ee0c0c0 | ||
|
|
78de918c37 | ||
|
|
ae8b866319 |
327
.cursor/plans/fix_issues_0325-1_f8488785.plan.md
Normal file
@@ -0,0 +1,327 @@
|
||||
---
|
||||
name: Fix Issues 0325-1
|
||||
overview: 修复 UniApp 移动端前端(5 个 UI 问题)和 PHP 后端(7 个业务逻辑问题)共 12 个问题,涉及会员码图片、海报生成、账单筛选、导航、资产数据展示、佣金周期轮巡、积分奖励、分销等级升级和 e2e 验收测试。
|
||||
todos:
|
||||
- id: a1-member-code-image
|
||||
content: 修复会员码页面:小程序 image 标签加 v-if 防护,API 返回值兜底
|
||||
status: completed
|
||||
- id: a2-spread-poster
|
||||
content: 修复分销海报:downloadFilestoreImage 失败时 Promise 需 resolve/reject,增加错误处理
|
||||
status: completed
|
||||
- id: a3-bill-remove-queue-refund
|
||||
content: 账单明细页移除"公排退款"标签和筛选项
|
||||
status: completed
|
||||
- id: a4-queue-status-back-btn
|
||||
content: 佣金状态页左上角增加返回按钮(NavBar)
|
||||
status: completed
|
||||
- id: a5-assets-data-and-back
|
||||
content: 后端 HjfAssets 接口补充 total_points_earned 字段 + 资产页增加返回按钮
|
||||
status: completed
|
||||
- id: b1-commission-guard
|
||||
content: 增加校验:推荐人自己必须有报单订单才能获得推荐返现佣金
|
||||
status: completed
|
||||
- id: b2-points-pre-upgrade
|
||||
content: 升级为会员分销等级前,不给直推/伞下奖励积分
|
||||
status: completed
|
||||
- id: b3-points-by-qty
|
||||
content: 积分奖励按订单中报单商品数量(而非订单数)发放
|
||||
status: completed
|
||||
- id: b4-umbrella-points
|
||||
content: 修复伞下积分:创客无伞下积分,云店及以上才有伞下奖励积分,检查配置与级差逻辑
|
||||
status: completed
|
||||
- id: b5-upgrade-count
|
||||
content: 修复创客升级:getDirectQueueOrderCount 补充 refund_status 检查,核实任务配置
|
||||
status: completed
|
||||
- id: b6-cycle-race
|
||||
content: 修复推荐返现循环并发竞态:用数据库锁或原子计数器序列化位次计算
|
||||
status: completed
|
||||
- id: b7-e2e-verify
|
||||
content: e2e 测试验收分销员等级配置的奖励积分(直推/伞下)和等级升级任务是否正确
|
||||
status: completed
|
||||
isProject: false
|
||||
---
|
||||
|
||||
# 修复 docs/issues-0325-1.md 中的问题
|
||||
|
||||
## 第一部分:UniApp 移动端前端问题
|
||||
|
||||
所有前端文件位于 `pro_v3.5.1/view/uniapp/` 目录下。
|
||||
|
||||
---
|
||||
|
||||
### A1. 会员码页面图片报错 (pages/users/user_member_code/index.vue)
|
||||
|
||||
**问题反馈:** 前端页面报错 `Failed to load local image resource /pages/users/user_member_code/false`
|
||||
|
||||
**问题分析:** 小程序端 `<image :src="qrc">` 没有 `v-if` 防护。当 `activityCodeApi` 接口返回 `routineUrl: false`(布尔值)时,`this.qrc` 被赋值为 `false`,运行时将其字符串化为路径 `/pages/users/user_member_code/false`,导致图片加载 500 错误。
|
||||
|
||||
**代码定位:**
|
||||
|
||||
```17:18:pro_v3.5.1/view/uniapp/pages/users/user_member_code/index.vue
|
||||
<!-- #ifdef MP -->
|
||||
<image :src="qrc" class="qrcode"></image>
|
||||
```
|
||||
|
||||
以及 API 回调处(约第 135 行):
|
||||
|
||||
```javascript
|
||||
this.qrc = routineUrl; // routineUrl 可能为 false/null
|
||||
```
|
||||
|
||||
**修复方案:**
|
||||
|
||||
- 在小程序的 `<image>` 标签上添加 `v-if="qrc"`(第 18 行),与 H5 分支保持一致
|
||||
- 在 `activityCodeApi()` 中添加兜底:`this.qrc = routineUrl || ''`
|
||||
|
||||
---
|
||||
|
||||
### A2. 分销海报加载不出来 (pages/users/user_spread_code/index.vue)
|
||||
|
||||
**问题反馈:** 海报加载不出来
|
||||
|
||||
**问题分析:** `downloadFilestoreImage()`(约第 354 行)返回的 Promise 在下载失败时**既不 resolve 也不 reject**,只调用了 `Tips()`。这导致 `await` 永久挂起,阻塞了整个海报生成流程。
|
||||
|
||||
```363:366:pro_v3.5.1/view/uniapp/pages/users/user_spread_code/index.vue
|
||||
fail: function() {
|
||||
return that.$util.Tips({
|
||||
title: ''
|
||||
});
|
||||
```
|
||||
|
||||
**修复方案:**
|
||||
|
||||
- 在 `downloadFilestoreImage` 的 `fail` 回调中添加 `reject()`(或 `resolve('')`),让 Promise 正常结束
|
||||
- 在 `spreadMsg` 中,将下载后的图片路径传入 `userPosterCanvas` 前,增加空值/空字符串检查
|
||||
- 可选:在海报生成循环外包 try/catch,确保 `uni.hideLoading()` 始终执行
|
||||
|
||||
---
|
||||
|
||||
### A3. 账单明细页 — 移除"公排退款" (pages/users/user_bill/index.vue)
|
||||
|
||||
**问题反馈:** 去掉公排退款
|
||||
|
||||
**问题分析:** 导航栏有"公排退款"筛选标签,列表项中也显示"公排退款"标记。需要全部移除。
|
||||
|
||||
**修复方案:** 从模板中删除以下内容:
|
||||
|
||||
- 导航栏中 `queue_refund` 类型对应的 `<view>`(第 23-27 行)
|
||||
- 列表项中的 `<text v-if="vo.type === 'queue_refund'" ...>公排退款</text>` 标记(第 47-50 行)
|
||||
|
||||
---
|
||||
|
||||
### A4. 佣金状态页 — 增加返回按钮 (pages/queue/status.vue)
|
||||
|
||||
**问题反馈:** 左上角增加返回按钮
|
||||
|
||||
**问题分析:** 页面顶部没有 NavBar 和返回按钮。
|
||||
|
||||
**修复方案:** 参照其他页面的已有模式(如 `user_spread_user/index.vue`):
|
||||
|
||||
- 从 `@/components/NavBar.vue` 导入 `NavBar`(小程序条件编译)
|
||||
- 在 `components` 中注册
|
||||
- 在模板中添加 `<NavBar titleText="佣金状态" :iconColor="iconColor" :textColor="iconColor" showBack :isScrolling="isScrolling" />`,用 `<!-- #ifdef MP -->` 条件编译包裹
|
||||
- 添加对应的 data 属性(`iconColor`、`isScrolling`)和滚动事件处理
|
||||
|
||||
---
|
||||
|
||||
### A5. 资产页 — 数据不显示 + 增加返回按钮 (pages/assets/index.vue)
|
||||
|
||||
**问题反馈:**
|
||||
|
||||
1. "累计获得积分"不显示数据,是否没读取到数据?
|
||||
2. 左上角增加返回按钮
|
||||
|
||||
**问题 1 分析:** "累计获得积分"显示为 `NaN`。前端读取 `assetsInfo.total_points_earned`,但后端 `HjfAssets::overview` 接口未返回该字段。
|
||||
|
||||
- 前端计算属性(约第 148 行):`Number(this.assetsInfo.total_points_earned).toLocaleString()` => `NaN`
|
||||
- 后端响应([HjfAssets.php](pro_v3.5.1/app/controller/api/v1/hjf/HjfAssets.php) 第 42-50 行):仅返回 `frozen_points`、`available_points` 等,缺少 `total_points_earned`
|
||||
|
||||
**修复方案(后端):** 在 `HjfAssets::overview()` 的响应中增加 `total_points_earned` 字段。其值应为 `frozen_points + available_points`(累计获得 = 当前待释放 + 已释放):
|
||||
|
||||
```php
|
||||
'total_points_earned' => $frozenPoints + (int)($user['available_points'] ?? 0),
|
||||
```
|
||||
|
||||
**问题 2:** 左上角没有返回按钮(同 A4)。
|
||||
|
||||
**修复方案:** 按照 A4 相同的模式添加带 `showBack` 的 NavBar。
|
||||
|
||||
---
|
||||
|
||||
## 第二部分:后端业务逻辑问题
|
||||
|
||||
所有后端文件位于 `pro_v3.5.1/app/` 目录下。
|
||||
|
||||
---
|
||||
|
||||
### B1. 自己不报单,推荐没有返现佣金(测试问题 #1)
|
||||
|
||||
**问题反馈:** "自己不报单(没有购买过报单商品的订单),推荐没有返现佣金的"
|
||||
|
||||
**问题分析:** [StoreOrderCreateServices.php](pro_v3.5.1/app/services/order/StoreOrderCreateServices.php)(约第 998-1028 行)中的佣金周期逻辑在**被推荐人**下单报单商品时计算佣金,但没有校验**推荐人自己**是否也购买过报单商品。按业务规则,推荐人自己必须先报单(购买过报单商品),推荐下级报单才能获得返现佣金。
|
||||
|
||||
**修复方案:** 在 `computeOrderProductTruePrice` 中计算周期佣金之前(约第 1004 行),增加校验:若推荐人(`$spread_uid`)自己没有任何已支付的 `is_queue_goods=1` 订单,则跳过佣金计算(`$oneBrokerage = 0`)。或者在 `Pay.php::compute()` 中写入 `one_brokerage` 前做此校验。
|
||||
|
||||
---
|
||||
|
||||
### B2. 升级成为会员分销等级前,不给奖励积分(测试问题 #2)
|
||||
|
||||
**问题反馈:** "判断升级成为**会员分销等级**前,不给奖励积分(直推奖励积分、伞下奖励积分)"
|
||||
|
||||
**问题分析:** 在 [Pay.php](pro_v3.5.1/app/listener/order/Pay.php)(第 180-184 行)中,流程是:先检查升级、再发放积分。这意味着如果当前订单使推荐人从 grade 0 升级为创客,`reward()` 调用时已经看到了新等级,会在触发升级的同一笔订单上就发放**直推奖励积分**或**伞下奖励积分**。
|
||||
|
||||
根据 PRD,直推奖励积分和伞下奖励积分均应从推荐人**已成为会员分销等级之后**的订单才开始发放。触发升级的那笔订单本身不应给新升级的用户发积分。
|
||||
|
||||
**修复方案:** 在升级检查执行前,记录各上级用户的"升级前等级"快照,然后在 `reward()` 中使用**升级前的等级**判断是否有资格获得直推/伞下奖励积分。具体方式:
|
||||
|
||||
- 在 Pay.php 中 `checkUserLevelFinish` 之前,快照相关用户的 `agent_level`
|
||||
- 将升级前的等级信息传入 `reward()`,用于资格判断
|
||||
- 或者在 `reward()` 中检查用户的 `agent_level` 是否在同一事务/时间窗口内被更新,若是则跳过
|
||||
|
||||
---
|
||||
|
||||
### B3. 积分应按订单中报单商品数量发放,而非按订单数(测试问题 #3)
|
||||
|
||||
**问题反馈:** "目前积分奖励是按订单数量来给了,需要调整为按报单商品数量,比如一次性下一个订单含3个报单商品,应该给1500积分,而不是500"
|
||||
|
||||
**问题分析:** `PointsRewardServices::reward()` 每笔订单只调用一次,发放基于等级的固定积分(如创客 500 分)。若**一个订单内**包含 3 个报单商品(商品数量=3),应发放 3x500=1500 分,而非 500 分。
|
||||
|
||||
**修复方案:**
|
||||
|
||||
- 修改 `reward()` 增加 `$qty` 参数(默认为 1),表示该订单中报单商品的数量
|
||||
- 在 `grantFrozenPoints` 中将 `$points * $qty` 计算实际积分
|
||||
- 在 [Pay.php](pro_v3.5.1/app/listener/order/Pay.php)(第 184 行)中,从 `$orderInfo` 的购物车信息计算订单内报单商品数量(`is_queue_goods=1` 的商品 `cart_num` 之和),传入 `reward()`
|
||||
- 在 [HjfOrderPayJob.php](pro_v3.5.1/app/jobs/hjf/HjfOrderPayJob.php) 中做同样的修改
|
||||
|
||||
---
|
||||
|
||||
### B4. 伞下奖励积分规则:创客无伞下积分,云店及以上才有(测试问题 #4)
|
||||
|
||||
**问题反馈:** "创客级别的分销员,伞下下单没有**伞下奖励积分**,升级为云店级别分销员之后,只要级别低于自己的,伞下下单都应有**伞下奖励积分**"
|
||||
|
||||
**问题分析:** 按 PRD 各等级积分配置:
|
||||
|
||||
|
||||
| 等级 | 直推奖励积分 | 伞下奖励积分 |
|
||||
| --------------- | ------ | ------ |
|
||||
| 创客 | 500 | 0 |
|
||||
| 云店 | 800 | 300 |
|
||||
| 服务中心(原PRD名:服务商) | 1000 | 200 |
|
||||
| 合伙人(原PRD名:分公司) | 1300 | 300 |
|
||||
|
||||
|
||||
> **注意:** 数据库中等级名称已调整,"服务商"改为"服务中心","分公司"改为"合伙人"。后续代码及配置中以数据库实际名称为准。
|
||||
|
||||
创客的伞下奖励积分为 **0**,这是**正确的设计**(非 Bug)。问题焦点是:**云店及以上**级别的会员在伞下下单后应获得伞下奖励积分,但目前可能未正确发放。
|
||||
|
||||
在 [PointsRewardServices.php](pro_v3.5.1/app/services/hjf/PointsRewardServices.php) 第 109 行,级差逻辑 `$actual = max(0, $reward - $lowerReward)` 可能导致云店的伞下积分被下级已获得的奖励抵消为 0。
|
||||
|
||||
**修复方案:**
|
||||
|
||||
- 核查 `eb_agent_level` 表中各等级的 `umbrella_reward_points` 是否与 PRD 一致(创客=0、云店=300、服务中心=200、合伙人=300)
|
||||
- 确认 `AgentLevelServices` 的 `getUmbrellaRewardPoints()` 和 `getDirectRewardPoints()` 正确读取该字段并返回
|
||||
- 如果数据配置正确但云店仍未拿到伞下积分,检查级差计算中 `$lowerReward` 的传递链是否正确——特别注意当中间层(如创客)的伞下积分为 0 时,传给上级的 `$lowerReward` 应为 0,云店的 `$actual` 应为 `max(0, 300 - 0) = 300`
|
||||
- 若中间层是以**直推奖励积分**(500)作为 `$lowerReward` 传递的,则需修复 `propagateReward` 使其在递归中区分直推与伞下,确保向上传递的是**伞下**奖励而非直推奖励
|
||||
|
||||
---
|
||||
|
||||
### B5. 用户 ID=14 只有 2 单就升级为创客(测试问题 #5)
|
||||
|
||||
**问题反馈:** "用户ID=14直推了2单就升级成为创客的分销等级了,但是目前分销等级中创客的升级任务配置的是直推3单?"
|
||||
|
||||
**问题分析:** [AgentLevelTaskServices.php](pro_v3.5.1/app/services/agent/AgentLevelTaskServices.php)(第 431 行)中 `getDirectQueueOrderCount()` 统计推荐人直推下级的报单订单数。可能原因:
|
||||
|
||||
- 统计包含了已退款的订单(查询条件有 `is_del=0`,但缺少 `refund_status` 检查)
|
||||
- `no_assess=0` 过滤条件未正确生效
|
||||
- `eb_agent_level_task` 表中创客的任务 `number` 被配置为 2 而非 3
|
||||
- 竞态条件:并发订单处理可能触发两次升级检查
|
||||
|
||||
**修复方案:**
|
||||
|
||||
- 检查 `eb_agent_level_task` 表确认创客的任务配置为 `type=6`、`number=3`
|
||||
- 在 `getDirectQueueOrderCount` 查询中补充 `refund_status` 条件检查(目前缺失,而其他任务类型均有 `refund_status => [0, 3]` 的检查)
|
||||
- 在升级检查处增加日志,记录升级时刻的精确计数
|
||||
|
||||
---
|
||||
|
||||
### B6. 推荐返现循环两次都给了 20%(测试问题 #6)
|
||||
|
||||
**问题反馈:** "**推荐返现循环**目前配置的是'[20,30,50]'。为何用户ID=14直推了2单出现了2次20%的返现佣金?"
|
||||
|
||||
**问题分析:** 在 [StoreOrderCreateServices.php](pro_v3.5.1/app/services/order/StoreOrderCreateServices.php) 第 1009-1015 行,位次计算通过统计推荐人下级所有已支付的报单订单数来确定。若两笔订单几乎同时处理,两次 `compute()` 调用可能看到相同的 `completedCount`,导致位次相同(都得到 20%)。正确行为应是:第 1 单 20%、第 2 单 30%、第 3 单 50%,然后循环。
|
||||
|
||||
```1015:1015:pro_v3.5.1/app/services/order/StoreOrderCreateServices.php
|
||||
$position = max(0, $completedCount - 1) % $cycleCount;
|
||||
```
|
||||
|
||||
**修复方案:**
|
||||
|
||||
- 添加数据库级别的锁(如对 spread_uid 维度加 `SELECT ... FOR UPDATE`),序列化周期位次计算
|
||||
- 或者在用户表中增加显式周期计数器字段(如 `eb_user` 表添加 `brokerage_cycle_position` 列),原子递增,而非依赖 count 查询
|
||||
- 或者使用 `ORDER BY id ASC` 按订单排名确定位次,而非仅统计总数
|
||||
|
||||
---
|
||||
|
||||
### B7. e2e 测试验收分销员等级配置(测试问题 #7).
|
||||
|
||||
**问题反馈:** "e2e测试验收一下分销员等级中配置的奖励积分(直推奖励积分、伞下奖励积分)和等级任务是否正确?"
|
||||
|
||||
**问题分析:** 需要端到端验证 `eb_agent_level` 和 `eb_agent_level_task` 表中的数据配置与 PRD 一致。
|
||||
|
||||
**验收清单:**
|
||||
|
||||
**1) `eb_agent_level` 表 — 各等级奖励积分配置(PRD 3.2):**
|
||||
|
||||
|
||||
| 等级 | grade | direct_reward_points(直推) | umbrella_reward_points(伞下) |
|
||||
| ---- | ----- | ------------------------ | -------------------------- |
|
||||
| 创客 | 1 | 500 | 0 |
|
||||
| 云店 | 2 | 800 | 300 |
|
||||
| 服务中心 | 3 | 1000 | 200 |
|
||||
| 合伙人 | 4 | 1300 | 300 |
|
||||
|
||||
|
||||
**2) `eb_agent_level_task` 表 — 各等级升级任务配置(PRD 3.2):**
|
||||
|
||||
|
||||
| 等级 | 任务类型 type | 任务要求 number | 说明 |
|
||||
| ---- | --------- | ----------- | ---------- |
|
||||
| 创客 | 6(直推报单单数) | 3 | 直推满 3 单 |
|
||||
| 云店 | 7(伞下报单业绩) | 30 | 伞下满 30 单 |
|
||||
| 云店 | 8(最低直推人数) | 3 | 至少 3 个直推 |
|
||||
| 服务中心 | 7(伞下报单业绩) | 100 | 伞下满 100 单 |
|
||||
| 服务中心 | 8(最低直推人数) | 3 | 至少 3 个直推 |
|
||||
| 合伙人 | 7(伞下报单业绩) | 1000 | 伞下满 1000 单 |
|
||||
| 合伙人 | 8(最低直推人数) | 3 | 至少 3 个直推 |
|
||||
|
||||
|
||||
**3) 功能验证场景(手动或脚本):**
|
||||
|
||||
- 创客升级:模拟 3 笔直推报单订单,确认准确在第 3 笔时升级
|
||||
- 积分发放:确认创客直推积分 500/单、伞下积分 0;云店直推 800/单、伞下 300/单
|
||||
- 佣金轮巡:模拟 3 笔直推报单订单,确认佣金比例依次为 20%→30%→50%
|
||||
- 批量报单:一个订单含多个报单商品时,积分按商品数量乘算
|
||||
|
||||
**修复方案:** 编写 SQL 查询脚本或 PHP 命令行工具验证上述配置,不一致则修正数据。
|
||||
|
||||
---
|
||||
|
||||
## 文件修改汇总
|
||||
|
||||
|
||||
| 问题编号 | 主要需修改的文件 |
|
||||
| ---- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| A1 | `view/uniapp/pages/users/user_member_code/index.vue` |
|
||||
| A2 | `view/uniapp/pages/users/user_spread_code/index.vue` |
|
||||
| A3 | `view/uniapp/pages/users/user_bill/index.vue` |
|
||||
| A4 | `view/uniapp/pages/queue/status.vue` |
|
||||
| A5 | `view/uniapp/pages/assets/index.vue`、`app/controller/api/v1/hjf/HjfAssets.php` |
|
||||
| B1 | `app/services/order/StoreOrderCreateServices.php` 或 `app/listener/order/Pay.php` |
|
||||
| B2 | `app/listener/order/Pay.php`、`app/services/hjf/PointsRewardServices.php` |
|
||||
| B3 | `app/services/hjf/PointsRewardServices.php`、`app/listener/order/Pay.php`、`app/jobs/hjf/HjfOrderPayJob.php` |
|
||||
| B4 | `app/services/hjf/PointsRewardServices.php`,核查 `eb_agent_level` 数据 |
|
||||
| B5 | `app/services/agent/AgentLevelTaskServices.php`,核查 `eb_agent_level_task` 数据 |
|
||||
| B6 | `app/services/order/StoreOrderCreateServices.php` |
|
||||
| B7 | 验证脚本 / SQL 查询(验收 `eb_agent_level` + `eb_agent_level_task` 数据配置) |
|
||||
|
||||
|
||||
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.DS_Store
|
||||
.claude/
|
||||
BIN
CRMEB_Pro_UI图库/images/170*50px.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
CRMEB_Pro_UI图库/images/270*75px.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
CRMEB_Pro_UI图库/images/86*86px.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
CRMEB_Pro_UI图库/images/banner-001.jpg
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
CRMEB_Pro_UI图库/images/bg01.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
CRMEB_Pro_UI图库/images/bg1.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
CRMEB_Pro_UI图库/images/logo1.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
CRMEB_Pro_UI图库/images/logo2.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
CRMEB_Pro_UI图库/images/member1.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
CRMEB_Pro_UI图库/images/member2.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
CRMEB_Pro_UI图库/images/pic-001.jpg
Normal file
|
After Width: | Height: | Size: 295 KiB |
BIN
CRMEB_Pro_UI图库/images/pic-001.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
CRMEB_Pro_UI图库/images/pic-002.jpg
Normal file
|
After Width: | Height: | Size: 606 KiB |
BIN
CRMEB_Pro_UI图库/images/support.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
600
DEPLOY_PLAN.md
Normal file
@@ -0,0 +1,600 @@
|
||||
# 黄精粉健康商城二次开发发布部署方案
|
||||
|
||||
> **环境**:云服务器已运行原始 CRMEB Pro v3.5(Docker + Nginx + Swoole + Redis + MySQL 5.7)
|
||||
> **分支**:`claude/hjf-queue-admin-apis-hsymG`
|
||||
> **变更范围**:44个文件(后端PHP新增30个文件 + 修改3个 + 前端JS/Vue 11个)
|
||||
|
||||
---
|
||||
|
||||
## 一、环境确认(部署前检查)
|
||||
|
||||
### 1.1 服务器环境要求
|
||||
|
||||
| 项目 | 要求 | 确认方式 |
|
||||
|------|------|---------|
|
||||
| PHP | ≥ 8.0,扩展:bcmath、mbstring、redis、curl | `php -v && php -m` |
|
||||
| MySQL | ≥ 5.7(已兼容,8.0 同样支持) | `mysql --version` |
|
||||
| Redis | ≥ 5.0 | `redis-cli --version` |
|
||||
| Node.js | ≥ 14(编译 Admin 前端用) | `node -v` |
|
||||
| npm | ≥ 6 | `npm -v` |
|
||||
| Composer | ≥ 2 | `composer --version` |
|
||||
| Swoole | ≥ 4.8 | `php --ri swoole` |
|
||||
|
||||
### 1.2 目录结构确认
|
||||
|
||||
```
|
||||
/var/www/ # 项目根目录(Dockerfile WORKDIR)
|
||||
├── public/ # Nginx 静态文件根目录
|
||||
├── view/admin/dist/ # Admin 构建产物(已有)
|
||||
├── view/uniapp/ # UniApp 源码(H5 构建产物需放入 public/)
|
||||
└── .env # 生产环境配置(不可覆盖)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、部署前备份(强制执行)
|
||||
|
||||
### 2.1 备份数据库
|
||||
|
||||
```bash
|
||||
# 在服务器上执行
|
||||
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
|
||||
mysqldump -u root -p \
|
||||
--single-transaction \
|
||||
--routines \
|
||||
--triggers \
|
||||
crmeb_db > /backup/db_before_hjf_${BACKUP_DATE}.sql
|
||||
|
||||
echo "备份完成:/backup/db_before_hjf_${BACKUP_DATE}.sql"
|
||||
```
|
||||
|
||||
### 2.2 备份当前代码
|
||||
|
||||
```bash
|
||||
# 备份关键修改文件(仅涉及本次二次开发的文件)
|
||||
cd /var/www
|
||||
tar -czf /backup/code_before_hjf_${BACKUP_DATE}.tar.gz \
|
||||
app/listener/order/Pay.php \
|
||||
route/api.php \
|
||||
route/admin.php \
|
||||
config/console.php \
|
||||
view/admin/dist/
|
||||
```
|
||||
|
||||
> ⚠️ **回滚依赖此备份,务必确认备份文件大小 > 0**
|
||||
|
||||
---
|
||||
|
||||
## 三、代码同步
|
||||
|
||||
### 3.1 方案:Git Pull(推荐)
|
||||
|
||||
服务器上的代码仓库已关联 Git remote,直接拉取目标分支:
|
||||
|
||||
```bash
|
||||
cd /var/www
|
||||
|
||||
# 确认当前分支
|
||||
git status
|
||||
git branch
|
||||
|
||||
# 拉取最新代码
|
||||
git fetch origin claude/hjf-queue-admin-apis-hsymG
|
||||
git checkout claude/hjf-queue-admin-apis-hsymG
|
||||
git pull origin claude/hjf-queue-admin-apis-hsymG
|
||||
```
|
||||
|
||||
### 3.2 方案:rsync 上传(备选,服务器无 Git 时使用)
|
||||
|
||||
```bash
|
||||
# 在本地开发机执行
|
||||
rsync -avz --progress \
|
||||
--exclude='.git' \
|
||||
--exclude='vendor/' \
|
||||
--exclude='view/admin/node_modules/' \
|
||||
--exclude='view/uniapp/node_modules/' \
|
||||
--exclude='.env' \
|
||||
--exclude='runtime/' \
|
||||
--exclude='public/uploads/' \
|
||||
./pro_v3.5.1/ \
|
||||
user@your-server:/var/www/
|
||||
```
|
||||
|
||||
> ⚠️ 注意 `--exclude='.env'`,生产环境的 `.env` 不能被开发环境覆盖
|
||||
|
||||
### 3.3 验证变更文件(同步后确认)
|
||||
|
||||
```bash
|
||||
cd /var/www
|
||||
|
||||
# 确认以下新目录/文件存在
|
||||
ls app/controller/admin/v1/hjf/ # 应有 MemberController.php / QueueController.php / PointsController.php
|
||||
ls app/controller/api/v1/hjf/ # 应有 AssetsController.php / PointsController.php / QueueController.php
|
||||
ls app/services/hjf/ # 应有5个 Services 文件
|
||||
ls app/jobs/hjf/ # 应有4个 Job 文件
|
||||
ls database/hjf_migration.sql # 迁移脚本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、数据库迁移
|
||||
|
||||
> ⚠️ **在备份完成后、服务重启前执行,避免新代码访问不存在的表**
|
||||
|
||||
### 4.1 执行迁移脚本
|
||||
|
||||
```bash
|
||||
cd /var/www
|
||||
|
||||
# 执行迁移(脚本已做幂等处理,重复执行安全)
|
||||
mysql -u root -p crmeb_db < database/hjf_migration.sql
|
||||
```
|
||||
|
||||
### 4.2 验证迁移结果
|
||||
|
||||
```bash
|
||||
mysql -u root -p crmeb_db << 'SQL'
|
||||
-- 确认新表存在
|
||||
SELECT TABLE_NAME FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME IN ('eb_queue_pool', 'eb_points_release_log');
|
||||
|
||||
-- 确认 eb_user 新字段
|
||||
SELECT COLUMN_NAME FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_user'
|
||||
AND COLUMN_NAME IN ('member_level','no_assess','frozen_points','available_points');
|
||||
|
||||
-- 确认 eb_store_product 新字段
|
||||
SELECT COLUMN_NAME FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_store_product'
|
||||
AND COLUMN_NAME IN ('is_queue_goods','allow_pay_types');
|
||||
|
||||
-- 确认 eb_store_order 新字段
|
||||
SELECT COLUMN_NAME FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'eb_store_order'
|
||||
AND COLUMN_NAME = 'is_queue_goods';
|
||||
|
||||
-- 确认系统配置写入(应返回15行)
|
||||
SELECT menu_name, value FROM eb_system_config
|
||||
WHERE menu_name LIKE 'hjf_%' ORDER BY sort;
|
||||
SQL
|
||||
```
|
||||
|
||||
预期输出:
|
||||
- 2张新表存在
|
||||
- eb_user 4个新字段
|
||||
- eb_store_product 2个新字段
|
||||
- eb_store_order 1个新字段
|
||||
- 15条 hjf_ 配置记录
|
||||
|
||||
---
|
||||
|
||||
## 五、后端依赖更新
|
||||
|
||||
### 5.1 检查 composer.json 是否有新依赖
|
||||
|
||||
```bash
|
||||
cd /var/www
|
||||
# 本次二次开发未新增 composer 依赖,但确认执行一次 install 确保一致性
|
||||
composer install --no-dev --optimize-autoloader
|
||||
```
|
||||
|
||||
### 5.2 清除 ThinkPHP 缓存
|
||||
|
||||
```bash
|
||||
cd /var/www
|
||||
|
||||
# 清除路由缓存(新增了 hjf 路由,必须清除)
|
||||
php think clear:cache
|
||||
|
||||
# 手动清除 runtime 缓存目录
|
||||
rm -rf runtime/cache/*
|
||||
rm -rf runtime/temp/*
|
||||
|
||||
# 如果使用了路由缓存
|
||||
rm -f runtime/route.php
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、Admin 前端编译
|
||||
|
||||
Admin 前端新增了6个页面(公排/会员/积分管理)+ 3个 API 文件,需重新编译。
|
||||
|
||||
### 6.1 安装依赖并构建
|
||||
|
||||
```bash
|
||||
cd /var/www/view/admin
|
||||
|
||||
# 安装依赖(如 node_modules 已存在可跳过)
|
||||
npm install
|
||||
|
||||
# 生产编译
|
||||
npm run build
|
||||
```
|
||||
|
||||
编译产物输出到 `view/admin/dist/`
|
||||
|
||||
### 6.2 将构建产物部署到 Nginx 静态目录
|
||||
|
||||
```bash
|
||||
# 根据服务器实际配置,将 dist/ 内容同步到 Nginx 服务的目录
|
||||
# 如果 Nginx 直接指向 view/admin/dist/,则无需额外操作
|
||||
|
||||
# 若 Nginx 配置的静态目录是 /var/www/public/admin/
|
||||
cp -r /var/www/view/admin/dist/* /var/www/public/admin/
|
||||
```
|
||||
|
||||
> 具体路径以服务器 Nginx 配置中 `root` 指令为准。
|
||||
|
||||
---
|
||||
|
||||
## 七、UniApp H5 前端编译
|
||||
|
||||
UniApp 前端新增了约10个页面(公排/资产/积分/会员/引导),需重新编译 H5 版本。
|
||||
|
||||
### 方案 A:使用 HBuilderX(推荐,图形化操作)
|
||||
|
||||
1. 打开 HBuilderX,导入项目 `view/uniapp/`
|
||||
2. 菜单 → 发行 → 网站 PC-Web 或 H5(勾选 H5)
|
||||
3. 编译后将 `unpackage/dist/build/h5/` 内容上传到服务器 `public/` 对应目录
|
||||
|
||||
### 方案 B:使用 uni-app CLI(无图形界面服务器适用)
|
||||
|
||||
```bash
|
||||
# 安装 @dcloudio/vue-cli-plugin-uni(如已安装可跳过)
|
||||
cd /var/www/view/uniapp
|
||||
npm install
|
||||
|
||||
# 编译 H5
|
||||
npx vue-cli-service uni-build --platform h5
|
||||
|
||||
# 将产物部署到服务器 public 目录
|
||||
cp -r dist/build/h5/* /var/www/public/h5/
|
||||
```
|
||||
|
||||
> UniApp 小程序版本(微信/支付宝)需在对应开发者工具中重新上传,不在本次服务器部署范围内。
|
||||
|
||||
---
|
||||
|
||||
## 八、Swoole 服务重启
|
||||
|
||||
ThinkPHP + Swoole 需要重启才能加载新的 PHP 文件(PHP-Swoole 常驻内存,不像 PHP-FPM 每次请求重载)。
|
||||
|
||||
### 8.1 确认当前 Swoole 进程
|
||||
|
||||
```bash
|
||||
ps aux | grep "php think" | grep -v grep
|
||||
# 或
|
||||
ps aux | grep swoole | grep -v grep
|
||||
```
|
||||
|
||||
### 8.2 优雅重启(推荐,不中断现有连接)
|
||||
|
||||
```bash
|
||||
# 找到主进程 PID
|
||||
SWOOLE_PID=$(ps aux | grep "php think" | grep -v grep | awk '{print $2}' | head -1)
|
||||
|
||||
# 发送 USR1 信号优雅重启(仅适用于 Swoole Server 模式)
|
||||
kill -USR1 $SWOOLE_PID
|
||||
echo "已发送优雅重启信号,PID=${SWOOLE_PID}"
|
||||
```
|
||||
|
||||
### 8.3 完全重启(若优雅重启不生效)
|
||||
|
||||
```bash
|
||||
# Docker 环境
|
||||
docker restart crmeb-app # 容器名以实际为准
|
||||
# 或
|
||||
docker-compose restart app
|
||||
|
||||
# 非 Docker 环境
|
||||
cd /var/www
|
||||
php think stop # 停止 Swoole
|
||||
sleep 2
|
||||
php think start # 启动 Swoole
|
||||
```
|
||||
|
||||
### 8.4 验证服务启动
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:20199/api/ping
|
||||
# 预期:200 或 404(非 500/502 即表示服务正常运行)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、队列 Worker 重启
|
||||
|
||||
think-queue 的队列 Worker 也是常驻进程,新增的 `HjfOrderPayJob` 等 Job 类需要重启 Worker 才能加载。
|
||||
|
||||
### 9.1 确认当前 Worker 进程
|
||||
|
||||
```bash
|
||||
ps aux | grep "queue:work\|queue:listen" | grep -v grep
|
||||
```
|
||||
|
||||
### 9.2 重启 Worker
|
||||
|
||||
```bash
|
||||
# 停止现有 Worker(发送 SIGTERM 允许当前任务执行完毕)
|
||||
pkill -f "queue:work"
|
||||
pkill -f "queue:listen"
|
||||
|
||||
sleep 3 # 等待当前任务完成
|
||||
|
||||
# 重新启动 Worker(后台运行)
|
||||
cd /var/www
|
||||
nohup php think queue:work \
|
||||
--queue CRMEB_PRO \
|
||||
--tries 3 \
|
||||
--sleep 3 \
|
||||
>> /var/log/crmeb_queue.log 2>&1 &
|
||||
|
||||
# 如有批量队列,额外启动
|
||||
nohup php think queue:work \
|
||||
--queue CRMEB_PRO_BATCH \
|
||||
--tries 3 \
|
||||
--sleep 3 \
|
||||
>> /var/log/crmeb_queue_batch.log 2>&1 &
|
||||
|
||||
echo "Worker 已启动,PID: $!"
|
||||
```
|
||||
|
||||
### 9.3 建议使用 Supervisor 管理 Worker 进程
|
||||
|
||||
```ini
|
||||
; /etc/supervisor/conf.d/crmeb-queue.conf
|
||||
[program:crmeb-queue-main]
|
||||
command=php /var/www/think queue:work --queue=CRMEB_PRO --tries=3 --sleep=3
|
||||
directory=/var/www
|
||||
autostart=true
|
||||
autorestart=true
|
||||
user=www-data
|
||||
numprocs=2
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/var/log/supervisor/crmeb-queue.log
|
||||
|
||||
[program:crmeb-queue-batch]
|
||||
command=php /var/www/think queue:work --queue=CRMEB_PRO_BATCH --tries=3 --sleep=3
|
||||
directory=/var/www
|
||||
autostart=true
|
||||
autorestart=true
|
||||
user=www-data
|
||||
numprocs=1
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/var/log/supervisor/crmeb-queue-batch.log
|
||||
```
|
||||
|
||||
```bash
|
||||
supervisorctl reread && supervisorctl update
|
||||
supervisorctl restart crmeb-queue-main crmeb-queue-batch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、定时任务注册
|
||||
|
||||
新增的每日积分释放任务需要注册到 cron。
|
||||
|
||||
```bash
|
||||
# 编辑 crontab
|
||||
crontab -e
|
||||
|
||||
# 添加以下行(每天凌晨 00:01 执行)
|
||||
1 0 * * * cd /var/www && php think hjf:release-points >> /var/log/hjf_release.log 2>&1
|
||||
```
|
||||
|
||||
验证注册:
|
||||
|
||||
```bash
|
||||
crontab -l | grep hjf
|
||||
# 应输出刚刚添加的行
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十一、部署后冒烟验证
|
||||
|
||||
### 11.1 接口健康检查
|
||||
|
||||
```bash
|
||||
# 设置环境变量(替换为真实 token)
|
||||
export SERVER=https://your-domain.com
|
||||
export USER_TOKEN="Bearer <用户token>"
|
||||
export ADMIN_TOKEN="Bearer <管理员token>"
|
||||
|
||||
# 公排状态接口
|
||||
curl -H "Authorization: $USER_TOKEN" $SERVER/api/hjf/queue/status
|
||||
# 预期:{"status":200,"data":{...}}
|
||||
|
||||
# 资产总览接口
|
||||
curl -H "Authorization: $USER_TOKEN" $SERVER/api/hjf/assets/overview
|
||||
# 预期:{"status":200,"data":{"now_money":...,"frozen_points":...}}
|
||||
|
||||
# Admin 会员列表
|
||||
curl -H "Authorization: $ADMIN_TOKEN" $SERVER/adminapi/hjf/member/list
|
||||
# 预期:{"status":200,"data":{"list":[...],"count":...}}
|
||||
```
|
||||
|
||||
### 11.2 运行 PHPUnit 冒烟测试
|
||||
|
||||
```bash
|
||||
cd /var/www
|
||||
|
||||
# 设置环境变量
|
||||
export HJF_API_BASE="https://your-domain.com/api"
|
||||
export HJF_ADMIN_BASE="https://your-domain.com/adminapi"
|
||||
export HJF_TOKEN="<用户token>"
|
||||
export HJF_ADMIN_TOKEN="<管理员token>"
|
||||
|
||||
# 运行冒烟测试(跳过需要手动验证的 P4-05)
|
||||
./vendor/bin/phpunit tests/hjf/SmokeTest.php --verbose
|
||||
```
|
||||
|
||||
### 11.3 验证积分释放命令
|
||||
|
||||
```bash
|
||||
cd /var/www
|
||||
|
||||
# 手动触发一次积分释放,验证命令可运行
|
||||
php think hjf:release-points
|
||||
|
||||
# 预期输出:
|
||||
# [HjfReleasePoints] 开始执行积分释放...
|
||||
# [HjfReleasePoints] 完成:处理 X 人,共释放 X 积分,日期 2026-03-xx
|
||||
```
|
||||
|
||||
### 11.4 验证支付回调入口(P4-04)
|
||||
|
||||
```bash
|
||||
# 查看 Pay.php 已挂载
|
||||
grep -n "HjfOrderPayJob" /var/www/app/listener/order/Pay.php
|
||||
# 应输出包含 HjfOrderPayJob::dispatch 的行
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十二、回滚方案
|
||||
|
||||
若部署后出现问题,按以下顺序回滚:
|
||||
|
||||
### 12.1 代码回滚(5分钟内可完成)
|
||||
|
||||
```bash
|
||||
cd /var/www
|
||||
|
||||
# Git 回滚到上一个稳定版本
|
||||
git stash || git reset --hard HEAD~1
|
||||
|
||||
# 或直接还原备份
|
||||
tar -xzf /backup/code_before_hjf_${BACKUP_DATE}.tar.gz -C /var/www/
|
||||
```
|
||||
|
||||
### 12.2 数据库回滚
|
||||
|
||||
数据库新增的表和字段不影响原有功能运行,**非必要不需要回滚**。
|
||||
|
||||
若确需回滚(建议先尝试仅回滚代码):
|
||||
|
||||
```bash
|
||||
mysql -u root -p crmeb_db << 'SQL'
|
||||
-- 删除新表
|
||||
DROP TABLE IF EXISTS eb_queue_pool;
|
||||
DROP TABLE IF EXISTS eb_points_release_log;
|
||||
|
||||
-- 删除 eb_user 新字段
|
||||
ALTER TABLE eb_user
|
||||
DROP COLUMN IF EXISTS member_level,
|
||||
DROP COLUMN IF EXISTS no_assess,
|
||||
DROP COLUMN IF EXISTS frozen_points,
|
||||
DROP COLUMN IF EXISTS available_points;
|
||||
|
||||
-- 删除 eb_store_product 新字段
|
||||
ALTER TABLE eb_store_product
|
||||
DROP COLUMN IF EXISTS is_queue_goods,
|
||||
DROP COLUMN IF EXISTS allow_pay_types;
|
||||
|
||||
-- 删除 eb_store_order 新字段
|
||||
ALTER TABLE eb_store_order
|
||||
DROP COLUMN IF EXISTS is_queue_goods;
|
||||
|
||||
-- 删除系统配置
|
||||
DELETE FROM eb_system_config WHERE menu_name LIKE 'hjf_%';
|
||||
SQL
|
||||
```
|
||||
|
||||
### 12.3 重启服务(回滚后执行)
|
||||
|
||||
```bash
|
||||
# 重启 Swoole
|
||||
docker restart crmeb-app # 或 kill -USR1 + 重启
|
||||
|
||||
# 重启 Worker
|
||||
supervisorctl restart crmeb-queue-main crmeb-queue-batch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十三、部署检查清单
|
||||
|
||||
```
|
||||
部署前
|
||||
□ 数据库已备份(验证备份文件大小 > 0)
|
||||
□ 关键代码已备份(Pay.php / route/ / admin dist)
|
||||
□ 服务器 PHP/MySQL/Redis 版本确认符合要求
|
||||
|
||||
代码同步
|
||||
□ git pull 成功 / rsync 上传完成
|
||||
□ app/services/hjf/ 目录存在,含5个文件
|
||||
□ app/jobs/hjf/ 目录存在,含4个文件
|
||||
□ database/hjf_migration.sql 存在
|
||||
|
||||
数据库迁移
|
||||
□ hjf_migration.sql 执行无 ERROR
|
||||
□ eb_queue_pool 表存在
|
||||
□ eb_points_release_log 表存在
|
||||
□ eb_user.member_level 字段存在
|
||||
□ eb_store_order.is_queue_goods 字段存在
|
||||
□ eb_system_config 含15条 hjf_ 配置
|
||||
|
||||
后端部署
|
||||
□ composer install 成功
|
||||
□ php think clear:cache 执行
|
||||
□ runtime/cache/ 已清空
|
||||
□ Swoole 重启成功(http 200 响应)
|
||||
□ Queue Worker 重启成功
|
||||
|
||||
前端部署
|
||||
□ Admin npm run build 成功,dist/ 已更新
|
||||
□ UniApp H5 编译并部署到 public/
|
||||
|
||||
定时任务
|
||||
□ crontab 已添加 hjf:release-points(每日 00:01)
|
||||
|
||||
冒烟验证
|
||||
□ /api/hjf/queue/status 返回 200
|
||||
□ /api/hjf/assets/overview 返回 200
|
||||
□ /adminapi/hjf/member/list 返回 200
|
||||
□ php think hjf:release-points 命令可正常运行
|
||||
□ PHPUnit SmokeTest 通过(或仅 skip,无 FAIL)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 附录:变更文件清单(本次二次开发共44个文件)
|
||||
|
||||
### 后端新增文件(34个)
|
||||
|
||||
| 目录 | 文件 | 说明 |
|
||||
|------|------|------|
|
||||
| app/controller/api/v1/hjf/ | QueueController, PointsController, AssetsController | 用户端3个接口控制器 |
|
||||
| app/controller/admin/v1/hjf/ | QueueController, MemberController, PointsController | Admin端3个接口控制器 |
|
||||
| app/services/hjf/ | QueuePoolServices, PointsRewardServices, PointsReleaseServices, MemberLevelServices, HjfAssetsServices | 5个业务服务 |
|
||||
| app/jobs/hjf/ | HjfOrderPayJob, QueueRefundJob, PointsReleaseJob, MemberLevelCheckJob | 4个异步Job |
|
||||
| app/dao/hjf/ | QueuePoolDao, PointsReleaseLogDao | 2个DAO |
|
||||
| app/model/hjf/ | QueuePool, PointsReleaseLog | 2个Model |
|
||||
| app/command/ | HjfReleasePoints | 定时任务命令 |
|
||||
| database/ | hjf_migration.sql | 数据库迁移脚本 |
|
||||
| tests/hjf/ | 5个测试文件 | 单元测试+冒烟测试 |
|
||||
|
||||
### 后端修改文件(3个)
|
||||
|
||||
| 文件 | 修改内容 |
|
||||
|------|---------|
|
||||
| app/listener/order/Pay.php | 新增公排入队钩子(is_queue_goods=1 时派发 HjfOrderPayJob) |
|
||||
| route/api.php | 注册用户端 hjf 路由组 |
|
||||
| route/admin.php | 注册 Admin 端 hjf 路由组 |
|
||||
| config/console.php | 注册 hjf:release-points 命令 |
|
||||
|
||||
### 前端文件(11个)
|
||||
|
||||
| 文件 | 修改内容 |
|
||||
|------|---------|
|
||||
| view/uniapp/api/hjfQueue.js 等3个 | USE_MOCK → false |
|
||||
| view/admin/src/api/hjfQueue.js 等3个 | USE_MOCK → false |
|
||||
| view/uniapp/main.js | 注册 HjfMemberBadge 全局组件 |
|
||||
| view/uniapp/pages/goodList.vue | 公排商品角标 |
|
||||
| view/uniapp/pages/user/index.vue | 会员等级徽章 |
|
||||
| view/uniapp/pages/user_spread_money/index.vue | 积分替换佣金 |
|
||||
| view/uniapp/pages/*/(新增约10个页面) | 公排/资产/积分/引导页 |
|
||||
315
docs/PRD_fsgx_V1.0.md
Normal file
@@ -0,0 +1,315 @@
|
||||
# 范氏国香商城小程序 · 产品需求文档(PRD)V1.0
|
||||
|
||||
> 技术底座:CRMEB Pro v3.5 二次开发
|
||||
> 文档日期:2026-03-23
|
||||
> 文档状态:当前分支产品需求基线(对齐 fsgx 需求)
|
||||
|
||||
---
|
||||
|
||||
## 1. 文档说明
|
||||
|
||||
### 1.1 文档目的
|
||||
|
||||
本文档基于《范氏国香小程序fsgx-V1.0.docx》整理,定义范氏国香商城小程序(微信端 + 管理后台)的功能范围、核心业务逻辑、参数配置和交付验收标准,并明确当前分支与目标需求的差异,作为后续研发、测试与运营的统一依据。
|
||||
|
||||
### 1.2 文档范围
|
||||
|
||||
- 用户端(微信小程序)功能需求
|
||||
- 管理后台(PC端)功能需求
|
||||
- 核心业务逻辑(推荐返现、会员等级、积分释放)
|
||||
- 数据改造与非功能性要求
|
||||
- 当前版本不一致/不满足项清单
|
||||
|
||||
### 1.3 术语定义
|
||||
|
||||
| 术语 | 定义 |
|
||||
|---|---|
|
||||
| 报单商品 | 参与推荐奖励与等级业绩统计的商品,当前目标主商品为艾制品三条套餐(4333元/单) |
|
||||
| 普通商品 | 不参与推荐奖励的商品,可支持积分支付 |
|
||||
| 待释放积分 | 推荐奖励入账后冻结的积分,按日释放 |
|
||||
| 已释放积分 | 已完成释放、可消费的积分,仅可用于普通商品 |
|
||||
| 直推 | 用户直接邀请并绑定的一级成员 |
|
||||
| 伞下 | 用户的所有直推及其下级组成的推荐网络 |
|
||||
| 会员分销等级 | 创客、云店、服务中心、合伙人 |
|
||||
| 级差 | 上级可获得的奖励与下级当前等级奖励之间的差额机制 |
|
||||
| 推荐返现循环 | 邀请满 3 人按 20%/30%/50%返现,后续继续按 3 人周期循环 |
|
||||
|
||||
### 1.4 版本记录
|
||||
|
||||
| 版本 | 日期 | 变更说明 | 负责人 |
|
||||
|---|---|---|---|
|
||||
| V1.0 | 2026-03-23 | 首版:按 fsgx 需求重编写,并纳入当前分支差异清单 | AI + 产品/研发 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 产品概述
|
||||
|
||||
### 2.1 产品背景
|
||||
|
||||
范氏国香商城定位于大健康艾制品电商场景,通过小程序承载商品销售、社交裂变与会员激励,形成“购买-推荐-复购”的增长闭环。
|
||||
|
||||
### 2.2 产品定位
|
||||
|
||||
| 维度 | 描述 |
|
||||
|---|---|
|
||||
| 产品形态 | 微信小程序 + PC 管理后台 |
|
||||
| 核心商品 | 艾制品三条套餐(4333元/单)及周边商品 |
|
||||
| 商业模式 | 社交裂变 + 推荐返现 + 会员积分体系 |
|
||||
| 目标用户 | 有健康消费需求且具备社交分享意愿的用户 |
|
||||
| 核心差异化 | 邀请三人返现免单机制 + 分级积分激励 |
|
||||
|
||||
### 2.3 目标用户
|
||||
|
||||
| 用户类型 | 特征 | 核心诉求 |
|
||||
|---|---|---|
|
||||
| 普通消费者 | 首购用户,关注商品价值 | 流畅下单与可见返现规则 |
|
||||
| 推广用户(创客) | 有一定社交资源 | 明确返现进度和积分收益 |
|
||||
| 团队用户(云店/服务商) | 有管理下级需求 | 团队数据透明、收益可追踪 |
|
||||
| 平台运营人员 | 负责运营与风控 | 高效配置、可追溯财务与订单 |
|
||||
|
||||
### 2.4 产品目标
|
||||
|
||||
- 为用户提供明确、可预期的推荐返现与积分成长体验
|
||||
- 通过返现循环与等级激励提高裂变转化与复购
|
||||
- 为运营提供“参数可配、过程可查、结果可审计”的后台系统
|
||||
- 保持 CRMEB 复用能力,降低二开复杂度与维护成本
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心业务逻辑
|
||||
|
||||
### 3.1 推荐返现机制(核心)
|
||||
|
||||
#### 3.1.1 基础规则
|
||||
|
||||
- 用户 A 邀请的直推成员按“购买报单商品并支付成功”计入有效推荐
|
||||
- 同一推荐周期按 3 人结算:
|
||||
- 第 1 人:返现 20%
|
||||
- 第 2 人:返现 30%
|
||||
- 第 3 人:返现 50%
|
||||
- 累计返现 100% 后进入下一轮 3 人循环
|
||||
- 返现金额进入用户现金余额,可提现(扣除手续费)
|
||||
|
||||
#### 3.1.2 可配置参数
|
||||
|
||||
- 周期人数(默认 3)
|
||||
- 周期内每位返现比例(默认 20/30/50)
|
||||
- 返现基数(按实付金额/按固定金额)
|
||||
- 返现发放时机(支付即发放/确认收货后)
|
||||
|
||||
#### 3.1.3 返现佣金记录
|
||||
- 同时记录报单商品订单产生的推荐人佣金明细记录:eb_user_brokerage表中status=1,type=get_brokerage,title=推广佣金
|
||||
|
||||
|
||||
#### 3.1.4 异常与边界
|
||||
|
||||
- 退款/撤单后,需回滚对应返现及进度
|
||||
- 同设备/同账号异常刷单需支持风控拦截
|
||||
- 后台人工取消订单时,需同步返现逆操作并记录审计日志
|
||||
|
||||
### 3.2 分销等级体系
|
||||
|
||||
| 等级 | 升级条件 | 直推积分奖励 | 伞下积分奖励 | 说明 |
|
||||
|---|---|---:|---:|---|
|
||||
| 创客 | 直推满3单 | 500 | 0 | 阈值可配置 |
|
||||
| 云店 | 伞下满30单(至少3直推) | 800 | 300 | 级差计算 |
|
||||
| 服务商 | 伞下满100单(至少3直推) | 1000 | 200 | 级差计算 |
|
||||
| 分公司 | 伞下满1000单(至少3直推) | 1300 | 300 | 级差计算 |
|
||||
|
||||
规则补充:
|
||||
|
||||
- 等级默认自动升级,允许后台手动调整
|
||||
- 支持“不考核”开关,标记用户不参与自动考核
|
||||
- 批量购买触发升级时,先升级后结算剩余单据奖励
|
||||
|
||||
### 3.3 账户与积分体系
|
||||
|
||||
| 账户 | 来源 | 用途 | 提现 |
|
||||
|---|---|---|---|
|
||||
| 现金余额 | 推荐返现、后台充值 | 消费、提现 | 可提现(默认7%手续费) |
|
||||
| 待释放积分 | 等级后推荐奖励 | 按日释放 | 不可提现 |
|
||||
| 已释放积分 | 每日释放所得 | 购买普通商品 | 不可提现 |
|
||||
|
||||
积分规则:
|
||||
|
||||
- 日释放比例默认 0.4%(千分之四),后台可调
|
||||
- 积分不可转赠,不可直接提现
|
||||
- 报单商品不允许积分支付
|
||||
- 更新相关推荐会员(直推积分奖励、伞下积分奖励获得者)的待释放积分(`frozen_points`)
|
||||
- 同时记录报单商品订单产生的待释放积分明细记录:eb_user_bill表中status=0,type=integral,title=直推积分奖励 | 伞下积分奖励
|
||||
|
||||
### 3.4 多单购买与升级联动
|
||||
|
||||
- 用户一次购买 N 单报单商品时:
|
||||
1. 先按新增有效业绩判断是否升级
|
||||
2. 从达标后剩余单数起,按新等级发放积分奖励
|
||||
3. 推荐返现按周期规则逐单累计
|
||||
|
||||
---
|
||||
|
||||
## 4. 用户端功能需求(小程序)
|
||||
|
||||
### 4.1 登录与注册
|
||||
|
||||
- 微信授权登录、手机号快捷绑定(P0)
|
||||
- 推荐关系参数绑定且不可篡改(P0)
|
||||
- 新用户规则引导页(P1)
|
||||
|
||||
### 4.2 首页
|
||||
|
||||
- Banner 与活动专区(P0)
|
||||
- 报单商品与普通商品推荐区(P0)
|
||||
- 公告通知(P1)
|
||||
|
||||
### 4.3 商品与购买
|
||||
|
||||
- 商品分为报单商品与普通商品
|
||||
- 订单提交与支付成功后触发:推荐返现 + 等级积分逻辑
|
||||
- 支付方式:
|
||||
- 微信/支付宝:所有商品
|
||||
- 余额:按后台商品配置
|
||||
- 积分:仅普通商品,且受后台配置控制
|
||||
|
||||
### 4.4 推荐裂变
|
||||
|
||||
- 专属分享海报和邀请链接
|
||||
- 推荐关系树可视化展示(直推/伞下)
|
||||
- 推荐收益列表(返现 + 积分)可追踪到订单
|
||||
- 推荐返现循环进度展示(当前周期第几人、已返现金额、下一档比例)
|
||||
|
||||
### 4.5 个人中心
|
||||
|
||||
- 我的订单:状态筛选、详情、物流、售后
|
||||
- 我的资产:现金余额、待释放积分、已释放积分
|
||||
- 我的推荐:人数、订单、等级、收益统计
|
||||
- 提现申请:显示手续费、预计到账金额
|
||||
|
||||
---
|
||||
|
||||
## 5. 管理后台功能需求(PC端)
|
||||
|
||||
### 5.1 数据看板
|
||||
|
||||
- 今日新增、订单、销售额、返现金额
|
||||
- 推荐转化漏斗(邀请点击 -> 绑定 -> 首购)
|
||||
- 会员等级分布与升级趋势
|
||||
|
||||
### 5.2 用户管理
|
||||
|
||||
- 用户查询、详情、关系树
|
||||
- 等级手动调整、不考核开关
|
||||
- 账户资金与积分人工调整(带原因与日志)
|
||||
|
||||
### 5.3 商品管理
|
||||
|
||||
- 报单商品标记 `is_queue_goods`
|
||||
- 支付方式可配置(余额/积分开关)
|
||||
- 上下架、库存、预警
|
||||
|
||||
### 5.4 订单管理
|
||||
|
||||
- 订单检索、详情、发货、售后
|
||||
- 支持后台取消订单并触发全额返还逻辑
|
||||
- 取消/退款对返现与积分的冲销记录
|
||||
|
||||
### 5.5 财务管理
|
||||
|
||||
- 推荐返现流水(按用户/订单/周期)
|
||||
- 提现申请审核与手续费管理
|
||||
- 积分发放与释放日志
|
||||
- 日/月/年报表导出
|
||||
|
||||
### 5.6 营销配置中心
|
||||
|
||||
- 推荐返现周期人数
|
||||
- 分段返现比例(如 20/30/50)
|
||||
- 等级升级门槛与奖励值
|
||||
- 积分释放比例
|
||||
- 提现手续费
|
||||
- 返佣范围配置:所有商品 / 仅报单商品
|
||||
|
||||
### 5.7 内容与活动管理
|
||||
|
||||
- Banner、文章、公告管理
|
||||
- 活动发布、报名、核销
|
||||
|
||||
---
|
||||
|
||||
## 6. 与当前版本不一致/不满足功能点(重点)
|
||||
|
||||
说明:以下“当前版本”基于当前分支代码与既有 HJF 方案,对照 fsgx V1.0 目标形成。
|
||||
|
||||
| 序号 | 功能点 | fsgx 目标要求 | 当前版本现状 | 差异结论 | 优先级 |
|
||||
|---:|---|---|---|---|---|
|
||||
| 1 | 核心激励模型 | 邀请三人返现 20/30/50 循环 | 以“公排进四退一”为主展示与规则 | 重大不一致 | P0 |
|
||||
| 2 | 返现来源定义 | 现金余额主要来源为推荐返现 | 当前语义与实现更偏公排退款 | 业务口径不一致 | P0 |
|
||||
| 3 | 普通会员奖励 | 普通会员可参与返现(升级后叠加积分) | 当前描述与逻辑偏“升级后才有主要奖励” | 奖励起点不一致 | P0 |
|
||||
| 4 | 批量购买升级结算 | 先升级再结算剩余单奖励 | 当前未形成明确落地逻辑 | 功能缺失 | P0 |
|
||||
| 5 | 后台取消订单返还 | 支持后台取消后全额返还 | 当前规则与流程未完整覆盖 | 功能缺失 | P0 |
|
||||
| 6 | 营销参数模型 | 返现比例与人数可自由配置 | 当前仍有公排触发倍数相关配置 | 参数模型不一致 | P0 |
|
||||
| 7 | 返佣范围配置 | 支持“所有商品/报单商品” | 已提出问题项,未确认完整落地 | 功能不完整 | P1 |
|
||||
| 8 | 商品编辑 is_queue_goods | 保存后需正确落库 | 已有缺陷记录:修改后未更新数据库 | 缺陷待修复 | P0 |
|
||||
| 9 | 前端文案与页面结构 | 以推荐返现为主叙事 | 当前存在 queue 公排页面及文案 | 交互叙事不一致 | P1 |
|
||||
| 10 | Mock 到真实接口收敛 | 关键模块应接入真实 API | 部分 HJF 模块仍为 USE_MOCK | 集成不完整 | P1 |
|
||||
|
||||
建议验收标准(针对差异):
|
||||
|
||||
- 返现配置改动后,下一笔有效订单按新规则生效并可追溯
|
||||
- 推荐三人循环在用户端可见进度且与财务流水一致
|
||||
- 取消订单时,返现与积分冲销一致且无脏账
|
||||
- `is_queue_goods` 在商品编辑保存后稳定落库并影响支付/奖励逻辑
|
||||
|
||||
---
|
||||
|
||||
## 7. 数据库与接口改造方案
|
||||
|
||||
### 7.1 数据模型建议
|
||||
|
||||
- 返现进度表:记录用户返现周期状态(周期索引、当前位次、累计返现金额)
|
||||
- 返现流水表:记录返现发放/冲销明细(来源订单、比例、金额、状态)
|
||||
- 奖励配置表:支持“周期人数 + 分段比例”可配置
|
||||
- 订单扩展字段:记录是否参与返现、返现计算版本
|
||||
|
||||
### 7.2 关键接口建议
|
||||
|
||||
- `GET /api/rebate/progress`:用户当前返现周期进度
|
||||
- `GET /api/rebate/logs`:返现流水列表
|
||||
- `PUT /admin/rebate/config`:返现配置管理
|
||||
- `POST /admin/order/cancel_refund`:后台取消并触发返还/冲销
|
||||
|
||||
### 7.3 兼容策略
|
||||
|
||||
- 保留旧数据结构,新增版本号字段区分公排历史与返现新逻辑
|
||||
- 新逻辑灰度开关,允许按时间或商品范围切换
|
||||
- 财务报表提供历史口径与新口径并行查询
|
||||
|
||||
---
|
||||
|
||||
## 8. 非功能性需求
|
||||
|
||||
### 8.1 性能
|
||||
|
||||
- 下单后奖励计算链路接口 P95 < 300ms(异步结算除外)
|
||||
- 财务流水分页查询在 10 万级数据下响应 < 2s
|
||||
- 每日积分释放任务在 5 分钟内完成
|
||||
|
||||
### 8.2 一致性与安全
|
||||
|
||||
- 奖励发放、冲销、提现须事务一致
|
||||
- 订单状态变化与奖励状态双向校验,避免重复发放
|
||||
- 所有金额计算使用高精度方案,禁止浮点误差
|
||||
- 关键操作(配置变更、人工调账、取消返还)必须审计留痕
|
||||
|
||||
### 8.3 可运维性
|
||||
|
||||
- 关键任务提供失败重试与报警
|
||||
- 提供“按订单重算奖励”工具接口(仅管理员可用)
|
||||
- 配置变更需记录操作者、变更前后值、生效时间
|
||||
|
||||
---
|
||||
|
||||
## 附录 A:本版本实施优先级(建议)
|
||||
|
||||
- P0(首批上线):核心返现引擎、订单取消返还、商品报单标记修复、财务流水闭环
|
||||
- P1(第二阶段):推荐进度可视化、营销配置增强、Mock 全量切换真实接口
|
||||
- P2(优化阶段):风控规则、运营分析看板深化、批量重算工具
|
||||
24
docs/deploy-h5-diagnose.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# 诊断 H5 部署问题(Unexpected token '<')
|
||||
# 在服务器上检查:文件是否存在、index.html 引用、Nginx root
|
||||
set -e
|
||||
REMOTE="root@182.92.142.158"
|
||||
REMOTE_PUBLIC="/www/wwwroot/hjf.suzhouyuqi.com/public"
|
||||
|
||||
echo "=== 1. 检查 index.html 引用的 JS 文件 ==="
|
||||
ssh "$REMOTE" "grep -oE 'src=[^>]+\.js' $REMOTE_PUBLIC/index.html 2>/dev/null || echo 'index.html 不存在或无法读取'"
|
||||
|
||||
echo ""
|
||||
echo "=== 2. 检查 static/js 下实际存在的文件 ==="
|
||||
ssh "$REMOTE" "ls $REMOTE_PUBLIC/static/js/index.*.js $REMOTE_PUBLIC/static/js/chunk-vendors.*.js 2>/dev/null || echo '文件不存在'"
|
||||
|
||||
echo ""
|
||||
echo "=== 3. 直接请求 JS 看返回类型(应为 application/javascript) ==="
|
||||
curl -sI "https://hjf.suzhouyuqi.com/static/js/chunk-vendors.54d49a5a.js" | head -5
|
||||
|
||||
echo ""
|
||||
echo "=== 4. 若上面 Content-Type 不是 javascript,说明 Nginx 未正确提供静态文件 ==="
|
||||
echo "请在宝塔/面板中检查站点配置:"
|
||||
echo " - root 必须为: $REMOTE_PUBLIC"
|
||||
echo " - 添加 location ~ ^/(static|assets|pages)/ { try_files \$uri =404; }"
|
||||
echo "参考: docs/nginx-hjf-cloud.conf.example"
|
||||
35
docs/deploy-h5.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# H5 前端一键部署到云服务器(需 sshpass,或已配置 SSH 免密)
|
||||
# 支持 HBuilder 导出 web 或 h5 路径
|
||||
set -e
|
||||
cd "$(dirname "$0")/.."
|
||||
REMOTE="root@182.92.142.158"
|
||||
REMOTE_PUBLIC="/www/wwwroot/hjf.suzhouyuqi.com/public"
|
||||
BACKUP_DIR="/www/wwwroot/backup"
|
||||
|
||||
# 优先使用 web,其次 h5
|
||||
if [ -d "pro_v3.5.1/view/uniapp/unpackage/dist/build/web" ]; then
|
||||
H5_SRC="pro_v3.5.1/view/uniapp/unpackage/dist/build/web"
|
||||
elif [ -d "pro_v3.5.1/view/uniapp/unpackage/dist/build/h5" ]; then
|
||||
H5_SRC="pro_v3.5.1/view/uniapp/unpackage/dist/build/h5"
|
||||
else
|
||||
echo "错误:未找到 H5 构建产物(web 或 h5),请先用 HBuilder 或 npm run build:h5 打包"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "备份云服务器 public 目录(上一版本)..."
|
||||
ssh "$REMOTE" "mkdir -p $BACKUP_DIR && tar -czf $BACKUP_DIR/hjf_public_\$(date +%Y%m%d_%H%M%S).tar.gz -C /www/wwwroot/hjf.suzhouyuqi.com public && echo '备份完成'"
|
||||
|
||||
echo "上传 H5 到 $REMOTE:$REMOTE_PUBLIC ..."
|
||||
# 先删除旧的 index.html、static、assets、pages,避免 /h5/ 路径残留
|
||||
ssh "$REMOTE" "cd $REMOTE_PUBLIC && rm -f index.html && rm -rf static assets pages 2>/dev/null; true"
|
||||
tar czf - -C "$H5_SRC" . | ssh "$REMOTE" "cd $REMOTE_PUBLIC && tar xzf -"
|
||||
|
||||
echo "修改权限 ..."
|
||||
ssh "$REMOTE" "chown -R www:www $REMOTE_PUBLIC && chmod -R 755 $REMOTE_PUBLIC"
|
||||
|
||||
echo ""
|
||||
echo "验证 index.html 引用路径(应为 /static/ 而非 /h5/static/):"
|
||||
ssh "$REMOTE" "grep -oE 'src=[^>]+\.js' $REMOTE_PUBLIC/index.html 2>/dev/null | head -3"
|
||||
echo ""
|
||||
echo "部署完成。访问 https://hjf.suzhouyuqi.com/ 验证。若仍报 Unexpected token '<',见 docs/deploy.md 4.7 节"
|
||||
233
docs/deploy.md
@@ -17,7 +17,49 @@
|
||||
|--------|----------|----------------|
|
||||
| 服务器 API | `pro_v3.5.1/`(排除 view、public/admin) | `/www/wwwroot/hjf.suzhouyuqi.com/` |
|
||||
| 管理后台前端 | `pro_v3.5.1/view/admin/dist/` | `/www/wwwroot/hjf.suzhouyuqi.com/public/admin/` |
|
||||
| H5 前端 | `pro_v3.5.1/view/uniapp/unpackage/dist/build/h5/` | `/www/wwwroot/hjf.suzhouyuqi.com/public/` |
|
||||
| H5 前端 | `pro_v3.5.1/view/uniapp/unpackage/dist/build/web/` 或 `.../h5/` | `/www/wwwroot/hjf.suzhouyuqi.com/public/` |
|
||||
|
||||
### 云服务器 Nginx 配置要求(H5 根路径访问必备)
|
||||
|
||||
域名根路径 `https://hjf.suzhouyuqi.com/` 需正确返回 H5 页面。若出现 `Unexpected token '<'`(请求 JS 时返回 HTML),通常是 Nginx 未正确提供静态文件。
|
||||
|
||||
**必须满足:**
|
||||
|
||||
1. **站点 root 指向 public**:`root /www/wwwroot/hjf.suzhouyuqi.com/public;`
|
||||
2. **index 顺序**:`index index.html index.php;`(优先 index.html)
|
||||
3. **静态文件优先**:对 `/static/`、`/assets/`、`/pages/` 等路径,Nginx 应先尝试本地文件,**仅当文件不存在**时才转发到 PHP/Swoole。
|
||||
|
||||
**推荐配置示例**(宝塔/ LNMP 站点):
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl http2;
|
||||
server_name hjf.suzhouyuqi.com;
|
||||
root /www/wwwroot/hjf.suzhouyuqi.com/public;
|
||||
index index.html index.php;
|
||||
|
||||
# 静态资源:直接由 Nginx 提供,不转发到 PHP
|
||||
location ~ ^/(static|assets|pages)/ {
|
||||
try_files $uri =404;
|
||||
expires 7d;
|
||||
}
|
||||
|
||||
# PHP 请求
|
||||
location ~ \.php$ {
|
||||
# 转发到 Swoole 或 php-fpm,按现有配置
|
||||
}
|
||||
|
||||
# 其余请求:先找静态文件,再走 PHP
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若使用 `if (!-e $request_filename) { proxy_pass ... }`,需确保**文件存在时不会进入 proxy**,否则 `/static/js/xxx.js` 会被错误地返回 HTML。
|
||||
|
||||
完整示例见 `docs/nginx-hjf-cloud.conf.example`。
|
||||
|
||||
---
|
||||
|
||||
@@ -152,6 +194,8 @@ tar -czvf /www/backup/hjf_admin_$(date +%Y%m%d_%H%M%S).tar.gz \
|
||||
|
||||
### 3.3 上传(本地)
|
||||
|
||||
**方式 A:rsync**(服务器需已安装 rsync)
|
||||
|
||||
```bash
|
||||
cd /Users/apple/scott2026/huangjingfen
|
||||
|
||||
@@ -160,6 +204,15 @@ rsync -avz --delete \
|
||||
root@182.92.142.158:/www/wwwroot/hjf.suzhouyuqi.com/public/admin/
|
||||
```
|
||||
|
||||
**方式 B:tar + ssh**(服务器无 rsync 时使用)
|
||||
|
||||
```bash
|
||||
cd /Users/apple/scott2026/huangjingfen
|
||||
|
||||
tar czf - -C pro_v3.5.1/view/admin/dist . | \
|
||||
ssh root@182.92.142.158 "cd /www/wwwroot/hjf.suzhouyuqi.com/public && rm -rf admin && mkdir -p admin && tar xzf - -C admin"
|
||||
```
|
||||
|
||||
### 3.4 上传后修改权限(服务器)
|
||||
|
||||
```bash
|
||||
@@ -173,13 +226,56 @@ chmod -R 775 /www/wwwroot/hjf.suzhouyuqi.com/public/admin
|
||||
|
||||
浏览器访问 `http://hjf.suzhouyuqi.com/admin/login`,确认页面正常。
|
||||
|
||||
### 3.6 本地环境部署
|
||||
|
||||
将管理后台前端打包并部署到本机,配合 `nginx-crmeb.conf` 与 Swoole 使用。
|
||||
|
||||
**前置条件:**
|
||||
|
||||
- Nginx 已加载 `pro_v3.5.1/nginx-crmeb.conf`(`root` 指向 `pro_v3.5.1/public`,80 反代到 20199)
|
||||
- Swoole API 已启动:`./help/start-api.sh` 或 `php -d memory_limit=300M think swoole`
|
||||
|
||||
**步骤:**
|
||||
|
||||
```bash
|
||||
# 1. 本地构建(同 3.1)
|
||||
cd /Users/apple/scott2026/huangjingfen/pro_v3.5.1/view/admin
|
||||
npm install # 依赖有变更时执行
|
||||
npm run build
|
||||
|
||||
# 2. 将构建产物复制到 public/admin(覆盖旧文件)
|
||||
cd /Users/apple/scott2026/huangjingfen
|
||||
rm -rf pro_v3.5.1/public/admin
|
||||
cp -r pro_v3.5.1/view/admin/dist pro_v3.5.1/public/admin
|
||||
```
|
||||
|
||||
或使用 rsync(保留权限、便于增量更新):
|
||||
|
||||
```bash
|
||||
cd /Users/apple/scott2026/huangjingfen
|
||||
rsync -av --delete pro_v3.5.1/view/admin/dist/ pro_v3.5.1/public/admin/
|
||||
```
|
||||
|
||||
**验证:**
|
||||
|
||||
浏览器访问 `http://127.0.0.1/admin/` 或 `http://127.0.0.1/admin/login`,确认管理后台页面正常。
|
||||
|
||||
---
|
||||
|
||||
## 四、子项目三:H5 前端
|
||||
|
||||
仅部署 H5 构建产物到 `public/`(站点根目录)。
|
||||
仅部署 H5 构建产物到 `public/`(站点根目录)。部署时仅覆盖 H5 相关文件,不删除 `admin/`、`index.php` 等。
|
||||
|
||||
### 4.1 本地构建
|
||||
### 4.1 本地打包(HBuilder 或 npm)
|
||||
|
||||
**方式 A:HBuilder 打包(推荐)**
|
||||
|
||||
1. 用 HBuilderX 打开 `pro_v3.5.1/view/uniapp` 项目
|
||||
2. 确认 `config/app.js` 中 `BASE_HOST` 已设为云服务器域名(如 `hjf.suzhouyuqi.com`)
|
||||
3. 菜单:发行 → 网站-H5 手机版(或 Web) → 填写网站标题 → 发行
|
||||
4. 构建产物在 `view/uniapp/unpackage/dist/build/web/` 或 `.../build/h5/`
|
||||
|
||||
**方式 B:命令行构建**
|
||||
|
||||
```bash
|
||||
cd /Users/apple/scott2026/huangjingfen/pro_v3.5.1/view/uniapp
|
||||
@@ -190,18 +286,24 @@ npm run build:h5
|
||||
|
||||
构建产物在 `view/uniapp/unpackage/dist/build/h5/`。
|
||||
|
||||
### 4.2 备份(服务器)
|
||||
### 4.2 备份(服务器,上传前执行)
|
||||
|
||||
上传前在服务器备份 `public` 目录,便于回滚:
|
||||
|
||||
```bash
|
||||
ssh root@182.92.142.158
|
||||
|
||||
mkdir -p /www/backup
|
||||
tar -czvf /www/backup/hjf_public_$(date +%Y%m%d_%H%M%S).tar.gz \
|
||||
mkdir -p /www/wwwroot/backup
|
||||
tar -czvf /www/wwwroot/backup/hjf_public_$(date +%Y%m%d_%H%M%S).tar.gz \
|
||||
-C /www/wwwroot/hjf.suzhouyuqi.com public
|
||||
```
|
||||
|
||||
> 一键部署脚本 `deploy-h5.sh` 会自动执行此备份后再上传。
|
||||
|
||||
### 4.3 上传(本地)
|
||||
|
||||
**方式 A:rsync**(服务器需已安装 rsync)
|
||||
|
||||
```bash
|
||||
cd /Users/apple/scott2026/huangjingfen
|
||||
|
||||
@@ -212,9 +314,122 @@ rsync -avz \
|
||||
|
||||
> 不使用 `--delete`,避免覆盖或删除 `admin/`、`index.php` 等文件。
|
||||
|
||||
### 4.4 验证
|
||||
**方式 B:tar + ssh**(服务器无 rsync 时使用)
|
||||
|
||||
浏览器访问 `http://hjf.suzhouyuqi.com/`,确认 H5 页面正常。
|
||||
```bash
|
||||
cd /Users/apple/scott2026/huangjingfen
|
||||
|
||||
tar czf - -C pro_v3.5.1/view/uniapp/unpackage/dist/build/h5 . | \
|
||||
ssh root@182.92.142.158 "cd /www/wwwroot/hjf.suzhouyuqi.com/public && tar xzf -"
|
||||
```
|
||||
|
||||
> 仅解压覆盖 H5 文件(index.html、static/ 等),不删除 `admin/`。
|
||||
|
||||
**方式 C:scp**
|
||||
|
||||
```bash
|
||||
cd /Users/apple/scott2026/huangjingfen
|
||||
|
||||
scp -r pro_v3.5.1/view/uniapp/unpackage/dist/build/h5/* \
|
||||
root@182.92.142.158:/www/wwwroot/hjf.suzhouyuqi.com/public/
|
||||
```
|
||||
|
||||
### 4.4 上传后修改权限(服务器)
|
||||
|
||||
```bash
|
||||
ssh root@182.92.142.158
|
||||
|
||||
chown -R www:www /www/wwwroot/hjf.suzhouyuqi.com/public
|
||||
chmod -R 755 /www/wwwroot/hjf.suzhouyuqi.com/public
|
||||
```
|
||||
|
||||
> 若仅更新 H5 根目录下的 index.html、static 等,可只对相关路径执行:
|
||||
> `chown -R www:www /www/wwwroot/hjf.suzhouyuqi.com/public/index.html /www/wwwroot/hjf.suzhouyuqi.com/public/static`
|
||||
|
||||
### 4.5 一键部署脚本(本地执行)
|
||||
|
||||
脚本 `docs/deploy-h5.sh` 会依次执行:**备份上一版本 → 上传 → 修改权限**。执行前确保已打包好 H5(`unpackage/dist/build/web/` 或 `h5/` 存在):
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# H5 前端一键部署到云服务器(需 sshpass,或已配置 SSH 免密)
|
||||
# 支持 HBuilder 导出 web 或 h5 路径
|
||||
set -e
|
||||
cd "$(dirname "$0")/.."
|
||||
REMOTE="root@182.92.142.158"
|
||||
REMOTE_PUBLIC="/www/wwwroot/hjf.suzhouyuqi.com/public"
|
||||
BACKUP_DIR="/www/wwwroot/backup"
|
||||
|
||||
# 优先使用 web,其次 h5
|
||||
if [ -d "pro_v3.5.1/view/uniapp/unpackage/dist/build/web" ]; then
|
||||
H5_SRC="pro_v3.5.1/view/uniapp/unpackage/dist/build/web"
|
||||
elif [ -d "pro_v3.5.1/view/uniapp/unpackage/dist/build/h5" ]; then
|
||||
H5_SRC="pro_v3.5.1/view/uniapp/unpackage/dist/build/h5"
|
||||
else
|
||||
echo "错误:未找到 H5 构建产物,请先用 HBuilder 或 npm run build:h5 打包"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "备份云服务器 public 目录(上一版本)..."
|
||||
ssh "$REMOTE" "mkdir -p $BACKUP_DIR && tar -czf $BACKUP_DIR/hjf_public_\$(date +%Y%m%d_%H%M%S).tar.gz -C /www/wwwroot/hjf.suzhouyuqi.com public && echo '备份完成'"
|
||||
|
||||
echo "上传 H5 到 $REMOTE:$REMOTE_PUBLIC ..."
|
||||
tar czf - -C "$H5_SRC" . | ssh "$REMOTE" "cd $REMOTE_PUBLIC && tar xzf -"
|
||||
|
||||
echo "修改权限 ..."
|
||||
ssh "$REMOTE" "chown -R www:www $REMOTE_PUBLIC && chmod -R 755 $REMOTE_PUBLIC"
|
||||
|
||||
echo "部署完成,请访问 https://hjf.suzhouyuqi.com/ 验证"
|
||||
```
|
||||
|
||||
用法:
|
||||
|
||||
```bash
|
||||
cd /Users/apple/scott2026/huangjingfen
|
||||
chmod +x docs/deploy-h5.sh
|
||||
./docs/deploy-h5.sh
|
||||
```
|
||||
|
||||
若需密码,可安装 `sshpass` 后使用:`SSHPASS='A@123456' sshpass -e ./docs/deploy-h5.sh`
|
||||
|
||||
### 4.6 验证
|
||||
|
||||
浏览器访问 `http://hjf.suzhouyuqi.com/` 或 `https://hjf.suzhouyuqi.com/`,确认 H5 页面正常。
|
||||
|
||||
### 4.7 H5 报错 `Unexpected token '<'` 排查
|
||||
|
||||
**现象**:访问根路径时控制台报 `index.xxx.js:1 Uncaught SyntaxError: Unexpected token '<'`。
|
||||
|
||||
**原因**:请求 JS 时服务器返回了 HTML(404 页或 index.php 输出)。常见情况:
|
||||
- **index.html 引用 `/h5/static/...`**:旧版 index 与当前部署路径不一致,`/h5/static/js/xxx.js` 返回 404 → HTML
|
||||
- **Nginx 未正确提供静态文件**:root 未指向 `.../public` 或缺少 `location ~ ^/(static|assets|pages)/`
|
||||
|
||||
**排查步骤**:
|
||||
|
||||
1. **检查 index.html 引用路径**:
|
||||
```bash
|
||||
curl -s "https://hjf.suzhouyuqi.com/" | grep -oE 'src=[^>]+\.js'
|
||||
```
|
||||
若出现 `/h5/static/`,说明服务器 index.html 为旧版,需重新部署。
|
||||
2. **重新构建并部署**(部署脚本会先清理旧 index.html、static 等):
|
||||
```bash
|
||||
# 本地:HBuilder 发行 H5 或 npm run build:h5
|
||||
./docs/deploy-h5.sh
|
||||
```
|
||||
3. **确认 Nginx root**:站点 root 必须为 `.../public`,见上文「云服务器 Nginx 配置要求」。
|
||||
4. **清除浏览器缓存**:强制刷新(Ctrl+Shift+R)或无痕模式访问。
|
||||
|
||||
---
|
||||
|
||||
## 四(补充)、管理后台登录滑块:`NOAUTH Authentication required`
|
||||
|
||||
若访问 `/adminapi/ajcaptcha` 或 `/adminapi/is_captcha` 返回 `{"msg":"NOAUTH Authentication required."}`,说明 **Redis 需要密码但 `.env` 中 `[REDIS]` 的 `PASSWORD` 与服务器 Redis 不一致**(或 Redis 开启了 `requirepass` 而 `.env` 为空)。
|
||||
|
||||
**处理:**
|
||||
|
||||
1. 在服务器上核对 Redis:`redis-cli -h <主机> -p 6379 -a '<实际密码>' ping`,将正确密码写入站点根目录 `.env` 的 `PASSWORD = ...`。
|
||||
2. 重启 Swoole / PHP 进程使配置生效。
|
||||
3. 项目已把 **滑块验证码(ajcaptcha)缓存改为本地 file**,不依赖 Redis 认证;部署后请同步更新 `config/ajcaptcha.php`。登录次数统计等仍走 Redis,**长期仍须修正 Redis 配置**。
|
||||
|
||||
---
|
||||
|
||||
@@ -247,5 +462,5 @@ tar -xzvf /www/backup/hjf_admin_YYYYMMDD_HHMMSS.tar.gz -C /www/wwwroot/hjf.suzho
|
||||
|
||||
# 回滚 H5(恢复 public/ 目录)
|
||||
rm -rf /www/wwwroot/hjf.suzhouyuqi.com/public
|
||||
tar -xzvf /www/backup/hjf_public_YYYYMMDD_HHMMSS.tar.gz -C /www/wwwroot/hjf.suzhouyuqi.com
|
||||
tar -xzvf /www/wwwroot/backup/hjf_public_YYYYMMDD_HHMMSS.tar.gz -C /www/wwwroot/hjf.suzhouyuqi.com
|
||||
```
|
||||
|
||||
289
docs/execution-plan.md
Normal file
@@ -0,0 +1,289 @@
|
||||
# 黄精粉健康商城 · 剩余开发任务执行方案
|
||||
|
||||
> 基于 PRD_V2.md + openclaw-frontend-tasks.md 的现状分析
|
||||
> 制定日期:2026-03-15
|
||||
> 当前分支:claude/hjf-queue-admin-apis-hsymG
|
||||
|
||||
---
|
||||
|
||||
## 一、现状盘点(已完成 vs 待完成)
|
||||
|
||||
### ✅ 已完成的任务
|
||||
|
||||
| 阶段 | 任务 | 说明 |
|
||||
|------|------|------|
|
||||
| Phase 0 | P0-01, P0-02 | UniApp + Admin Mock 数据文件 |
|
||||
| Stage 1A | P1A-01~06 | 全部6个 API 模块(uniapp + admin) |
|
||||
| Stage 1B | P1B-01~04 | 全部4个公共组件(QueueProgress / AssetCard / MemberBadge / RefundNotice) |
|
||||
| Stage 1C | P1C-01~06 | 全部6个新 UniApp 页面(公排状态/历史/规则 + 资产总览/积分明细 + 引导页) |
|
||||
| Stage 1D | P1D-02 | 商品详情页:`is_queue_goods` 角标 + 公排提示条 |
|
||||
| Stage 1D | P1D-03 | 购买确认页:多单拆分提示 + 公排入队说明 |
|
||||
| Stage 1D | P1D-04 | 支付结果页:公排入队成功提示 + 查看公排入口 |
|
||||
| Stage 1D | P1D-06 | 提现页:7% 手续费动态计算 + 提示文案 |
|
||||
| Stage 1E | P1E-01~06 | 全部6个 Admin 新页面(公排订单/财务/配置 + 会员管理/配置 + 积分日志) |
|
||||
| Stage 1F | P1F-01~07 | 全部路由注册(pages.json + Admin hjfQueue.js 路由模块 + index.js 导入) |
|
||||
| Stage 1G | P1G-01 | Admin 用户管理列表:`member_level`、`no_assess` 列和筛选项 |
|
||||
|
||||
---
|
||||
|
||||
### ⏳ 待完成的任务(本方案覆盖范围)
|
||||
|
||||
```
|
||||
Phase 1 尾单(4项)
|
||||
├── P1D-01 首页:报单商品角标 + 公排入口Banner
|
||||
├── P1D-05 推荐收益页:积分替换佣金显示
|
||||
├── P1D-07 个人中心:HjfMemberBadge等级徽章嵌入
|
||||
└── P1G-02 Admin商品编辑:报单标记 + 积分支付白名单
|
||||
|
||||
Phase 2 数据库迁移(5项)
|
||||
Phase 3 后端 API 开发(16项)
|
||||
Phase 4 前后端联调集成(5项)
|
||||
Phase 5 完整测试(8项)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、执行方案
|
||||
|
||||
### 阶段 A:Phase 1 收尾(前端,可立即执行)
|
||||
|
||||
> 依赖:无。可在当前 Mock 模式下独立完成。
|
||||
> 目标:让 Phase 1 所有38个任务全部 `[x]`,解锁 CP-01 评审检查点。
|
||||
|
||||
---
|
||||
|
||||
#### 任务 A1 — P1D-01:首页报单商品角标
|
||||
|
||||
**文件**:`pro_v3.5.1/view/uniapp/pages/index/index.vue`
|
||||
|
||||
**改造内容**:
|
||||
1. 在商品列表卡片的商品名/图片处,检查 `item.is_queue_goods == 1`,叠加渲染 `报单` 角标(红色标签,参考 goods_details 中已有的 `.queue-goods-tag` 样式)。
|
||||
2. 在首页 Banner 区或活动专区下方,增加"公排进度"快捷入口行(复用 `HjfQueueProgress` 组件缩略版,或仅放文字按钮跳转 `/pages/queue/status`)。
|
||||
3. 无需新增 API 调用,角标从商品列表字段 `is_queue_goods` 读取即可。
|
||||
|
||||
**验收标准**:报单商品卡片右上角出现红色"报单"角标;点击公排入口可跳转公排状态页。
|
||||
|
||||
---
|
||||
|
||||
#### 任务 A2 — P1D-05:推荐收益页积分替换佣金
|
||||
|
||||
**文件**:`pro_v3.5.1/view/uniapp/pages/users/user_spread_money/index.vue`
|
||||
|
||||
**改造内容**:
|
||||
1. 将列表中"佣金"字样统一替换为"积分",金额字段从 `money`/`commission` 改为读取 `points`。
|
||||
2. 展示积分类型标签:`reward_direct`(直推奖励)/ `reward_umbrella`(伞下奖励)。
|
||||
3. 导入 `import { getTeamIncome } from '@/api/hjfMember.js'`,替换原有 API 调用。
|
||||
4. 数值格式:整数积分,不保留小数;去掉 `¥` 符号,改为"积分"后缀。
|
||||
|
||||
**验收标准**:推荐收益列表显示积分数量而非金额,类型标签正确区分直推/伞下。
|
||||
|
||||
---
|
||||
|
||||
#### 任务 A3 — P1D-07:个人中心会员等级徽章
|
||||
|
||||
**文件**:`pro_v3.5.1/view/uniapp/pages/user/index.vue`
|
||||
|
||||
**改造内容**:
|
||||
1. 引入 `HjfMemberBadge` 组件,在用户头像/昵称旁嵌入等级徽章。
|
||||
```js
|
||||
import HjfMemberBadge from '@/components/HjfMemberBadge.vue'
|
||||
```
|
||||
2. 从 `getMemberInfo` API(已有 Mock)获取 `member_level`,传入组件 `:level` prop。
|
||||
3. 在资产快捷入口区域已有的 `hjf-nav-row` 基础上,补充"待释放积分"数值预览(展示 `frozen_points`,不换页即可看到大数字)。
|
||||
4. 已有的公排查询 + 资产入口导航行保持不变,不重复建设。
|
||||
|
||||
**验收标准**:昵称旁出现对应等级的彩色徽章;资产行显示待释放积分数。
|
||||
|
||||
---
|
||||
|
||||
#### 任务 A4 — P1G-02:Admin 商品编辑-报单标记与支付方式
|
||||
|
||||
**文件**:`pro_v3.5.1/view/admin/src/pages/product/creatProduct/index.vue`
|
||||
|
||||
**改造内容**:
|
||||
1. 在商品基本信息 Tab 中增加"报单商品"开关(iView `i-switch`),绑定 `formValidate.is_queue_goods`,默认 `false`。
|
||||
2. 在支付方式 Tab / 销售设置区域,增加复选框组"允许积分支付"(`allow_pay_types`),选项:`待释放积分`、`已释放积分`;报单商品开关开启时,此项置灰并强制清空。
|
||||
3. 表单提交时将 `is_queue_goods`(0/1)和 `allow_pay_types`(数组序列化)一并提交。
|
||||
4. 编辑回显时正确反填两个字段。
|
||||
|
||||
**验收标准**:新建/编辑商品可设置报单标记;报单商品自动禁用积分支付选项。
|
||||
|
||||
---
|
||||
|
||||
### 阶段 B:Phase 2 数据库迁移
|
||||
|
||||
> 依赖:后端开发环境就绪(ThinkPHP 8 + MySQL 8.0)。
|
||||
> 建议由后端工程师执行,前端工程师无需等待此阶段。
|
||||
|
||||
| 任务 | 操作 | 目标 |
|
||||
|------|------|------|
|
||||
| P2-01 | CREATE TABLE | `eb_queue_pool`(公排池,9个字段,含复合索引) |
|
||||
| P2-02 | CREATE TABLE | `eb_points_release_log`(积分释放日志,7个字段) |
|
||||
| P2-03 | ALTER TABLE | `eb_user` 增加4字段:`member_level`、`no_assess`、`frozen_points`、`available_points` |
|
||||
| P2-04 | ALTER TABLE | `eb_store_product` 增加2字段:`is_queue_goods`、`allow_pay_types` |
|
||||
| P2-05 | INSERT | `eb_system_config` 插入9项系统配置键值对(公排倍数、释放比例、手续费率、各等级门槛和奖励) |
|
||||
|
||||
**关键索引(P2-01)**:
|
||||
```sql
|
||||
INDEX idx_uid (uid),
|
||||
INDEX idx_status_add_time (status, add_time),
|
||||
INDEX idx_queue_no (queue_no),
|
||||
INDEX idx_trigger_batch (trigger_batch)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 阶段 C:Phase 3 后端 API 开发
|
||||
|
||||
> 依赖:Phase 2 完成。
|
||||
> 开发顺序:先核心引擎,再外围接口,最后定时任务。
|
||||
|
||||
#### C1 — 公排引擎(优先级最高)
|
||||
|
||||
| 任务 | 文件/类 | 内容 |
|
||||
|------|---------|------|
|
||||
| P3-01 | `QueuePool` Service | 入队逻辑(写 `eb_queue_pool`,Redis 分布式锁防并发) |
|
||||
| P3-02 | `QueueRefund` Service | 退款触发逻辑(每入N单检查退款,使用 think-queue 异步处理) |
|
||||
| P3-03 | `QueueController` | 用户端接口:`GET /hjf/queue/status`、`GET /hjf/queue/history` |
|
||||
| P3-04 | `AdminQueueController` | Admin接口:`GET /hjf/queue/order`、`GET /hjf/queue/config`、`POST /hjf/queue/config`、`GET /hjf/queue/finance` |
|
||||
|
||||
**核心逻辑要点**:
|
||||
- 支付回调成功后:判断 `is_queue_goods` → 多单拆分 → 逐单调用 `QueuePool::enqueue()` → 检查触发条件
|
||||
- Redis Key:`hjf:queue:lock`(分布式锁),`hjf:queue:pending_count`(待触发计数)
|
||||
- 退款写入 `eb_user.now_money`(复用 CRMEB 余额字段),记录 `eb_user_bill`
|
||||
|
||||
#### C2 — 积分奖励引擎
|
||||
|
||||
| 任务 | 文件/类 | 内容 |
|
||||
|------|---------|------|
|
||||
| P3-05 | `PointsReward` Service | 级差计算:按会员等级发放直推/伞下积分,写入 `frozen_points` |
|
||||
| P3-06 | `PointsRelease` Job | 每日凌晨定时任务:`frozen_points × 0.4‰ → available_points`,写 `eb_points_release_log` |
|
||||
| P3-07 | `PointsController` | 用户端接口:`GET /hjf/points/detail`(5类型筛选,分页) |
|
||||
| P3-08 | `AdminPointsController` | Admin接口:`GET /hjf/points/release-log` |
|
||||
|
||||
**每日释放公式**:`release_amount = FLOOR(frozen_points × rate / 1000)`,`rate` 取系统配置 `hjf_release_rate`(默认 4)。
|
||||
|
||||
#### C3 — 会员等级体系
|
||||
|
||||
| 任务 | 文件/类 | 内容 |
|
||||
|------|---------|------|
|
||||
| P3-09 | `MemberLevel` Service | 升级判断:直推单数 / 伞下业绩单数达标后自动升级;伞下业绩分离逻辑 |
|
||||
| P3-10 | `AdminMemberController` | Admin接口:`GET /hjf/member/list`、`PUT /hjf/member/level/:uid`、`GET/POST /hjf/member/config` |
|
||||
|
||||
**升级触发时机**:每次订单支付回调完成后,对推荐链上的所有上级异步检查升级条件。
|
||||
|
||||
#### C4 — 资产接口
|
||||
|
||||
| 任务 | 文件/类 | 内容 |
|
||||
|------|---------|------|
|
||||
| P3-11 | `AssetsController` | `GET /hjf/assets/overview`:返回余额 + 积分汇总(复用 `eb_user` 字段) |
|
||||
| P3-12 | `AssetsController` | `GET /hjf/assets/cash/detail`:现金流水(分页,复用 `eb_user_bill`) |
|
||||
|
||||
#### C5 — 路由注册
|
||||
|
||||
| 任务 | 内容 |
|
||||
|------|------|
|
||||
| P3-13 | `route/api.php`:注册用户端全部 hjf 路由(含鉴权中间件) |
|
||||
| P3-14 | `route/admin.php`:注册 Admin 端全部 hjf 路由(含权限中间件) |
|
||||
|
||||
#### C6 — 单元测试桩
|
||||
|
||||
| 任务 | 内容 |
|
||||
|------|------|
|
||||
| P3-15 | 公排引擎单元测试:入队/触发退款/分布式锁 |
|
||||
| P3-16 | 积分计算单元测试:级差计算/每日释放精度(bcmath) |
|
||||
|
||||
---
|
||||
|
||||
### 阶段 D:Phase 4 前后端联调集成
|
||||
|
||||
> 依赖:Phase 2 + Phase 3 完成,测试环境可访问真实 API。
|
||||
|
||||
| 任务 | 内容 | 操作 |
|
||||
|------|------|------|
|
||||
| P4-01 | 关闭 Mock 开关 | 将所有 `const USE_MOCK = true` 改为 `false`(UniApp + Admin 共8个文件) |
|
||||
| P4-02 | UniApp 冒烟测试 | 登录 → 查看公排状态 → 资产总览 → 积分明细 → 推荐收益 |
|
||||
| P4-03 | Admin 冒烟测试 | 公排订单列表 → 公排配置保存 → 会员等级调整 → 积分日志查询 |
|
||||
| P4-04 | 支付回调联调 | 测试购买报单商品 → 公排入队 → 积分发放 → 等级升级完整链路 |
|
||||
| P4-05 | 定时任务验证 | 手动触发每日积分释放任务,验证 `release_log` 记录正确 |
|
||||
|
||||
**Mock 关闭检查清单**:
|
||||
```
|
||||
uniapp/api/hjfQueue.js USE_MOCK → false
|
||||
uniapp/api/hjfAssets.js USE_MOCK → false
|
||||
uniapp/api/hjfMember.js USE_MOCK → false
|
||||
admin/src/api/hjfQueue.js USE_MOCK → false
|
||||
admin/src/api/hjfMember.js USE_MOCK → false
|
||||
admin/src/api/hjfPoints.js USE_MOCK → false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 阶段 E:Phase 5 完整测试
|
||||
|
||||
> 依赖:Phase 4 联调通过。
|
||||
|
||||
| 任务 | 类型 | 内容 |
|
||||
|------|------|------|
|
||||
| P5-01 | 前端渲染测试 | 所有新页面在3个Mock场景(A/B/C)下截图验收 |
|
||||
| P5-02 | 后端接口测试 | 用 Postman/Apifox 验证所有 P3 接口的响应格式和边界值 |
|
||||
| P5-03 | 公排边界测试 | 精确触发:第4单入队时退款到第1单;多人同时入队(并发锁) |
|
||||
| P5-04 | 积分精度测试 | bcmath 计算:`1000000 × 4 / 1000 = 4000`(无浮点误差) |
|
||||
| P5-05 | 会员升级测试 | 直推3单后自动升级创客;伞下30单升云店;业绩分离逻辑 |
|
||||
| P5-06 | 并发压测 | 1000并发用户同时访问公排状态页;公排入队 200 TPS |
|
||||
| P5-07 | E2E 全流程 | 新用户注册 → 引导页 → 购买报单商品 → 等待公排退款 → 申请提现 |
|
||||
| P5-08 | 回归测试 | CRMEB 原有功能(登录/商品/订单/支付)未被改造影响 |
|
||||
|
||||
---
|
||||
|
||||
## 三、执行优先级与分工建议
|
||||
|
||||
```
|
||||
立即可执行(无依赖,Agent 可直接实施)
|
||||
├── A1 首页报单角标 ← 最简单,约30分钟
|
||||
├── A2 推荐收益页积分替换 ← 约45分钟
|
||||
├── A3 个人中心等级徽章 ← 约30分钟
|
||||
└── A4 Admin商品编辑改造 ← 约60分钟
|
||||
|
||||
等待后端就绪(并行推进)
|
||||
├── B 数据库迁移 ← DBA/后端工程师
|
||||
├── C 后端API开发 ← 后端工程师(C1优先)
|
||||
└── D 联调集成 ← 前后端协作
|
||||
|
||||
最终验收
|
||||
└── E 完整测试 ← 测试工程师
|
||||
```
|
||||
|
||||
**关键路径**:`A1~A4 完成` → `CP-01 评审` → `B+C 并行` → `D 联调` → `E 测试`
|
||||
|
||||
---
|
||||
|
||||
## 四、风险点与注意事项
|
||||
|
||||
| 风险 | 描述 | 应对措施 |
|
||||
|------|------|---------|
|
||||
| 公排并发竞争 | 多单同时入队可能重复触发退款 | Redis `SET NX EX` 分布式锁,退款前二次检查状态 |
|
||||
| 积分浮点误差 | `3600 × 0.4‰` 在 PHP 中存在精度问题 | 全程使用 `bcmath`:`bcmul($points, '4', 0)` → `bcdiv(..., '1000', 0)` |
|
||||
| 伞下业绩分离 | 下级升级后业绩需从上级扣除 | 升级事件写入消息队列,异步重算上级业绩;加数据库事务 |
|
||||
| Admin 路由权限 | hjf 新路由需配置到角色权限表 | P3-14 后端路由注册时同步写 `eb_system_menus` |
|
||||
| CRMEB 原生字段冲突 | `eb_user` 新增字段可能影响原有查询 | ALTER TABLE 使用 `DEFAULT 0`,不破坏现有 NULL 约束 |
|
||||
|
||||
---
|
||||
|
||||
## 五、当前可立即下达的指令(Agent 参考)
|
||||
|
||||
按优先级排序,每条指令对应一个独立任务,完成后 `git commit` 即可:
|
||||
|
||||
```
|
||||
1. feat(P1D-01): 首页报单商品角标与公排快捷入口
|
||||
文件: pages/index/index.vue
|
||||
|
||||
2. feat(P1D-05): 推荐收益页积分替换佣金
|
||||
文件: pages/users/user_spread_money/index.vue
|
||||
|
||||
3. feat(P1D-07): 个人中心嵌入HjfMemberBadge等级徽章
|
||||
文件: pages/user/index.vue
|
||||
|
||||
4. feat(P1G-02): Admin商品编辑报单标记与积分支付配置
|
||||
文件: admin/src/pages/product/creatProduct/index.vue
|
||||
```
|
||||
37
docs/fsgx-issues-0325-1.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# uniapp移动端
|
||||
|
||||
## 会员码页面(pages/users/user_member_code/index)
|
||||
- 1. 前端页面报错:
|
||||
` [渲染层网络层错误] Failed to load local image resource /pages/users/user_member_code/false
|
||||
the server responded with a status of 500 (HTTP/1.1 500 Internal Server Error) `
|
||||
|
||||
## 分销海报页面(pages/users/user_spread_code/index)
|
||||
- 1. 海报加载不出来
|
||||
|
||||
## 我的资产-》账单明细页面(pages/users/user_bill/index)
|
||||
- 1. 去掉公排退款
|
||||
|
||||
## 页面: pages/queue/status
|
||||
- 1. 左上角增加返回按钮
|
||||
|
||||
## 页面:pages/assets/index
|
||||
- 1. "累计获得积分"不显示数据,是否没读取到数据?
|
||||
- 2. 左上角增加返回按钮
|
||||
|
||||
---
|
||||
|
||||
# 其他测试问题
|
||||
|
||||
- 1. 自己不报单(没有购买过报单商品的订单),推荐没有返现佣金的,
|
||||
- 2. 判断升级成为**会员分销等级**前,不给奖励积分(直推奖励积分、伞下奖励积分),
|
||||
- 3. 目前积分奖励是按订单数量来给了,需要调整为按报单商品数量,比如一次性下一个订单含3个报单商品,应该给1500积分,而不是500,
|
||||
- 4. 创客级别的分销员,伞下下单没有**伞下奖励积分**,升级为云店级别分销员之后,只要级别低于自己的,伞下下单都应有**伞下奖励积分**
|
||||
- 5. 用户ID=14直推了2单就升级成为创客的**分销等级**了,但是目前分销等级中创客的升级任务配置的是直推3单?
|
||||
- 6. **推荐返现循环**目前配置的是"[20,30,50]"。为何用户ID=14直推了2单出现了2次20%的返现佣金?
|
||||
- 7. e2e测试验收一下分销员等级中配置的奖励积分(直推奖励积分、伞下奖励积分)和等级任务是否正确?
|
||||
|
||||
# 相关文件
|
||||
|
||||
- 1. **相关文件**:`docs/PRD_fsgx_V1.0.md` `docs/page-dev-specs-fsgx.md`,
|
||||
|
||||
|
||||
37
docs/fsgx-issues-0327-1.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# 核心功能测试结果
|
||||
|
||||
- 分销员直推没有获得返现佣金,测试数据:uid=20升级为创客分销等级后,下级用户下报单商品订单支付后,uid=20并没有eb_user_brokerage返现佣金记录。
|
||||
- 分销海报页面, pages/users/user_spread_code/index, 获取不到二维码
|
||||
fetch("https://www.fsgx.cn/api/user/routine_code", {
|
||||
"headers": {
|
||||
"accept": "*/*",
|
||||
"accept-language": "zh-CN,zh;q=0.9",
|
||||
"authori-zation": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoIjoiMTRlMWI2MDBiMWZkNTc5ZjQ3NDMzYjg4ZThkODUyOTEiLCJpc3MiOiJ3d3cuZnNneC5jbiIsImF1ZCI6Ind3dy5mc2d4LmNuIiwiaWF0IjoxNzc0NjY2NzA1LCJuYmYiOjE3NzQ2NjY3MDUsImV4cCI6MTc3NTI3MTUwNSwianRpIjp7ImlkIjoyMCwidHlwZSI6InJvdXRpbmUifX0.lbxfmmPVMNFpZmx9EXcb_7viz-YeMC_QymX6tiuCkD4",
|
||||
"cache-control": "no-cache",
|
||||
"content-type": "application/json",
|
||||
"form-type": "routine",
|
||||
"pragma": "no-cache",
|
||||
"sec-fetch-dest": "empty",
|
||||
"sec-fetch-mode": "cors",
|
||||
"sec-fetch-site": "cross-site",
|
||||
"x-source": "370474988fa2275c"
|
||||
},
|
||||
"referrer": "https://servicewechat.com/wx998d9e0a925a1a13/devtools/page-frame.html",
|
||||
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||
"body": null,
|
||||
"method": "GET",
|
||||
"mode": "cors",
|
||||
"credentials": "omit"
|
||||
});
|
||||
{"status":200,"msg":"ok","data":{"url":false}}
|
||||
|
||||
- `pro_v3.5.1/.cursor/plans/fix_issues_0325-1_f8488785.plan.md`对文档中“B7. e2e 测试验收分销员等级配置(测试问题 #7)”执行e2e测试
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 测试
|
||||
|
||||
# 相关文件
|
||||
1. **相关文件**:`docs/PRD_fsgx_V1.0.md` `docs/page-dev-specs-fsgx.md`,`pro_v3.5.1/.cursor/plans/fix_issues_0325-1_f8488785.plan.md`
|
||||
|
||||
35
docs/fsgx-issues-0328-1.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# uniapp移动端
|
||||
|
||||
## 佣金记录页面
|
||||
- 1. **已修复**点击“查看全部”时出现参数错误,是不是路径错误?
|
||||
|
||||
## 提现页面,pages/users/user_cash/index
|
||||
- 1. **已修复**提现到余额,不收取手续费
|
||||
|
||||
## 佣金状态页面,pages/queue/status
|
||||
- 1. **已修复**顶部保持和pages/users/user_cash/index页面中的class="cash-withdrawal"的背影色样式一致
|
||||
|
||||
## 我的资产页面,pages/assets/index
|
||||
- 1. **已修复**顶部保持和pages/users/user_cash/index页面中的class="cash-withdrawal"的背影色样式一致
|
||||
|
||||
# API接口
|
||||
|
||||
## fsgx每日积分释放
|
||||
- 1. 手动触发接口就释放一次当日积分,没有看到用户的冻结积分被释放,没有看到任务执行记录
|
||||
请求接口:https://www.fsgx.cn/adminapi/system/timer/run_now/21
|
||||
响应 ```{"status":200,"msg":"任务已触发并执行成功","data":{"result":null}}```
|
||||
|
||||
---
|
||||
|
||||
# 其他测试问题
|
||||
|
||||
## **测试问题**
|
||||
- 1. **已修复**返现佣金计算不对
|
||||
A. **已修复**目前新的分销员佣金是按20%,20%,30%,50%来计算的,前2个直推订单返现佣金都是20%,不对,应该是按配置的佣金分档比例(JSON)”[20,30,50]“的来轮巡执行佣金计算
|
||||
B. **已修复**一次下单购买多个报单商品的情况,佣金计算不对,目前按当前佣金比例的N倍来计算,应该按配置的佣金分档比例(JSON)”[20,30,50]“的来执行轮巡执行佣金计算
|
||||
|
||||
# 相关文件
|
||||
|
||||
- 1. **相关文件**:`docs/PRD_fsgx_V1.0.md` `docs/page-dev-specs-fsgx.md`,`.cursor/plans/fix_issues_0325-1_f8488785.plan.md`
|
||||
|
||||
|
||||
31
docs/fsgx-issues-0330-1.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# 测试问题
|
||||
|
||||
## 分销员的**直推积分奖励**问题1
|
||||
- **已检查**当前用户UID=30推荐UID=34推荐UID=31,现在UID=31购买的报单商品订单,
|
||||
检查UID=30创客是否有直推积分奖励,如果有是不对的,原因:UID=34,UID=30都是创客分销员,一个订单在同一个级别的分销员只能获得一次直推积分奖励,且是直推关系。
|
||||
|
||||
## 分销员的**直推积分奖励**问题2
|
||||
- case1: 当前用户UID=2推荐UID=46推荐UID=47,现在UID=47购买的报单商品订单情况下(目前数据库中有订单和用户数据),验证如下:
|
||||
检查UID=46是创客:
|
||||
UID=2是否有直推积分奖励,如果没有是不对的,原因:UID=2分销等级>UID=46,是应该获得直推积分奖励的差额部分,使用**直推积分奖励**的递归计算方法,逐一查询上级的直推积分奖励**直到最高分销等级结束**;
|
||||
检查UID=46还不是创客:
|
||||
UID=2是否有直推积分奖励,如果有是不对的,原因:不是直推关系;
|
||||
- case2: 当前用户UID=46推荐UID=47推荐UID=48,现在UID=48购买的报单商品订单情况下(目前数据库中有订单和用户数据),验证如下:
|
||||
检查UID=46应该没有直推积分奖励才对,因为UID=46不是UID=48的直接推荐人,
|
||||
- **直推积分奖励**落库的时候一定要检查直推关系。
|
||||
|
||||
|
||||
范氏国香,U1->U2->U54->U55->56, U2有购买记录的,U55和U56购买后,U1和U2都没有积分
|
||||
|
||||
## 新增**伞下积分奖励**开关功能
|
||||
- **已修复**新增伞下积分奖励开关功能,默认是关闭的
|
||||
|
||||
## 我的页面,pages/user/index
|
||||
- **已修复**隐藏“pages/users/user_member_code/index”入口
|
||||
|
||||
## 我的资产页面,pages/assets/index
|
||||
- **已修复**积分明细跳转路径修改为:pages/users/user_integral_detail/index
|
||||
- **已修复**顶部navbar改成和pages/users/user_spread_user/index页面一样的样式,同时美化页面其他部分的样式
|
||||
|
||||
## 佣金状态页面,pages/queue/status
|
||||
- **已修复**顶部navbar改成和pages/users/user_spread_user/index页面一样的样式,同时美化页面其他部分的样式
|
||||
144
docs/fsgx-phase7-config-checklist.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# 范氏国香商城 — Phase 7 后台配置与验收清单
|
||||
|
||||
> 本文档为运营人员在部署后,通过 CRMEB 管理后台完成配置的操作指南,同时提供全链路测试步骤。
|
||||
|
||||
---
|
||||
|
||||
## 7.1 执行数据库迁移
|
||||
|
||||
在服务器上执行以下 SQL 迁移脚本(每次部署后执行一次,使用 `INSERT IGNORE` 和 `ADD COLUMN IF NOT EXISTS` 保证幂等性):
|
||||
|
||||
```bash
|
||||
mysql -u root -p fsgx-shop < pro_v3.5.1/help/migrations/fsgx_v1.sql
|
||||
```
|
||||
|
||||
**迁移内容:**
|
||||
- `eb_store_product` 新增 `is_queue_goods` 字段
|
||||
- `eb_store_order` 新增 `is_queue_goods` 字段(冗余,加速佣金计数)
|
||||
- `eb_user` 新增 `frozen_points`、`available_points`、`no_assess` 字段
|
||||
- `eb_system_config` 插入 4 个返佣配置键
|
||||
- `eb_system_timer` 插入每日积分释放定时任务
|
||||
|
||||
---
|
||||
|
||||
## 7.2 后台分销等级配置
|
||||
|
||||
路径:**营销 → 分销 → 分销等级**
|
||||
|
||||
创建以下 4 个等级(按顺序,level 值 1~4):
|
||||
|
||||
| 等级 | 名称 | 直推人数条件 | 伞下有效订单数 | 佣金上浮比例 |
|
||||
|------|-------|------------|--------------|------------|
|
||||
| 1 | 创客 | 直推 ≥ 1 人 | - | +0% |
|
||||
| 2 | 云店 | 直推 ≥ 3 人 | - | +5% |
|
||||
| 3 | 服务商 | 直推 ≥ 10 人 | 伞下 ≥ 30 单 | +10% |
|
||||
| 4 | 分公司 | 直推 ≥ 30 人 | 伞下 ≥ 100 单 | +15% |
|
||||
|
||||
> 注意:等级升级任务条件可根据业务调整,以上为推荐默认值。
|
||||
|
||||
---
|
||||
|
||||
## 7.3 后台运营配置
|
||||
|
||||
### 7.3.1 开启人人分销
|
||||
|
||||
路径:**营销 → 分销 → 分销设置**
|
||||
|
||||
- 分销功能:**开启**
|
||||
- 分销类型:**人人分销**(所有用户均可参与)
|
||||
|
||||
### 7.3.2 返佣设置(fsgx 周期佣金)
|
||||
|
||||
路径:**营销 → 分销 → 返佣设置 → 推荐佣金(fsgx)Tab**
|
||||
|
||||
| 配置项 | 推荐值 | 说明 |
|
||||
|--------------|----------------|----------------------------------|
|
||||
| 佣金周期人数 | `3` | 推荐3人为一个完整周期 |
|
||||
| 各档佣金比例 | `[20,30,50]` | 第1人20%,第2人30%,第3人50%,JSON格式 |
|
||||
| 返佣范围 | 仅报单商品 | 仅 `is_queue_goods=1` 的商品参与 |
|
||||
| 佣金发放时机 | 支付即发放 | 用户付款后立即发放佣金 |
|
||||
|
||||
> 如果返佣设置页面没有"推荐佣金(fsgx)"Tab,请确认已运行 `fsgx_v1.sql` 迁移脚本。
|
||||
|
||||
### 7.3.3 提现设置
|
||||
|
||||
路径:**财务 → 分销财务 → 提现设置(已存在)**
|
||||
|
||||
- 提现手续费率:`7%`
|
||||
- 最低提现金额:`100 元`
|
||||
- 支持提现方式:微信零钱、支付宝、银行卡
|
||||
|
||||
### 7.3.4 报单商品配置
|
||||
|
||||
路径:**商品 → 商品列表 → 编辑目标商品 → 其他设置**
|
||||
|
||||
- 将参与周期佣金的商品标记为"报单商品"(`is_queue_goods = 1`)
|
||||
- 建议在商品名称/描述中注明"报单商品"
|
||||
|
||||
---
|
||||
|
||||
## 7.4 全链路验收测试
|
||||
|
||||
### 测试环境准备
|
||||
|
||||
1. 准备 3 个测试账号:`用户A`(推荐人)、`用户B/C/D`(被推荐人)
|
||||
2. 确保用户B/C/D 通过用户A 的邀请链接注册(绑定 `spread_uid = A.uid`)
|
||||
3. 准备至少 1 个标记了 `is_queue_goods=1` 的报单商品
|
||||
|
||||
### 测试步骤
|
||||
|
||||
#### Step 1:注册与推荐关系绑定
|
||||
|
||||
- [ ] 用户B 通过用户A 邀请链接打开小程序并注册
|
||||
- [ ] 后台验证:`eb_user.spread_uid = A.uid`
|
||||
|
||||
#### Step 2:购买报单商品(第1人)
|
||||
|
||||
- [ ] 用户B 购买报单商品并支付成功
|
||||
- [ ] 验证用户A 获得第1周期佣金(应为商品价格的 **20%**)
|
||||
- [ ] 验证用户A 的 `frozen_points` 增加
|
||||
- [ ] 小程序"推荐佣金"页:`cycle_current = 1/3`
|
||||
|
||||
#### Step 3:购买报单商品(第2人)
|
||||
|
||||
- [ ] 用户C 通过用户A 邀请链接注册并购买报单商品
|
||||
- [ ] 验证用户A 获得第2周期佣金(应为商品价格的 **30%**)
|
||||
- [ ] 小程序"推荐佣金"页:`cycle_current = 2/3`
|
||||
|
||||
#### Step 4:购买报单商品(第3人,完成一个周期)
|
||||
|
||||
- [ ] 用户D 通过用户A 邀请链接注册并购买报单商品
|
||||
- [ ] 验证用户A 获得第3周期佣金(应为商品价格的 **50%**)
|
||||
- [ ] 验证:一个周期累计佣金 = 商品价格的 **100%**
|
||||
- [ ] 小程序"推荐佣金"页:`cycle_current = 0/3`(新周期开始)
|
||||
|
||||
#### Step 5:分销等级自动升级验证
|
||||
|
||||
- [ ] 用户A 直推了3人(B/C/D),满足"云店"升级条件(直推≥3人)
|
||||
- [ ] 后台验证:`eb_user.agent_level = 2`(云店)
|
||||
- [ ] 小程序个人中心:等级标签显示"云店"
|
||||
|
||||
#### Step 6:积分释放验证
|
||||
|
||||
- [ ] 等待次日 2:00 AM 定时任务执行(或手动触发测试)
|
||||
- [ ] 验证:用户A 的 `frozen_points` 减少 0.4‰,`available_points` 对应增加
|
||||
- [ ] 后台积分日志页(/admin/hjf/points/log)可查看释放记录
|
||||
|
||||
#### Step 7:提现流程验证
|
||||
|
||||
- [ ] 用户A 在小程序申请提现(输入金额)
|
||||
- [ ] 验证手续费率 7% 正确扣除
|
||||
- [ ] 后台审核通过后,`brokerage_price` 对应减少
|
||||
|
||||
---
|
||||
|
||||
## 7.5 异常场景验收
|
||||
|
||||
- [ ] 非报单商品(`is_queue_goods=0`)下单:验证不触发周期佣金计算(`brokerage_scope=queue_only` 时)
|
||||
- [ ] 报单商品订单确认页:验证"积分抵扣"入口不显示
|
||||
- [ ] 不考核用户购买报单商品:佣金仍正常发放给推荐人
|
||||
- [ ] 管理后台用户列表:可见 `frozen_points`、`available_points` 两列,并可操作"不考核"
|
||||
|
||||
---
|
||||
|
||||
*以上配置完成后,范氏国香商城 fsgx 改造即告完成,可正式上线运营。*
|
||||
14
docs/issues-0321-1.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# 管理后台
|
||||
|
||||
## 分销员等级页面路径:/admin/setting/membership_level/index
|
||||
1. 列表中显示“直推奖励积分、伞下奖励积分”字段
|
||||
|
||||
## 用户列表页面路径:/admin/user/list
|
||||
0. 分销等级名称与库不一致(如 uid=1、`agent_level=2` 仍显示「0普通会员」)
|
||||
1. 列表中显示“可用积分、待释放(冻结)积分“字段
|
||||
2. 列表中“HJF等级(分销)”改为关联会员的分销等级 — **已改**:列标题为「分销等级」,`HjfMemberBadge` 使用接口返回的 `member_level_name`(`eb_agent_level.name`),筛选区文案为「分销等级」。
|
||||
3. 分销等级名称与库不一致(如 uid=1、`agent_level=2` 仍显示「等级二」)— **已修**:`UserServices::index` 与 `MemberLevelServices::getUserLevelName` 经 `AgentLevelServices::pickHjfLevelRowForUserListDisplay` 解析——若 `agent_level` 指向 CRMEB 默认行(名称非创客/云店/服务商/分公司)但 `grade` 与 HJF 官方等级一致,则展示改为该 grade 下的 HJF 官方行;并保留「仅 is_del=0」「id 未命中时按 grade 回退」等逻辑。
|
||||
|
||||
|
||||
## 商品列表页面路径:/admin/product/product_list
|
||||
1. 列表不显示商品 — **已修**:`crmeb/basic/BaseController.php` 被替换为明文 stub 后,与 Swoole 加密的 `config/auth.php` 不兼容,导致 Model 初始化时授权回调在 line 82 抛异常,所有商品查询均返回 400。已从 `feature/fsgx` 分支恢复加密版 `BaseController.php` 和 `Common.php`。
|
||||
63
docs/issues-0323-1.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# 管理后台
|
||||
|
||||
## 编辑商品页面,路径:admin/product/add_product?id=18&from_page=1
|
||||
|
||||
1. **已修复**是否报单商品:1=是,修改保存后没有更新数据库中的值
|
||||
|
||||
## 返佣设置页面,路径:/admin/setting/system_config_rake_back
|
||||
|
||||
1. **已修复**”返佣范围、佣金发放时机“修改后保存不落库(数据库没有修改)
|
||||
2. **已修复**推荐佣金(fsgx)tab页中”返佣范围、佣金发放时机“没有显示选中项
|
||||
|
||||
## 用户列表页面,路径: /admin/user/list
|
||||
|
||||
1. **已修复**操作“不考核”,提交后报错
|
||||
2. **已修复**HJF等级改为分销等级,但是没有关联用户的分销等级,没显示数据(queue分支下该功能是ok的)
|
||||
|
||||
## 分销等级页面,路径:admin/setting/membership_level/index
|
||||
|
||||
1. **已修复**列表中显示“直推奖励积分、伞下奖励积分”和升级等级任务(queue分支下该功能是ok的,可以直接合并过来)
|
||||
|
||||
## 定时任务页面,路径:/admin/system/crontab
|
||||
|
||||
1. **已修复**增加“手动触发”功能按钮,可以手动触发即执行任务立,
|
||||
2. **已修复**手动触发“fsgx每日积分释放”任务失败,
|
||||
|
||||
|
||||
## 用户列表页面,路径:/admin/user/list
|
||||
1. **已修复**“直推人数满、伞下订单数”没有显示数据,参考分销员管理页面实现逻辑(/admin/agent/agent_manage/index)实现数据显示。
|
||||
|
||||
---
|
||||
|
||||
|
||||
# uniapp移动端
|
||||
|
||||
## 修改密码页面
|
||||
1. **已修复**点击获取验证,去除安全验证,直接发送验证码
|
||||
|
||||
## 佣金记录页面,uniapp/pages/users/user_spread_money
|
||||
1. **已修复**团队业绩统计数据的伞下人数不显示
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 测试
|
||||
|
||||
## 测试数据:
|
||||
|
||||
1. 测试账号:UID:1, 手机号:1860001111; UID:2, 手机号:18621813282 ;UID:3, 手机号:17887996868 ;
|
||||
UID:4, 手机号:15324401259;UID:5, 手机号:17887996868; UID:6, 手机号:15821676725; 测试账号密码默认:A123456
|
||||
2. 推荐关系: uid=2推荐uid=4,uid=5, uid=6
|
||||
3. **已修复**uid=4,5,6购买报单商品后推荐人uid=2没有佣金/返现产生,
|
||||
4. 分销会员uid=2的积分奖励“待释放(冻结)积分”没有
|
||||
|
||||
|
||||
## 手动测试问题
|
||||
|
||||
1. 排查原因:eb_store_order报单商品订单完成后在管理后台中的2个页面看不到奖励积分明细,
|
||||
2. 积分日志页面/admin/marketing/user_point/index看不到奖励积分明细,
|
||||
3. 推荐人会员(直推积分奖励、伞下积分奖励获得者)的待释放积分(`frozen_points`)的值没有update,
|
||||
4. 同时没有记录报单商品订单产生的待释放积分明细记录:eb_user_bill表中status=0,type=integral,title=直推积分奖励 | 伞下积分奖励
|
||||
5. **已修复**佣金记录页面/admin/finance/finance/commission中用户返现佣金记录详情中看不到返现佣金明细
|
||||
6. **相关文件**:`docs/PRD_fsgx_V1.0.md` `docs/page-dev-specs-fsgx.md`,
|
||||
|
||||
34
docs/nginx-hjf-cloud.conf.example
Normal file
@@ -0,0 +1,34 @@
|
||||
# 云服务器 hjf.suzhouyuqi.com 站点 Nginx 配置示例
|
||||
# 用于宝塔/LNMP:复制到站点配置或 include 使用
|
||||
# 关键:root 指向 public,静态文件 /static/、/assets/、/pages/ 由 Nginx 直接提供
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl http2;
|
||||
server_name hjf.suzhouyuqi.com;
|
||||
root /www/wwwroot/hjf.suzhouyuqi.com/public;
|
||||
index index.html index.php;
|
||||
|
||||
# SSL 证书(宝塔通常自动配置)
|
||||
# ssl_certificate ...
|
||||
# ssl_certificate_key ...
|
||||
|
||||
# H5 静态资源:直接由 Nginx 提供,避免返回 HTML 导致 "Unexpected token '<'"
|
||||
location ~ ^/(static|assets|pages)/ {
|
||||
try_files $uri =404;
|
||||
expires 7d;
|
||||
}
|
||||
|
||||
# PHP 请求(按现有 Swoole/php-fpm 配置)
|
||||
location ~ \.php$ {
|
||||
proxy_pass http://127.0.0.1:20199;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
# 其余请求:先找静态文件,再走入口
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
}
|
||||
846
docs/page-dev-specs-fsgx.md
Normal file
@@ -0,0 +1,846 @@
|
||||
# 范氏国香商城 · 页面开发说明文档(V2 — 基于分销模块复用)
|
||||
|
||||
> 对应 PRD:`docs/PRD_fsgx_V1.0.md`
|
||||
> 技术底座:CRMEB Pro v3.5 二次开发(UniApp + iView Admin)
|
||||
> 文档日期:2026-03-23
|
||||
> 文档状态:V2 — 基于分销模块最大化复用原则修订
|
||||
|
||||
---
|
||||
|
||||
## 核心原则
|
||||
|
||||
> **最大限度复用 CRMEB 分销模块**:
|
||||
> 1. "创客/云店/服务商/分公司"四级体系 → 使用 CRMEB **分销等级**(`agent_level` 表)
|
||||
> 2. "推荐佣金 20/30/50"→ 在 CRMEB **分销佣金**(`brokerage`)计算链路上改造
|
||||
> 3. 佣金配置 → 扩展 CRMEB **返佣设置**(`rake_back`)
|
||||
> 4. 佣金记录 → 复用 CRMEB **佣金记录**(`UserBrokerage` / `UserBill`)
|
||||
> 5. 推荐关系 → 复用 CRMEB **推广关系**(`spread_uid`)
|
||||
> 6. 提现 → 复用 CRMEB **提现功能**(`extract`)
|
||||
> 7. 仅在 CRMEB 不覆盖的功能点上做自定义扩展(积分释放、报单标记等)
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
- [Part 1: 小程序端(UniApp)](#part-1-小程序端uniapp)
|
||||
- [1.1 新用户引导页](#11-新用户引导页)
|
||||
- [1.2 登录页](#12-登录页)
|
||||
- [1.3 首页](#13-首页)
|
||||
- [1.4 商品详情页](#14-商品详情页)
|
||||
- [1.5 订单确认页](#15-订单确认页)
|
||||
- [1.6 支付结果页](#16-支付结果页)
|
||||
- [1.7 推荐佣金进度页](#17-推荐佣金进度页)
|
||||
- [1.8 佣金收益页](#18-佣金收益页)
|
||||
- [1.9 推荐佣金规则说明页](#19-推荐佣金规则说明页)
|
||||
- [1.10 个人中心页](#110-个人中心页)
|
||||
- [1.11 我的资产页](#111-我的资产页)
|
||||
- [1.12 积分明细页](#112-积分明细页)
|
||||
- [1.13 推广中心/团队页](#113-推广中心团队页)
|
||||
- [1.14 提现页](#114-提现页)
|
||||
- [Part 2: 管理后台(Admin Vue)](#part-2-管理后台admin-vue)
|
||||
- [2.1 分销员管理](#21-分销员管理)
|
||||
- [2.2 佣金记录](#22-佣金记录)
|
||||
- [2.3 返佣设置](#23-返佣设置)
|
||||
- [2.4 分销等级管理](#24-分销等级管理)
|
||||
- [2.5 积分日志](#25-积分日志)
|
||||
- [2.6 商品编辑 - 报单标记](#26-商品编辑---报单标记)
|
||||
- [2.7 商品列表](#27-商品列表)
|
||||
- [2.8 提现申请管理](#28-提现申请管理)
|
||||
- [2.9 用户管理](#29-用户管理)
|
||||
- [Part 3: 后端改造要点](#part-3-后端改造要点)
|
||||
- [3.1 佣金计算链路改造](#31-佣金计算链路改造)
|
||||
- [3.2 分销等级映射](#32-分销等级映射)
|
||||
- [3.3 积分体系(自定义扩展)](#33-积分体系自定义扩展)
|
||||
- [Part 4: 公共组件与 API 层](#part-4-公共组件与-api-层)
|
||||
- [4.1 UniApp 组件](#41-uniapp-组件)
|
||||
- [4.2 API 文件](#42-api-文件)
|
||||
- [4.3 Mock 数据](#43-mock-数据)
|
||||
|
||||
---
|
||||
|
||||
## 模块映射总览
|
||||
|
||||
| fsgx 需求 | CRMEB 分销模块对应 | 改造方式 |
|
||||
|---|---|---|
|
||||
| 推荐关系绑定 | `spread_uid`(推广关系) | 直接复用 |
|
||||
| 推荐佣金 20/30/50 | 一级佣金 `one_brokerage` | 改造计算逻辑:从固定比例改为周期循环比例 |
|
||||
| 创客/云店/服务商/分公司 | `agent_level`(分销等级) | 配置 4 个分销等级,升级条件对齐 |
|
||||
| 等级积分奖励 | 暂无直接对应 | 在佣金发放链路上新增积分奖励逻辑 |
|
||||
| 佣金提现 | `extract`(提现模块) | 直接复用,手续费配置为 7% |
|
||||
| 佣金记录 | `UserBrokerage` / `UserBill` | 直接复用 |
|
||||
| 推广中心 | `user_spread_user` / `user_spread_money` | 复用 + 文案改造 |
|
||||
| 返佣配置 | `rake_back`(返佣设置) | 扩展:增加周期人数、分段比例、返佣范围 |
|
||||
| 分销员管理 | `agentManage`(分销员管理) | 直接复用 |
|
||||
| 佣金财务流水 | `finance/commission`(佣金记录) | 直接复用 |
|
||||
| 报单商品标记 | `is_queue_goods`(自定义字段) | 自定义扩展 |
|
||||
| 积分释放 | 无对应 | 自定义扩展 |
|
||||
|
||||
---
|
||||
|
||||
## Part 1: 小程序端(UniApp)
|
||||
|
||||
基础路径:`pro_v3.5.1/view/uniapp/`
|
||||
|
||||
---
|
||||
|
||||
### 1.1 新用户引导页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/guide/hjf_intro.vue` |
|
||||
| 路由 | `pages/guide/hjf_intro`(pages.json,custom nav) |
|
||||
| 当前状态 | **需改造(文案)** |
|
||||
| PRD 章节 | 4.1 登录与注册 — 新用户引导(P1) |
|
||||
| 优先级 | P1 |
|
||||
|
||||
**改造要点**
|
||||
|
||||
仅更新 `MOCK_GUIDE_DATA` 中的轮播文案:
|
||||
|
||||
| slide | 当前文案 | 目标文案 |
|
||||
|---|---|---|
|
||||
| 1 | 欢迎来到黄精粉健康商城 | 欢迎来到范氏国香商城 |
|
||||
| 2 | 公排返利机制 — 每进4单退1单 | 推荐佣金 — 邀请3人购买即可免单 |
|
||||
| 3 | 会员积分体系 — 推荐好友即获积分 | 分级积分奖励 — 升级后推荐再得积分 |
|
||||
|
||||
**验收标准**
|
||||
|
||||
- 文案为推荐佣金叙事,品牌名为"范氏国香"
|
||||
- 阅读完成后写入本地标记不再重复展示
|
||||
|
||||
---
|
||||
|
||||
### 1.2 登录页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/users/login/index.vue` |
|
||||
| 当前状态 | **CRMEB 直接复用** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
CRMEB 分销模块的 `spread` 参数绑定机制完全满足需求。确认以下逻辑正常:
|
||||
|
||||
- 分享链接携带 `spread` / `spid` 参数
|
||||
- 首次登录自动绑定 `spread_uid`,不可篡改
|
||||
- 绑定推荐关系后自动成为推广人(需后台"人人分销"开启)
|
||||
|
||||
**依赖 API**
|
||||
|
||||
- CRMEB 原有授权/手机号绑定接口
|
||||
|
||||
**验收标准**
|
||||
|
||||
- 推荐关系绑定正确
|
||||
- 后台"人人分销"开启后,新注册用户自动成为分销员
|
||||
|
||||
---
|
||||
|
||||
### 1.3 首页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/index/index.vue` |
|
||||
| 当前状态 | **CRMEB DIY 直接复用** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
无代码改动,仅通过后台 DIY 配置报单商品(4333 元)推荐位。
|
||||
|
||||
---
|
||||
|
||||
### 1.4 商品详情页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/goods_details/index.vue` |
|
||||
| 当前状态 | **需改造(文案 + 逻辑)** |
|
||||
| PRD 章节 | 4.3 商品与购买(P0) |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 说明 |
|
||||
|---|---|
|
||||
| 报单标记文案 | `is_queue_goods` 标记文案从"公排商品"改为"报单商品" |
|
||||
| 佣金提示 | 报单商品展示"推荐好友购买,可获佣金奖励" |
|
||||
| 佣金展示 | 复用 CRMEB 商品详情中的"预计佣金"展示(`product.attrInfo.brokerage`) |
|
||||
| 积分支付 | 报单商品隐藏积分支付入口 |
|
||||
|
||||
**依赖 API**
|
||||
|
||||
- `GET /api/product/detail/{id}` — CRMEB 原有(含 `is_queue_goods`、佣金信息)
|
||||
|
||||
**验收标准**
|
||||
|
||||
- 报单商品展示"报单商品"角标 + 佣金提示
|
||||
- 普通商品展示标准详情
|
||||
- 佣金金额显示正确
|
||||
|
||||
---
|
||||
|
||||
### 1.5 订单确认页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/goods/order_confirm/index.vue` |
|
||||
| 当前状态 | **需改造** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 说明 |
|
||||
|---|---|
|
||||
| 积分支付过滤 | 报单商品(`is_queue_goods === 1`)禁用积分支付 |
|
||||
| 佣金预览 | 复用 CRMEB 订单确认中的佣金计算,展示"本单推荐人可获佣金 ¥X" |
|
||||
|
||||
**依赖 API**
|
||||
|
||||
- `POST /api/order/confirm` / `POST /api/order/create` — CRMEB 原有
|
||||
|
||||
---
|
||||
|
||||
### 1.6 支付结果页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/goods/order_pay_status/index.vue` |
|
||||
| 当前状态 | **需改造(文案)** |
|
||||
| 优先级 | P1 |
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 当前 | 目标 |
|
||||
|---|---|---|
|
||||
| 报单商品提示 | "您的订单已进入公排队列" | "支付成功!推荐好友购买可获得佣金" |
|
||||
| 跳转按钮 | "查看公排状态" | "查看推荐佣金"→ 跳转 `pages/queue/status` |
|
||||
|
||||
---
|
||||
|
||||
### 1.7 推荐佣金进度页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/queue/status.vue` |
|
||||
| 当前状态 | **核心改造** |
|
||||
| PRD 章节 | 4.4 推荐裂变 — 佣金进度(P0) |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**功能描述(目标)**
|
||||
|
||||
展示当前用户的推荐佣金周期进度:
|
||||
|
||||
- 顶部:周期进度环(第 N 人 / 共 3 人,已获佣金 X%)
|
||||
- 中部:三段进度条(20% → 30% → 50%),标注每档完成状态
|
||||
- 底部:我的佣金记录列表
|
||||
|
||||
**实现方案 — 基于分销模块**
|
||||
|
||||
| 数据来源 | CRMEB 模块 | 说明 |
|
||||
|---|---|---|
|
||||
| 佣金进度 | 统计用户下级购买报单商品数量 | 对 `spread_uid` 下级的报单商品订单计数,取模周期人数得当前位次 |
|
||||
| 佣金记录 | `UserBrokerage` 佣金记录 | 筛选类型 `get_brokerage`(一级佣金),即为推荐佣金记录 |
|
||||
| 累计佣金 | `brokerage_price`(佣金余额) | CRMEB 用户表已有字段 |
|
||||
|
||||
**API 接口**
|
||||
|
||||
复用 CRMEB 原有接口 + 新增 1 个进度聚合接口:
|
||||
|
||||
```
|
||||
GET /api/hjf/brokerage/progress (新增)
|
||||
|
||||
Response:
|
||||
{
|
||||
cycle_total: 3, // 周期人数(来自 rake_back 配置)
|
||||
cycle_current: 1, // 当前周期已完成人数
|
||||
cycle_rates: [20, 30, 50], // 各档比例(来自 rake_back 配置)
|
||||
total_brokerage: "4333.00" // 累计佣金收入
|
||||
}
|
||||
|
||||
GET /api/spread/commission/detail?page=1&limit=15 (CRMEB 原有,佣金明细)
|
||||
```
|
||||
|
||||
**依赖组件**
|
||||
|
||||
- `HjfQueueProgress` → 改造为周期进度环组件
|
||||
|
||||
**验收标准**
|
||||
|
||||
- 进度环数据与用户实际推荐报单商品订单数一致
|
||||
- 佣金记录列表复用佣金明细数据
|
||||
- 空态引导文案
|
||||
|
||||
---
|
||||
|
||||
### 1.8 佣金收益页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/users/user_spread_money/index.vue` |
|
||||
| 当前状态 | **CRMEB 复用 + 文案确认** |
|
||||
| PRD 章节 | 4.4 推荐裂变 — 推荐收益列表(P1) |
|
||||
| 优先级 | P1 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
CRMEB 原有"佣金收益"页面已包含:佣金明细列表、收入/支出 Tab、分页加载。直接复用,无需改造文案(本身就叫"佣金")。
|
||||
|
||||
**注意**:原 `pages/queue/history.vue` 不再作为独立入口,改为跳转到此页面,或将 `history.vue` 重定向到 `user_spread_money`。
|
||||
|
||||
**依赖 API**
|
||||
|
||||
- `GET /api/spread/commission/detail` — CRMEB 原有佣金明细
|
||||
|
||||
**验收标准**
|
||||
|
||||
- 列表展示佣金收入记录
|
||||
- 分页正常
|
||||
|
||||
---
|
||||
|
||||
### 1.9 推荐佣金规则说明页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/queue/rules.vue` |
|
||||
| 当前状态 | **核心改造(静态文案)** |
|
||||
| 优先级 | P1 |
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 当前 | 目标 |
|
||||
|---|---|---|
|
||||
| 机制标题 | "进四退一流程" | "推荐佣金流程" |
|
||||
| 流程图 | 4 人入队触发退款 | A 推荐 B/C/D,A 获 20%/30%/50% 佣金 |
|
||||
| 示例金额 | ¥3,600 | ¥4,333 |
|
||||
| 等级说明 | 无 | 新增"升级创客后,每单额外获得 500 积分"说明 |
|
||||
|
||||
---
|
||||
|
||||
### 1.10 个人中心页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/user/index.vue` |
|
||||
| 当前状态 | **需改造(文案 + 入口)** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 当前 | 目标 |
|
||||
|---|---|---|
|
||||
| 入口文案 | "公排查询" | "推荐佣金" |
|
||||
| 跳转路径 | `/pages/queue/status` | 保持不变 |
|
||||
| 等级展示 | class `vip` 区域 | 改为从 CRMEB `agent_level_name`(分销等级名称)获取,显示"创客/云店/服务商/分公司" |
|
||||
| 推广中心入口 | CRMEB 原有"分销中心"入口 | 确认可见,文案可改为"推广中心" |
|
||||
|
||||
**依赖 API**
|
||||
|
||||
- `GET /api/user` — CRMEB 原有(含 `agent_level`、`brokerage_price` 等字段)
|
||||
|
||||
---
|
||||
|
||||
### 1.11 我的资产页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/assets/index.vue` |
|
||||
| 当前状态 | **需改造** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 当前 | 目标 |
|
||||
|---|---|---|
|
||||
| 现金余额 | 展示 `now_money` | 改为展示 `brokerage_price`(佣金余额),或两者都展示 |
|
||||
| 来源文案 | "公排累计退款" | "推荐累计佣金" |
|
||||
| 统计字段 | `total_queue_refund` | 改为累计佣金收入(从 `UserBrokerage` 汇总) |
|
||||
|
||||
**API 接口**
|
||||
|
||||
```
|
||||
GET /api/hjf/assets/overview (保留的自定义聚合接口)
|
||||
|
||||
Response:
|
||||
{
|
||||
brokerage_price: "7200.00", // 佣金余额(可提现)= CRMEB user.brokerage_price
|
||||
frozen_points: 15000, // 待释放积分(自定义)
|
||||
available_points: 3200, // 已释放积分(自定义)
|
||||
today_release: 6, // 今日释放量(自定义)
|
||||
total_brokerage: "14400.00", // 累计佣金收入
|
||||
total_points_earned: 18200,
|
||||
agent_level: 2,
|
||||
agent_level_name: "云店" // 来自 CRMEB agent_level
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.12 积分明细页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/assets/points_detail.vue` |
|
||||
| 当前状态 | **保持(自定义模块)** |
|
||||
| 优先级 | P1 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
积分释放体系(待释放/已释放/每日释放)为自定义扩展,不属于 CRMEB 分销模块。保持现有实现,集成时 `USE_MOCK` 改为 `false`。
|
||||
|
||||
---
|
||||
|
||||
### 1.13 推广中心/团队页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/users/user_spread_user/index.vue` |
|
||||
| 当前状态 | **CRMEB 复用 + 增强** |
|
||||
| PRD 章节 | 4.4 推荐裂变(P1) |
|
||||
| 优先级 | P1 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
CRMEB 原有"推广中心"页面已包含:直推成员列表、推广人数统计、推广海报。
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 说明 |
|
||||
|---|---|
|
||||
| 顶部增加 | 嵌入佣金周期进度摘要组件(复用 `HjfQueueProgress`) |
|
||||
| 数据增强 | 每个成员增加"是否已购报单商品"标记(需后端接口增加字段) |
|
||||
|
||||
**依赖 API**
|
||||
|
||||
- `GET /api/spread/people` — CRMEB 推广人列表
|
||||
- `GET /api/spread/count` — CRMEB 推广统计
|
||||
- `GET /api/hjf/brokerage/progress` — 自定义进度聚合
|
||||
|
||||
---
|
||||
|
||||
### 1.14 提现页
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/users/user_cash/index.vue` |
|
||||
| 当前状态 | **CRMEB 直接复用** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
CRMEB 提现功能完全满足需求:提现金额输入、手续费计算(后台配 7%)、渠道选择、提交审核。
|
||||
|
||||
确认后台 `rake_back` 配置中 `extract_time`(佣金冻结天数)和手续费率配置正确即可。
|
||||
|
||||
---
|
||||
|
||||
## Part 2: 管理后台(Admin Vue)
|
||||
|
||||
基础路径:`pro_v3.5.1/view/admin/src/`
|
||||
|
||||
---
|
||||
|
||||
### 2.1 分销员管理
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/agent/agentManage.vue` |
|
||||
| 路由 | `/admin/agent/agent_manage/index`(CRMEB 原有) |
|
||||
| 当前状态 | **CRMEB 直接复用** |
|
||||
| PRD 章节 | 5.2 用户管理(P0) |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
CRMEB 原有"分销员管理"页面已包含:分销员列表、筛选(等级/昵称/手机号)、推广人列表弹窗(含推广订单、佣金字段)、统计卡片。
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 说明 |
|
||||
|---|---|
|
||||
| 等级筛选 | 确认下拉中包含"创客/云店/服务商/分公司"选项(来自 `agent_level` 配置) |
|
||||
|
||||
**验收标准**
|
||||
|
||||
- 分销员列表展示正确
|
||||
- 推广人列表弹窗可查看推荐关系与佣金明细
|
||||
|
||||
---
|
||||
|
||||
### 2.2 佣金记录
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/finance/commission/index.vue` |
|
||||
| 路由 | `/admin/finance/finance/commission`(CRMEB 原有) |
|
||||
| 当前状态 | **CRMEB 直接复用** |
|
||||
| PRD 章节 | 5.5 财务管理 — 佣金流水(P0) |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
CRMEB 原有"佣金记录"页面已包含:佣金流水列表、用户/时间/金额筛选、明细弹窗。所有通过分销佣金发放的记录自动出现在此页面。
|
||||
|
||||
**注意**:原 `pages/hjf/queueFinance` **不再需要**,其功能完全由 CRMEB 佣金记录覆盖。
|
||||
|
||||
---
|
||||
|
||||
### 2.3 返佣设置
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | 系统配置 `rake_back` Tab(通过 `SystemConfigServices::rakeBackFormBuild` 生成) |
|
||||
| 路由 | `/admin/setting/system_config_rake_back`(CRMEB 原有) |
|
||||
| 当前状态 | **需改造(核心)** |
|
||||
| PRD 章节 | 5.6 营销配置中心(P0) |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**功能描述**
|
||||
|
||||
CRMEB 返佣设置页面,通过 `rakeBackFormBuild` 方法动态生成表单。
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 当前 | 目标 |
|
||||
|---|---|---|
|
||||
| 一级返佣比例 | 固定百分比 `store_brokerage_ratio` | 改为多段比例:支持配置周期人数 + 各档比例(如 3 人循环 20/30/50) |
|
||||
| 二级返佣 | `store_brokerage_two` | 保留,或设为 0(fsgx 无二级返佣需求) |
|
||||
| 新增配置 | — | `brokerage_cycle_count`(周期人数,默认 3) |
|
||||
| 新增配置 | — | `brokerage_cycle_rates`(各档比例 JSON,如 `[20,30,50]`) |
|
||||
| 新增配置 | — | `brokerage_scope`(返佣范围:`all` 所有商品 / `queue_only` 仅报单商品) |
|
||||
| 新增配置 | — | `brokerage_timing`(发放时机:`on_pay` 支付即发 / `on_confirm` 确认收货后) |
|
||||
|
||||
**后端改造**
|
||||
|
||||
- `SystemConfigServices::rakeBackFormBuild()` — 新增上述配置字段的表单项
|
||||
- `SystemConfigValidate` — 增加对应验证规则
|
||||
- `eb_system_config` 表 — 新增配置键值对
|
||||
|
||||
**验收标准**
|
||||
|
||||
- 返佣设置页展示新增配置项
|
||||
- 保存后配置值正确持久化
|
||||
- 佣金计算链路读取新配置生效
|
||||
|
||||
---
|
||||
|
||||
### 2.4 分销等级管理
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/setting/membershipLevel/index.vue` |
|
||||
| 路由 | `/admin/setting/membership_level/index`(CRMEB 原有) |
|
||||
| 当前状态 | **CRMEB 复用 + 配置对齐** |
|
||||
| PRD 章节 | 5.6 营销配置 — 等级门槛与奖励(P0) |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
使用 CRMEB 分销等级(`agent_level` 表)管理"创客/云店/服务商/分公司"。
|
||||
|
||||
**配置要求**
|
||||
|
||||
在后台配置 4 个分销等级:
|
||||
|
||||
| 等级 | 名称 | 升级条件(等级任务) | 一级佣金上浮 | 二级佣金上浮 |
|
||||
|---|---|---|---|---|
|
||||
| Lv.1 | 创客 | 直推满 3 单 | 按需配置 | 0 |
|
||||
| Lv.2 | 云店 | 伞下满 30 单(至少 3 直推) | 按需配置 | 按需配置 |
|
||||
| Lv.3 | 服务商 | 伞下满 100 单(至少 3 直推) | 按需配置 | 按需配置 |
|
||||
| Lv.4 | 分公司 | 伞下满 1000 单(至少 3 直推) | 按需配置 | 按需配置 |
|
||||
|
||||
**等级任务配置**
|
||||
|
||||
通过 CRMEB 的"等级任务"机制(`agent_level_task` 表)设置升级条件:
|
||||
|
||||
- 任务类型:推广人数(直推)、推广订单数(伞下)
|
||||
- 升级条件自动判定,满足后自动升级
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 说明 |
|
||||
|---|---|
|
||||
| 等级数据 | 在后台创建 4 个等级 + 对应等级任务 |
|
||||
| 佣金上浮 | 等级的 `one_brokerage`/`two_brokerage` 字段配置上浮百分比,通过 `AgentLevelServices::getAgentLevelBrokerage` 自动叠加到基础比例 |
|
||||
| 积分奖励 | 需在佣金发放链路中新增积分逻辑(见 Part 3) |
|
||||
|
||||
**注意**:原 `pages/hjf/memberLevel` 和 `pages/hjf/memberConfig` **不再需要**,其功能由 CRMEB 分销等级管理覆盖。
|
||||
|
||||
**依赖 API**
|
||||
|
||||
- `GET /adminapi/agent/level` — CRMEB 分销等级列表
|
||||
- `POST /adminapi/agent/level` — 创建等级
|
||||
- `PUT /adminapi/agent/level/{id}` — 编辑等级
|
||||
- `GET /adminapi/agent/level_task` — 等级任务管理
|
||||
|
||||
---
|
||||
|
||||
### 2.5 积分日志
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/hjf/pointsLog/index.vue` |
|
||||
| 路由 | `/admin/hjf/points/log`(自定义路由,保留) |
|
||||
| 当前状态 | **保持(自定义模块)** |
|
||||
| 优先级 | P1 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
积分释放体系为自定义扩展,CRMEB 分销模块不覆盖。保留现有 `pointsLog` 页面,集成时 `USE_MOCK` 改 `false`。
|
||||
|
||||
---
|
||||
|
||||
### 2.6 商品编辑 - 报单标记
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/product/productAdd/components/otherSet.vue` |
|
||||
| 当前状态 | **缺陷修复(P0)** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**缺陷说明**
|
||||
|
||||
`is_queue_goods` 修改保存后未更新数据库(`issues-0323-1.md`)。
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 说明 |
|
||||
|---|---|
|
||||
| 前端 | 确认 `is_queue_goods` 包含在商品保存 payload |
|
||||
| 后端 | 确认 `StoreProductServices` 保存时处理 `is_queue_goods` |
|
||||
| 佣金联动 | 当 `brokerage_scope = queue_only` 时,仅报单商品参与佣金计算 |
|
||||
|
||||
---
|
||||
|
||||
### 2.7 商品列表
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/product/productList/index.vue` |
|
||||
| 当前状态 | **已修复,确认稳定** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
报单商品 Tab 筛选已修复。确认 `is_queue_goods` 筛选生效即可。
|
||||
|
||||
---
|
||||
|
||||
### 2.8 提现申请管理
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/finance/userExtract/index.vue` |
|
||||
| 路由 | `/admin/finance/user_extract/index`(CRMEB 原有) |
|
||||
| 当前状态 | **CRMEB 直接复用** |
|
||||
| PRD 章节 | 5.5 财务管理 — 提现审核(P0) |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**复用说明**
|
||||
|
||||
CRMEB 提现管理完全满足需求。确认手续费率 7% 在 `rake_back` 配置中正确设置。
|
||||
|
||||
---
|
||||
|
||||
### 2.9 用户管理
|
||||
|
||||
| 属性 | 内容 |
|
||||
|---|---|
|
||||
| 页面路径 | `pages/user/list/index.vue` |
|
||||
| 当前状态 | **需增强** |
|
||||
| 优先级 | P0 |
|
||||
|
||||
**改造要点**
|
||||
|
||||
| 改造项 | 说明 |
|
||||
|---|---|
|
||||
| 新增列 | 分销等级名称(`agent_level_name`,CRMEB 已支持) |
|
||||
| 新增列 | 待释放积分(`frozen_points`)、已释放积分(`available_points`)— 自定义字段 |
|
||||
| 操作增强 | "调整分销等级"按钮 → 调用 CRMEB `agentManage/giveAgentLevel` 接口 |
|
||||
| 操作增强 | "设置不考核"开关 → 自定义接口 `hjf/member/{uid}/no_assess` |
|
||||
|
||||
**依赖 API**
|
||||
|
||||
- `GET /adminapi/user/user` — CRMEB 用户列表
|
||||
- `POST /adminapi/agent/manage/give_agent_level` — CRMEB 赋予分销等级
|
||||
- `PUT /adminapi/hjf/member/{uid}/no_assess` — 自定义不考核设置
|
||||
|
||||
---
|
||||
|
||||
## Part 3: 后端改造要点
|
||||
|
||||
---
|
||||
|
||||
### 3.1 佣金计算链路改造(核心)
|
||||
|
||||
**改造位置**:`app/services/order/StoreOrderCreateServices.php`(计算佣金金额)+ `app/services/order/StoreOrderTakeServices.php`(发放佣金)
|
||||
|
||||
**当前逻辑**
|
||||
|
||||
```
|
||||
一级佣金 = 商品价格 × (store_brokerage_ratio + 等级上浮)
|
||||
```
|
||||
|
||||
**目标逻辑**
|
||||
|
||||
```
|
||||
1. 读取 brokerage_scope 配置:
|
||||
- 若 queue_only,仅 is_queue_goods=1 的商品参与
|
||||
2. 查询推荐人当前周期位置:
|
||||
- 统计推荐人下级购买报单商品的有效订单数
|
||||
- position = count % cycle_count (0-indexed)
|
||||
3. 当前单的佣金比例 = cycle_rates[position]
|
||||
4. 一级佣金 = 商品实付金额 × 当前比例%
|
||||
5. 若推荐人有分销等级(创客及以上),额外发放积分奖励
|
||||
```
|
||||
|
||||
**关键文件**
|
||||
|
||||
| 文件 | 改造说明 |
|
||||
|---|---|
|
||||
| `app/services/order/StoreOrderCreateServices.php` | 修改佣金金额计算:从固定比例改为查询周期位次后取对应比例 |
|
||||
| `app/services/order/StoreOrderTakeServices.php` | `backOrderBrokerage` 方法:发放佣金时,若有分销等级则额外调用积分奖励逻辑 |
|
||||
| `app/services/agent/AgentLevelServices.php` | `getAgentLevelBrokerage`:确认等级佣金上浮逻辑与周期比例的叠加方式(加法 or 替代) |
|
||||
| `app/services/system/config/SystemConfigServices.php` | `rakeBackFormBuild`:新增周期配置表单 |
|
||||
|
||||
**数据表变更**
|
||||
|
||||
| 表 | 变更 |
|
||||
|---|---|
|
||||
| `eb_system_config` | 新增键:`brokerage_cycle_count`、`brokerage_cycle_rates`、`brokerage_scope`、`brokerage_timing` |
|
||||
| `eb_user`(可选) | 新增字段:`frozen_points`、`available_points`、`no_assess`(若积分模块需要) |
|
||||
|
||||
---
|
||||
|
||||
### 3.2 分销等级映射
|
||||
|
||||
使用 CRMEB `agent_level` 表,无需新建等级表。
|
||||
|
||||
| fsgx 等级 | agent_level 配置 | 等级任务 |
|
||||
|---|---|---|
|
||||
| 创客 | Lv.1, name="创客" | 任务:直推报单商品订单 ≥ 3 |
|
||||
| 云店 | Lv.2, name="云店" | 任务:伞下报单商品订单 ≥ 30,且直推 ≥ 3 |
|
||||
| 服务商 | Lv.3, name="服务商" | 任务:伞下报单商品订单 ≥ 100,且直推 ≥ 3 |
|
||||
| 分公司 | Lv.4, name="分公司" | 任务:伞下报单商品订单 ≥ 1000,且直推 ≥ 3 |
|
||||
|
||||
**注意**:CRMEB 等级任务可能不直接支持"仅计报单商品订单"的条件,需确认 `AgentLevelTaskServices` 是否支持自定义筛选,或需改造任务判定逻辑。
|
||||
|
||||
---
|
||||
|
||||
### 3.3 积分体系(自定义扩展)
|
||||
|
||||
积分释放(待释放/已释放/每日释放)不属于 CRMEB 分销模块,保持为自定义扩展:
|
||||
|
||||
- 在佣金发放时(`StoreOrderTakeServices::backOrderBrokerage`),若推荐人有分销等级,同步发放积分到 `frozen_points`
|
||||
- 定时任务:每日将 `frozen_points` 的 0.4‰ 转入 `available_points`
|
||||
- 积分消费:购买普通商品时扣减 `available_points`
|
||||
|
||||
---
|
||||
|
||||
## Part 4: 公共组件与 API 层
|
||||
|
||||
---
|
||||
|
||||
### 4.1 UniApp 组件
|
||||
|
||||
基础路径:`pro_v3.5.1/view/uniapp/components/`
|
||||
|
||||
| 组件 | 文件 | 改造说明 | 优先级 |
|
||||
|---|---|---|---|
|
||||
| HjfQueueProgress | `HjfQueueProgress.vue` | 改为佣金周期进度环:接收 `cycleCurrent/cycleTotal/cycleRates` | P0 |
|
||||
| HjfRefundNotice | `HjfRefundNotice.vue` | 改为佣金到账通知弹窗 | P0 |
|
||||
| HjfAssetCard | `HjfAssetCard.vue` | 文案"公排退款"→"推荐佣金";余额来源改为 `brokerage_price` | P1 |
|
||||
| HjfMemberBadge | `HjfMemberBadge.vue` | 保持,等级名称来源改为 `agent_level_name` | P1 |
|
||||
| HjfDemoPanel | `HjfDemoPanel.vue` | 保持不变(调试用) | — |
|
||||
|
||||
---
|
||||
|
||||
### 4.2 API 文件
|
||||
|
||||
#### 可移除/简化的 API 文件
|
||||
|
||||
由于分销模块复用,以下自定义 API 可简化:
|
||||
|
||||
| 文件 | 当前 | 目标 |
|
||||
|---|---|---|
|
||||
| UniApp `hjfQueue.js` | 公排状态/历史(Mock) | 仅保留 `getBrokerageProgress()` 一个聚合接口;佣金记录由 CRMEB 佣金明细接口代替 |
|
||||
| UniApp `hjfMember.js` | 会员信息/团队(Mock) | 由 CRMEB `spread` 系列接口代替,可移除 |
|
||||
| Admin `hjfQueue.js` | 公排订单/配置/财务(Mock) | 移除:佣金订单由 CRMEB 佣金记录代替;配置由 `rake_back` 代替 |
|
||||
| Admin `hjfMember.js` | 会员列表/配置/等级(Mock) | 移除:由 CRMEB `agent_level` 接口代替 |
|
||||
|
||||
#### 保留的自定义 API 文件
|
||||
|
||||
| 文件 | 用途 |
|
||||
|---|---|
|
||||
| UniApp `hjfAssets.js` | 资产聚合接口(余额+积分+佣金统计),`USE_MOCK` 改 `false` |
|
||||
| Admin `hjfPoints.js` | 积分释放日志,`USE_MOCK` 改 `false` |
|
||||
|
||||
#### 新增接口汇总
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|---|---|---|
|
||||
| `/api/hjf/brokerage/progress` | GET | 佣金周期进度聚合(周期位次、比例、累计佣金) |
|
||||
| `/api/hjf/assets/overview` | GET | 资产总览聚合(佣金余额+积分+等级) |
|
||||
|
||||
---
|
||||
|
||||
### 4.3 Mock 数据
|
||||
|
||||
| 文件 | 改造说明 |
|
||||
|---|---|
|
||||
| UniApp `hjfMockData.js` | 公排模块数据替换为佣金数据(字段对齐佣金结构);`total_queue_refund` → `total_brokerage`;引导文案更新 |
|
||||
| Admin `hjfMockData.js` | 移除公排 Mock(`MOCK_QUEUE_*`);会员 Mock 保持(`MOCK_MEMBER_*`)直到 CRMEB 接口完全对接 |
|
||||
|
||||
---
|
||||
|
||||
## 附录:pages.json 路由改造
|
||||
|
||||
| 路由 | 当前标题 | 目标标题 |
|
||||
|---|---|---|
|
||||
| `pages/queue/status` | `公排状态` | `推荐佣金` |
|
||||
| `pages/queue/history` | `公排历史` | `佣金记录`(或重定向到 `user_spread_money`) |
|
||||
| `pages/queue/rules` | `公排规则` | `佣金规则` |
|
||||
|
||||
---
|
||||
|
||||
## 附录:Admin 路由改造
|
||||
|
||||
原 `hjfQueue.js` 路由精简:
|
||||
|
||||
| 路由 | 当前 | 目标 |
|
||||
|---|---|---|
|
||||
| `queue/order` | 公排订单管理 | **移除**,使用 CRMEB `/admin/finance/finance/commission` |
|
||||
| `queue/finance` | 公排财务流水 | **移除**,使用 CRMEB `/admin/finance/finance/commission` |
|
||||
| `queue/config` | 公排配置 | **移除**,使用 CRMEB `/admin/setting/system_config_rake_back` |
|
||||
| `member/level` | 会员等级管理 | **移除**,使用 CRMEB `/admin/agent/agent_manage/index` |
|
||||
| `member/config` | 会员配置 | **移除**,使用 CRMEB `/admin/setting/membership_level/index` |
|
||||
| `points/log` | 积分日志 | **保留** |
|
||||
|
||||
精简后 `hjfQueue.js` 路由仅保留 `points/log`,建议重命名文件为 `hjfCustom.js`。
|
||||
|
||||
---
|
||||
|
||||
## 附录:开发优先级总览
|
||||
|
||||
| 优先级 | 页面/任务 | 数量 |
|
||||
|---|---|---|
|
||||
| **P0** | 佣金计算链路改造(后端核心)、返佣设置扩展、商品编辑修复、分销等级配置、推荐佣金进度页、订单确认页、个人中心、我的资产、登录、提现、商品列表、用户管理增强、HjfQueueProgress 组件 | 13 |
|
||||
| **P1** | 佣金规则说明页、佣金收益页确认、积分明细、推广中心增强、积分日志 Mock 切换、HjfAssetCard/HjfMemberBadge 文案、引导页文案、支付结果文案 | 8 |
|
||||
| **P2** | 首页 DIY 配置 | 1 |
|
||||
|
||||
---
|
||||
|
||||
## 附录:被移除/合并的自定义页面清单
|
||||
|
||||
以下原 `pages/hjf/` 页面因功能被 CRMEB 分销模块覆盖而**不再需要独立维护**:
|
||||
|
||||
| 原页面 | 替代方案 |
|
||||
|---|---|
|
||||
| `pages/hjf/queueOrder` | CRMEB `finance/commission`(佣金记录) |
|
||||
| `pages/hjf/queueFinance` | CRMEB `finance/commission`(佣金记录) |
|
||||
| `pages/hjf/queueConfig` | CRMEB `setting/system_config_rake_back`(返佣设置,扩展) |
|
||||
| `pages/hjf/memberLevel` | CRMEB `agent/agentManage`(分销员管理) |
|
||||
| `pages/hjf/memberConfig` | CRMEB `setting/membershipLevel`(分销等级管理) |
|
||||
| UniApp `pages/queue/history` | CRMEB `users/user_spread_money`(佣金收益),或保留并重定向 |
|
||||
19
docs/renew-code-comment.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# 替换源代码中原厂的信息
|
||||
|
||||
## 注解内容替换
|
||||
1. 查询源代码中注解:```// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>```
|
||||
替换为: ```
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
```
|
||||
2. 查询源代码中注解 `crmeb.com`替换为 `uj345.cn`
|
||||
|
||||
## 限制
|
||||
1. 仅限修改代码注释或不影响代码逻辑的部分,不修改代码逻辑。
|
||||
BIN
docs/测试结果0327.xlsx
Normal file
BIN
docs/测试结果0330.xlsx
Normal file
BIN
docs/范氏国香小程序fsgx-V1.0.docx
Normal file
BIN
docs/黄精粉小程序PRD&界面设计.docx
Normal file
289
pro_v3.5.1/.cursor/plans/fsgx_development_tasks_ff68a8e9.plan.md
Normal file
@@ -0,0 +1,289 @@
|
||||
---
|
||||
name: fsgx development tasks
|
||||
overview: 基于 page-dev-specs-fsgx.md(V2 分销模块复用方案),将全部开发工作拆解为 7 个阶段、24 个具体任务,按依赖关系排序,后端核心先行、前端改造跟进、最后清理与验收。
|
||||
todos:
|
||||
- id: p1-db-schema
|
||||
content: "Phase1: 数据表变更 — eb_system_config 新增 4 个配置键 + eb_user 新增 frozen_points/available_points/no_assess"
|
||||
status: completed
|
||||
- id: p1-rake-back
|
||||
content: "Phase1: 返佣设置扩展 — SystemConfigServices::rakeBackFormBuild() 新增周期人数、分段比例、返佣范围、发放时机表单项"
|
||||
status: completed
|
||||
- id: p1-brokerage-calc
|
||||
content: "Phase1: 佣金计算链路改造(核心)— StoreOrderCreateServices 周期循环比例 + StoreOrderTakeServices 积分发放"
|
||||
status: completed
|
||||
- id: p1-product-fix
|
||||
content: "Phase1: 商品报单标记修复 — otherSet.vue payload + StoreProductServices 保存 is_queue_goods"
|
||||
status: completed
|
||||
- id: p2-progress-api
|
||||
content: "Phase2: 新增 GET /api/hjf/brokerage/progress 佣金周期进度聚合接口"
|
||||
status: completed
|
||||
- id: p2-assets-api
|
||||
content: "Phase2: 新增 GET /api/hjf/assets/overview 资产总览聚合接口"
|
||||
status: completed
|
||||
- id: p2-points-cron
|
||||
content: "Phase2: 积分释放定时任务 — 每日 frozen_points 0.4‰ 转 available_points + 日志"
|
||||
status: completed
|
||||
- id: p2-no-assess-api
|
||||
content: "Phase2: 新增 PUT /adminapi/hjf/member/{uid}/no_assess 不考核接口"
|
||||
status: completed
|
||||
- id: p3-admin-route
|
||||
content: "Phase3: Admin 路由精简 — hjfQueue.js 移除 5 条旧路由,仅保留 points/log"
|
||||
status: completed
|
||||
- id: p3-admin-api-clean
|
||||
content: "Phase3: Admin API 清理 — 移除 hjfQueue.js 和 hjfMember.js"
|
||||
status: completed
|
||||
- id: p3-uniapp-api-clean
|
||||
content: "Phase3: UniApp API 简化 — hjfQueue.js 仅保留 getBrokerageProgress(),移除 hjfMember.js"
|
||||
status: completed
|
||||
- id: p3-pages-json
|
||||
content: "Phase3: pages.json 路由标题改造 — 公排状态/历史/规则 → 推荐佣金/佣金记录/佣金规则"
|
||||
status: completed
|
||||
- id: p4-queue-status
|
||||
content: "Phase4: 推荐佣金进度页核心改造 — pages/queue/status.vue 整体重写"
|
||||
status: completed
|
||||
- id: p4-goods-detail
|
||||
content: "Phase4: 商品详情页改造 — 报单标记文案 + 佣金提示 + 隐藏积分支付"
|
||||
status: completed
|
||||
- id: p4-order-confirm
|
||||
content: "Phase4: 订单确认页改造 — 报单商品禁用积分支付 + 佣金预览"
|
||||
status: completed
|
||||
- id: p4-user-center
|
||||
content: "Phase4: 个人中心页改造 — 入口文案 + 等级展示改为 agent_level_name"
|
||||
status: completed
|
||||
- id: p4-assets-page
|
||||
content: "Phase4: 我的资产页改造 — 余额来源 + 文案 + 对接聚合接口"
|
||||
status: completed
|
||||
- id: p4-components
|
||||
content: "Phase4: 组件改造 — HjfQueueProgress/HjfRefundNotice/HjfAssetCard"
|
||||
status: completed
|
||||
- id: p5-guide-text
|
||||
content: "Phase5: 引导页 + 规则页 + 支付结果页文案改造"
|
||||
status: completed
|
||||
- id: p5-spread-enhance
|
||||
content: "Phase5: 推广中心增强 — 嵌入佣金进度摘要 + 报单商品标记"
|
||||
status: completed
|
||||
- id: p5-mock-update
|
||||
content: "Phase5: Mock 数据更新 — 公排字段→佣金字段"
|
||||
status: completed
|
||||
- id: p6-admin-user
|
||||
content: "Phase6: Admin 用户管理增强 — 新增列 + 操作按钮"
|
||||
status: completed
|
||||
- id: p6-points-mock
|
||||
content: "Phase6: 积分日志 USE_MOCK 改 false"
|
||||
status: completed
|
||||
- id: p7-config-test
|
||||
content: "Phase7: 后台配置(分销等级 + 人人分销 + 返佣设置 + 提现费率)+ 全链路验收测试"
|
||||
status: completed
|
||||
isProject: false
|
||||
---
|
||||
|
||||
# 范氏国香商城 — 开发任务计划
|
||||
|
||||
基于 [docs/page-dev-specs-fsgx.md](docs/page-dev-specs-fsgx.md) 制定,按依赖关系分 7 个阶段执行。
|
||||
|
||||
---
|
||||
|
||||
## 依赖关系总览
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Phase1[Phase1_后端核心] --> Phase2[Phase2_后端接口]
|
||||
Phase1 --> Phase3[Phase3_前端清理]
|
||||
Phase2 --> Phase4[Phase4_前端P0改造]
|
||||
Phase3 --> Phase4
|
||||
Phase4 --> Phase5[Phase5_前端P1改造]
|
||||
Phase4 --> Phase6[Phase6_Admin增强]
|
||||
Phase5 --> Phase7[Phase7_配置验收]
|
||||
Phase6 --> Phase7
|
||||
```
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: 后端核心改造(P0,所有前端依赖此阶段)
|
||||
|
||||
### 1.1 数据表变更
|
||||
|
||||
- `eb_system_config` 新增 4 个配置键:`brokerage_cycle_count`、`brokerage_cycle_rates`、`brokerage_scope`、`brokerage_timing`
|
||||
- `eb_user` 新增字段:`frozen_points`、`available_points`、`no_assess`(积分模块用)
|
||||
|
||||
### 1.2 返佣设置扩展
|
||||
|
||||
- 文件:[app/services/system/config/SystemConfigServices.php](pro_v3.5.1/app/services/system/config/SystemConfigServices.php)
|
||||
- 在 `rakeBackFormBuild()` 方法中新增表单项:周期人数、各档比例 JSON、返佣范围(所有/仅报单)、发放时机(支付即发/确认收货后)
|
||||
- 增加验证规则
|
||||
|
||||
### 1.3 佣金计算链路改造(核心中的核心)
|
||||
|
||||
- 文件:[app/services/order/StoreOrderCreateServices.php](pro_v3.5.1/app/services/order/StoreOrderCreateServices.php)
|
||||
- 修改一级佣金计算:固定比例 → 查询推荐人下级报单商品有效订单数 → 取模周期人数得位次 → `cycle_rates[position]` 取当前比例
|
||||
- 判断 `brokerage_scope`:若 `queue_only` 则仅 `is_queue_goods=1` 的商品参与
|
||||
- 文件:[app/services/order/StoreOrderTakeServices.php](pro_v3.5.1/app/services/order/StoreOrderTakeServices.php)
|
||||
- `backOrderBrokerage` 方法:佣金发放后,若推荐人有分销等级,同步发放积分到 `frozen_points`
|
||||
|
||||
### 1.4 商品报单标记修复
|
||||
|
||||
- 前端:[view/admin/src/pages/product/productAdd/components/otherSet.vue](pro_v3.5.1/view/admin/src/pages/product/productAdd/components/otherSet.vue) — 确认 `is_queue_goods` 在保存 payload 中
|
||||
- 后端:`StoreProductServices` — 确认保存逻辑处理 `is_queue_goods` 字段写入
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: 后端新增接口 + 积分体系
|
||||
|
||||
### 2.1 佣金周期进度聚合接口
|
||||
|
||||
- 新增 `GET /api/hjf/brokerage/progress`
|
||||
- 逻辑:统计 `spread_uid` 下级购买报单商品的有效订单数,取模 `brokerage_cycle_count`,返回 `cycle_total`/`cycle_current`/`cycle_rates`/`total_brokerage`
|
||||
|
||||
### 2.2 资产总览聚合接口
|
||||
|
||||
- 新增 `GET /api/hjf/assets/overview`
|
||||
- 返回 `brokerage_price`(CRMEB 字段)+ `frozen_points`/`available_points`/`today_release`(自定义)+ `agent_level_name`(CRMEB 字段)
|
||||
|
||||
### 2.3 积分释放定时任务
|
||||
|
||||
- 定时任务:每日将 `frozen_points` 的 0.4‰ 转入 `available_points`
|
||||
- 积分消费扣减逻辑
|
||||
- 积分日志写入
|
||||
|
||||
### 2.4 不考核接口
|
||||
|
||||
- 新增 `PUT /adminapi/hjf/member/{uid}/no_assess`
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: 前端清理 — 移除旧模块
|
||||
|
||||
### 3.1 Admin 路由精简
|
||||
|
||||
- [view/admin/src/router/modules/hjfQueue.js](pro_v3.5.1/view/admin/src/router/modules/hjfQueue.js) — 移除 `queue/order`、`queue/finance`、`queue/config`、`member/level`、`member/config` 路由,仅保留 `points/log`
|
||||
- 建议重命名文件为 `hjfCustom.js`
|
||||
|
||||
### 3.2 Admin API 文件清理
|
||||
|
||||
- 移除 `admin/src/api/hjfQueue.js`(佣金订单/配置/财务由 CRMEB 佣金记录覆盖)
|
||||
- 移除 `admin/src/api/hjfMember.js`(由 CRMEB `agent_level` 接口覆盖)
|
||||
|
||||
### 3.3 UniApp API 文件简化
|
||||
|
||||
- `uniapp/api/hjfQueue.js` — 仅保留 `getBrokerageProgress()` 一个聚合接口,移除公排相关函数
|
||||
- `uniapp/api/hjfMember.js` — 可移除,由 CRMEB `spread` 系列接口替代
|
||||
|
||||
### 3.4 UniApp pages.json 路由标题改造
|
||||
|
||||
- `pages/queue/status`:公排状态 → 推荐佣金
|
||||
- `pages/queue/history`:公排历史 → 佣金记录(或重定向到 `user_spread_money`)
|
||||
- `pages/queue/rules`:公排规则 → 佣金规则
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: 前端 P0 改造
|
||||
|
||||
### 4.1 推荐佣金进度页(核心改造)
|
||||
|
||||
- [view/uniapp/pages/queue/status.vue](pro_v3.5.1/view/uniapp/pages/queue/status.vue) — 整体改造
|
||||
- 顶部:周期进度环(调用 `/api/hjf/brokerage/progress`)
|
||||
- 底部:佣金记录列表(调用 CRMEB `/api/spread/commission/detail`)
|
||||
- 组件 `HjfQueueProgress.vue` 改为佣金周期进度环
|
||||
|
||||
### 4.2 商品详情页改造
|
||||
|
||||
- [view/uniapp/pages/goods_details/index.vue](pro_v3.5.1/view/uniapp/pages/goods_details/index.vue)
|
||||
- "公排商品"→"报单商品"标记文案
|
||||
- 报单商品增加佣金提示
|
||||
- 报单商品隐藏积分支付入口
|
||||
|
||||
### 4.3 订单确认页改造
|
||||
|
||||
- [view/uniapp/pages/goods/order_confirm/index.vue](pro_v3.5.1/view/uniapp/pages/goods/order_confirm/index.vue)
|
||||
- 报单商品禁用积分支付
|
||||
- 展示"本单推荐人可获佣金 ¥X"
|
||||
|
||||
### 4.4 个人中心页改造
|
||||
|
||||
- [view/uniapp/pages/user/index.vue](pro_v3.5.1/view/uniapp/pages/user/index.vue)
|
||||
- "公排查询"→"推荐佣金"入口文案
|
||||
- 等级展示改为从 CRMEB `agent_level_name` 获取
|
||||
|
||||
### 4.5 我的资产页改造
|
||||
|
||||
- [view/uniapp/pages/assets/index.vue](pro_v3.5.1/view/uniapp/pages/assets/index.vue)
|
||||
- 余额来源改为 `brokerage_price`
|
||||
- "公排累计退款"→"推荐累计佣金"
|
||||
- 调用 `/api/hjf/assets/overview` 聚合接口
|
||||
|
||||
### 4.6 组件改造
|
||||
|
||||
- `HjfQueueProgress.vue` → 佣金周期进度环(props: `cycleCurrent/cycleTotal/cycleRates`)
|
||||
- `HjfRefundNotice.vue` → 佣金到账通知弹窗
|
||||
- `HjfAssetCard.vue` → 文案改为"推荐佣金",余额来源改为 `brokerage_price`
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: 前端 P1 改造
|
||||
|
||||
### 5.1 新用户引导页文案
|
||||
|
||||
- [view/uniapp/pages/guide/hjf_intro.vue](pro_v3.5.1/view/uniapp/pages/guide/hjf_intro.vue) + `hjfMockData.js`
|
||||
- 品牌名改为"范氏国香",公排叙事改为佣金叙事
|
||||
|
||||
### 5.2 佣金规则说明页改造
|
||||
|
||||
- [view/uniapp/pages/queue/rules.vue](pro_v3.5.1/view/uniapp/pages/queue/rules.vue)
|
||||
- "进四退一"→"推荐佣金流程",示例金额 ¥4,333
|
||||
- 新增等级积分说明
|
||||
|
||||
### 5.3 支付结果页文案
|
||||
|
||||
- [view/uniapp/pages/goods/order_pay_status/index.vue](pro_v3.5.1/view/uniapp/pages/goods/order_pay_status/index.vue)
|
||||
- "进入公排队列"→"推荐好友可获佣金"
|
||||
|
||||
### 5.4 推广中心增强
|
||||
|
||||
- [view/uniapp/pages/users/user_spread_user/index.vue](pro_v3.5.1/view/uniapp/pages/users/user_spread_user/index.vue)
|
||||
- 顶部嵌入佣金周期进度摘要
|
||||
- 成员列表增加"是否已购报单商品"标记
|
||||
|
||||
### 5.5 Mock 数据更新
|
||||
|
||||
- `hjfMockData.js`(UniApp + Admin)— 公排字段替换为佣金字段
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Admin 后台增强
|
||||
|
||||
### 6.1 用户管理增强
|
||||
|
||||
- [view/admin/src/pages/user/list/index.vue](pro_v3.5.1/view/admin/src/pages/user/list/index.vue)
|
||||
- 新增列:分销等级名称、待释放积分、已释放积分
|
||||
- 操作列增加"调整分销等级"和"设置不考核"按钮
|
||||
|
||||
### 6.2 积分日志 Mock 切换
|
||||
|
||||
- [view/admin/src/pages/hjf/pointsLog/index.vue](pro_v3.5.1/view/admin/src/pages/hjf/pointsLog/index.vue)
|
||||
- `USE_MOCK` 改为 `false`,对接真实接口
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: 配置与验收
|
||||
|
||||
### 7.1 后台分销等级配置
|
||||
|
||||
- 通过 CRMEB 后台创建 4 个分销等级(创客/云店/服务商/分公司)
|
||||
- 配置等级任务(直推人数、伞下订单数)
|
||||
- 配置各等级佣金上浮比例
|
||||
|
||||
### 7.2 后台运营配置
|
||||
|
||||
- 开启"人人分销"
|
||||
- 返佣设置:配置周期人数=3,比例=[20,30,50],范围=仅报单商品
|
||||
- 提现手续费率 7%
|
||||
- 首页 DIY 配置报单商品推荐位
|
||||
|
||||
### 7.3 全链路验收测试
|
||||
|
||||
- 注册→绑定推荐关系→购买报单商品→佣金计算→佣金发放→积分奖励→提现
|
||||
- 分销等级自动升级验证
|
||||
- 佣金周期进度正确性验证
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
name: fsgx page dev specs
|
||||
overview: 基于 PRD_fsgx_V1.0.md,创建一份以页面为单位的完整开发说明文档 docs/page-dev-specs-fsgx.md,涵盖小程序端和管理后台端所有需要新建或改造的页面,每页标注:当前状态、目标功能、API 依赖、改造要点和验收标准。
|
||||
todos:
|
||||
- id: write-page-dev-specs
|
||||
content: 在 docs/page-dev-specs-fsgx.md 编写完整的页面开发说明文档,涵盖小程序 14 页 + 管理后台 10 页 + 公共组件与 API 层
|
||||
status: completed
|
||||
isProject: false
|
||||
---
|
||||
|
||||
# 范氏国香页面开发说明文档
|
||||
|
||||
## 输出文件
|
||||
|
||||
创建 [docs/page-dev-specs-fsgx.md](docs/page-dev-specs-fsgx.md),以页面为单位组织,分为小程序端和管理后台端两大部分。
|
||||
|
||||
## 文档结构
|
||||
|
||||
### Part 1: 小程序端(UniApp)-- 共 14 个页面
|
||||
|
||||
按功能域分组:
|
||||
|
||||
**引导与登录(2 页)**
|
||||
|
||||
- `pages/guide/hjf_intro` -- 新用户引导轮播(当前:公排文案,改造为推荐返现叙事)
|
||||
- `pages/users/login/index` -- 登录页(CRMEB 复用,需确认推荐参数绑定逻辑)
|
||||
|
||||
**首页与商品(4 页)**
|
||||
|
||||
- `pages/index` -- 首页(CRMEB DIY 复用,需配置报单商品推荐区)
|
||||
- `pages/goods_details/index` -- 商品详情(改造:展示"报单商品"标记与返现提示)
|
||||
- `pages/goods/order_confirm/index` -- 订单确认(改造:积分支付逻辑、报单商品不可积分支付校验)
|
||||
- `pages/goods/order_pay_status/index` -- 支付结果(改造:支付成功后展示返现信息)
|
||||
|
||||
**推荐返现(3 页,核心改造区,原 queue/ 目录)**
|
||||
|
||||
- `pages/queue/status` → 改造为"推荐返现进度"(当前:公排状态)
|
||||
- `pages/queue/history` → 改造为"返现历史记录"(当前:公排历史)
|
||||
- `pages/queue/rules` → 改造为"推荐返现规则说明"(当前:进四退一规则)
|
||||
|
||||
**个人中心与资产(5 页)**
|
||||
|
||||
- `pages/user/index` -- 个人中心 Tab 页(改造:入口文案从"公排查询"改为"推荐返现")
|
||||
- `pages/assets/index` -- 我的资产(改造:余额来源从公排退款改为推荐返现)
|
||||
- `pages/assets/points_detail` -- 积分明细(保持,确认字段对齐)
|
||||
- `pages/users/user_spread_user/index` -- 我的推荐/团队(改造:增加返现周期进度展示)
|
||||
- `pages/users/user_cash/index` -- 提现页(CRMEB 复用,确认手续费 7%)
|
||||
|
||||
### Part 2: 管理后台(Admin Vue)-- 共 10 个页面
|
||||
|
||||
**自定义业务页(hjf/ 目录,6 页)**
|
||||
|
||||
- `pages/hjf/queueOrder` → 改造为"推荐返现订单管理"
|
||||
- `pages/hjf/queueFinance` → 改造为"返现财务流水"
|
||||
- `pages/hjf/queueConfig` → 改造为"返现配置"(周期人数 + 分段比例)
|
||||
- `pages/hjf/memberLevel` -- 会员等级管理(保持,确认接口对接)
|
||||
- `pages/hjf/memberConfig` -- 会员配置(保持,确认参数模型)
|
||||
- `pages/hjf/pointsLog` -- 积分日志(保持,确认日释放记录)
|
||||
|
||||
**CRMEB 改造页(4 页)**
|
||||
|
||||
- `pages/product/productAdd/components/otherSet` -- 商品编辑(修复 is_queue_goods 落库缺陷)
|
||||
- `pages/product/productList` -- 商品列表(保持,确认报单筛选)
|
||||
- `pages/setting/membershipLevel` -- 返佣设置(改造:返佣范围配置)
|
||||
- `pages/user/list` -- 用户管理(改造:增加等级调整、不考核开关)
|
||||
|
||||
### Part 3: 公共组件与 API 层
|
||||
|
||||
**UniApp 组件(5 个,需改造或新增)**
|
||||
|
||||
- `HjfQueueProgress` → 改为返现周期进度组件
|
||||
- `HjfRefundNotice` → 改为返现到账通知
|
||||
- `HjfAssetCard` -- 资产卡片(改造:余额来源文案)
|
||||
- `HjfMemberBadge` -- 等级徽章(保持)
|
||||
- `HjfDemoPanel` -- 演示面板(保持)
|
||||
|
||||
**API 文件改造(6 个文件)**
|
||||
|
||||
- UniApp: `hjfQueue.js` → 改为 rebate 接口, `hjfAssets.js`, `hjfMember.js`
|
||||
- Admin: `hjfQueue.js` → 改为 rebate 接口, `hjfMember.js`, `hjfPoints.js`
|
||||
|
||||
### 每个页面的说明模板
|
||||
|
||||
每页包含以下字段:
|
||||
|
||||
- 页面路径与路由
|
||||
- 当前状态(已有/需新建/需改造)
|
||||
- PRD 对应章节
|
||||
- 功能描述与交互流程
|
||||
- 依赖的 API 接口(含请求/响应格式)
|
||||
- 依赖的组件
|
||||
- 与当前版本的差异说明(如有)
|
||||
- 验收标准
|
||||
- 优先级(P0/P1/P2)
|
||||
|
||||
94
pro_v3.5.1/.cursor/plans/fsgx_prd_document_dc5247ea.plan.md
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
name: fsgx PRD document
|
||||
overview: 根据《范氏国香小程序fsgx-V1.0》需求文档,对照当前代码库(基于黄精粉 HJF PRD V2.0),编写一份新的 PRD 文档 `docs/PRD_fsgx_V1.0.md`,标注所有与当前版本不一致或当前版本不满足的功能点。
|
||||
todos:
|
||||
- id: write-prd
|
||||
content: 在 docs/PRD_fsgx_V1.0.md 编写完整的 PRD 文档,包含所有章节
|
||||
status: completed
|
||||
isProject: false
|
||||
---
|
||||
|
||||
# 范氏国香小程序 PRD 文档编写计划
|
||||
|
||||
## 文档输出
|
||||
|
||||
在 [docs/PRD_fsgx_V1.0.md](docs/PRD_fsgx_V1.0.md) 创建新的 PRD 文档。
|
||||
|
||||
## 关键差异分析结果
|
||||
|
||||
通过对比 fsgx V1.0 需求文档与当前代码库(HJF PRD V2.0 + 实际实现),识别出以下核心差异:
|
||||
|
||||
### 1. 品牌与商品变更
|
||||
|
||||
- 产品名称:黄精粉健康商城 → **范氏国香商城**
|
||||
- 核心商品:黄精粉套餐 3600 元/单 → **艾制品三条套餐 4333 元/单**
|
||||
- 产品定位:黄精粉(健康食品) → **艾制品(健康艾灸产品)**
|
||||
|
||||
### 2. 核心业务逻辑 -- 奖励机制(重大变更)
|
||||
|
||||
**当前版本(HJF)**:"公排进四退一"全局排队池机制,每进 4 单退 1 单全额返还。
|
||||
|
||||
**fsgx V1.0 要求**:"邀请三人自己免单"直推返现机制:
|
||||
|
||||
- 推荐第 1 人购买 → 推荐人获 **20%** 现金返还
|
||||
- 推荐第 2 人购买 → 推荐人获 **30%** 现金返还
|
||||
- 推荐第 3 人购买 → 推荐人获 **50%** 现金返还(合计 100% 免单)
|
||||
- 第 4 人起循环上述比例 + 额外积分奖励
|
||||
- 推荐人数和返现比例后台**可自由设置**
|
||||
|
||||
**影响范围**:
|
||||
|
||||
- 后端:需重写奖励计算引擎,从全局队列退款改为直推层级返现
|
||||
- 前端 uniapp:`pages/queue/` 下的公排页面需改造为推荐返现展示
|
||||
- 前端 admin:`pages/hjf/queueOrder/`、`queueConfig/`、`queueFinance/` 需改造
|
||||
- Mock 数据:`hjfMockData.js` 中的公排相关数据需替换为返现数据
|
||||
|
||||
### 3. 现金余额来源变更
|
||||
|
||||
- **当前版本**:公排退款 + 后台手动充值
|
||||
- **fsgx V1.0**:**推荐返现** + 后台手动充值(无公排退款概念)
|
||||
|
||||
### 4. 普通会员即可获得推荐奖励(变更)
|
||||
|
||||
- **当前版本**:普通会员无奖励,升级创客后才有直推积分
|
||||
- **fsgx V1.0**:普通会员升级为分销会员后直推即可获得 20%+30%+50% **现金**奖励;创客及以上额外获得**积分**奖励
|
||||
|
||||
### 5. 批量购买升级规则(新增)
|
||||
|
||||
- fsgx V1.0 新增:"一次购买多单时,如果符合升级条件,先升级,然后 N-1 单可额外获得积分奖励"
|
||||
- 当前版本无此逻辑
|
||||
|
||||
### 6. 订单取消方式(变更)
|
||||
|
||||
- **当前版本**:已付款订单不可取消,退款仅通过公排
|
||||
- **fsgx V1.0**:**可通过后台取消订单,实现全额返还**
|
||||
|
||||
### 7. 返佣配置参数(变更)
|
||||
|
||||
- **当前版本**:公排触发倍数(N=4)
|
||||
- **fsgx V1.0**:推荐奖励比例 = 3 人循环(20%+30%+50%),人数和比例均可配置
|
||||
|
||||
### 8. 一致保留的功能
|
||||
|
||||
以下功能 fsgx V1.0 与当前版本**一致**,无需变更:
|
||||
|
||||
- 四级分销等级体系(创客/云店/服务商/分公司)及升级门槛
|
||||
- 积分体系(待释放积分 → 按日 0.4% 释放 → 已释放积分)
|
||||
- 积分支付(仅普通商品)
|
||||
- 提现手续费 7%
|
||||
- 报单商品标记 `is_queue_goods`
|
||||
- 登录注册、首页、商品管理、订单管理、活动管理、内容管理等基础模块
|
||||
|
||||
## 文档结构
|
||||
|
||||
PRD 文档将包含以下章节:
|
||||
|
||||
1. **文档说明** -- 术语定义、版本信息
|
||||
2. **产品概述** -- 产品背景、定位、目标用户
|
||||
3. **核心业务逻辑** -- 推荐返现机制、会员等级、账户积分体系
|
||||
4. **用户端功能需求** -- 登录注册、首页、商品购买、推荐裂变、个人中心
|
||||
5. **管理后台功能需求** -- 仪表盘、用户管理、商品管理、订单管理、财务管理、活动管理、营销配置、内容管理、数据统计
|
||||
6. **与当前版本差异总结** -- 专门章节,表格列出所有差异项及影响评估
|
||||
7. **数据库改造方案**
|
||||
8. **非功能性需求**
|
||||
|
||||
@@ -322,7 +322,7 @@ php think swoole
|
||||
|
||||
5. 后台登录:
|
||||
http://域名/admin
|
||||
默认账号:admin 密码:A@123456
|
||||
默认账号:admin 密码:A@123456 或 A123456
|
||||
|
||||
|
||||
## 启动命令
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app;
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app;
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace app\command;
|
||||
|
||||
|
||||
133
pro_v3.5.1/app/command/HjfPatchMissingRewards.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use app\services\agent\AgentLevelServices;
|
||||
use app\services\hjf\PointsRewardServices;
|
||||
use app\services\user\UserServices;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 补偿历史报单订单缺失的积分奖励
|
||||
*
|
||||
* 用法:
|
||||
* php think hjf:patch-rewards # 扫描全部报单订单
|
||||
* php think hjf:patch-rewards --order-id=11 # 仅补偿指定订单
|
||||
* php think hjf:patch-rewards --dry-run # 仅扫描不执行
|
||||
*/
|
||||
class HjfPatchMissingRewards extends Command
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('hjf:patch-rewards')
|
||||
->setDescription('补偿历史报单订单缺失的冻结积分奖励')
|
||||
->addOption('order-id', null, Option::VALUE_OPTIONAL, '指定订单ID,不传则扫描全部')
|
||||
->addOption('dry-run', null, Option::VALUE_NONE, '仅扫描打印,不实际执行');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output): int
|
||||
{
|
||||
$orderId = $input->getOption('order-id');
|
||||
$dryRun = $input->getOption('dry-run');
|
||||
|
||||
$output->writeln('[HjfPatchRewards] 开始扫描缺失积分奖励的报单订单...');
|
||||
|
||||
$query = Db::name('store_order')
|
||||
->where('is_queue_goods', 1)
|
||||
->where('paid', 1)
|
||||
->where('is_del', 0)
|
||||
->where('is_system_del', 0);
|
||||
|
||||
if ($orderId) {
|
||||
$query->where('id', (int)$orderId);
|
||||
}
|
||||
|
||||
$orders = $query->field('id,order_id,uid,spread_uid,one_brokerage')->select()->toArray();
|
||||
|
||||
if (empty($orders)) {
|
||||
$output->writeln('[HjfPatchRewards] 没有找到符合条件的报单订单');
|
||||
return 0;
|
||||
}
|
||||
|
||||
$output->writeln(sprintf('[HjfPatchRewards] 找到 %d 笔报单订单', count($orders)));
|
||||
|
||||
/** @var PointsRewardServices $pointsService */
|
||||
$pointsService = app()->make(PointsRewardServices::class);
|
||||
/** @var AgentLevelServices $agentLevelServices */
|
||||
$agentLevelServices = app()->make(AgentLevelServices::class);
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
|
||||
$patched = 0;
|
||||
$skipped = 0;
|
||||
|
||||
foreach ($orders as $order) {
|
||||
// 幂等检查:points_release_log 中是否已有 reward_direct/reward_umbrella 记录
|
||||
$hasRewardLog = Db::name('points_release_log')
|
||||
->where('order_id', $order['order_id'])
|
||||
->whereIn('type', ['reward_direct', 'reward_umbrella'])
|
||||
->count();
|
||||
|
||||
if ($hasRewardLog > 0) {
|
||||
$skipped++;
|
||||
$output->writeln(sprintf(' [SKIP] 订单 #%d (%s) 已有积分奖励记录', $order['id'], $order['order_id']));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$order['spread_uid'] || $order['spread_uid'] <= 0) {
|
||||
$skipped++;
|
||||
$output->writeln(sprintf(' [SKIP] 订单 #%d (%s) 无推荐人', $order['id'], $order['order_id']));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($dryRun) {
|
||||
$output->writeln(sprintf(
|
||||
' [DRY-RUN] 订单 #%d (%s) uid=%d spread_uid=%d 需要补发积分',
|
||||
$order['id'], $order['order_id'], $order['uid'], $order['spread_uid']
|
||||
));
|
||||
$patched++;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$uid = (int)$order['uid'];
|
||||
// 先执行等级升级检查,确保积分奖励使用正确的 agent_level
|
||||
$userCacheInfo = $userServices->getUserCacheInfo($uid);
|
||||
$spreadUid = $userCacheInfo ? (int)($userCacheInfo['spread_uid'] ?? 0) : (int)$order['spread_uid'];
|
||||
$twoSpreadUid = 0;
|
||||
if ($spreadUid > 0 && $oneUserInfo = $userServices->getUserCacheInfo($spreadUid)) {
|
||||
$twoSpreadUid = $userServices->getSpreadUid($spreadUid, $oneUserInfo, false);
|
||||
}
|
||||
$uids = array_values(array_filter(array_unique([$uid, $spreadUid, $twoSpreadUid])));
|
||||
$agentLevelServices->checkUserLevelFinish($uid, $uids);
|
||||
|
||||
// 发放积分奖励(PointsRewardServices 内部已做幂等检查)
|
||||
$pointsService->reward($uid, (string)$order['order_id'], (int)$order['id']);
|
||||
$patched++;
|
||||
$output->writeln(sprintf(
|
||||
' [PATCHED] 订单 #%d (%s) uid=%d 等级检查+积分奖励已补发',
|
||||
$order['id'], $order['order_id'], $uid
|
||||
));
|
||||
} catch (\Throwable $e) {
|
||||
$output->writeln(sprintf(
|
||||
' [ERROR] 订单 #%d (%s): %s',
|
||||
$order['id'], $order['order_id'], $e->getMessage()
|
||||
));
|
||||
Log::error("[HjfPatchRewards] 订单 #{$order['id']} 补发失败: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$output->writeln(sprintf(
|
||||
'[HjfPatchRewards] 完成:补发 %d 笔,跳过 %d 笔%s',
|
||||
$patched, $skipped, $dryRun ? ' (dry-run 模式)' : ''
|
||||
));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
49
pro_v3.5.1/app/command/HjfReleasePoints.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use app\services\hjf\PointsReleaseServices;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
|
||||
/**
|
||||
* 积分每日释放命令
|
||||
*
|
||||
* 用法:
|
||||
* php think hjf:release-points
|
||||
*
|
||||
* 触发时机:
|
||||
* - 每天凌晨 00:01 由 crontab 或 Swoole Timer 调用
|
||||
* - P4-05 联调验证时手动执行
|
||||
*
|
||||
* Class HjfReleasePoints
|
||||
* @package app\command
|
||||
*/
|
||||
class HjfReleasePoints extends Command
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('hjf:release-points')
|
||||
->setDescription('执行黄精粉健康商城每日积分释放(frozen_points × 4‰ → available_points)');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output): int
|
||||
{
|
||||
$output->writeln('[HjfReleasePoints] 开始执行积分释放...');
|
||||
|
||||
/** @var PointsReleaseServices $service */
|
||||
$service = app()->make(PointsReleaseServices::class);
|
||||
$result = $service->executeRelease();
|
||||
|
||||
$output->writeln(sprintf(
|
||||
'[HjfReleasePoints] 完成:处理 %d 人,共释放 %d 积分,日期 %s',
|
||||
$result['processed'],
|
||||
$result['total_released'],
|
||||
$result['release_date']
|
||||
));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
170
pro_v3.5.1/app/command/HjfVerifyAgentConfig.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\command;
|
||||
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* e2e 验收:分销员等级配置检验命令
|
||||
*
|
||||
* 用法:
|
||||
* php think hjf:verify-agent-config
|
||||
*
|
||||
* 说明:
|
||||
* 验证 eb_agent_level 和 eb_agent_level_task 表中的数据配置与 PRD 3.2 一致。
|
||||
* 若不一致则输出差异明细并自动修正(--fix 参数),修正后输出最终结果。
|
||||
*
|
||||
* Class HjfVerifyAgentConfig
|
||||
* @package app\command
|
||||
*/
|
||||
class HjfVerifyAgentConfig extends Command
|
||||
{
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('hjf:verify-agent-config')
|
||||
->setDescription('e2e 验收分销员等级奖励积分与升级任务配置是否与 PRD 一致,传入 --fix 自动修正')
|
||||
->addOption('fix', null, \think\console\input\Option::VALUE_NONE, '自动修正不一致的配置');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output): int
|
||||
{
|
||||
$fix = (bool)$input->getOption('fix');
|
||||
$hasError = false;
|
||||
|
||||
$output->writeln('');
|
||||
$output->writeln('========================================================');
|
||||
$output->writeln(' HJF 分销员等级配置 e2e 验收');
|
||||
$output->writeln('========================================================');
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 1) eb_agent_level — 奖励积分配置(PRD 3.2)
|
||||
// ----------------------------------------------------------------
|
||||
$output->writeln('');
|
||||
$output->writeln('【1】eb_agent_level 奖励积分配置');
|
||||
$output->writeln('------------------------------------------------------------');
|
||||
|
||||
$expectedLevels = [
|
||||
1 => ['name_hint' => '创客', 'direct_reward_points' => 500, 'umbrella_reward_points' => 0],
|
||||
2 => ['name_hint' => '云店', 'direct_reward_points' => 800, 'umbrella_reward_points' => 300],
|
||||
3 => ['name_hint' => '服务中心', 'direct_reward_points' => 1000, 'umbrella_reward_points' => 200],
|
||||
4 => ['name_hint' => '合伙人', 'direct_reward_points' => 1300, 'umbrella_reward_points' => 300],
|
||||
];
|
||||
|
||||
$levels = Db::name('agent_level')
|
||||
->whereIn('grade', array_keys($expectedLevels))
|
||||
->field('id,name,grade,direct_reward_points,umbrella_reward_points')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$levelsByGrade = [];
|
||||
foreach ($levels as $level) {
|
||||
$levelsByGrade[(int)$level['grade']] = $level;
|
||||
}
|
||||
|
||||
foreach ($expectedLevels as $grade => $expected) {
|
||||
if (!isset($levelsByGrade[$grade])) {
|
||||
$output->writeln(" [MISS] grade={$grade} ({$expected['name_hint']}) 行不存在!");
|
||||
$hasError = true;
|
||||
continue;
|
||||
}
|
||||
$row = $levelsByGrade[$grade];
|
||||
$errors = [];
|
||||
if ((int)$row['direct_reward_points'] !== $expected['direct_reward_points']) {
|
||||
$errors[] = "direct_reward_points={$row['direct_reward_points']}(期望 {$expected['direct_reward_points']})";
|
||||
}
|
||||
if ((int)$row['umbrella_reward_points'] !== $expected['umbrella_reward_points']) {
|
||||
$errors[] = "umbrella_reward_points={$row['umbrella_reward_points']}(期望 {$expected['umbrella_reward_points']})";
|
||||
}
|
||||
if ($errors) {
|
||||
$hasError = true;
|
||||
$output->writeln(" [FAIL] grade={$grade} {$row['name']}:" . implode(',', $errors));
|
||||
if ($fix) {
|
||||
Db::name('agent_level')->where('id', $row['id'])->update([
|
||||
'direct_reward_points' => $expected['direct_reward_points'],
|
||||
'umbrella_reward_points' => $expected['umbrella_reward_points'],
|
||||
]);
|
||||
$output->writeln(" [FIX] 已修正 grade={$grade} {$row['name']}");
|
||||
}
|
||||
} else {
|
||||
$output->writeln(" [OK] grade={$grade} {$row['name']} direct={$row['direct_reward_points']} umbrella={$row['umbrella_reward_points']}");
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 2) eb_agent_level_task — 升级任务配置(PRD 3.2)
|
||||
// ----------------------------------------------------------------
|
||||
$output->writeln('');
|
||||
$output->writeln('【2】eb_agent_level_task 升级任务配置');
|
||||
$output->writeln('------------------------------------------------------------');
|
||||
|
||||
// PRD 任务配置:[grade => [[type, number, description], ...]]
|
||||
$expectedTasks = [
|
||||
1 => [[6, 3, '直推满 3 单']],
|
||||
2 => [[7, 30, '伞下满 30 单'], [8, 3, '至少 3 个直推']],
|
||||
3 => [[7, 100, '伞下满 100 单'], [8, 3, '至少 3 个直推']],
|
||||
4 => [[7, 1000, '伞下满 1000 单'], [8, 3, '至少 3 个直推']],
|
||||
];
|
||||
|
||||
foreach ($expectedTasks as $grade => $tasks) {
|
||||
if (!isset($levelsByGrade[$grade])) {
|
||||
$output->writeln(" [SKIP] grade={$grade} 等级行不存在,跳过任务检查");
|
||||
continue;
|
||||
}
|
||||
$levelId = $levelsByGrade[$grade]['id'];
|
||||
$levelName = $levelsByGrade[$grade]['name'];
|
||||
|
||||
foreach ($tasks as [$type, $number, $desc]) {
|
||||
$taskRow = Db::name('agent_level_task')
|
||||
->where('level_id', $levelId)
|
||||
->where('type', $type)
|
||||
->field('id,number')
|
||||
->find();
|
||||
|
||||
if (!$taskRow) {
|
||||
$hasError = true;
|
||||
$output->writeln(" [MISS] grade={$grade} {$levelName} type={$type}({$desc})行不存在!");
|
||||
if ($fix) {
|
||||
Db::name('agent_level_task')->insert([
|
||||
'level_id' => $levelId,
|
||||
'type' => $type,
|
||||
'number' => $number,
|
||||
]);
|
||||
$output->writeln(" [FIX] 已插入 grade={$grade} type={$type} number={$number}");
|
||||
}
|
||||
} elseif ((int)$taskRow['number'] !== $number) {
|
||||
$hasError = true;
|
||||
$output->writeln(" [FAIL] grade={$grade} {$levelName} type={$type}({$desc})number={$taskRow['number']}(期望 {$number})");
|
||||
if ($fix) {
|
||||
Db::name('agent_level_task')->where('id', $taskRow['id'])->update(['number' => $number]);
|
||||
$output->writeln(" [FIX] 已修正 grade={$grade} type={$type} number={$number}");
|
||||
}
|
||||
} else {
|
||||
$output->writeln(" [OK] grade={$grade} {$levelName} type={$type}({$desc})number={$taskRow['number']}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// 输出汇总
|
||||
// ----------------------------------------------------------------
|
||||
$output->writeln('');
|
||||
$output->writeln('========================================================');
|
||||
if ($hasError) {
|
||||
if ($fix) {
|
||||
$output->writeln(' 结果:检测到配置不一致,已自动修正。');
|
||||
} else {
|
||||
$output->writeln(' 结果:检测到配置不一致,请使用 --fix 自动修正,或手动更新数据库。');
|
||||
}
|
||||
} else {
|
||||
$output->writeln(' 结果:所有配置与 PRD 一致,验收通过 ✓');
|
||||
}
|
||||
$output->writeln('========================================================');
|
||||
$output->writeln('');
|
||||
|
||||
return $hasError ? 1 : 0;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,7 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace app\command;
|
||||
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\controller;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\common\controller;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin;
|
||||
|
||||
use app\Request;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin;
|
||||
|
||||
use app\services\agent\DivisionApplyServices;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin;
|
||||
|
||||
use app\Request;
|
||||
@@ -109,7 +104,8 @@ class Login
|
||||
try {
|
||||
aj_captcha_check_two($captchaType, $captchaVerification);
|
||||
} catch (\Throwable $e) {
|
||||
return app('json')->fail($e->getError());
|
||||
$msg = method_exists($e, 'getError') ? $e->getError() : $e->getMessage();
|
||||
return app('json')->fail($msg);
|
||||
}
|
||||
}
|
||||
validate(\app\validate\admin\setting\SystemAdminValidate::class)->scene('get')->check(['account' => $account, 'pwd' => $password]);
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\agent;
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\agent;
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\agent;
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\cms;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\cms;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\community;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\community;
|
||||
|
||||
use think\annotation\Inject;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\community;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\diy;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\diy;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\finance;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\finance;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\finance;
|
||||
|
||||
|
||||
|
||||
32
pro_v3.5.1/app/controller/admin/v1/hjf/HjfMember.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 范氏国香 fsgx — Admin 会员管理接口
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\hjf;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
use app\Request;
|
||||
use app\services\user\UserServices;
|
||||
|
||||
class HjfMember extends AuthController
|
||||
{
|
||||
/**
|
||||
* PUT /adminapi/hjf/member/{uid}/no_assess
|
||||
* 设置/取消用户不考核状态
|
||||
*/
|
||||
public function setNoAssess(Request $request, int $uid)
|
||||
{
|
||||
if ($uid <= 0) return $this->fail('参数错误');
|
||||
|
||||
/** @var UserServices $userServices */
|
||||
$userServices = app()->make(UserServices::class);
|
||||
$user = $userServices->get($uid, ['uid', 'no_assess']);
|
||||
if (!$user) return $this->fail('用户不存在');
|
||||
|
||||
$noAssess = (int)$request->post('no_assess', 1);
|
||||
$userServices->update($uid, ['no_assess' => $noAssess ? 1 : 0], 'uid');
|
||||
|
||||
return $this->success($noAssess ? '已设置不考核' : '已取消不考核');
|
||||
}
|
||||
}
|
||||
65
pro_v3.5.1/app/controller/admin/v1/hjf/HjfPoints.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 范氏国香 fsgx — Admin 积分日志接口
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\hjf;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
use app\Request;
|
||||
use think\facade\Db;
|
||||
|
||||
class HjfPoints extends AuthController
|
||||
{
|
||||
/**
|
||||
* GET /adminapi/hjf/points/release_log
|
||||
* 积分释放日志(来自 UserBill,type = integral,mark 包含"积分")
|
||||
*/
|
||||
public function releaseLog(Request $request)
|
||||
{
|
||||
$page = (int)$request->get('page', 1);
|
||||
$limit = (int)$request->get('limit', 20);
|
||||
$keyword = trim((string)$request->get('keyword', ''));
|
||||
$type = trim((string)$request->get('type', ''));
|
||||
|
||||
$query = Db::table('eb_user_bill')
|
||||
->alias('b')
|
||||
->leftJoin('eb_user u', 'u.uid = b.uid')
|
||||
->where('b.category', 'integral')
|
||||
->field('b.id, b.uid, b.title, b.mark, b.number, b.balance, b.pm, b.add_time, u.nickname, u.avatar');
|
||||
|
||||
if ($keyword !== '') {
|
||||
$query->where(function ($q) use ($keyword) {
|
||||
$q->whereLike('u.nickname', "%{$keyword}%")
|
||||
->whereOr('b.uid', $keyword);
|
||||
});
|
||||
}
|
||||
|
||||
if ($type !== '') {
|
||||
$typeMap = [
|
||||
'release' => 'frozen_points_release',
|
||||
'brokerage'=> 'frozen_points_brokerage',
|
||||
'consume' => '',
|
||||
];
|
||||
if ($type === 'consume') {
|
||||
$query->where('b.pm', 0);
|
||||
} elseif (isset($typeMap[$type]) && $typeMap[$type] !== '') {
|
||||
$query->where('b.link_type', $typeMap[$type]);
|
||||
}
|
||||
}
|
||||
|
||||
$count = $query->count();
|
||||
$list = $query->order('b.id', 'desc')
|
||||
->page($page, $limit)
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
foreach ($list as &$item) {
|
||||
$item['add_time_str'] = date('Y-m-d H:i:s', (int)$item['add_time']);
|
||||
$item['pm_label'] = $item['pm'] ? '收入' : '支出';
|
||||
}
|
||||
unset($item);
|
||||
|
||||
return $this->success(['list' => $list, 'count' => $count]);
|
||||
}
|
||||
}
|
||||
161
pro_v3.5.1/app/controller/admin/v1/hjf/MemberController.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controller\admin\v1\hjf;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
use app\dao\user\UserDao;
|
||||
use app\services\agent\AgentLevelServices;
|
||||
use app\services\hjf\MemberLevelServices;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Admin · 会员管理接口(改造复用版)
|
||||
*
|
||||
* 复用 eb_agent_level 体系,使用 eb_user.agent_level 字段。
|
||||
*
|
||||
* GET /adminapi/hjf/member/list — 会员列表
|
||||
* PUT /adminapi/hjf/member/level/:uid — 手动调整会员等级
|
||||
* GET /adminapi/hjf/member/config — 获取会员等级配置(从 eb_agent_level 读取)
|
||||
* POST /adminapi/hjf/member/config — 保存会员等级配置(写入 eb_agent_level)
|
||||
*
|
||||
* Class MemberController
|
||||
* @package app\controller\admin\v1\hjf
|
||||
*/
|
||||
class MemberController extends AuthController
|
||||
{
|
||||
#[Inject]
|
||||
protected UserDao $userDao;
|
||||
|
||||
#[Inject]
|
||||
protected MemberLevelServices $levelServices;
|
||||
|
||||
#[Inject]
|
||||
protected AgentLevelServices $agentLevelServices;
|
||||
|
||||
/**
|
||||
* 会员列表(分页)
|
||||
*/
|
||||
public function memberList(): mixed
|
||||
{
|
||||
$where = $this->request->getMore([
|
||||
['keyword', ''],
|
||||
['member_level', ''],
|
||||
['page', 1],
|
||||
['limit', 20],
|
||||
]);
|
||||
$page = (int)$where['page'];
|
||||
$limit = (int)$where['limit'];
|
||||
|
||||
$condition = [];
|
||||
if ($where['keyword'] !== '') {
|
||||
$condition['uid|nickname|phone'] = ['like', '%' . $where['keyword'] . '%'];
|
||||
}
|
||||
|
||||
if ($where['member_level'] !== '') {
|
||||
$grade = (int)$where['member_level'];
|
||||
if ($grade === 0) {
|
||||
$condition['agent_level'] = 0;
|
||||
} else {
|
||||
$agentLevelId = $this->agentLevelServices->getLevelIdByGrade($grade);
|
||||
$condition['agent_level'] = $agentLevelId ?: -1;
|
||||
}
|
||||
}
|
||||
|
||||
$count = $this->userDao->count($condition);
|
||||
$list = $this->userDao->selectList(
|
||||
$condition,
|
||||
'uid,nickname,avatar,phone,agent_level,frozen_points,available_points,now_money,spread_uid,add_time',
|
||||
$page,
|
||||
$limit,
|
||||
'uid',
|
||||
'desc'
|
||||
);
|
||||
|
||||
$levelList = $this->agentLevelServices->dao->getList(['is_del' => 0, 'status' => 1]);
|
||||
$levelMap = array_column($levelList, null, 'id');
|
||||
|
||||
foreach ($list as &$item) {
|
||||
$agentLevelId = (int)($item['agent_level'] ?? 0);
|
||||
$levelInfo = $levelMap[$agentLevelId] ?? null;
|
||||
$item['member_level'] = $levelInfo ? (int)$levelInfo['grade'] : 0;
|
||||
$item['member_level_name'] = $levelInfo ? $levelInfo['name'] : '普通会员';
|
||||
$item['direct_order_count'] = $this->levelServices->getDirectQueueOrderCount((int)$item['uid']);
|
||||
$item['umbrella_order_count'] = $this->levelServices->getUmbrellaQueueOrderCount((int)$item['uid']);
|
||||
$item['direct_spread_count'] = $this->levelServices->getDirectSpreadCount((int)$item['uid']);
|
||||
}
|
||||
unset($item);
|
||||
|
||||
return $this->success(compact('list', 'count'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动调整会员等级
|
||||
*/
|
||||
public function updateLevel(int $uid): mixed
|
||||
{
|
||||
$data = $this->request->getMore([
|
||||
['member_level', 0],
|
||||
]);
|
||||
$grade = (int)$data['member_level'];
|
||||
|
||||
if ($grade < 0 || $grade > 4) {
|
||||
return $this->fail('等级范围 0-4');
|
||||
}
|
||||
|
||||
$user = $this->userDao->get($uid);
|
||||
if (!$user) {
|
||||
return $this->fail('用户不存在');
|
||||
}
|
||||
|
||||
$this->levelServices->setUserLevel($uid, $grade);
|
||||
|
||||
return $this->success('更新成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员等级配置(从 eb_agent_level 表读取)
|
||||
*/
|
||||
public function getConfig(): mixed
|
||||
{
|
||||
$levelList = $this->agentLevelServices->dao->getList(['is_del' => 0, 'status' => 1]);
|
||||
$config = [];
|
||||
foreach ($levelList as $level) {
|
||||
$config[] = [
|
||||
'id' => $level['id'],
|
||||
'name' => $level['name'],
|
||||
'grade' => $level['grade'],
|
||||
'direct_reward_points' => $level['direct_reward_points'] ?? 0,
|
||||
'umbrella_reward_points' => $level['umbrella_reward_points'] ?? 0,
|
||||
];
|
||||
}
|
||||
return $this->success($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存会员等级配置(写入 eb_agent_level 表)
|
||||
*/
|
||||
public function saveConfig(): mixed
|
||||
{
|
||||
$levels = $this->request->post('levels', []);
|
||||
if (!is_array($levels)) {
|
||||
return $this->fail('参数格式错误');
|
||||
}
|
||||
|
||||
foreach ($levels as $item) {
|
||||
if (empty($item['id'])) continue;
|
||||
$updateData = [];
|
||||
if (isset($item['direct_reward_points'])) {
|
||||
$updateData['direct_reward_points'] = (int)$item['direct_reward_points'];
|
||||
}
|
||||
if (isset($item['umbrella_reward_points'])) {
|
||||
$updateData['umbrella_reward_points'] = (int)$item['umbrella_reward_points'];
|
||||
}
|
||||
if ($updateData) {
|
||||
$this->agentLevelServices->dao->update((int)$item['id'], $updateData);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success('保存成功');
|
||||
}
|
||||
}
|
||||
42
pro_v3.5.1/app/controller/admin/v1/hjf/PointsController.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controller\admin\v1\hjf;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
use app\dao\hjf\PointsReleaseLogDao;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Admin · 积分管理接口
|
||||
*
|
||||
* GET /adminapi/hjf/points/release-log — 积分释放日志(分页)
|
||||
*
|
||||
* Class PointsController
|
||||
* @package app\controller\admin\v1\hjf
|
||||
*/
|
||||
class PointsController extends AuthController
|
||||
{
|
||||
#[Inject]
|
||||
protected PointsReleaseLogDao $dao;
|
||||
|
||||
/**
|
||||
* 积分释放日志(分页)
|
||||
*/
|
||||
public function releaseLog(): mixed
|
||||
{
|
||||
$where = $this->request->getMore([
|
||||
['keyword', ''],
|
||||
['type', ''],
|
||||
['start_time', ''],
|
||||
['end_time', ''],
|
||||
['page', 1],
|
||||
['limit', 20],
|
||||
]);
|
||||
$page = (int)$where['page'];
|
||||
$limit = (int)$where['limit'];
|
||||
unset($where['page'], $where['limit']);
|
||||
|
||||
return $this->success($this->dao->getAdminList($where, $page, $limit));
|
||||
}
|
||||
}
|
||||
108
pro_v3.5.1/app/controller/admin/v1/hjf/QueueController.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controller\admin\v1\hjf;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
use app\dao\hjf\QueuePoolDao;
|
||||
use app\services\system\config\SystemConfigServices;
|
||||
use crmeb\services\SystemConfigService;
|
||||
use think\annotation\Inject;
|
||||
|
||||
/**
|
||||
* Admin · 公排管理接口
|
||||
*
|
||||
* GET /adminapi/hjf/queue/order — 公排订单列表
|
||||
* GET /adminapi/hjf/queue/config — 获取公排配置
|
||||
* POST /adminapi/hjf/queue/config — 保存公排配置
|
||||
* GET /adminapi/hjf/queue/finance — 公排退款财务流水
|
||||
*
|
||||
* Class QueueController
|
||||
* @package app\controller\admin\v1\hjf
|
||||
*/
|
||||
class QueueController extends AuthController
|
||||
{
|
||||
#[Inject]
|
||||
protected QueuePoolDao $dao;
|
||||
|
||||
/**
|
||||
* 公排订单列表(分页 + 筛选)
|
||||
*/
|
||||
public function orderList(): mixed
|
||||
{
|
||||
$where = $this->request->getMore([
|
||||
['keyword', ''],
|
||||
['status', ''],
|
||||
['start_time', ''],
|
||||
['end_time', ''],
|
||||
['page', 1],
|
||||
['limit', 20],
|
||||
]);
|
||||
$page = (int)$where['page'];
|
||||
$limit = (int)$where['limit'];
|
||||
unset($where['page'], $where['limit']);
|
||||
|
||||
return $this->success($this->dao->getAdminList($where, $page, $limit));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公排配置
|
||||
*/
|
||||
public function getConfig(): mixed
|
||||
{
|
||||
$config = [
|
||||
'trigger_multiple' => (int)SystemConfigService::get('hjf_trigger_multiple', 4),
|
||||
'release_rate' => (int)SystemConfigService::get('hjf_release_rate', 4),
|
||||
'withdraw_fee_rate' => (int)SystemConfigService::get('hjf_withdraw_fee_rate', 7),
|
||||
'enabled' => (bool)SystemConfigService::get('hjf_queue_pool_enable', 0),
|
||||
'umbrella_reward_enable' => (bool)SystemConfigService::get('hjf_umbrella_reward_enable', 0),
|
||||
];
|
||||
return $this->success($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存公排配置
|
||||
*/
|
||||
public function saveConfig(SystemConfigServices $configServices): mixed
|
||||
{
|
||||
$data = $this->request->getMore([
|
||||
['trigger_multiple', 4],
|
||||
['release_rate', 4],
|
||||
['withdraw_fee_rate', 7],
|
||||
['enabled', 1],
|
||||
['umbrella_reward_enable', 0],
|
||||
]);
|
||||
|
||||
$map = [
|
||||
'hjf_trigger_multiple' => (int)$data['trigger_multiple'],
|
||||
'hjf_release_rate' => (int)$data['release_rate'],
|
||||
'hjf_withdraw_fee_rate' => (int)$data['withdraw_fee_rate'],
|
||||
'hjf_queue_pool_enable' => (int)$data['enabled'],
|
||||
'hjf_umbrella_reward_enable' => (int)$data['umbrella_reward_enable'],
|
||||
];
|
||||
|
||||
foreach ($map as $key => $value) {
|
||||
$configServices->setConfig($key, (string)$value);
|
||||
}
|
||||
|
||||
return $this->success('保存成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 公排退款财务流水(分页)
|
||||
*/
|
||||
public function financeList(): mixed
|
||||
{
|
||||
$where = $this->request->getMore([
|
||||
['start_time', ''],
|
||||
['end_time', ''],
|
||||
['page', 1],
|
||||
['limit', 20],
|
||||
]);
|
||||
$page = (int)$where['page'];
|
||||
$limit = (int)$where['limit'];
|
||||
unset($where['page'], $where['limit']);
|
||||
|
||||
return $this->success($this->dao->getFinanceList($where, $page, $limit));
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\activityBackground;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\activityFrame;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\bargain;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\card;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\card;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\card;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\combination;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\coupon;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\coupon;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\coupon;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\discounts;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\integral;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\integral;
|
||||
|
||||
use app\controller\admin\AuthController;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\integral;
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\integral;
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\live;
|
||||
|
||||
use think\annotation\Inject;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\live;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\live;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\controller\admin\v1\marketing\lottery;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\controller\admin\v1\marketing\lottery;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\controller\admin\v1\marketing\lottery;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\promotions;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\seckill;
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: CRMEB Team <admin@crmeb.com>
|
||||
// | Author: ScottPan Team
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace app\controller\admin\v1\marketing\seckill;
|
||||
|
||||