From a59d428e788b3c1f68f83d0cd56d6cb42b82e622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Wed, 15 Jul 2026 13:30:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(shopOrder):=20=E6=96=B0=E5=A2=9E=E7=A1=AE?= =?UTF-8?q?=E8=AE=A4=E7=BA=BF=E4=B8=8B=E6=94=B6=E6=AC=BE=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=87=AD=E8=AF=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构确认线下收款为独立组件 OfflinePaymentModal.vue - 新增支付凭证字段 paymentVoucher,支持图片上传与预览 - 上传限制为 jpg/png 格式,单张图片最大 10MB - API confirmOfflinePayment 新增 paymentVoucher 参数 - 页面移除原 Modal.confirm 逻辑,改为调用新组件弹窗 - 修复 buyerRemarks 和 merchantRemarks 类型错误 - 后端 shop_order 表待新增 payment_voucher 字段和接口支持 - 同步更新相关接口模型与视图交互逻辑 feat(shopGoodsBrowse): 新增用户商品浏览记录管理功能 - 新增 ShopGoodsBrowse 接口模型及分页查询、删除接口 - 前端新增浏览记录管理页面,实现列表展示和删除 - 支持基于用户ID、商品ID、浏览来源和日期范围搜索 - 列表显示商品图片、名称、价格、浏览次数及时间等信息 - 添加图片预览和操作确认弹窗,保障操作体验和安全 --- .workbuddy/memory/2026-07-15.md | 14 + src/api/shop/shopGoodsBrowse/index.ts | 30 +++ src/api/shop/shopGoodsBrowse/model/index.ts | 42 +++ src/api/shop/shopOrder/index.ts | 11 +- src/api/shop/shopOrder/model/index.ts | 6 +- .../shopGoodsBrowse/components/search.vue | 87 +++++++ src/views/shop/shopGoodsBrowse/index.vue | 196 ++++++++++++++ .../components/OfflinePaymentModal.vue | 241 ++++++++++++++++++ src/views/shop/shopOrder/index.vue | 40 +-- 9 files changed, 636 insertions(+), 31 deletions(-) create mode 100644 src/api/shop/shopGoodsBrowse/index.ts create mode 100644 src/api/shop/shopGoodsBrowse/model/index.ts create mode 100644 src/views/shop/shopGoodsBrowse/components/search.vue create mode 100644 src/views/shop/shopGoodsBrowse/index.vue create mode 100644 src/views/shop/shopOrder/components/OfflinePaymentModal.vue diff --git a/.workbuddy/memory/2026-07-15.md b/.workbuddy/memory/2026-07-15.md index 15f2031..6eb248c 100644 --- a/.workbuddy/memory/2026-07-15.md +++ b/.workbuddy/memory/2026-07-15.md @@ -41,3 +41,17 @@ - 后端无 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`: + - 用 `` + `` + `` 单张图片上传。 + - 上传走 `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` +- 后端待办:`shop_order` 表需新增 `payment_voucher` 字段;`confirm-offline-payment` 接口需接收并持久化 `paymentVoucher` 参数。 diff --git a/src/api/shop/shopGoodsBrowse/index.ts b/src/api/shop/shopGoodsBrowse/index.ts new file mode 100644 index 0000000..4c6b0dd --- /dev/null +++ b/src/api/shop/shopGoodsBrowse/index.ts @@ -0,0 +1,30 @@ +import request from '@/utils/request'; +import type { ApiResult, PageResult } from '@/api'; +import type { ShopGoodsBrowse, ShopGoodsBrowseParam } from './model'; + +/** + * 后台管理:分页查询浏览记录 + */ +export async function pageShopGoodsBrowse(params: ShopGoodsBrowseParam) { + const res = await request.get>>( + '/shop/shop-goods-browse/admin/page', + { params } + ); + if (res.data.code === 0) { + return res.data.data; + } + return Promise.reject(new Error(res.data.message)); +} + +/** + * 后台管理:删除单条浏览记录 + */ +export async function removeShopGoodsBrowse(id?: number) { + const res = await request.delete>( + '/shop/shop-goods-browse/admin/' + id + ); + if (res.data.code === 0) { + return res.data.message; + } + return Promise.reject(new Error(res.data.message)); +} diff --git a/src/api/shop/shopGoodsBrowse/model/index.ts b/src/api/shop/shopGoodsBrowse/model/index.ts new file mode 100644 index 0000000..4b7e25c --- /dev/null +++ b/src/api/shop/shopGoodsBrowse/model/index.ts @@ -0,0 +1,42 @@ +import type { PageParam } from '@/api'; + +/** + * 用户商品浏览记录 + */ +export interface ShopGoodsBrowse { + id?: number; + userId?: number; + goodsId?: number; + tenantId?: number; + merchantId?: number; + /** 浏览次数 */ + visitCount?: number; + /** 最后浏览时间 */ + lastVisitTime?: string; + /** 浏览来源 */ + browseSource?: string; + createTime?: string; + updateTime?: string; + /** 商品名称(关联查询) */ + goodsName?: string; + /** 商品封面图(关联查询) */ + goodsImage?: string; + /** 商品价格(关联查询) */ + price?: string; + /** 市场价(关联查询) */ + salePrice?: string; +} + +/** + * 浏览记录查询参数 + */ +export interface ShopGoodsBrowseParam extends PageParam { + id?: number; + userId?: number; + goodsId?: number; + merchantId?: number; + tenantId?: number; + browseSource?: string; + startTime?: string; + endTime?: string; +} diff --git a/src/api/shop/shopOrder/index.ts b/src/api/shop/shopOrder/index.ts index c58b7d1..0bd2ab3 100644 --- a/src/api/shop/shopOrder/index.ts +++ b/src/api/shop/shopOrder/index.ts @@ -154,12 +154,19 @@ export async function refundShopOrder(data: ShopOrder) { /** * 确认线下付款收款 * 商家确认已收到线下转账(微信转账/银行汇款等),确认后订单进入待发货状态 + * @param id 订单ID + * @param remarks 备注(可选) + * @param paymentVoucher 支付凭证图片地址(可选) */ -export async function confirmOfflinePayment(id: number, remarks?: string) { +export async function confirmOfflinePayment( + id: number, + remarks?: string, + paymentVoucher?: string +) { const res = await request.put>( MODULES_API_URL + '/shop/shop-order/confirm-offline-payment/' + id, null, - { params: { remarks } } + { params: { remarks, paymentVoucher } } ); if (res.data.code === 0) { return res.data.message; diff --git a/src/api/shop/shopOrder/model/index.ts b/src/api/shop/shopOrder/model/index.ts index e89add4..255b079 100644 --- a/src/api/shop/shopOrder/model/index.ts +++ b/src/api/shop/shopOrder/model/index.ts @@ -129,6 +129,8 @@ export interface ShopOrder { invoiceNo?: string; // 支付时间 payTime?: string; + // 线下收款支付凭证(图片地址,确认线下收款时上传) + paymentVoucher?: string; // 退款时间 refundTime?: string; // 申请退款时间 @@ -142,9 +144,9 @@ export interface ShopOrder { // 系统版本号 0当前版本 value=其他版本 version?: number; // 买家备注 - buyerRemarks: undefined; + buyerRemarks?: string; // 商家备注 - merchantRemarks: undefined; + merchantRemarks?: string; // 用户id userId?: number; // 备注 diff --git a/src/views/shop/shopGoodsBrowse/components/search.vue b/src/views/shop/shopGoodsBrowse/components/search.vue new file mode 100644 index 0000000..ac76ef3 --- /dev/null +++ b/src/views/shop/shopGoodsBrowse/components/search.vue @@ -0,0 +1,87 @@ + + + + diff --git a/src/views/shop/shopGoodsBrowse/index.vue b/src/views/shop/shopGoodsBrowse/index.vue new file mode 100644 index 0000000..3ba9c22 --- /dev/null +++ b/src/views/shop/shopGoodsBrowse/index.vue @@ -0,0 +1,196 @@ + + + + + + + diff --git a/src/views/shop/shopOrder/components/OfflinePaymentModal.vue b/src/views/shop/shopOrder/components/OfflinePaymentModal.vue new file mode 100644 index 0000000..2782f1d --- /dev/null +++ b/src/views/shop/shopOrder/components/OfflinePaymentModal.vue @@ -0,0 +1,241 @@ + + + + + + diff --git a/src/views/shop/shopOrder/index.vue b/src/views/shop/shopOrder/index.vue index 4418283..4b87ac7 100644 --- a/src/views/shop/shopOrder/index.vue +++ b/src/views/shop/shopOrder/index.vue @@ -369,6 +369,13 @@ :data="current" @done="reload" /> + + + @@ -399,14 +406,14 @@ import { toDateString } from 'ele-admin-pro'; import OrderInfo from './components/orderInfo.vue'; import DeliveryModal from './components/deliveryModal.vue'; + import OfflinePaymentModal from './components/OfflinePaymentModal.vue'; import { ShopOrder, ShopOrderParam } from '@/api/shop/shopOrder/model'; import { pageShopOrder, repairOrder, removeShopOrder, removeBatchShopOrder, - updateShopOrder, refundShopOrder, - confirmOfflinePayment + updateShopOrder, refundShopOrder } from '@/api/shop/shopOrder'; import { updateUser } from '@/api/system/user'; import { getPayType } from '@/utils/shop'; @@ -427,6 +434,8 @@ const showMove = ref(false); // 是否显示发货弹窗 const showDelivery = ref(false); + // 是否显示确认线下收款弹窗 + const showOfflinePayment = ref(false); // 加载状态 const loading = ref(true); // 激活的标签(支持从路由参数初始化,如 /shop/shopOrder?tab=all) @@ -647,31 +656,8 @@ // 确认线下付款收款 const handleConfirmOfflinePayment = (record: ShopOrder) => { - let remarksValue = ''; - Modal.confirm({ - title: '确认线下收款', - content: createVNode('div', null, [ - createVNode('p', { style: 'margin-bottom: 8px' }, '确认已收到该订单的线下付款(微信转账/银行汇款等)?'), - createVNode('p', { style: 'margin-bottom: 8px; color: #999; font-size: 12px' }, `订单号:${record.orderNo}`), - createVNode('input', { - id: 'offline-remarks-input', - placeholder: '可填写备注(如:微信转账已收到)', - style: 'width: 100%; padding: 4px 8px; border: 1px solid #d9d9d9; border-radius: 4px;', - onInput: (e: any) => { remarksValue = e.target.value; } - }) - ]), - okText: '确认收款', - okType: 'success', - onOk: async () => { - try { - await confirmOfflinePayment(record.orderId!, remarksValue || undefined); - message.success('确认收款成功,订单已进入待发货状态'); - reload(); - } catch (error: any) { - message.error(error.message || '确认收款失败'); - } - } - }); + current.value = record; + showOfflinePayment.value = true; }; // 发货处理