- 将所有页面和菜单中超级管理员校验由数字1改为布尔true - 平台管理、门店中心菜单项仅在isSuperAdmin===true时显示 - 门店中心页面移除店员门槛,改为超级管理员访问限制 - 非超级管理员访问门店中心弹窗提示并返回 - 首页工作台入口及相关访问权限判定切换为布尔判断 - 优化首屏加载状态,避免权限校验闪烁和误判
6.3 KiB
项目长期记忆(websopy-taro)
核心约定
开发者身份的表示方式
- 开发者身份主校验位 =
sys_user.is_developer布尔位(数据库列is_developer),登录态MainController.loginByDeveloperSms校验它才允许开发者登录。 - 后端仓库:
/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 最终确认,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/clerkTenantIdstate)。 - 注意:前端
vip-review/vip-upgrade等页面的变量名仍残留VIP_ROLE_*、pendingVipCount、dealerPrice等旧标识符(仅文案改成了「开发者」),后端角色与缓存 key 仍对应这些旧名,重命名需谨慎。
超级管理员(isSuperAdmin=true)访问门槛(2026-07-23 确认)
- 用户对象字段
isSuperAdmin((user as any)?.isSuperAdmin === true,布尔 true 才算),前端此前未引用,由后端sys_user返回。 - 平台管理(
pages/admin/index/index)与门店中心(pages/store/center/index)两个入口,菜单与首页工作台均只在isSuperAdmin===true时显示(原先平台管理是isAdmin、门店中心是店员storeInfo)。 - 门店中心页面已改为「仅超级管理员可进」:移除原
getMyClerk()店员门槛;非超管访问弹「仅超级管理员可访问」并navigateBack;超管若同时是店员仍会加载门店信息用于头部,否则头部兜底显示「门店中心」+ 管理员昵称/手机号。 - 两页都用
useUser()的loading(userLoading)做首屏门卫,避免超管用户未从 storage 解析完时先闪「无访问权限」。注意:pages/store/center的入口曾依赖user.tsx里的storeInfo(getMyClerk),现已不再用storeInfo决定菜单可见性。
后端代码风格(com.gxwebsoft.core)
- Controller 继承
BaseController,统一返回ApiResult(成功code=0,失败code=1),用success()/fail()。 - 「按 userId 置一个标志位」的范式:
new User(){{setUserId(); setXxx();}}→userService.updateById(u)(参考updateStatus/updateRecommend/auditUser)。 - 用户变更后如需同步 websopy,经
syncMessageProducer.sendUserSyncMessage("websopy","UPDATE",user)(在UserServiceImpl内,@Autowired(required=false)注入)。 - 用户相关代码都在
com.gxwebsoft.common.system(entity/service/controller),业务应用数据在com.gxwebsoft.websopy(无 Controller)。
⚠️ Taro 小程序 nutui-react-taro 兼容性陷阱(2026-07-23 确认)
问题:@nutui/nutui-react-taro@2.7.4 的 Cell / Price / Divider / Button 等展示类组件,内部用 React.createElement("div", ...) 构建布局。Taro 4 的 babel/swc 没有把这些 div 转成 view,而 dist/base.wxml 里完全没有 <div> 模板,导致这些组件在 weapp 中"空壳化"——外层元素不存在,内层内容(<div>)被丢弃。
症状:组件位置完全空白 / 按钮不可见 / 价格显示为空。Text/View 与 @nutui/icons-react-taro 的图标(Tips/Check/Close/Clock,基于 SVG)渲染正常。
解决办法(最小改动):在该页面用 Taro 原生组件替代:
| nutui(不可用) | Taro 原生 / 项目自定义 |
|---|---|
import { Button, Cell, Price, Divider } from '@nutui/nutui-react-taro' |
import { Button } from '@tarojs/components' + import Price from '@/components/common/Price' |
<Cell title="X" description={Y} /> |
<View className="flex justify-between px-4 py-3 border-b border-gray-100"><Text className="text-gray-600">X</Text><Text className="text-gray-800">{Y}</Text></View> |
<Price price={n} size="large" thousands /> |
<Price price={n} size="large" />(用项目自定义 Price,不用 nutui 的) |
<Divider /> |
用 border-b border-gray-100 替代 |
<Button type="primary" block loading={x} onClick={y}>...</Button> |
<Button loading={x} onClick={y} className="flex-1 bg-blue-500 text-white rounded-full border-0">...</Button>(className 控制颜色,loading prop 仍然支持) |
适用范围判断:项目里其它页面(qr-login、register、passport/forget 等)也用了 nutui 的 Cell/Card/Divider/Button,遇到同类"组件消失"现象时按同样模式替换即可。已修:src/passport/pay/index.tsx(2026-07-23,扫码进入小程序后支付页空白的 bug)。
验证手段:跑 npm run build:weapp 后在 dist/<page>/index.js 里 grep nut-cell|nut-button|nut-divider|nut-price,应为 0;grep l.zx(Taro Button 在 weapp 编译后的局部变量名)应出现 2 次(取消 + 立即支付)。
已知的 nutui 组件清单(按 2026-07-23 grep 结果):Button 在 passport/pay, passport/login/setting/forget/register, pages/order/*, pages/booking/*, components/common/{FixedButton,EmptyState} 等大量页面;Cell 在 passport/pay, pages/order/order.tsx;Divider 在 passport/pay, passport/qr-login;Price 在 passport/pay。修复顺序建议:pay(已修)→ 视觉影响最大的页面 → 批量。