fix(weapp): 修复支付页nutui组件导致内容空白问题
- 替换支付页中nutui的Button、Cell、Price、Divider组件为Taro原生组件或项目自定义组件 - 修正商品名称、价格类型和支付金额显示,使用flex布局及Text组件自绘内容 - 调整按钮样式,统一为带蓝色背景和圆角的自定义样式 - 移除nutui Price组件中的thousands属性,使用项目自定义Price组件 - 解决微信小程序中nutui组件因div渲染缺失导致UI元素不显示的问题 - 保持支付流程及状态逻辑无改动,仅优化展示兼容性和稳定性
This commit is contained in:
30
.idea/workspace.xml
generated
30
.idea/workspace.xml
generated
@@ -4,10 +4,8 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="2de94e4f-0587-4c9b-8bfd-e87e0ae95b81" name="更改" comment="feat(weapp): 新增开发者中心与平台管理入口及相关功能 - 小程序端新增开发者中心和平台管理页面模块,完善功能入口 - 新增开发者中心页面(概览、我的应用、API Key和工单) - 新增平台管理页面(管理首页、应用审核、Git权限审核、域名绑定审核和工单处理) - 复刻PC端/api/app/*相关API接口,基地址使用WEBSOPY_API_BASE_URL - 增加公共组件StatCard、EntryGrid、CellRow以支持新页面UI - 修改首页增加开发者中心和平台管理角色入口,仅对对应用户显示 - 用户页面菜单新增开发者中心和平台管理入口条件展示 - 约定开发者身份使用sys_user.is_developer布尔字段,不再依赖角色表 - 更新登录态业务,菜单是否显示基于登录接口返回">
|
<list default="true" id="2de94e4f-0587-4c9b-8bfd-e87e0ae95b81" name="更改" comment="feat(weapp): 新增开发者中心与平台管理入口及功能 - 小程序端新增开发者中心和平台管理页面模块,完善功能入口 - 新增开发者中心页面(概览、我的应用、API Key和工单) - 新增平台管理页面(管理首页、应用审核、Git权限审核、域名绑定审核和工单处理) - 复刻PC端/api/app/*相关API接口,基地址使用WEBSOPY_API_BASE_URL - 增加公共组件StatCard、EntryGrid、CellRow以支持新页面UI - 修改首页增加开发者中心和平台管理角色入口,仅对对应用户显示 - 用户页面菜单新增开发者中心和平台管理入口条件展示 - 约定开发者身份使用sys_user.is_developer布尔字段,不再依赖角色表 - 更新登录态业务,菜单是否显示基于登录接口返回的isDeveloper/isAdmin字段 - vip-review审核通过流程调整为只调用setUserDeveloper,后台替换角色为developer并置isDeveloper=1">
|
||||||
<change beforePath="$PROJECT_DIR$/.workbuddy/memory/2026-07-22.md" beforeDir="false" afterPath="$PROJECT_DIR$/.workbuddy/memory/2026-07-22.md" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.workbuddy/memory/MEMORY.md" beforeDir="false" afterPath="$PROJECT_DIR$/.workbuddy/memory/MEMORY.md" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/pages/user/vip-review/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/user/vip-review/index.tsx" afterDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -119,15 +117,7 @@
|
|||||||
<workItem from="1784131049625" duration="2304000" />
|
<workItem from="1784131049625" duration="2304000" />
|
||||||
<workItem from="1784133736973" duration="4614000" />
|
<workItem from="1784133736973" duration="4614000" />
|
||||||
<workItem from="1784585070286" duration="3047000" />
|
<workItem from="1784585070286" duration="3047000" />
|
||||||
<workItem from="1784638429525" duration="14271000" />
|
<workItem from="1784638429525" duration="16147000" />
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00016" summary="fix(passport): 添加邀请接受接口调试日志 - 在接受邀请请求前打印token和请求URL、参数 - 在请求响应后输出接口响应及返回数据 - 在调用失败时打印错误信息及异常日志 - 保持请求流程和状态管理不变,增强调试能力">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1775909811705</created>
|
|
||||||
<option name="number" value="00016" />
|
|
||||||
<option name="presentableId" value="LOCAL-00016" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1775909811705</updated>
|
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00017" summary="fix(passport): 优化邀请码接受失败的用户提示和处理 - 针对“用户不存在”、“用户创建失败”及“请先登录”提示,改为弹窗提示需登录 - 在弹窗中增加“去登录”按钮,点击后跳转到登录页面,并携带重定向token参数 - 其他错误仍使用原Toast提示方式展示错误信息 - 保留错误日志打印,便于排查异常情况">
|
<task id="LOCAL-00017" summary="fix(passport): 优化邀请码接受失败的用户提示和处理 - 针对“用户不存在”、“用户创建失败”及“请先登录”提示,改为弹窗提示需登录 - 在弹窗中增加“去登录”按钮,点击后跳转到登录页面,并携带重定向token参数 - 其他错误仍使用原Toast提示方式展示错误信息 - 保留错误日志打印,便于排查异常情况">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
@@ -513,7 +503,15 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1784707342940</updated>
|
<updated>1784707342940</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="65" />
|
<task id="LOCAL-00065" summary="feat(weapp): 新增开发者中心与平台管理入口及功能 - 小程序端新增开发者中心和平台管理页面模块,完善功能入口 - 新增开发者中心页面(概览、我的应用、API Key和工单) - 新增平台管理页面(管理首页、应用审核、Git权限审核、域名绑定审核和工单处理) - 复刻PC端/api/app/*相关API接口,基地址使用WEBSOPY_API_BASE_URL - 增加公共组件StatCard、EntryGrid、CellRow以支持新页面UI - 修改首页增加开发者中心和平台管理角色入口,仅对对应用户显示 - 用户页面菜单新增开发者中心和平台管理入口条件展示 - 约定开发者身份使用sys_user.is_developer布尔字段,不再依赖角色表 - 更新登录态业务,菜单是否显示基于登录接口返回的isDeveloper/isAdmin字段 - vip-review审核通过流程调整为只调用setUserDeveloper,后台替换角色为developer并置isDeveloper=1">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1784709736683</created>
|
||||||
|
<option name="number" value="00065" />
|
||||||
|
<option name="presentableId" value="LOCAL-00065" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1784709736683</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="66" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -533,7 +531,6 @@
|
|||||||
<component name="VcsManagerConfiguration">
|
<component name="VcsManagerConfiguration">
|
||||||
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
||||||
<option name="CHECK_NEW_TODO" value="false" />
|
<option name="CHECK_NEW_TODO" value="false" />
|
||||||
<MESSAGE value="feat(api-keys): 优化隐私协议同意逻辑及样式 - 修正api-keys样式导入路径,改为developer路径 - 在开发者申请页面增加服务协议和隐私政策勾选框 - 提交时校验协议是否已勾选,未勾选时提示用户 - 优化申请页面协议区域样式及交互 - 在用户验证页面添加隐私政策同意勾选框 - 提交用户验证表单时检查协议同意状态 - 增加打开服务协议和隐私政策的链接跳转 - 更新项目配置,增加passport/webview路由配置 - 修复createTicket函数中日期格式正则表达式问题" />
|
|
||||||
<MESSAGE value="refactor(config): 移除开发者中心和企业控制台的自定义导航样式 - 删除了开发者中心页面配置中的 navigationStyle: 'custom' - 删除了企业控制台页面配置中的 navigationStyle: 'custom' - 简化了页面配置,保持默认导航样式 - 有助于提升页面兼容性和维护性" />
|
<MESSAGE value="refactor(config): 移除开发者中心和企业控制台的自定义导航样式 - 删除了开发者中心页面配置中的 navigationStyle: 'custom' - 删除了企业控制台页面配置中的 navigationStyle: 'custom' - 简化了页面配置,保持默认导航样式 - 有助于提升页面兼容性和维护性" />
|
||||||
<MESSAGE value="feat(userVerify): 添加阿里云身份证二要素核验功能 - 在接口层新增 verifyIdCard 接口,实现姓名与身份证号核验 - userVerify 页面提交时增加身份核验逻辑,核验失败阻止提交 - 调用核验接口时显示加载状态,并根据结果提示用户 - 后端依赖 aliyun cloudauth,提供实人认证相关服务接口 - 完成基本的错误捕获与用户提示,提升实名认证流程安全性" />
|
<MESSAGE value="feat(userVerify): 添加阿里云身份证二要素核验功能 - 在接口层新增 verifyIdCard 接口,实现姓名与身份证号核验 - userVerify 页面提交时增加身份核验逻辑,核验失败阻止提交 - 调用核验接口时显示加载状态,并根据结果提示用户 - 后端依赖 aliyun cloudauth,提供实人认证相关服务接口 - 完成基本的错误捕获与用户提示,提升实名认证流程安全性" />
|
||||||
<MESSAGE value="refactor(api): 规范前端API接口地址并统一路径前缀 - 修正开发者、小程序和企业相关API的基础URL,避免重复添加/api前缀 - 统一调整developer、enterprise、invite等模块接口路径,保持与后端Controller一致 - 新增权限申请及消息通知相关API,并完善相关函数实现 - 规范请求参数传递,移除多余包装,改用直接传递对象方式 - 新增API Key重置、版本发布/回滚等接口支持 feat(invite): 重构邀请登录流程支持未注册快速加入 - 完整重写invite页,分离已注册用户和未注册用户的按钮显示和交互 - 实现未注册用户微信手机号授权后自动注册登录及自动加入应用 - 已注册用户直接确认加入应用,无需手机号授权弹窗 - 统一使用getPhoneNumber按钮处理两种状态并修复“授权码不能为空”报错 - 前端配合后端改造,支持已登录用户可直接通过Authorization头加入应用 fix(developer): 修复开发者中心应用加载问题 - 修复只查询创建的应用导致邀请加入的应用不显示的问题 - 同时请求创建应用和参与应用接口,合并并去重应用列表 - 新增pageJoinedApp接口调用及合并逻辑,提高应用列表完整性和体验" />
|
<MESSAGE value="refactor(api): 规范前端API接口地址并统一路径前缀 - 修正开发者、小程序和企业相关API的基础URL,避免重复添加/api前缀 - 统一调整developer、enterprise、invite等模块接口路径,保持与后端Controller一致 - 新增权限申请及消息通知相关API,并完善相关函数实现 - 规范请求参数传递,移除多余包装,改用直接传递对象方式 - 新增API Key重置、版本发布/回滚等接口支持 feat(invite): 重构邀请登录流程支持未注册快速加入 - 完整重写invite页,分离已注册用户和未注册用户的按钮显示和交互 - 实现未注册用户微信手机号授权后自动注册登录及自动加入应用 - 已注册用户直接确认加入应用,无需手机号授权弹窗 - 统一使用getPhoneNumber按钮处理两种状态并修复“授权码不能为空”报错 - 前端配合后端改造,支持已登录用户可直接通过Authorization头加入应用 fix(developer): 修复开发者中心应用加载问题 - 修复只查询创建的应用导致邀请加入的应用不显示的问题 - 同时请求创建应用和参与应用接口,合并并去重应用列表 - 新增pageJoinedApp接口调用及合并逻辑,提高应用列表完整性和体验" />
|
||||||
@@ -558,7 +555,8 @@
|
|||||||
<MESSAGE value="refactor(user): 统一品牌名称为“威数谱软件” - 将项目中所有“威硕谱软件”名称修改为“威数谱软件” - 更新协议页面、欢迎消息、礼品卡等多处文本内容 - 修改小程序配置文件中的项目名称和显示标题 - 优化开发者申请页部分文案,明确开发者身份描述 - 保证所有界面及配置中的品牌名称统一一致" />
|
<MESSAGE value="refactor(user): 统一品牌名称为“威数谱软件” - 将项目中所有“威硕谱软件”名称修改为“威数谱软件” - 更新协议页面、欢迎消息、礼品卡等多处文本内容 - 修改小程序配置文件中的项目名称和显示标题 - 优化开发者申请页部分文案,明确开发者身份描述 - 保证所有界面及配置中的品牌名称统一一致" />
|
||||||
<MESSAGE value="refactor(user): 将VIP身份统一改为开发者标记 - 审核通过时不再新增角色,而是更新用户isDeveloper布尔标记 - 后端UserService新增markAsDeveloper方法,通过updateById设置isDeveloper - UserController新增PUT接口更新开发者标记,权限使用sys:userRole:save - 前端api新增setUserDeveloper调用新的审核接口 - vip-review页面移除角色相关代码,改为调用setUserDeveloper方法 - 约定开发者身份即sys_user.is_developer字段,不再依赖角色表记录 - app.config.ts追加开发者中心与平台管理相关页面路由 - 新增开发者中心、平台管理的多个API模块(apikey、appProduct、appDomain、developer请求等) - 添加公共工具方法和复用组件用于开发者中心及平台管理功能 - 统一品牌名称为“威数谱软件”,更新文案及界面展现一致性" />
|
<MESSAGE value="refactor(user): 将VIP身份统一改为开发者标记 - 审核通过时不再新增角色,而是更新用户isDeveloper布尔标记 - 后端UserService新增markAsDeveloper方法,通过updateById设置isDeveloper - UserController新增PUT接口更新开发者标记,权限使用sys:userRole:save - 前端api新增setUserDeveloper调用新的审核接口 - vip-review页面移除角色相关代码,改为调用setUserDeveloper方法 - 约定开发者身份即sys_user.is_developer字段,不再依赖角色表记录 - app.config.ts追加开发者中心与平台管理相关页面路由 - 新增开发者中心、平台管理的多个API模块(apikey、appProduct、appDomain、developer请求等) - 添加公共工具方法和复用组件用于开发者中心及平台管理功能 - 统一品牌名称为“威数谱软件”,更新文案及界面展现一致性" />
|
||||||
<MESSAGE value="feat(weapp): 新增开发者中心与平台管理入口及相关功能 - 小程序端新增开发者中心和平台管理页面模块,完善功能入口 - 新增开发者中心页面(概览、我的应用、API Key和工单) - 新增平台管理页面(管理首页、应用审核、Git权限审核、域名绑定审核和工单处理) - 复刻PC端/api/app/*相关API接口,基地址使用WEBSOPY_API_BASE_URL - 增加公共组件StatCard、EntryGrid、CellRow以支持新页面UI - 修改首页增加开发者中心和平台管理角色入口,仅对对应用户显示 - 用户页面菜单新增开发者中心和平台管理入口条件展示 - 约定开发者身份使用sys_user.is_developer布尔字段,不再依赖角色表 - 更新登录态业务,菜单是否显示基于登录接口返回" />
|
<MESSAGE value="feat(weapp): 新增开发者中心与平台管理入口及相关功能 - 小程序端新增开发者中心和平台管理页面模块,完善功能入口 - 新增开发者中心页面(概览、我的应用、API Key和工单) - 新增平台管理页面(管理首页、应用审核、Git权限审核、域名绑定审核和工单处理) - 复刻PC端/api/app/*相关API接口,基地址使用WEBSOPY_API_BASE_URL - 增加公共组件StatCard、EntryGrid、CellRow以支持新页面UI - 修改首页增加开发者中心和平台管理角色入口,仅对对应用户显示 - 用户页面菜单新增开发者中心和平台管理入口条件展示 - 约定开发者身份使用sys_user.is_developer布尔字段,不再依赖角色表 - 更新登录态业务,菜单是否显示基于登录接口返回" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="feat(weapp): 新增开发者中心与平台管理入口及相关功能 - 小程序端新增开发者中心和平台管理页面模块,完善功能入口 - 新增开发者中心页面(概览、我的应用、API Key和工单) - 新增平台管理页面(管理首页、应用审核、Git权限审核、域名绑定审核和工单处理) - 复刻PC端/api/app/*相关API接口,基地址使用WEBSOPY_API_BASE_URL - 增加公共组件StatCard、EntryGrid、CellRow以支持新页面UI - 修改首页增加开发者中心和平台管理角色入口,仅对对应用户显示 - 用户页面菜单新增开发者中心和平台管理入口条件展示 - 约定开发者身份使用sys_user.is_developer布尔字段,不再依赖角色表 - 更新登录态业务,菜单是否显示基于登录接口返回" />
|
<MESSAGE value="feat(weapp): 新增开发者中心与平台管理入口及功能 - 小程序端新增开发者中心和平台管理页面模块,完善功能入口 - 新增开发者中心页面(概览、我的应用、API Key和工单) - 新增平台管理页面(管理首页、应用审核、Git权限审核、域名绑定审核和工单处理) - 复刻PC端/api/app/*相关API接口,基地址使用WEBSOPY_API_BASE_URL - 增加公共组件StatCard、EntryGrid、CellRow以支持新页面UI - 修改首页增加开发者中心和平台管理角色入口,仅对对应用户显示 - 用户页面菜单新增开发者中心和平台管理入口条件展示 - 约定开发者身份使用sys_user.is_developer布尔字段,不再依赖角色表 - 更新登录态业务,菜单是否显示基于登录接口返回的isDeveloper/isAdmin字段 - vip-review审核通过流程调整为只调用setUserDeveloper,后台替换角色为developer并置isDeveloper=1" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="feat(weapp): 新增开发者中心与平台管理入口及功能 - 小程序端新增开发者中心和平台管理页面模块,完善功能入口 - 新增开发者中心页面(概览、我的应用、API Key和工单) - 新增平台管理页面(管理首页、应用审核、Git权限审核、域名绑定审核和工单处理) - 复刻PC端/api/app/*相关API接口,基地址使用WEBSOPY_API_BASE_URL - 增加公共组件StatCard、EntryGrid、CellRow以支持新页面UI - 修改首页增加开发者中心和平台管理角色入口,仅对对应用户显示 - 用户页面菜单新增开发者中心和平台管理入口条件展示 - 约定开发者身份使用sys_user.is_developer布尔字段,不再依赖角色表 - 更新登录态业务,菜单是否显示基于登录接口返回的isDeveloper/isAdmin字段 - vip-review审核通过流程调整为只调用setUserDeveloper,后台替换角色为developer并置isDeveloper=1" />
|
||||||
<option name="NON_MODAL_COMMIT_POSTPONE_SLOW_CHECKS" value="false" />
|
<option name="NON_MODAL_COMMIT_POSTPONE_SLOW_CHECKS" value="false" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
23
.workbuddy/memory/2026-07-23.md
Normal file
23
.workbuddy/memory/2026-07-23.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# 2026-07-23
|
||||||
|
|
||||||
|
## 扫码进入小程序后支付页空白 bug
|
||||||
|
|
||||||
|
**现象**:用户从 web 端订单详情生成 QR 码 → 微信扫码进入小程序 → `passport/pay` 页面只显示卡片标题"确认支付"、"支付金额"标签、底部提示文案,**商品名称/价格类型/价格/分隔线/取消按钮/立即支付按钮全部缺失**,无法继续支付流程。
|
||||||
|
|
||||||
|
**根因**:`@nutui/nutui-react-taro@2.7.4` 的 Cell / Price / Divider / Button 内部用 `React.createElement("div", ...)`,而 `dist/base.wxml` 里只有 `<view>` / `<text>` / `<button>` 模板没有 `<div>`。这些组件在 weapp 中"空壳化"。截图里只显示纯 Text/View 和图标(来自 `@nutui/icons-react-taro` 的 SVG),没有显示的内容全部是 nutui-react-taro 组件。
|
||||||
|
|
||||||
|
**修复**:只改 `src/passport/pay/index.tsx` 一个文件,把 4 个 nutui 组件换成 Taro 原生 / 项目自定义组件:
|
||||||
|
|
||||||
|
- `import { Button, Cell, Price, Divider } from '@nutui/nutui-react-taro'` → `import { Button } from '@tarojs/components'` + `import Price from '@/components/common/Price'`
|
||||||
|
- `<Cell>` → `<View>` + `<Text>` 自绘(用 `flex justify-between px-4 py-3 border-b border-gray-100`)
|
||||||
|
- `<Price size="large" thousands>` → `<Price size="large">`(项目自定义组件)
|
||||||
|
- `<Divider>` → `border-b border-gray-100` 替代
|
||||||
|
- `<Button type="primary" block>` → `<Button className="bg-blue-500 text-white rounded-full">`(className 控制颜色)
|
||||||
|
- error/paid/loading 三个分支里的 `<Button type="primary">` 也一并替换
|
||||||
|
|
||||||
|
**验证**:
|
||||||
|
- `npm run build:weapp` → `Compiled successfully in 14.45s`
|
||||||
|
- `dist/passport/pay/index.js` 里 `nut-cell|nut-button|nut-divider|nut-price` 全部为 0;按钮编译成 `l.zx`(Taro Button 局部变量名)
|
||||||
|
- 文件最终 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 等。如果以后用户反馈"按钮/输入框看不到或不可点",按同样模式替换即可。这次没改,避免一次改动面太大。
|
||||||
@@ -15,3 +15,24 @@
|
|||||||
- 「按 userId 置一个标志位」的范式:`new User(){{setUserId(); setXxx();}}` → `userService.updateById(u)`(参考 `updateStatus`/`updateRecommend`/`auditUser`)。
|
- 「按 userId 置一个标志位」的范式:`new User(){{setUserId(); setXxx();}}` → `userService.updateById(u)`(参考 `updateStatus`/`updateRecommend`/`auditUser`)。
|
||||||
- 用户变更后如需同步 websopy,经 `syncMessageProducer.sendUserSyncMessage("websopy","UPDATE",user)`(在 `UserServiceImpl` 内,`@Autowired(required=false)` 注入)。
|
- 用户变更后如需同步 websopy,经 `syncMessageProducer.sendUserSyncMessage("websopy","UPDATE",user)`(在 `UserServiceImpl` 内,`@Autowired(required=false)` 注入)。
|
||||||
- 用户相关代码都在 `com.gxwebsoft.common.system`(entity/service/controller),业务应用数据在 `com.gxwebsoft.websopy`(无 Controller)。
|
- 用户相关代码都在 `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(已修)→ 视觉影响最大的页面 → 批量。
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import React, { useState, useEffect, useCallback } from 'react'
|
import React, { useState, useEffect, useCallback } from 'react'
|
||||||
import { View, Text } from '@tarojs/components'
|
import { View, Text, Button } from '@tarojs/components'
|
||||||
import { Button, Cell, Price, Divider } from '@nutui/nutui-react-taro'
|
import { Tips, Check, Close, Clock } from '@nutui/icons-react-taro'
|
||||||
import { Check, Close, Tips, Clock } from '@nutui/icons-react-taro'
|
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
import { request } from '@/utils/request'
|
import { request } from '@/utils/request'
|
||||||
import { getOpenId, loginByOpenId } from '@/api/passport/wx-login'
|
import { getOpenId, loginByOpenId } from '@/api/passport/wx-login'
|
||||||
import type { User } from '@/api/system/user/model'
|
import type { User } from '@/api/system/user/model'
|
||||||
import { saveStorageByLoginUser } from '@/utils/server'
|
import { saveStorageByLoginUser } from '@/utils/server'
|
||||||
import { TenantId, WebsopyBaseUrl } from '@/config/app'
|
import { TenantId, WebsopyBaseUrl } from '@/config/app'
|
||||||
|
import Price from '@/components/common/Price'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 小程序支付页面
|
* 小程序支付页面
|
||||||
@@ -312,7 +312,12 @@ const PayPage: React.FC = () => {
|
|||||||
<Close className="text-red-500 mb-4" size="48" />
|
<Close className="text-red-500 mb-4" size="48" />
|
||||||
<Text className="block text-gray-800 text-lg mb-2">获取订单失败</Text>
|
<Text className="block text-gray-800 text-lg mb-2">获取订单失败</Text>
|
||||||
<Text className="block text-gray-500 mb-6">{errorMsg}</Text>
|
<Text className="block text-gray-500 mb-6">{errorMsg}</Text>
|
||||||
<Button type="primary" onClick={handleBack}>返回</Button>
|
<Button
|
||||||
|
onClick={handleBack}
|
||||||
|
className="bg-blue-500 text-white rounded-full px-6"
|
||||||
|
>
|
||||||
|
返回
|
||||||
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
@@ -333,7 +338,12 @@ const PayPage: React.FC = () => {
|
|||||||
已支付 ¥{Number(detail.payPrice).toFixed(2)}
|
已支付 ¥{Number(detail.payPrice).toFixed(2)}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
<Button type="primary" onClick={handleBack}>完成</Button>
|
<Button
|
||||||
|
onClick={handleBack}
|
||||||
|
className="bg-blue-500 text-white rounded-full px-6"
|
||||||
|
>
|
||||||
|
完成
|
||||||
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
@@ -347,21 +357,26 @@ const PayPage: React.FC = () => {
|
|||||||
<View className="bg-white rounded-lg shadow-sm p-4 mb-4">
|
<View className="bg-white rounded-lg shadow-sm p-4 mb-4">
|
||||||
<Text className="block text-lg font-bold text-gray-800 mb-3">确认支付</Text>
|
<Text className="block text-lg font-bold text-gray-800 mb-3">确认支付</Text>
|
||||||
|
|
||||||
<Cell title="商品名称" description={detail?.productName || '-'} />
|
{/* 商品名称 */}
|
||||||
<Cell title="价格类型" description={getPriceDesc()} />
|
<View className="flex items-center justify-between px-4 py-3 border-b border-gray-100">
|
||||||
|
<Text className="text-gray-600">商品名称</Text>
|
||||||
<View className="flex items-center justify-between px-4 py-3">
|
<Text className="text-gray-800">{detail?.productName || '-'}</Text>
|
||||||
<Text className="text-gray-600">支付金额</Text>
|
|
||||||
<Price
|
|
||||||
price={detail?.payPrice}
|
|
||||||
size="large"
|
|
||||||
thousands
|
|
||||||
/>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Divider />
|
{/* 价格类型 */}
|
||||||
|
<View className="flex items-center justify-between px-4 py-3 border-b border-gray-100">
|
||||||
|
<Text className="text-gray-600">价格类型</Text>
|
||||||
|
<Text className="text-gray-800">{getPriceDesc() || '-'}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
<View className="flex items-start px-4 py-2">
|
{/* 支付金额 */}
|
||||||
|
<View className="flex items-center justify-between px-4 py-3">
|
||||||
|
<Text className="text-gray-600">支付金额</Text>
|
||||||
|
<Price price={detail?.payPrice} size="large" />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* 提示 */}
|
||||||
|
<View className="flex items-start px-4 py-2 mt-2 border-t border-gray-100">
|
||||||
<Tips className="text-orange-500 mr-2 mt-1" size="16" />
|
<Tips className="text-orange-500 mr-2 mt-1" size="16" />
|
||||||
<Text className="text-sm text-gray-500">
|
<Text className="text-sm text-gray-500">
|
||||||
支付成功后即可在「已购产品」中使用该应用
|
支付成功后即可在「已购产品」中使用该应用
|
||||||
@@ -373,18 +388,15 @@ const PayPage: React.FC = () => {
|
|||||||
<View className="fixed bottom-0 left-0 right-0 p-4 bg-white border-t border-gray-100">
|
<View className="fixed bottom-0 left-0 right-0 p-4 bg-white border-t border-gray-100">
|
||||||
<View className="flex gap-3">
|
<View className="flex gap-3">
|
||||||
<Button
|
<Button
|
||||||
block
|
|
||||||
onClick={handleBack}
|
onClick={handleBack}
|
||||||
className="flex-1"
|
className="flex-1 bg-gray-100 text-gray-700 rounded-full border-0"
|
||||||
>
|
>
|
||||||
取消
|
取消
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
|
||||||
block
|
|
||||||
loading={paying}
|
loading={paying}
|
||||||
onClick={handlePay}
|
onClick={handlePay}
|
||||||
className="flex-1"
|
className="flex-1 bg-blue-500 text-white rounded-full border-0"
|
||||||
>
|
>
|
||||||
{paying ? '支付中...' : '立即支付'}
|
{paying ? '支付中...' : '立即支付'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user