Files
websopy-taro/.workbuddy/memory/MEMORY.md
T
gxwebsoft 2e80a49ca1 feat(official): 实现企业官网分包及内容展示
- 新增官方分包目录及页面(首页、资讯列表、详情、关于我们、留言、我的)
- 自定义实现底部导航组件 OfficialTabBar,解决微信 tabBar 不支持分包问题
- 统一接口调用走 shop-api 代理,无新增 CMS 域名,减少合法域名负担
- 新增 CMS 站点信息获取接口及留言咨询提交与查询接口
- 设计并完善官网富文本样式,品牌色统一为 #185FA5,并更新 tailwind 配置
- 首页新增企业官网入口卡片,方便用户访问官网内容
- 完成官网分包构建验证,解决 Taro 构建批量删除保护问题
- 规范 CMS 字段使用,适配字段名称及状态含义
- 后续计划对历史页面 NutUI 组件进行空壳化整改,及更新 UI 设计文档
2026-08-11 08:48:16 +08:00

56 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目长期记忆(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/clerkTenantId` state)。
- 注意:前端 `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)。
## 官网分包 official2026-08-11 落地)
- 位置 `src/official/`6 页:index/article/article-detail/about/message/mine+ `src/official/components/`OfficialTabBar/ArticleCard/SectionTitle),在 `src/app.config.ts``subpackages` 中 root=`official`。入口在 `src/pages/index/index.tsx` 搜索栏下的「企业官网」卡片。
- 数据层统一从 `@/api/official` 引入(re-export `src/api/cms/*`)。**内容请求走默认 shop-api(`https://shop-api.websoft.top/api`),shop-api 已代理 `/cms` 前缀,不要另配 cms-api 域名**(避免小程序合法域名白名单成本)。租户靠 `TenantId` 请求头。
- CMS 字段陷阱:文章封面 `image`(非 cover)、摘要 `overview`(非 summary)、`ARTICLE_STATUS.PUBLISHED = 0`0 才是已发布);留言内容字段是 `need`(非 content),小程序提交带 `source:'miniapp'`
- 微信原生 tabBar **不支持分包页面**,官网底部导航是自实现的 `OfficialTabBar`(用 `redirectTo`)。
- 品牌色统一 tokentailwind `brand` 色阶(600=`#185FA5`+ `app.scss``--brand-color/--brand-light`。富文本用 `.official-rich`(定义在 `app.scss`px 自动转 rpx)。
## ⚠️ Taro 构建陷阱:dist 清空触发批量删除保护(2026-08-11)
`npm run build:weapp` 启动时 Taro 会 `emptyOutputDir` 清空 `dist/`,文件数 >50 会被安全删除守卫中断并抛 `SAFE_DELETE_BULK_CONFIRM_REQUIRED`
**解决**:构建前先 `mv dist /tmp/taro-dist-bak/dist-$(date +%s)`,再执行构建,完成后 `rm -rf /tmp/taro-dist-bak`
## ⚠️ 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`,应为 0grep `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(已修)→ 视觉影响最大的页面 → 批量。