207 lines
22 KiB
Markdown
207 lines
22 KiB
Markdown
# 2026-07-15
|
||
|
||
## shopOrder 选项卡默认改为全部
|
||
|
||
- 需求:`/shop/shopOrder` 选项卡默认从"待发货"改为"全部"。
|
||
- 改动 `src/views/shop/shopOrder/index.vue`:`activeKey` 初始值在路由参数 `tab` 无效时的回退值由 `'undelivered'` 改为 `'all'`。
|
||
- `datasource` 中 `getStatusFilterByTab('all')` 返回 `undefined`,即不传 `statusFilter`,查全部订单,符合预期。
|
||
|
||
## 修复 shopOrder 页面默认待发货tab数据不正确
|
||
|
||
- 根因:`activeKey` 默认为 `'undelivered'`,但 `datasource` 函数只设了 `where.type = 0`,没有设 `statusFilter`。`statusFilter` 只在用户点击 tab 触发 `onTabs` 时才设置。所以页面初次加载时查的是全部订单而非待发货订单。
|
||
- 修复:提取 `getStatusFilterByTab(key)` 公共映射函数,在 `datasource` 中当 `where.statusFilter` 未设置时从 `activeKey` 自动推导。`onTabs` 也简化为复用同一函数。
|
||
- 文件:`src/views/shop/shopOrder/index.vue`
|
||
|
||
## Dashboard 订单总数点击跳转支持指定 tab
|
||
|
||
- Dashboard 中"订单总数"/"总营业额"跳转链接改为 `/shop/shopOrder?tab=all`,"待发货订单"改为 `?tab=undelivered`,"退款申请"改为 `?tab=refunded`。
|
||
- shopOrder 页面读取 `route.query.tab` 初始化 `activeKey`,无效值回退到 `'undelivered'`。
|
||
- 文件:`src/views/shop/dashboard/index.vue`、`src/views/shop/shopOrder/index.vue`
|
||
|
||
## Dashboard 待处理事项新增"待付款订单"
|
||
|
||
- 在待发货订单上方新增"待付款订单"统计项,使用 `statusFilter=0` 查询,点击跳转 `/shop/shopOrder?tab=unpaid`。
|
||
- shopOrder 页面取消注释"待付款"tab,`validTabs` 加入 `unpaid`。
|
||
- 新增 `dot-gold` 样式。
|
||
- 文件:`src/views/shop/dashboard/index.vue`、`src/views/shop/shopOrder/index.vue`
|
||
|
||
## Dashboard 引入 useTenantStore,创建时间读租户信息
|
||
|
||
- 引入 `useTenantStore`,`loadData` 中调用 `tenantStore.fetchTenantInfo()` 替代直接调用 `getTenantInfo()` API。
|
||
- 基本信息"创建时间"改为读取 `tenantStore.company?.createTime`。
|
||
- 运行天数也改为从 `tenantStore.company?.createTime` 计算,移除独立的 `tenantCreateTime` ref。
|
||
- 文件:`src/views/shop/dashboard/index.vue`
|
||
|
||
## Dashboard 欢迎横幅新增商城Logo
|
||
|
||
- 通过 `getShopSettingCategoryValues('basic')` 获取商城设置,读取 `shopLogo` 字段。
|
||
- 使用 `getCompressedImageUrl(shopLogo, { width: 200, quality: 90 })` 压缩图片。
|
||
- 在 welcome-banner 左侧用 `a-avatar` (64px, square) 展示,无 Logo 时不显示。
|
||
- 文件:`src/views/shop/dashboard/index.vue`
|
||
|
||
## 新增 useAppSubscriptionStore(websopy 应用订阅特殊接口)
|
||
|
||
- 新增 `src/api/app/appSubscription/model.ts`:AppSubscription 实体及参数/返回类型,对照后端 `com.gxwebsoft.app.entity.AppSubscription`。
|
||
- 新增 `src/api/app/appSubscription/index.ts`:封装 `AppSubscriptionController` 全部 14 个接口。
|
||
- 特殊接口域名 `https://websopy-api.websoft.top/api`(与项目主 API 域名不同),复用 `@/utils/request`(共享登录态 token、401 处理),传绝对 URL。
|
||
- 后端无 context-path;baseURL=`https://websopy-api.websoft.top/api`,接口路径用 `/app/subscription/xxx`。
|
||
- 后端 `BaseController` 成功 code=0;`success(IPage)` 转成 `PageResult{list,count}`,与项目 `@/api` 的 PageResult 结构一致。
|
||
- 新增 `src/store/modules/appSubscription.ts`:`useAppSubscriptionStore`(Pinia Options API 风格,对齐 site.ts/statistics.ts),聚合列表/详情/支付状态/订阅管理方法。列表/详情缓存5分钟;`checkStatus`/`checkPurchased` 实时请求;订阅/支付/管理类操作成功后调 `invalidateCache()` 失效缓存。
|
||
|
||
## 确认线下收款新增上传凭证功能
|
||
|
||
- 背景:原"确认线下收款"用 `Modal.confirm` + `createVNode` 动态拼一个 input,只有备注,没有上传凭证。用户需要加凭证上传。
|
||
- 字段决策:新增 `paymentVoucher?: string` 字段(不复用 comments/merchantRemarks,因为凭证是图片URL非文本)。顺带修复 `buyerRemarks`/`merchantRemarks` 类型 bug(`undefined` → `string?`)。
|
||
- 重构为独立组件 `src/views/shop/shopOrder/components/OfflinePaymentModal.vue`:
|
||
- 用 `<a-modal>` + `<a-form>` + `<a-upload list-type="picture-card">` 单张图片上传。
|
||
- 上传走 `uploadOss`(`src/api/system/file`),存储返回的 `path`(与项目 `UploadCert` 组件约定一致),预览用 `getUrl(path)` 补全。
|
||
- 凭证必填,备注可选;校验 jpg/png、≤10MB;支持点击预览大图。
|
||
- API `confirmOfflinePayment(id, remarks?, paymentVoucher?)` 新增第三参数,通过 query params 传给后端。
|
||
- `index.vue`:移除原 `Modal.confirm`/`createVNode` 逻辑,改为打开新组件(`v-model:visible` + `:data="current"` + `@done="reload"`),与 `DeliveryModal` 模式一致。
|
||
- 类型检查:新增 0 错误,顺带消掉原 `okType: 'success'` 的类型错误(antdv4 ButtonType 不含 success,新组件去掉了 ok-type)。
|
||
- 改动文件:`src/api/shop/shopOrder/model/index.ts`、`src/api/shop/shopOrder/index.ts`、`src/views/shop/shopOrder/components/OfflinePaymentModal.vue`(新增)、`src/views/shop/shopOrder/index.vue`
|
||
- 后端待办(已完成):后端项目 `/Users/gxwebsoft/JAVA/guilixu-java`(MyBatis-Plus 3.4.3.3,无 Flyway/Liquibase,DDL 手动管理,SQL 脚本放 `sql/` 目录):
|
||
- `ShopOrder.java` 实体新增 `paymentVoucher` 字段(payTime 之后)。
|
||
- `ShopOrderController.confirmOfflinePayment` 新增 `@RequestParam paymentVoucher`。
|
||
- `ShopOrderService` 接口 + `ShopOrderServiceImpl` 实现方法签名加 `paymentVoucher` 参数,lambdaUpdate 加 `.set(paymentVoucher 非空, ShopOrder::getPaymentVoucher, paymentVoucher)`。
|
||
- DDL 脚本 `sql/shop_order_payment_voucher.sql`:`ALTER TABLE shop_order ADD COLUMN payment_voucher VARCHAR(500) NULL ... AFTER pay_time`。
|
||
- 注意:方法签名从 2 参变 3 参,全项目仅 Controller 一处调用,无断裂。
|
||
|
||
## Dashboard 到期时间显示订阅信息 + 立即订阅/扫码支付
|
||
|
||
- 改造 `src/views/shop/dashboard/index.vue` 基本信息「到期时间」行:三态渲染(active 显示 expireTime + 已激活 tag + ≤7天到期提醒;pending 显示待支付 + 去支付;无订阅显示立即订阅)。
|
||
- **productId 关联条件**:`app_product.tenantId = userStore.info.tenantId`(非 siteInfo.appId)。通过 `pageProducts({tenantId,current:1,size:1})` 取该租户应用。
|
||
- 新增 `src/api/app/appProduct/{model.ts,index.ts}`:AppProduct 类型 + `pageProducts` 接口(GET /api/app/product/page,分页参数 current/size,注意与项目 page/limit 不同)。
|
||
- 「立即订阅」流程:选 month/year → 免费应用调 `subscribe()` 直接激活;付费应用调 `generatePayQrcode()` 生成小程序码 → Modal 展示二维码 → 每 2.5s 轮询 `checkStatus(subscriptionNo)`,paid 后关闭+刷新(最多 5 分钟)。envVersion 按 `import.meta.env.DEV` 自动判断 trial/release。
|
||
- pending 订阅「去支付」复用 `subscriptionStore.pay(id,'wechat')`(用 `'miniappQrcode' in result` 类型守卫窄化)生成小程序码,不重复创建订阅。
|
||
- 小程序端支付页 `websopy-taro/src/passport/pay/index.tsx`:扫码 scene=subscriptionNo → detail-by-no → mp-prepay → requestPayment → mp-confirm,后端写 Redis `wxpay:paid:{no}=1`,Web 端 checkStatus 据此感知。
|
||
- 移除 dashboard 不再使用的 `siteInfo` 解构(原到期时间读 `siteInfo.expirationTime`,已改为订阅 expireTime),修复 noUnusedLocals 报错。
|
||
|
||
## 修复后端 generatePayQrcode 报错 "Field 'price_type' doesn't have a default value"
|
||
|
||
- 现象:dashboard 点「立即订阅」付费应用调 `generatePayQrcode` 时,后端 insert app_subscription 报 `price_type` 无默认值。
|
||
- 根因:后端 `AppSubscriptionController.generatePayQrcode`(websopy-java)创建订阅时漏了 `setPriceType()`,而 DB `price_type` 为 NOT NULL 无默认值。对比 `subscribe` 方法有 `setPriceType`。
|
||
- 参考 `websopy-pc/app/pages/console/pay/[subscriptionNo].vue`:它用 `subscribe` 创建订阅 + `pay(id,'wechat')` 生成二维码(两步),避开了 `generatePayQrcode`,所以没遇到此 bug。
|
||
- 修复(后端 `AppSubscriptionController.java` generatePayQrcode 方法):补全 `setPriceType(product.getPriceType())` + `setOriginalPrice`/`setPayStatus(0)`/`setTenantId`,对齐 subscribe。**前端无需改动**,重启后端即可。
|
||
- 注意:`subscribe` 价格计算用 `price/100`(当分转元),`generatePayQrcode` 直接用 `price`(当元),两者不一致;schema 标注 price 为「元」,故 `generatePayQrcode` 价格逻辑更合理,保留不动。
|
||
|
||
## 修复价格多了100倍(product.price 实际单位是分)
|
||
|
||
- 用户反馈:`generatePayQrcode` 算出的金额多了100倍。确认 `product.price` 实际存的是**分**(非 schema 标注的元),故 `subscribe` 的 `/100` 是对的,`generatePayQrcode` 直接用 price 是错的。
|
||
- 后端 `AppSubscriptionController.generatePayQrcode` 价格计算改为 `price/100` 转元(对齐 subscribe),年付按10个月(*10,对齐 subscribe 年付优惠),季付*3,月付*1。
|
||
- 前端 `dashboard/index.vue` 参考价同步修正:`monthPrice = price/100`,`yearPrice = monthPrice*10`(原为 price 直接 + *12)。
|
||
- 结论:product.price 实际单位是**分**,所有价格展示/计算都需 /100 转元。
|
||
|
||
## 改用 subscribe+pay 避开 generatePayQrcode 的 price_type 报错
|
||
|
||
- 现象:用户反馈 `generatePayQrcode` 仍报 `price_type` 无默认值(报错 SQL 字段集是修复前的,说明后端未重启/未重编译,`setPriceType` 修复未生效)。
|
||
- 关键认知:`generatePayQrcode` 后端**不接收 priceType 参数**(从 `product.getPriceType()` 取),所以前端传 priceType 给它也没用,无法绕过。
|
||
- 修复(前端方案,不依赖后端重启):dashboard `confirmSubscribe` 改用 `subscribe` + `pay` 两步(参考 websopy-pc 的 `pay/[subscriptionNo].vue` 模式):
|
||
- `subscribe` 创建订阅(后端有 `setPriceType`,不报错;价格 `/100` 正确)→ 免费 `status=active` 直接成功
|
||
- 付费 `status=pending` → `pay(subscriptionId,'wechat')` 生成小程序码 → Modal 展示 + 轮询 `checkStatus`
|
||
- 移除 `confirmSubscribe` 里的 `isFreeProduct` 分支(改用 `subResult.status` 判断);`isFreeProduct` 仍用于订阅 Modal 的免费提示。
|
||
- vue-tsc 验证 dashboard 零 error TS(总错误 1778 不变)。
|
||
- 后端 `generatePayQrcode` 的 `setPriceType` 修复仍保留(重启后端后该接口也能用),但前端已不依赖它。
|
||
|
||
## 订阅 productId 改为固定 65(小程序商城)
|
||
|
||
- 需求:dashboard 立即订阅请求的 productId 从动态(按 `tenantId` 查 `app_product`)改为写死 `65`。
|
||
- 改动 `src/views/shop/dashboard/index.vue`:
|
||
- imports:`pageProducts` → `getProductDetail`。
|
||
- `loadSubscriptionInfo`:移除 `userStore.info.tenantId` 判断和 `pageProducts({tenantId,current:1,size:1})` 调用,改为 `getProductDetail(65)` 查固定产品详情;定义 `FIXED_PRODUCT_ID = 65` 常量,订阅列表过滤和 `currentProduct.productId` 统一使用该常量。
|
||
- `confirmSubscribe` 无需改动(用 `currentProduct.productId`,已自动是 65)。
|
||
- `getProductDetail(65)` 返回的 product 含 name/priceType/price,前端参考价 `monthPrice = price/100`、`yearPrice = monthPrice*10` 仍适用。
|
||
- vue-tsc 验证 dashboard 零 error TS(总错误 1778 不变)。
|
||
|
||
## shopGoodsBrowse 列表商品图片改用 OSS 压缩函数
|
||
|
||
- 文件:`src/views/shop/shopGoodsBrowse/index.vue`
|
||
- 引入 `getCompressedImageUrl`(来自 `src/utils/image.ts`),将商品图片 `:src="record.goodsImage"` 改为 `:src="getCompressedImageUrl(record.goodsImage)"`。
|
||
- 与 `shopGoods`、`shopOrder`、`dashboard` 等页面保持一致:默认宽度 240px、质量 90、自动补全 OSS 域名、跳过已含 `x-oss-process` 的 URL。
|
||
- 预览行为未改(仍走 a-image 默认 src 预览)。
|
||
|
||
## 电脑版后台新订单红点提示(全局)
|
||
|
||
- 需求:电脑版后台有新订单时显示红点,让管理员知道有新订单。
|
||
- 关键发现:系统已有菜单红点基础设施(`menu-title.vue` 读 `item.meta.badge` 渲染徽章;`user.ts` `setMenuBadge(path,value,color)`;`layout/index.vue` 有 `.ele-menu-badge` 样式),但 `useOrderNotify` 原为组件级(dashboard/cms dashboard/shopOrder 三处各自独立轮询),未接通红点。
|
||
- 改造 `src/views/shop/shopOrder/useOrderNotify.ts` 为**模块级全局单例**:
|
||
- 轮询/状态/红点全部模块级变量(enabled、hasNewOrder、lastOrderId、timer),多组件调用只一个轮询。
|
||
- 检测到新订单 → triggerNotify(叮声+语音+遍历回调Set)+ `setOrderBadge(true)` 调 `userStore.setMenuBadge('/shop/shopOrder','dot','#ff4d4f')`。
|
||
- 新增 `clearBadge()`:立即清红点 + 重查最新订单同步 lastOrderId(标记"已查看")。
|
||
- `onNewOrder` 回调用 Set 管理,组件 onBeforeUnmount 自动移除;`start()` 幂等,由 layout 调一次。
|
||
- `src/layout/components/menu-title.vue`:`badge==='dot'` 时用 `<a-badge dot />` 纯红点,否则原数字徽章逻辑。
|
||
- `src/layout/index.vue`:setup 调 `useOrderNotify().start()` 全局启动,后台任意页面生效。
|
||
- `src/views/shop/shopOrder/index.vue`:`onMounted` + `onActivated` 调 `clearBadge()`(兼容 keep-alive `cache-key`,用 `orderBadgeMounted` 标志防首次双触发)。
|
||
- `src/views/shop/dashboard/index.vue`:`quickLinks` 改 computed,订单管理项 `badge: hasNewOrder.value`;`quick-icon` 加红点 span + pulse 动画样式。
|
||
- 决策(用户确认):红点=新订单未查看(进订单页清除);位置=订单管理菜单+dashboard快速入口订单管理图标;声音保留并全局化。
|
||
- 构建验证:`vite build --outDir dist_verify` 通过(EXIT:0)。原 `pnpm build` 失败仅因 vite 清空 `dist/assets` 被安全删除保护拦截(83文件>50阈值),与代码无关。
|
||
|
||
## shopOrder 订单详情页(orderInfo.vue)支付方式下增加支付凭证图
|
||
|
||
- 背景:之前 `OfflinePaymentModal` 确认线下收款时已支持上传 `paymentVoucher`(OSS path),但订单详情页只展示「线下付款」tag,看不到凭证图。
|
||
- 改动 `src/views/shop/shopOrder/components/orderInfo.vue`:
|
||
- 模板:在「支付方式」`<a-descriptions-item>` 之后、「开票状态」之前新增「支付凭证」项,`v-if="form.paymentVoucher"`,`:span="3"` 占满整行。
|
||
- 缩略图用 `a-image`,`:width="120"`,`getCompressedImageUrl(form.paymentVoucher, { width: 750 })`(按用户要求宽度 750),`preview-src-list` 用 `ensureFullUrl(form.paymentVoucher)` 给原图预览。
|
||
- 引入 `ensureFullUrl` 来自 `@/utils/image`(已有 `getCompressedImageUrl`)。
|
||
- form reactive 默认值新增 `paymentVoucher: undefined`,对齐 `ShopOrder` model。
|
||
- `ShopOrder` model 中 `paymentVoucher?: string` 字段早就存在(payTime 之后),无需改 model/API。
|
||
- 用户场景:仅线下付款(payType=9)的订单才有此凭证图,条件渲染自然处理。
|
||
|
||
## Dashboard 基本信息 6 字段数据源重构(product + subscription)
|
||
|
||
- 需求:dashboard「基本信息」面板原先混用硬编码/tenant/siteStore,改为统一从 `app_product.product_id=65` + `app_subscription` 读取,语义更准确。
|
||
- 字段映射决策(用户确认):
|
||
- 系统名称 → `currentProduct.productName`(原硬编码 '小程序商城')
|
||
- 版本号 → `currentProduct.version`(原硬编码 '2.0.0')
|
||
- 运行状态 → `currentProduct.publishStatus` + 中文映射 + a-tag 颜色(原 `siteStore.statusText`)
|
||
- 创建时间 → `currentSubscription.startTime`(原 `tenantStore.company?.createTime`)
|
||
- 到期时间 → `currentSubscription.expireTime`(保持不变,原本就是这个)
|
||
- 系统运行天数 → 自 `currentSubscription.startTime` 起累计(原自 `tenantStore.company?.createTime`;后改为 startTime,与"创建时间"行同源,语义统一)
|
||
- 改动 `src/views/shop/dashboard/index.vue`:
|
||
- 删除硬编码 `systemInfo` reactive(已确认 cms 那两个 systemInfo 是独立 const,互不影响)。
|
||
- import 移除 `reactive`。
|
||
- 新增 `productStatusText` computed:publishStatus → {text,color} 映射(published=已发布/green、pending_review=审核中/orange、developing=开发中/blue、rejected=已驳回/red、deprecated=已下架/red),未知状态显示原始值,无 product 显示 '-'。
|
||
- 重写 `runDays` computed:数据源由 `tenantStore.company?.createTime` 改为 `currentSubscription.value?.startTime`(与"创建时间"行同源),注释说明续费新增订阅记录会重置计数的边界行为。
|
||
- 模板 6 个字段全部重绑,每个字段加 `subscriptionLoading` 骨架屏分支(避免空白/老数据闪现)。
|
||
- 「系统运行」加 `a-tooltip title="自您首次开通小程序商城起"`(用户要求)。
|
||
- 数据流复用:`loadSubscriptionInfo()` 原本就调 `getProductDetail(65)` 填充 `currentProduct`,无需新增接口调用。
|
||
- 类型校验:vue-tsc 对 `shop/dashboard/index.vue` 行级错误 0 条;cms 那批历史错误与本次无关。
|
||
|
||
## Dashboard 到期时间续费功能 + 标签矛盾修复
|
||
|
||
- 背景:dashboard「到期时间」行原先在订阅已过期时同时显示绿色「已激活」标签 + 「(已过期)」红字,状态自相矛盾;且即将到期/已过期时无续费入口(用户反馈"没有按钮呢")。
|
||
- 改动 `src/views/shop/dashboard/index.vue`:
|
||
- 标签动态化:`a-tag :color="isExpired ? 'red' : 'green'"`,文案 `已过期/已激活`;已过期时显示「(已过期N天)」。
|
||
- 新增续费按钮:`showRenewButton`(`daysToExpire <= 7` 即即将到期或已过期时显示),点击 `onRenew`。
|
||
- 复用订阅 Modal:新增 `subscribeMode`('subscribe'|'renew')+ `renewing` 状态,Modal 的 title/okText/confirm-loading/@ok 按 mode 动态切换;免费应用 alert 文案也按 mode 区分。
|
||
- `confirmRenew` 调 `subscriptionStore.renew(sub.id, selectedPeriod)`(POST /app/subscription/renew/{id}?period=month|year),成功后 `refreshSubscription()`。
|
||
- `onSubscribe` 补设 `subscribeMode='subscribe'`。
|
||
- 续费 API 语义:`renewSubscription` 返回 string(同步完成,疑似余额扣款/免费续期)。若后端续费需走微信扫码支付,需改为返回支付二维码结构并接 pay 流程——待后端确认。
|
||
- 关键字段再确认(用户):开始时间用 `appSubscription.startTime`,到期时间用 `appSubscription.expireTime`,daysToExpire 与 `dayjs()`(浏览器本地时间)对比。
|
||
|
||
## Dashboard 续费改走 subscribe+pay 扫码(后端 renew 接口未实现)
|
||
|
||
- 触发:用户截图显示 `POST /api/app/subscription/renew/90` 返回 404,确认后端没有实现 renew 接口。
|
||
- 方案:续费不再调 `store.renew` / `renewSubscription`,改为复用现有 `subscribe + pay` 扫码支付链路(与首次订阅完全一致)。后端 subscribe 对已有 active 订阅会处理续期/创建新记录。
|
||
- 改动 `src/views/shop/dashboard/index.vue` 的 `confirmRenew`:
|
||
- 删掉 `await subscriptionStore.renew(sub.id, ...)` 改为 `subscribe({ productId, subscriptionPeriod })`。
|
||
- 免费应用走 `subResult.status === 'active'` 分支,提示「续费成功」并刷新。
|
||
- 付费应用走 `pay(subscriptionId, 'wechat', envVersion)` → 拿到 `miniappQrcode` → 弹支付 Modal + `startPolling`。
|
||
- `payProductName` fallback 文案改为「应用续费」(与订阅的「应用订阅」区分)。
|
||
- `onRenew` 入口、`subscribeMode='renew'`、续费 Modal title/按钮复用不变,UI 上用户感知不到底层调的是 subscribe。
|
||
- 教训/记录:调后端接口前最好先确认接口是否真实存在;前端 `api/app/appSubscription/index.ts` 的 `renewSubscription` 函数可保留(防止后端后续补上接口),但 dashboard 暂不调用。
|
||
|
||
## Dashboard 续费最终定稿:方案1 renew+pay(前端已就绪,等后端实现)
|
||
|
||
- 触发:上一步用 subscribe 走续费,后端返回「您已订阅该应用,无需重复购买」——subscribe 对已有 active 订阅是拒绝的,续费不能复用 subscribe。
|
||
- 定稿方案(用户确认):方案1 —— 后端实现 `/renew/{id}?period=xxx` 返回 `SubscribeResult`(含 subscriptionId),前端再调 `pay` 生成小程序码。与 subscribe+pay 对称,职责清晰。
|
||
- 三处改动(前端已全部就绪,等后端补 renew 接口即可联调通):
|
||
1. `src/api/app/appSubscription/index.ts` `renewSubscription`:返回类型 `string` → `SubscribeResult`;取 `res.data.data`(原取 `res.data.message`)。
|
||
2. `src/store/modules/appSubscription.ts` `renew`:返回类型 `string` → `SubscribeResult`,返回 result 而非 msg。
|
||
3. `src/views/shop/dashboard/index.vue` `confirmRenew`:改回调 `subscriptionStore.renew(sub.id, period)` 拿 `renewResult` → 免费(status=active)直接成功;付费走 `pay(renewResult.subscriptionId, 'wechat', envVersion)` → 弹码 + `startPolling`。与 confirmSubscribe 完全对称,仅第一步 subscribe→renew、传 sub.id 而非 productId。
|
||
- **后端接口约定(待实现)**:`POST /api/app/subscription/renew/{id}?period=month|year`
|
||
- 入参:id=原订阅ID,period=month/year
|
||
- 逻辑:校验原订阅归属 → 创建 pending 续费记录(startTime=原expireTime或now,expireTime=新到期)→ 返回 `{ subscriptionId, subscriptionNo, status, message, payPrice?, orderNo? }`(同 SubscribeResult)
|
||
- 前端拿到后调 `pay/{subscriptionId}` 生成微信小程序码,与订阅流程一致
|
||
- 续费按钮触发条件不变:`showRenewButton`(daysToExpire<=7,即将到期或已过期)。
|