feat(shopOrder): 支持订单商品图片OSS压缩及新增支付方式
- 新增utils/image.ts,提供图片URL补全及OSS压缩参数拼接功能 - 订单列表商品图片列改为使用压缩后图片URL,提高加载性能 - shopOrder相关支付类型注释更新,新增银联支付、POS机支付等多种方式 - 更新支付组件及订单信息界面,新增并显示银联支付、POS机支付、免费、积分支付、货到付款等支付标签 - 订单支付状态标签支持区分“已付款”和“待收货付款”状态 - shopOrder数据model中支付类型及代付类型描述同步更新 - 修复shop utils中payType标签获取的边界条件错误 - 注释掉dashboard待办事项中优惠券使用项,暂停显示该统计数据
This commit is contained in:
@@ -34,3 +34,16 @@
|
|||||||
### 订单新订单语音提醒同步刷新
|
### 订单新订单语音提醒同步刷新
|
||||||
- `src/views/shop/shopOrder/useOrderNotify.ts` 增加 `onNewOrder` 回调参数,检测到新订单触发提醒(叮声+语音)时同时调用回调。
|
- `src/views/shop/shopOrder/useOrderNotify.ts` 增加 `onNewOrder` 回调参数,检测到新订单触发提醒(叮声+语音)时同时调用回调。
|
||||||
- `src/views/shop/shopOrder/index.vue` 调用 `useOrderNotify({ onNewOrder: () => reload() })`,使新订单提醒时自动刷新表格数据,保持数据同步。
|
- `src/views/shop/shopOrder/index.vue` 调用 `useOrderNotify({ onNewOrder: () => reload() })`,使新订单提醒时自动刷新表格数据,保持数据同步。
|
||||||
|
|
||||||
|
## 2026-07-14 订单列表商品图片接入 OSS 压缩
|
||||||
|
|
||||||
|
### 改动内容
|
||||||
|
- 参考 `/Users/gxwebsoft/VUE/xinlong-shop-taro/src/utils/image.ts`,在管理后台新增 `src/utils/image.ts`:
|
||||||
|
- `ensureFullUrl(url)`:补全 OSS 域名为完整 URL
|
||||||
|
- `getCompressedImageUrl(url, options?)`:拼接 `x-oss-process=image/resize,w_${width}/quality,Q_${quality}` 压缩参数
|
||||||
|
- `src/views/shop/shopOrder/index.vue`:
|
||||||
|
- 引入 `getCompressedImageUrl`
|
||||||
|
- 订单列表商品图片列 `<a-avatar :src="item.image" />` 改为 `<a-avatar :src="getCompressedImageUrl(item.image)" />`
|
||||||
|
|
||||||
|
### 待办
|
||||||
|
- 用户提到后端也需要此方法,但当前工作区只有前端代码,后端实现需在后端项目补充。
|
||||||
|
|||||||
@@ -85,9 +85,9 @@ export interface ShopOrder {
|
|||||||
coachId?: number;
|
coachId?: number;
|
||||||
// 支付的用户id
|
// 支付的用户id
|
||||||
payUserId?: number;
|
payUserId?: number;
|
||||||
// 0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
// 0余额支付, 1微信支付, 2支付宝, 3银联支付, 4现金支付, 5POS机支付, 6免费, 7积分支付, 8货到付款, 9~18 已废弃
|
||||||
payType?: number;
|
payType?: number;
|
||||||
// 代付支付方式,0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
// 代付支付方式, 0余额支付, 1微信支付, 2支付宝, 3银联支付, 4现金支付, 5POS机支付, 6免费, 7积分支付, 8货到付款, 9~18 已废弃
|
||||||
friendPayType?: number;
|
friendPayType?: number;
|
||||||
// 0未付款,1已付款
|
// 0未付款,1已付款
|
||||||
payStatus?: number;
|
payStatus?: number;
|
||||||
|
|||||||
@@ -45,21 +45,45 @@
|
|||||||
{ value: 1, label: '微信支付', key: 'wxPay', icon: 'WechatOutlined' },
|
{ value: 1, label: '微信支付', key: 'wxPay', icon: 'WechatOutlined' },
|
||||||
{
|
{
|
||||||
value: 2,
|
value: 2,
|
||||||
label: '会员卡支付',
|
label: '支付宝',
|
||||||
key: 'userCardPay',
|
key: 'aliPay',
|
||||||
icon: 'IdcardOutlined'
|
icon: 'AlipayCircleOutlined'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 3,
|
value: 3,
|
||||||
label: '支付宝支付',
|
label: '银联支付',
|
||||||
key: 'aliPay',
|
key: 'unionPay',
|
||||||
icon: 'AlipayCircleOutlined'
|
icon: 'IdcardOutlined'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 4,
|
value: 4,
|
||||||
label: '现金支付',
|
label: '现金支付',
|
||||||
key: 'cashPayment',
|
key: 'cashPayment',
|
||||||
icon: 'PayCircleOutlined'
|
icon: 'PayCircleOutlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 5,
|
||||||
|
label: 'POS机支付',
|
||||||
|
key: 'posPay',
|
||||||
|
icon: 'IdcardOutlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 6,
|
||||||
|
label: '免费',
|
||||||
|
key: 'freePay',
|
||||||
|
icon: 'IdcardOutlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 7,
|
||||||
|
label: '积分支付',
|
||||||
|
key: 'pointsPay',
|
||||||
|
icon: 'IdcardOutlined'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 8,
|
||||||
|
label: '货到付款',
|
||||||
|
key: 'codPay',
|
||||||
|
icon: 'IdcardOutlined'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
76
src/utils/image.ts
Normal file
76
src/utils/image.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* 图片压缩参数配置
|
||||||
|
*/
|
||||||
|
export interface ImageCompressOptions {
|
||||||
|
/** 图片宽度(px),默认 300 */
|
||||||
|
width?: number;
|
||||||
|
/** 图片质量 0-100,默认 90 */
|
||||||
|
quality?: number;
|
||||||
|
/** 是否启用压缩,默认 true */
|
||||||
|
enabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认压缩参数
|
||||||
|
*/
|
||||||
|
const DEFAULT_OPTIONS: Required<ImageCompressOptions> = {
|
||||||
|
width: 240,
|
||||||
|
quality: 90,
|
||||||
|
enabled: true
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OSS 域名(文件上传接口同域)
|
||||||
|
*/
|
||||||
|
const OSS_BASE_URL = 'https://oss.wsdns.cn';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确保图片 URL 为完整路径
|
||||||
|
*
|
||||||
|
* 后端可能返回相对路径(如 /uploads/xxx.jpg),需要补全 OSS 域名。
|
||||||
|
*
|
||||||
|
* @param url 原始图片 URL
|
||||||
|
* @returns 完整图片 URL
|
||||||
|
*/
|
||||||
|
export function ensureFullUrl(url: string): string {
|
||||||
|
if (!url) return '';
|
||||||
|
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
// 相对路径:补全 OSS 域名
|
||||||
|
return `${OSS_BASE_URL}${url.startsWith('/') ? '' : '/'}${url}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 OSS 压缩后的图片 URL
|
||||||
|
*
|
||||||
|
* 默认给图片 URL 拼接阿里云 OSS 图片处理参数,实现等比缩放 + 质量压缩。
|
||||||
|
* 使用场景:商品列表、商品卡片等缩略图展示。
|
||||||
|
*
|
||||||
|
* 注意:预览原图时不需要调用此函数,直接用原始 URL 即可。
|
||||||
|
*
|
||||||
|
* @param url 原始图片 URL
|
||||||
|
* @param options 压缩选项
|
||||||
|
* @returns 处理后的图片 URL
|
||||||
|
*/
|
||||||
|
export function getCompressedImageUrl(
|
||||||
|
url: string,
|
||||||
|
options?: ImageCompressOptions
|
||||||
|
): string {
|
||||||
|
// 先补全为完整 URL
|
||||||
|
const fullUrl = ensureFullUrl(url);
|
||||||
|
if (!fullUrl) return '';
|
||||||
|
|
||||||
|
const { width, quality, enabled } = { ...DEFAULT_OPTIONS, ...options };
|
||||||
|
|
||||||
|
// 未启用压缩,原样返回
|
||||||
|
if (!enabled) return fullUrl;
|
||||||
|
|
||||||
|
// 已包含 OSS 处理参数,避免重复拼接
|
||||||
|
if (fullUrl.includes('x-oss-process')) return fullUrl;
|
||||||
|
|
||||||
|
// 已有其他 query 参数用 & 拼接,否则用 ?
|
||||||
|
const separator = fullUrl.includes('?') ? '&' : '?';
|
||||||
|
|
||||||
|
return `${fullUrl}${separator}x-oss-process=image/resize,w_${width}/quality,Q_${quality}`;
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ export function getPayType(index?: number): any {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 5,
|
value: 5,
|
||||||
label: 'POS机'
|
label: 'POS机支付'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 6,
|
value: 6,
|
||||||
@@ -38,7 +38,7 @@ export function getPayType(index?: number): any {
|
|||||||
label: '货到付款'
|
label: '货到付款'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
if (index) {
|
if (index != null) {
|
||||||
return payType[index]?.label || '';
|
return payType[index]?.label || '';
|
||||||
}
|
}
|
||||||
return payType;
|
return payType;
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ const couponUsedCount = ref(0);
|
|||||||
const todoItems = computed(() => [
|
const todoItems = computed(() => [
|
||||||
{ label: '待发货订单', value: pendingShipmentCount.value, to: '/shop/shopOrder', tagColor: 'blue', dotColor: 'dot-blue', urgent: pendingShipmentCount.value > 0 },
|
{ label: '待发货订单', value: pendingShipmentCount.value, to: '/shop/shopOrder', tagColor: 'blue', dotColor: 'dot-blue', urgent: pendingShipmentCount.value > 0 },
|
||||||
{ label: '退款申请', value: pendingRefundCount.value, to: '/shop/shopOrder', tagColor: 'orange', dotColor: 'dot-orange', urgent: pendingRefundCount.value > 0 },
|
{ label: '退款申请', value: pendingRefundCount.value, to: '/shop/shopOrder', tagColor: 'orange', dotColor: 'dot-orange', urgent: pendingRefundCount.value > 0 },
|
||||||
{ label: '优惠券使用', value: couponUsedCount.value, to: '/market/coupon', tagColor: 'cyan', dotColor: 'dot-cyan', urgent: false },
|
// { label: '优惠券使用', value: couponUsedCount.value, to: '/market/coupon', tagColor: 'cyan', dotColor: 'dot-cyan', urgent: false },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 今日统计(使用computed确保响应式更新)
|
// 今日统计(使用computed确保响应式更新)
|
||||||
|
|||||||
@@ -71,7 +71,8 @@
|
|||||||
label="支付状态"
|
label="支付状态"
|
||||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||||
>
|
>
|
||||||
<a-tag v-if="form.payStatus == 1" color="green">已付款</a-tag>
|
<a-tag v-if="form.payStatus == 1 && form.payType !== 8" color="green">已付款</a-tag>
|
||||||
|
<a-tag v-if="form.payStatus == 1 && form.payType === 8" color="blue">待收货付款</a-tag>
|
||||||
<a-tag v-if="form.payStatus == 0">未付款</a-tag>
|
<a-tag v-if="form.payStatus == 0">未付款</a-tag>
|
||||||
<a-tag v-if="form.payStatus == 3">未付款,占场中</a-tag>
|
<a-tag v-if="form.payStatus == 3">未付款,占场中</a-tag>
|
||||||
</a-descriptions-item>
|
</a-descriptions-item>
|
||||||
@@ -116,30 +117,33 @@
|
|||||||
<WechatOutlined class="tag-icon" />
|
<WechatOutlined class="tag-icon" />
|
||||||
微信支付
|
微信支付
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-if="form.payType == 2">积分</a-tag>
|
<a-tag v-if="form.payType == 2">
|
||||||
<a-tag v-if="form.payType == 3">
|
|
||||||
<AlipayCircleOutlined class="tag-icon" />
|
<AlipayCircleOutlined class="tag-icon" />
|
||||||
支付宝
|
支付宝
|
||||||
</a-tag>
|
</a-tag>
|
||||||
|
<a-tag v-if="form.payType == 3">
|
||||||
|
<IdcardOutlined class="tag-icon" />
|
||||||
|
银联支付
|
||||||
|
</a-tag>
|
||||||
<a-tag v-if="form.payType == 4">
|
<a-tag v-if="form.payType == 4">
|
||||||
<IdcardOutlined class="tag-icon" />
|
<IdcardOutlined class="tag-icon" />
|
||||||
现金
|
现金支付
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-if="form.payType == 5">
|
<a-tag v-if="form.payType == 5">
|
||||||
<IdcardOutlined class="tag-icon" />
|
<IdcardOutlined class="tag-icon" />
|
||||||
POS机
|
POS机支付
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-if="form.payType == 6">
|
<a-tag v-if="form.payType == 6">
|
||||||
<IdcardOutlined class="tag-icon" />
|
<IdcardOutlined class="tag-icon" />
|
||||||
VIP月卡
|
免费
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-if="form.payType == 7">
|
<a-tag v-if="form.payType == 7">
|
||||||
<IdcardOutlined class="tag-icon" />
|
<IdcardOutlined class="tag-icon" />
|
||||||
VIP年卡
|
积分支付
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-if="form.payType == 8">
|
<a-tag v-if="form.payType == 8">
|
||||||
<IdcardOutlined class="tag-icon" />
|
<IdcardOutlined class="tag-icon" />
|
||||||
VIP次卡
|
货到付款
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<a-tag v-if="form.payType == 9">
|
<a-tag v-if="form.payType == 9">
|
||||||
<IdcardOutlined class="tag-icon" />
|
<IdcardOutlined class="tag-icon" />
|
||||||
@@ -541,9 +545,9 @@
|
|||||||
coachId: undefined,
|
coachId: undefined,
|
||||||
// 支付的用户id
|
// 支付的用户id
|
||||||
payUserId: undefined,
|
payUserId: undefined,
|
||||||
// 0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
// 0余额支付, 1微信支付, 2支付宝, 3银联支付, 4现金支付, 5POS机支付, 6免费, 7积分支付, 8货到付款, 9~18 已废弃
|
||||||
payType: undefined,
|
payType: undefined,
|
||||||
// 代付支付方式,0余额支付, 1微信支付,102微信Native,2会员卡支付,3支付宝,4现金,5POS机,6VIP月卡,7VIP年卡,8VIP次卡,9IC月卡,10IC年卡,11IC次卡,12免费,13VIP充值卡,14IC充值卡,15积分支付,16VIP季卡,17IC季卡,18代付
|
// 代付支付方式, 0余额支付, 1微信支付, 2支付宝, 3银联支付, 4现金支付, 5POS机支付, 6免费, 7积分支付, 8货到付款, 9~18 已废弃
|
||||||
friendPayType: undefined,
|
friendPayType: undefined,
|
||||||
// 0未付款,1已付款
|
// 0未付款,1已付款
|
||||||
payStatus: undefined,
|
payStatus: undefined,
|
||||||
|
|||||||
@@ -175,7 +175,7 @@
|
|||||||
<template v-for="(item, index) in record.orderGoods" :key="index">
|
<template v-for="(item, index) in record.orderGoods" :key="index">
|
||||||
<div class="item py-1">
|
<div class="item py-1">
|
||||||
<a-space :id="`g-${index}`">
|
<a-space :id="`g-${index}`">
|
||||||
<a-avatar :src="item.image" shape="square" :size="80" />
|
<a-avatar :src="getCompressedImageUrl(item.image)" shape="square" :size="80" />
|
||||||
<span>{{ item.goodsName }}</span>
|
<span>{{ item.goodsName }}</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
@@ -376,6 +376,7 @@
|
|||||||
} from '@/api/shop/shopOrder';
|
} from '@/api/shop/shopOrder';
|
||||||
import { updateUser } from '@/api/system/user';
|
import { updateUser } from '@/api/system/user';
|
||||||
import { getPayType } from '@/utils/shop';
|
import { getPayType } from '@/utils/shop';
|
||||||
|
import { getCompressedImageUrl } from '@/utils/image';
|
||||||
import { message, Modal } from 'ant-design-vue';
|
import { message, Modal } from 'ant-design-vue';
|
||||||
import { useOrderNotify } from './useOrderNotify';
|
import { useOrderNotify } from './useOrderNotify';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user