feat(user): 补充开发者审核通过时添加店员记录功能
- 引入 addShopStoreUser 接口用于新增门店店员记录 - 新增 clerkStoreId 和 clerkTenantId 状态,保存当前审核店员的门店和租户信息 - 在审核通过后调用 addShopStoreUser,添加申请人为当前门店店员 - 保证只有当 clerkStoreId 存在时才执行新增操作 - 更新工作记录文档,补充审核通过流程中新添加的店员记录步骤 - 保持原有升级开发者逻辑和接口调用不变
This commit is contained in:
20
.idea/workspace.xml
generated
20
.idea/workspace.xml
generated
@@ -116,15 +116,7 @@
|
||||
<workItem from="1784133736973" duration="4614000" />
|
||||
<workItem from="1784585070286" duration="3047000" />
|
||||
<workItem from="1784638429525" duration="16147000" />
|
||||
<workItem from="1784798575885" duration="656000" />
|
||||
</task>
|
||||
<task id="LOCAL-00019" summary="feat(passport): 重写登录与邀请加入流程,支持微信手机号一键登录 - 完全重写 passport/login.tsx,实现微信手机号一键登录功能 - 支持登录页面携带 redirect 参数,登录后自动跳转回原页面 - 登录成功后自动处理邀请加入应用,支持邀请关系绑定 - 重写 passport/invite/index.tsx,实现扫码邀请加入应用完整流程 - 支持调用 wx.login 获取 code,使用 loginByOpenId 判断注册状态 - 未注册用户自动跳转登录页完成微信手机号登录再加入应用 - 已登录用户直接执行加入应用操作,加入接口支持 Authorization 头 - 解决邀请页面与登录页面间旧授权码混用导致加入失败问题 - 处理后端 401 错误,优先使用微信授权码免登录接口 - 优化用户体验,添加服务协议与隐私政策弹窗及错误提示 - 页面状态管理改进,加入加载、检查登录、错误和跳转反馈">
|
||||
<option name="closed" value="true" />
|
||||
<created>1775962292970</created>
|
||||
<option name="number" value="00019" />
|
||||
<option name="presentableId" value="LOCAL-00019" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1775962292970</updated>
|
||||
<workItem from="1784798575885" duration="986000" />
|
||||
</task>
|
||||
<task id="LOCAL-00020" summary="feat(invite): 重构邀请加入流程,实现已登录用户免授权直接加入 - 完全重写邀请页逻辑,区分已登录与未注册用户按钮显示 - 已登录用户显示“确认加入”按钮,点击用 wx.login 获取 code 加入 - 未注册用户显示“微信手机号快速加入”按钮,授权手机号后完成注册登录再加入 - 移除跳转登录页面逻辑,所有流程在邀请页内完成 - 加入接口统一使用 Authorization 头携带 token,确保身份双重验证 - 优化背景、粒子和扫描线效果,提升界面视觉体验 - 增加错误处理提示,加入失败时显示详细原因并可返回首页 - 协议勾选仅在未注册用户显示,确保合规授权流程">
|
||||
<option name="closed" value="true" />
|
||||
@@ -510,7 +502,15 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1784799951929</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="68" />
|
||||
<task id="LOCAL-00068" summary="fix(weapp): 修复支付页nutui组件导致内容空白问题 - 替换支付页中nutui的Button、Cell、Price、Divider组件为Taro原生组件或项目自定义组件 - 修正商品名称、价格类型和支付金额显示,使用flex布局及Text组件自绘内容 - 调整按钮样式,统一为带蓝色背景和圆角的自定义样式 - 移除nutui Price组件中的thousands属性,使用项目自定义Price组件 - 解决微信小程序中nutui组件因div渲染缺失导致UI元素不显示的问题 - 保持支付流程及状态逻辑无改动,仅优化展示兼容性和稳定性">
|
||||
<option name="closed" value="true" />
|
||||
<created>1784800111045</created>
|
||||
<option name="number" value="00068" />
|
||||
<option name="presentableId" value="LOCAL-00068" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1784800111045</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="69" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
|
||||
@@ -21,3 +21,14 @@
|
||||
- 文件最终 413 行,diff 集中在 import + 渲染区,逻辑(数据获取、JSAPI 支付、状态判断 payStatus vs status)没动
|
||||
|
||||
**遗留**:项目其它页面(passport/{login,forget,register,setting,unified-qr,qr-login}、pages/order/*、pages/booking/*、components/common/{FixedButton,EmptyState}、components/QRLoginScanner)也用了 nutui Button/Checkbox/Input/Card/Tabs/Tag 等。如果以后用户反馈"按钮/输入框看不到或不可点",按同样模式替换即可。这次没改,避免一次改动面太大。
|
||||
|
||||
## vip-review 审核通过补充:添加 shop_store_user 记录
|
||||
|
||||
**背景**:之前实现的 `src/pages/user/vip-review/index.tsx` 审核通过只调了 `updateShopDealerApply` + `setUserDeveloper`,漏了"给申请人加一条门店店员记录"。用户 2026-07-23 指出"审核通过的操作,还是要添加一条记录到 shopStoreUser,可能之前理解错了",要求补上。
|
||||
|
||||
**修改**(仅前端一个文件):
|
||||
- import 增加 `addShopStoreUser`(来自 `@/api/shop/shopStoreUser`)。
|
||||
- 新增 state `clerkStoreId` / `clerkTenantId`,在 `getMyClerk()` 成功后写入(店员记录自带 `storeId`/`tenantId`)。
|
||||
- `handleApprove` 在 `setUserDeveloper` 之后调 `addShopStoreUser({ userId, storeId: clerkStoreId, tenantId: clerkTenantId, isDelete: 0, comments: '开发者审核通过自动添加' })`,仅当 `clerkStoreId` 存在时执行。
|
||||
|
||||
**依赖**:后端 `POST /shop/shop-store-user`(ShopStoreUserController.save,需 `shop:shopStoreUser:save` 权限,店员已有);tenantId 复用审核店员的租户,避免前端另取。
|
||||
@@ -7,7 +7,7 @@
|
||||
- 后端仓库:`/Users/gxwebsoft/JAVA/com.gxwebsoft.core`(单 Maven 模块,包名 `com.gxwebsoft` 分包)。
|
||||
- 标记接口:`PUT /api/system/user/developer/{userId}`(`UserController.setDeveloper` → `UserService.markAsDeveloper`),成功后经 `syncMessageProducer` 同步 websopy。
|
||||
- 前端调用:`@/api/system/user` 的 `setUserDeveloper(userId)`。
|
||||
- **vip-review 审核通过流程(用户 2026-07-22 最终确认)**:前端 `handleApprove` 只调 `setUserDeveloper(userId)`(不碰 `sys_user_role`)。后端 `markAsDeveloper` 做两件事:① 把 `sys_user.is_developer` 置 `1`;② **替换**用户角色为 `developer`——`roleService.getByRoleCode(roleCode=developer, tenantId=用户租户)` 找到角色 → 删掉该用户现有 `sys_user_role` → 只绑定 developer 这一个角色,**不与原角色并存**(角色替换包 try/catch,失败不影响 isDeveloper 落库)。即"升级为开发者 = 单角色 developer + isDeveloper 标记位",不是新增第二个角色。
|
||||
- **vip-review 审核通过流程(用户 2026-07-22 最终确认,2026-07-23 补充)**:前端 `handleApprove` 依次调 ① `updateShopDealerApply(applyStatus=20)`;② `setUserDeveloper(userId)`(不碰 `sys_user_role`);③ **`addShopStoreUser`**——在当前门店下给申请人补一条 `shop_store_user`(店员)记录(`userId=申请人, storeId=审核店员所属门店, tenantId=同店员, isDelete=0`)。后端 `markAsDeveloper` 做两件事:① 把 `sys_user.is_developer` 置 `1`;② **替换**用户角色为 `developer`——`roleService.getByRoleCode(roleCode=developer, tenantId=用户租户)` 找到角色 → 删掉该用户现有 `sys_user_role` → 只绑定 developer 这一个角色,**不与原角色并存**(角色替换包 try/catch,失败不影响 isDeveloper 落库)。即"升级为开发者 = 单角色 developer + isDeveloper 标记位 + 一条门店店员记录",不是新增第二个角色。审核店员的 `storeId/tenantId` 来自 `getMyClerk()` 返回值(存于 `clerkStoreId/clerkTenantId` state)。
|
||||
- 注意:前端 `vip-review` / `vip-upgrade` 等页面的变量名仍残留 `VIP_ROLE_*`、`pendingVipCount`、`dealerPrice` 等旧标识符(仅文案改成了「开发者」),后端角色与缓存 key 仍对应这些旧名,重命名需谨慎。
|
||||
|
||||
### 后端代码风格(com.gxwebsoft.core)
|
||||
|
||||
@@ -4,7 +4,7 @@ import Taro, { useDidShow } from '@tarojs/taro'
|
||||
import { listShopDealerApply, updateShopDealerApply } from '@/api/shop/shopDealerApply'
|
||||
import type { ShopDealerApply } from '@/api/shop/shopDealerApply/model'
|
||||
import { setUserDeveloper } from '@/api/system/user'
|
||||
import { getMyClerk } from '@/api/shop/shopStoreUser'
|
||||
import { getMyClerk, addShopStoreUser } from '@/api/shop/shopStoreUser'
|
||||
|
||||
definePageConfig({
|
||||
navigationBarTitleText: '开发者审核',
|
||||
@@ -44,6 +44,8 @@ const VipReviewPage: React.FC = () => {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [isClerk, setIsClerk] = useState(false)
|
||||
const [clerkStoreId, setClerkStoreId] = useState<number>()
|
||||
const [clerkTenantId, setClerkTenantId] = useState<number>()
|
||||
const loadingRef = useRef(false)
|
||||
|
||||
// 验证当前用户是否为店员
|
||||
@@ -52,6 +54,9 @@ const VipReviewPage: React.FC = () => {
|
||||
.then(data => {
|
||||
if (data) {
|
||||
setIsClerk(true)
|
||||
// 记录当前店员所属门店与租户,审核通过时用于给申请人添加店员记录
|
||||
setClerkStoreId(data.storeId)
|
||||
setClerkTenantId(data.tenantId)
|
||||
} else {
|
||||
setIsClerk(false)
|
||||
Taro.showToast({ title: '仅门店店员可访问', icon: 'none' })
|
||||
@@ -132,6 +137,17 @@ const VipReviewPage: React.FC = () => {
|
||||
// 审核通过:升级为开发者(后端 markAsDeveloper 会置 is_developer=1 并把角色替换为 developer)
|
||||
await setUserDeveloper(item.userId!)
|
||||
|
||||
// 审核通过:在当前门店下给申请人添加一条店员(shop_store_user)记录
|
||||
if (clerkStoreId) {
|
||||
await addShopStoreUser({
|
||||
userId: item.userId!,
|
||||
storeId: clerkStoreId,
|
||||
tenantId: clerkTenantId,
|
||||
isDelete: 0,
|
||||
comments: '开发者审核通过自动添加',
|
||||
})
|
||||
}
|
||||
|
||||
Taro.showToast({ title: '已通过', icon: 'success' })
|
||||
loadList(activeTab)
|
||||
} catch (e: any) {
|
||||
|
||||
Reference in New Issue
Block a user