feat:【mall 商城】交易订单(70% ele 初始化)
This commit is contained in:
@@ -66,7 +66,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
title: '订单详情',
|
title: '订单详情',
|
||||||
activePath: '/mall/trade/order',
|
activePath: '/mall/trade/order',
|
||||||
},
|
},
|
||||||
component: () => import('#/views/mall/trade/order/modules/detail.vue'),
|
component: () => import('#/views/mall/trade/order/detail/index.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: String.raw`after-sale/detail/:id(\d+)`,
|
path: String.raw`after-sale/detail/:id(\d+)`,
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeGridPropTypes } from '#/adapter/vxe-table';
|
||||||
import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore';
|
import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import { DeliveryTypeEnum } from '@vben/constants';
|
import { DeliveryTypeEnum, DICT_TYPE } from '@vben/constants';
|
||||||
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
import { convertToInteger, formatToFraction } from '@vben/utils';
|
||||||
|
|
||||||
import { getSimpleDeliveryExpressList } from '#/api/mall/trade/delivery/express';
|
import { getSimpleDeliveryExpressList } from '#/api/mall/trade/delivery/express';
|
||||||
import { getSimpleDeliveryPickUpStoreList } from '#/api/mall/trade/delivery/pickUpStore';
|
import { getSimpleDeliveryPickUpStoreList } from '#/api/mall/trade/delivery/pickUpStore';
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
import { getAreaTree } from '#/api/system/area';
|
||||||
import { getDictOptions } from '@vben/hooks';
|
|
||||||
|
|
||||||
import { getRangePickerDefaultProps } from '#/utils';
|
import { getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
const pickUpStoreList = ref<MallDeliveryPickUpStoreApi.PickUpStore[]>([]);
|
const pickUpStoreList = ref<MallDeliveryPickUpStoreApi.PickUpStore[]>([]);
|
||||||
@@ -28,6 +28,8 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: getDictOptions(DICT_TYPE.TRADE_ORDER_STATUS, 'number'),
|
options: getDictOptions(DICT_TYPE.TRADE_ORDER_STATUS, 'number'),
|
||||||
|
placeholder: '请选择订单状态',
|
||||||
|
clearable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -36,13 +38,10 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE, 'number'),
|
options: getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE, 'number'),
|
||||||
|
placeholder: '请选择支付方式',
|
||||||
|
clearable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
fieldName: 'name',
|
|
||||||
label: '品牌名称',
|
|
||||||
component: 'Input',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
fieldName: 'createTime',
|
fieldName: 'createTime',
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
@@ -58,6 +57,8 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: getDictOptions(DICT_TYPE.TERMINAL, 'number'),
|
options: getDictOptions(DICT_TYPE.TERMINAL, 'number'),
|
||||||
|
placeholder: '请选择订单来源',
|
||||||
|
clearable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -66,6 +67,8 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
options: getDictOptions(DICT_TYPE.TRADE_DELIVERY_TYPE, 'number'),
|
options: getDictOptions(DICT_TYPE.TRADE_DELIVERY_TYPE, 'number'),
|
||||||
|
placeholder: '请选择配送方式',
|
||||||
|
clearable: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -74,8 +77,12 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleDeliveryExpressList,
|
api: getSimpleDeliveryExpressList,
|
||||||
labelField: 'name',
|
fieldNames: {
|
||||||
valueField: 'id',
|
label: 'name',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
|
placeholder: '请选择快递公司',
|
||||||
|
clearable: true,
|
||||||
},
|
},
|
||||||
dependencies: {
|
dependencies: {
|
||||||
triggerFields: ['deliveryType'],
|
triggerFields: ['deliveryType'],
|
||||||
@@ -88,8 +95,12 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleDeliveryPickUpStoreList,
|
api: getSimpleDeliveryPickUpStoreList,
|
||||||
labelField: 'name',
|
fieldNames: {
|
||||||
valueField: 'id',
|
label: 'name',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
|
placeholder: '请选择自提门店',
|
||||||
|
clearable: true,
|
||||||
},
|
},
|
||||||
dependencies: {
|
dependencies: {
|
||||||
triggerFields: ['deliveryType'],
|
triggerFields: ['deliveryType'],
|
||||||
@@ -100,16 +111,56 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
|||||||
fieldName: 'pickUpVerifyCode',
|
fieldName: 'pickUpVerifyCode',
|
||||||
label: '核销码',
|
label: '核销码',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入核销码',
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
dependencies: {
|
dependencies: {
|
||||||
triggerFields: ['deliveryType'],
|
triggerFields: ['deliveryType'],
|
||||||
show: (values) => values.deliveryType === DeliveryTypeEnum.PICK_UP.type,
|
show: (values) => values.deliveryType === DeliveryTypeEnum.PICK_UP.type,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'no',
|
||||||
|
label: '订单号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入订单号',
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'userId',
|
||||||
|
label: '用户 UID',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入用户 UID',
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'userNickname',
|
||||||
|
label: '用户昵称',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入用户昵称',
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'userMobile',
|
||||||
|
label: '用户电话',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入用户电话',
|
||||||
|
clearable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表格列配置 */
|
/** 表格列配置 */
|
||||||
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
export function useGridColumns(): VxeGridPropTypes.Columns {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'expand',
|
type: 'expand',
|
||||||
@@ -162,11 +213,10 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
},
|
},
|
||||||
minWidth: 80,
|
minWidth: 80,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
field: 'payPrice',
|
field: 'payPrice',
|
||||||
title: '实际支付',
|
title: '实际支付',
|
||||||
formatter: 'formatFenToYuanAmount',
|
formatter: 'formatAmount2',
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -212,3 +262,199 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 订单备注表单配置 */
|
||||||
|
export function useRemarkFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'id',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'remark',
|
||||||
|
label: '备注',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
type: 'textarea',
|
||||||
|
rows: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单调价表单配置 */
|
||||||
|
export function usePriceFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'id',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'payPrice',
|
||||||
|
label: '应付金额(总)',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入应付金额(总)',
|
||||||
|
disabled: true,
|
||||||
|
formatter: (value: string) => `${value}元`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'adjustPrice',
|
||||||
|
label: '订单调价',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入订单调价',
|
||||||
|
step: 0.1,
|
||||||
|
precision: 2,
|
||||||
|
},
|
||||||
|
help: '订单调价。 正数,加价;负数,减价',
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'newPayPrice',
|
||||||
|
label: '调价后',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '',
|
||||||
|
formatter: (value: string) => `${value}元`,
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['payPrice', 'adjustPrice'],
|
||||||
|
disabled: true,
|
||||||
|
trigger(values, form) {
|
||||||
|
const originalPrice = convertToInteger(values.payPrice);
|
||||||
|
const adjustPrice = convertToInteger(values.adjustPrice);
|
||||||
|
const newPrice = originalPrice + adjustPrice;
|
||||||
|
form.setFieldValue('newPayPrice', formatToFraction(newPrice));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单修改地址表单配置 */
|
||||||
|
export function useAddressFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'id',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'receiverName',
|
||||||
|
label: '收件人',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入收件人名称',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'receiverMobile',
|
||||||
|
label: '手机号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入收件人手机号',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'receiverAreaId',
|
||||||
|
label: '所在地',
|
||||||
|
component: 'ApiTreeSelect',
|
||||||
|
componentProps: {
|
||||||
|
api: () => getAreaTree(),
|
||||||
|
fieldNames: {
|
||||||
|
label: 'name',
|
||||||
|
value: 'id',
|
||||||
|
children: 'children',
|
||||||
|
},
|
||||||
|
placeholder: '请选择收件人所在地',
|
||||||
|
treeDefaultExpandAll: true,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'receiverDetailAddress',
|
||||||
|
label: '详细地址',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入收件人详细地址',
|
||||||
|
type: 'textarea',
|
||||||
|
rows: 3,
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单发货表单配置 */
|
||||||
|
export function useDeliveryFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
component: 'Input',
|
||||||
|
fieldName: 'id',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'expressType',
|
||||||
|
label: '发货方式',
|
||||||
|
component: 'RadioGroup',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{ label: '快递', value: 'express' },
|
||||||
|
{ label: '无需发货', value: 'none' },
|
||||||
|
],
|
||||||
|
buttonStyle: 'solid',
|
||||||
|
optionType: 'button',
|
||||||
|
},
|
||||||
|
defaultValue: 'express',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'logisticsId',
|
||||||
|
label: '物流公司',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
api: getSimpleDeliveryExpressList,
|
||||||
|
fieldNames: {
|
||||||
|
label: 'name',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
|
placeholder: '请选择物流公司',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['expressType'],
|
||||||
|
show: (values) => values.expressType === 'express',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'logisticsNo',
|
||||||
|
label: '物流单号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入物流单号',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['expressType'],
|
||||||
|
show: (values) => values.expressType === 'express',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|||||||
277
apps/web-ele/src/views/mall/trade/order/detail/data.ts
Normal file
277
apps/web-ele/src/views/mall/trade/order/detail/data.ts
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MallOrderApi } from '#/api/mall/trade/order';
|
||||||
|
|
||||||
|
import { h } from 'vue';
|
||||||
|
|
||||||
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
|
import { fenToYuan, formatDateTime } from '@vben/utils';
|
||||||
|
|
||||||
|
import { DictTag } from '#/components/dict-tag';
|
||||||
|
|
||||||
|
/** 订单基础信息 schema */
|
||||||
|
export function useOrderInfoSchema() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'no',
|
||||||
|
label: '订单号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'user.nickname',
|
||||||
|
label: '买家',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'type',
|
||||||
|
label: '订单类型',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(DictTag, {
|
||||||
|
type: DICT_TYPE.TRADE_ORDER_TYPE,
|
||||||
|
value: data?.type,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'terminal',
|
||||||
|
label: '订单来源',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(DictTag, {
|
||||||
|
type: DICT_TYPE.TERMINAL,
|
||||||
|
value: data?.terminal,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'userRemark',
|
||||||
|
label: '买家留言',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'remark',
|
||||||
|
label: '商家备注',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'payOrderId',
|
||||||
|
label: '支付单号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'payChannelCode',
|
||||||
|
label: '付款方式',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(DictTag, {
|
||||||
|
type: DICT_TYPE.PAY_CHANNEL_CODE,
|
||||||
|
value: data?.payChannelCode,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'brokerageUser.nickname',
|
||||||
|
label: '推广用户',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单状态信息 schema */
|
||||||
|
export function useOrderStatusSchema() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
label: '订单状态',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(DictTag, {
|
||||||
|
type: DICT_TYPE.TRADE_ORDER_STATUS,
|
||||||
|
value: data?.status,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'reminder',
|
||||||
|
label: '提醒',
|
||||||
|
render: () =>
|
||||||
|
h('div', { class: 'space-y-1' }, [
|
||||||
|
h('div', '买家付款成功后,货款将直接进入您的商户号(微信、支付宝)'),
|
||||||
|
h('div', '请及时关注你发出的包裹状态,确保可以配送至买家手中'),
|
||||||
|
h(
|
||||||
|
'div',
|
||||||
|
'如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商',
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 订单金额信息 schema */
|
||||||
|
export function useOrderPriceSchema() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'totalPrice',
|
||||||
|
label: '商品总额',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
`${fenToYuan(data?.totalPrice ?? 0)} 元`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'deliveryPrice',
|
||||||
|
label: '运费金额',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
`${fenToYuan(data?.deliveryPrice ?? 0)} 元`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'adjustPrice',
|
||||||
|
label: '订单调价',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
`${fenToYuan(data?.adjustPrice ?? 0)} 元`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'couponPrice',
|
||||||
|
label: '优惠劵优惠',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(
|
||||||
|
'span',
|
||||||
|
{ class: 'text-red-500' },
|
||||||
|
`${fenToYuan(data?.couponPrice ?? 0)} 元`,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'vipPrice',
|
||||||
|
label: 'VIP 优惠',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(
|
||||||
|
'span',
|
||||||
|
{ class: 'text-red-500' },
|
||||||
|
`${fenToYuan(data?.vipPrice ?? 0)} 元`,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'discountPrice',
|
||||||
|
label: '活动优惠',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(
|
||||||
|
'span',
|
||||||
|
{ class: 'text-red-500' },
|
||||||
|
`${fenToYuan(data?.discountPrice ?? 0)} 元`,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'pointPrice',
|
||||||
|
label: '积分抵扣',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(
|
||||||
|
'span',
|
||||||
|
{ class: 'text-red-500' },
|
||||||
|
`${fenToYuan(data?.pointPrice ?? 0)} 元`,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'payPrice',
|
||||||
|
label: '应付金额',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
`${fenToYuan(data?.payPrice ?? 0)} 元`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 收货信息 schema */
|
||||||
|
export function useDeliveryInfoSchema() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'deliveryType',
|
||||||
|
label: '配送方式',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
h(DictTag, {
|
||||||
|
type: DICT_TYPE.TRADE_DELIVERY_TYPE,
|
||||||
|
value: data?.deliveryType,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'receiverName',
|
||||||
|
label: '收货人',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'receiverMobile',
|
||||||
|
label: '联系电话',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'receiverAddress',
|
||||||
|
label: '收货地址',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
`${data?.receiverAreaName} ${data?.receiverDetailAddress}`.trim(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'deliveryTime',
|
||||||
|
label: '发货时间',
|
||||||
|
render: (data: MallOrderApi.Order) =>
|
||||||
|
formatDateTime(data?.deliveryTime || '') as string,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 商品信息 columns */
|
||||||
|
export function useProductColumns(): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'spuName',
|
||||||
|
title: '商品',
|
||||||
|
minWidth: 300,
|
||||||
|
slots: { default: 'spuName' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'price',
|
||||||
|
title: '商品原价',
|
||||||
|
width: 150,
|
||||||
|
formatter: 'formatFenToYuanAmount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'count',
|
||||||
|
title: '数量',
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'payPrice',
|
||||||
|
title: '合计',
|
||||||
|
width: 150,
|
||||||
|
formatter: 'formatFenToYuanAmount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'afterSaleStatus',
|
||||||
|
title: '售后状态',
|
||||||
|
width: 120,
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.TRADE_ORDER_ITEM_AFTER_SALE_STATUS },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 物流详情 columns */
|
||||||
|
export function useExpressTrackColumns(): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'time',
|
||||||
|
title: '时间',
|
||||||
|
width: 180,
|
||||||
|
formatter: 'formatDateTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'content',
|
||||||
|
title: '物流状态',
|
||||||
|
minWidth: 300,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 操作日志 columns */
|
||||||
|
export function useOperateLogColumns(): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'createTime',
|
||||||
|
title: '操作时间',
|
||||||
|
width: 180,
|
||||||
|
formatter: 'formatDateTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'userType',
|
||||||
|
title: '操作人',
|
||||||
|
width: 100,
|
||||||
|
slots: { default: 'userType' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'content',
|
||||||
|
title: '操作内容',
|
||||||
|
minWidth: 200,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
456
apps/web-ele/src/views/mall/trade/order/detail/index.vue
Normal file
456
apps/web-ele/src/views/mall/trade/order/detail/index.vue
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { MallDeliveryExpressApi } from '#/api/mall/trade/delivery/express';
|
||||||
|
import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore';
|
||||||
|
import type { MallOrderApi } from '#/api/mall/trade/order';
|
||||||
|
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import { confirm, Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
import {
|
||||||
|
DeliveryTypeEnum,
|
||||||
|
DICT_TYPE,
|
||||||
|
TradeOrderStatusEnum,
|
||||||
|
} from '@vben/constants';
|
||||||
|
import { useTabs } from '@vben/hooks';
|
||||||
|
import { fenToYuan, formatDateTime } from '@vben/utils';
|
||||||
|
|
||||||
|
import { ElCard, ElMessage, ElTag } from 'element-plus';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import * as DeliveryExpressApi from '#/api/mall/trade/delivery/express';
|
||||||
|
import * as DeliveryPickUpStoreApi from '#/api/mall/trade/delivery/pickUpStore';
|
||||||
|
import * as TradeOrderApi from '#/api/mall/trade/order';
|
||||||
|
import { DictTag } from '#/components/dict-tag';
|
||||||
|
import { TableAction } from '#/components/table-action';
|
||||||
|
|
||||||
|
import DeliveryForm from '../modules/delevery-form.vue';
|
||||||
|
import UpdateAddressForm from '../modules/update-address-form.vue';
|
||||||
|
import UpdatePriceForm from '../modules/update-price-form.vue';
|
||||||
|
import RemarkForm from '../modules/update-remark-form.vue';
|
||||||
|
import {
|
||||||
|
useExpressTrackColumns,
|
||||||
|
useOperateLogColumns,
|
||||||
|
useProductColumns,
|
||||||
|
} from './data';
|
||||||
|
|
||||||
|
defineOptions({ name: 'TradeOrderDetail' });
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const tabs = useTabs();
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const orderId = ref(0);
|
||||||
|
const order = ref<MallOrderApi.Order>({
|
||||||
|
logs: [],
|
||||||
|
});
|
||||||
|
const deliveryExpressList = ref<MallDeliveryExpressApi.SimpleDeliveryExpress[]>(
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const expressTrackList = ref<any[]>([]);
|
||||||
|
const pickUpStore = ref<MallDeliveryPickUpStoreApi.PickUpStore | undefined>();
|
||||||
|
|
||||||
|
const [ProductGrid, productGridApi] = useVbenVxeGrid({
|
||||||
|
gridOptions: {
|
||||||
|
cellConfig: {
|
||||||
|
height: 60,
|
||||||
|
},
|
||||||
|
columns: useProductColumns(),
|
||||||
|
data: [],
|
||||||
|
height: 'auto',
|
||||||
|
border: true,
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<MallOrderApi.OrderItem>,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [ExpressTrackGrid, expressTrackGridApi] = useVbenVxeGrid({
|
||||||
|
gridOptions: {
|
||||||
|
columns: useExpressTrackColumns(),
|
||||||
|
data: [],
|
||||||
|
border: true,
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [OperateLogGrid, operateLogGridApi] = useVbenVxeGrid({
|
||||||
|
gridOptions: {
|
||||||
|
columns: useOperateLogColumns(),
|
||||||
|
data: [],
|
||||||
|
border: true,
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [DeliveryFormModal, deliveryFormModalApi] = useVbenModal({
|
||||||
|
connectedComponent: DeliveryForm,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [RemarkFormModal, remarkFormModalApi] = useVbenModal({
|
||||||
|
connectedComponent: RemarkForm,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [AddressFormModal, addressFormModalApi] = useVbenModal({
|
||||||
|
connectedComponent: UpdateAddressForm,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [PriceFormModal, priceFormModalApi] = useVbenModal({
|
||||||
|
connectedComponent: UpdatePriceForm,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 获得详情 */
|
||||||
|
async function getDetail() {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await TradeOrderApi.getOrder(orderId.value);
|
||||||
|
if (res === null) {
|
||||||
|
ElMessage.error('交易订单不存在');
|
||||||
|
handleBack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
order.value = res;
|
||||||
|
productGridApi.setGridOptions({ data: res.items || [] });
|
||||||
|
operateLogGridApi.setGridOptions({ data: res.logs || [] });
|
||||||
|
|
||||||
|
// 如果配送方式为快递,则查询物流公司
|
||||||
|
if (res.deliveryType === DeliveryTypeEnum.EXPRESS.type) {
|
||||||
|
deliveryExpressList.value =
|
||||||
|
await DeliveryExpressApi.getSimpleDeliveryExpressList();
|
||||||
|
if (res.logisticsId) {
|
||||||
|
expressTrackList.value = await TradeOrderApi.getExpressTrackList(
|
||||||
|
res.id!,
|
||||||
|
);
|
||||||
|
expressTrackGridApi.setGridOptions({
|
||||||
|
data: expressTrackList.value || [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
res.deliveryType === DeliveryTypeEnum.PICK_UP.type &&
|
||||||
|
res.pickUpStoreId
|
||||||
|
) {
|
||||||
|
pickUpStore.value = await DeliveryPickUpStoreApi.getDeliveryPickUpStore(
|
||||||
|
res.pickUpStoreId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 各种操作 */
|
||||||
|
const handleRemark = () => {
|
||||||
|
remarkFormModalApi.setData(order.value).open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelivery = () => {
|
||||||
|
deliveryFormModalApi.setData(order.value).open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdateAddress = () => {
|
||||||
|
addressFormModalApi.setData(order.value).open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdatePrice = () => {
|
||||||
|
priceFormModalApi.setData(order.value).open();
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 核销 */
|
||||||
|
const handlePickUp = async () => {
|
||||||
|
await confirm('确认核销订单吗?');
|
||||||
|
const loadingInstance = ElMessage({
|
||||||
|
message: '正在处理中...',
|
||||||
|
duration: 0,
|
||||||
|
type: 'info',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await TradeOrderApi.pickUpOrder(order.value.id!);
|
||||||
|
ElMessage.success('核销成功');
|
||||||
|
await getDetail();
|
||||||
|
} finally {
|
||||||
|
loadingInstance.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 返回列表页 */
|
||||||
|
function handleBack() {
|
||||||
|
tabs.closeCurrentTab();
|
||||||
|
router.push('/mall/trade/order');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(async () => {
|
||||||
|
orderId.value = Number(route.params.id);
|
||||||
|
await getDetail();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page auto-content-height :title="order.no" :loading="loading">
|
||||||
|
<template #extra>
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '返回',
|
||||||
|
type: 'default',
|
||||||
|
icon: 'lucide:arrow-left',
|
||||||
|
onClick: handleBack,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '调整价格',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: handleUpdatePrice,
|
||||||
|
ifShow: order.status === TradeOrderStatusEnum.UNPAID.status,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: handleRemark,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: handleDelivery,
|
||||||
|
ifShow:
|
||||||
|
order.status === TradeOrderStatusEnum.UNDELIVERED.status &&
|
||||||
|
order.deliveryType === DeliveryTypeEnum.EXPRESS.type,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '修改地址',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: handleUpdateAddress,
|
||||||
|
ifShow:
|
||||||
|
order.status === TradeOrderStatusEnum.UNDELIVERED.status &&
|
||||||
|
order.deliveryType === DeliveryTypeEnum.EXPRESS.type,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '核销',
|
||||||
|
type: 'primary',
|
||||||
|
onClick: handlePickUp,
|
||||||
|
ifShow:
|
||||||
|
order.status === TradeOrderStatusEnum.UNDELIVERED.status &&
|
||||||
|
order.deliveryType === DeliveryTypeEnum.PICK_UP.type,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 各种操作的弹窗 -->
|
||||||
|
<DeliveryFormModal @success="getDetail" />
|
||||||
|
<RemarkFormModal @success="getDetail" />
|
||||||
|
<AddressFormModal @success="getDetail" />
|
||||||
|
<PriceFormModal @success="getDetail" />
|
||||||
|
|
||||||
|
<!-- 订单信息 -->
|
||||||
|
<ElCard class="mb-4">
|
||||||
|
<template #header>
|
||||||
|
<span class="font-bold">订单信息</span>
|
||||||
|
</template>
|
||||||
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">订单号:</span>
|
||||||
|
<span>{{ order.no }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">买家:</span>
|
||||||
|
<span>{{ order.user?.nickname }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">订单类型:</span>
|
||||||
|
<DictTag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="order.type" />
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">订单来源:</span>
|
||||||
|
<DictTag :type="DICT_TYPE.TERMINAL" :value="order.terminal" />
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">买家留言:</span>
|
||||||
|
<span>{{ order.userRemark }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">商家备注:</span>
|
||||||
|
<span>{{ order.remark }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">支付单号:</span>
|
||||||
|
<span>{{ order.payOrderId }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">付款方式:</span>
|
||||||
|
<DictTag
|
||||||
|
:type="DICT_TYPE.PAY_CHANNEL_CODE"
|
||||||
|
:value="order.payChannelCode"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">推广用户:</span>
|
||||||
|
<span>{{ order.brokerageUser?.nickname }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ElCard>
|
||||||
|
|
||||||
|
<!-- 订单状态 -->
|
||||||
|
<ElCard class="mb-4">
|
||||||
|
<template #header>
|
||||||
|
<span class="font-bold">订单状态</span>
|
||||||
|
</template>
|
||||||
|
<div class="space-y-2">
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">订单状态:</span>
|
||||||
|
<DictTag :type="DICT_TYPE.TRADE_ORDER_STATUS" :value="order.status" />
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">提醒:</span>
|
||||||
|
<div class="space-y-1">
|
||||||
|
<div>买家付款成功后,货款将直接进入您的商户号(微信、支付宝)</div>
|
||||||
|
<div>请及时关注你发出的包裹状态,确保可以配送至买家手中</div>
|
||||||
|
<div>
|
||||||
|
如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ElCard>
|
||||||
|
|
||||||
|
<!-- 商品信息 -->
|
||||||
|
<div class="mb-4">
|
||||||
|
<ProductGrid table-title="商品信息">
|
||||||
|
<template #spuName="{ row }">
|
||||||
|
<div class="flex flex-1 flex-col items-start gap-1 text-left">
|
||||||
|
<span class="text-sm">{{ row.spuName }}</span>
|
||||||
|
<div class="flex flex-wrap gap-1">
|
||||||
|
<ElTag
|
||||||
|
v-for="(property, index) in row.properties"
|
||||||
|
:key="index"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{{ property.propertyName }}: {{ property.valueName }}
|
||||||
|
</ElTag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ProductGrid>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 费用信息 -->
|
||||||
|
<ElCard class="mb-4">
|
||||||
|
<template #header>
|
||||||
|
<span class="font-bold">费用信息</span>
|
||||||
|
</template>
|
||||||
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-4">
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">商品总额:</span>
|
||||||
|
<span>{{ fenToYuan(order.totalPrice ?? 0) }} 元</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">运费金额:</span>
|
||||||
|
<span>{{ fenToYuan(order.deliveryPrice ?? 0) }} 元</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">订单调价:</span>
|
||||||
|
<span>{{ fenToYuan(order.adjustPrice ?? 0) }} 元</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">优惠劵优惠:</span>
|
||||||
|
<span class="text-red-500"
|
||||||
|
>{{ fenToYuan(order.couponPrice ?? 0) }} 元</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">VIP 优惠:</span>
|
||||||
|
<span class="text-red-500"
|
||||||
|
>{{ fenToYuan(order.vipPrice ?? 0) }} 元</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">活动优惠:</span>
|
||||||
|
<span class="text-red-500"
|
||||||
|
>{{ fenToYuan(order.discountPrice ?? 0) }} 元</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">积分抵扣:</span>
|
||||||
|
<span class="text-red-500"
|
||||||
|
>{{ fenToYuan(order.pointPrice ?? 0) }} 元</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">应付金额:</span>
|
||||||
|
<span>{{ fenToYuan(order.payPrice ?? 0) }} 元</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ElCard>
|
||||||
|
|
||||||
|
<!-- 收货信息 -->
|
||||||
|
<ElCard class="mb-4">
|
||||||
|
<template #header>
|
||||||
|
<span class="font-bold">收货信息</span>
|
||||||
|
</template>
|
||||||
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">配送方式:</span>
|
||||||
|
<DictTag
|
||||||
|
:type="DICT_TYPE.TRADE_DELIVERY_TYPE"
|
||||||
|
:value="order.deliveryType"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">收货人:</span>
|
||||||
|
<span>{{ order.receiverName }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">联系电话:</span>
|
||||||
|
<span>{{ order.receiverMobile }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex md:col-span-3">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">收货地址:</span>
|
||||||
|
<span
|
||||||
|
>{{ order.receiverAreaName }}
|
||||||
|
{{ order.receiverDetailAddress }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="mr-2 min-w-fit text-gray-600">发货时间:</span>
|
||||||
|
<span>{{ formatDateTime(order.deliveryTime || '') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ElCard>
|
||||||
|
|
||||||
|
<!-- 物流详情 -->
|
||||||
|
<div v-if="expressTrackList.length > 0" class="mt-4">
|
||||||
|
<ExpressTrackGrid table-title="物流详情" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作日志 -->
|
||||||
|
<div>
|
||||||
|
<OperateLogGrid table-title="操作日志">
|
||||||
|
<template #userType="{ row }">
|
||||||
|
<ElTag v-if="row.userId === 0" type="info"> 系统 </ElTag>
|
||||||
|
<DictTag v-else :type="DICT_TYPE.USER_TYPE" :value="row.userType" />
|
||||||
|
</template>
|
||||||
|
</OperateLogGrid>
|
||||||
|
</div>
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
@@ -2,10 +2,9 @@
|
|||||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
import type { MallOrderApi } from '#/api/mall/trade/order';
|
import type { MallOrderApi } from '#/api/mall/trade/order';
|
||||||
|
|
||||||
import { h } from 'vue';
|
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { DocAlert, Page, prompt, useVbenModal } from '@vben/common-ui';
|
import { DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
||||||
import {
|
import {
|
||||||
DeliveryTypeEnum,
|
DeliveryTypeEnum,
|
||||||
DICT_TYPE,
|
DICT_TYPE,
|
||||||
@@ -13,26 +12,34 @@ import {
|
|||||||
} from '@vben/constants';
|
} from '@vben/constants';
|
||||||
import { fenToYuan } from '@vben/utils';
|
import { fenToYuan } from '@vben/utils';
|
||||||
|
|
||||||
import { ElImage, ElInput, ElTag } from 'element-plus';
|
import { ElImage, ElTag } from 'element-plus';
|
||||||
|
|
||||||
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
import { getOrderPage, updateOrderRemark } from '#/api/mall/trade/order';
|
import { getOrderPage } from '#/api/mall/trade/order';
|
||||||
import { DictTag } from '#/components/dict-tag';
|
import { DictTag } from '#/components/dict-tag';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { useGridColumns, useGridFormSchema } from './data';
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
import DeleveryForm from './modules/delevery-form.vue';
|
import DeleveryForm from './modules/delevery-form.vue';
|
||||||
|
import RemarkForm from './modules/update-remark-form.vue';
|
||||||
|
|
||||||
|
const { push } = useRouter();
|
||||||
|
|
||||||
const [DeleveryFormModal, deleveryFormModalApi] = useVbenModal({
|
const [DeleveryFormModal, deleveryFormModalApi] = useVbenModal({
|
||||||
connectedComponent: DeleveryForm,
|
connectedComponent: DeleveryForm,
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [RemarkFormModal, remarkFormModalApi] = useVbenModal({
|
||||||
|
connectedComponent: RemarkForm,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
/** 刷新表格 */
|
/** 刷新表格 */
|
||||||
function onRefresh() {
|
function handleRefresh() {
|
||||||
gridApi.query();
|
gridApi.query();
|
||||||
}
|
}
|
||||||
const { push } = useRouter();
|
|
||||||
/** 详情 */
|
/** 详情 */
|
||||||
function handleDetail(row: MallOrderApi.Order) {
|
function handleDetail(row: MallOrderApi.Order) {
|
||||||
push({ name: 'TradeOrderDetail', params: { id: row.id } });
|
push({ name: 'TradeOrderDetail', params: { id: row.id } });
|
||||||
@@ -44,27 +51,8 @@ function handleDelivery(row: MallOrderApi.Order) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 备注 */
|
/** 备注 */
|
||||||
function handleRemake(row: MallOrderApi.Order) {
|
function handleRemark(row: MallOrderApi.Order) {
|
||||||
prompt({
|
remarkFormModalApi.setData(row).open();
|
||||||
component: () => {
|
|
||||||
return h(ElInput, {
|
|
||||||
defaultValue: row.remark,
|
|
||||||
rows: 3,
|
|
||||||
type: 'textarea',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
content: '请输入订单备注',
|
|
||||||
title: '订单备注',
|
|
||||||
modelPropName: 'value',
|
|
||||||
}).then(async (val) => {
|
|
||||||
if (val) {
|
|
||||||
await updateOrderRemark({
|
|
||||||
id: row.id as number,
|
|
||||||
remark: val,
|
|
||||||
});
|
|
||||||
onRefresh();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const [Grid, gridApi] = useVbenVxeGrid({
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
@@ -93,6 +81,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
},
|
},
|
||||||
rowConfig: {
|
rowConfig: {
|
||||||
keyField: 'id',
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
},
|
},
|
||||||
toolbarConfig: {
|
toolbarConfig: {
|
||||||
refresh: true,
|
refresh: true,
|
||||||
@@ -114,9 +103,10 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
url="https://doc.iocoder.cn/mall/trade-cart/"
|
url="https://doc.iocoder.cn/mall/trade-cart/"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<DeleveryFormModal @success="onRefresh" />
|
|
||||||
|
<DeleveryFormModal @success="handleRefresh" />
|
||||||
|
<RemarkFormModal @success="handleRefresh" />
|
||||||
<Grid table-title="订单列表">
|
<Grid table-title="订单列表">
|
||||||
<!-- TODO @霖:列表有点丑 -->
|
|
||||||
<template #expand_content="{ row }">
|
<template #expand_content="{ row }">
|
||||||
<div class="order-items">
|
<div class="order-items">
|
||||||
<div
|
<div
|
||||||
@@ -125,23 +115,24 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
class="order-item"
|
class="order-item"
|
||||||
>
|
>
|
||||||
<div class="order-item-image">
|
<div class="order-item-image">
|
||||||
<ElImage :src="item.picUrl" class="h-40 w-40" />
|
<ElImage :src="item.picUrl" class="h-10 w-10" />
|
||||||
</div>
|
</div>
|
||||||
<div class="order-item-content">
|
<div class="order-item-content">
|
||||||
<div class="order-item-name">
|
<div class="order-item-name">
|
||||||
{{ item.spuName }}
|
{{ item.spuName }}
|
||||||
<ElTag
|
<ElTag
|
||||||
v-for="property in item.properties"
|
v-for="(property, index) in item.properties"
|
||||||
:key="property.id"
|
:key="index"
|
||||||
class="ml-1"
|
class="ml-1"
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
{{ property.propertyName }}: {{ property.valueName }}
|
{{ property.propertyName }}: {{ property.valueName }}
|
||||||
</ElTag>
|
</ElTag>
|
||||||
</div>
|
</div>
|
||||||
<div class="order-item-info">
|
<div class="order-item-info">
|
||||||
<span>
|
<span>
|
||||||
原价:{{ fenToYuan(item.price) }} 元 / 数量:{{
|
原价:{{ fenToYuan(item.price || 0) }} 元 / 数量:{{
|
||||||
item.count
|
item.count || 0
|
||||||
}}个
|
}}个
|
||||||
</span>
|
</span>
|
||||||
<DictTag
|
<DictTag
|
||||||
@@ -176,7 +167,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
{
|
{
|
||||||
label: '备注',
|
label: '备注',
|
||||||
link: true,
|
link: true,
|
||||||
onClick: handleRemake.bind(null, row),
|
onClick: handleRemark.bind(null, row),
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MallOrderApi } from '#/api/mall/trade/order';
|
import type { MallOrderApi } from '#/api/mall/trade/order';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { getSimpleDeliveryExpressList } from '#/api/mall/trade/delivery/express';
|
|
||||||
import { deliveryOrder } from '#/api/mall/trade/order';
|
import { deliveryOrder } from '#/api/mall/trade/order';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
import { useDeliveryFormSchema } from '../data';
|
||||||
|
|
||||||
const emit = defineEmits(['success']);
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const formData = ref<MallOrderApi.DeliveryRequest>();
|
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
const [Form, formApi] = useVbenForm({
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
componentProps: {
|
componentProps: {
|
||||||
@@ -25,53 +21,7 @@ const [Form, formApi] = useVbenForm({
|
|||||||
labelWidth: 120,
|
labelWidth: 120,
|
||||||
},
|
},
|
||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: [
|
schema: useDeliveryFormSchema(),
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'id',
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: [''],
|
|
||||||
show: () => false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// TODO @xingyu:发货默认选中第一个?
|
|
||||||
{
|
|
||||||
fieldName: 'expressType',
|
|
||||||
label: '发货方式',
|
|
||||||
component: 'RadioGroup',
|
|
||||||
componentProps: {
|
|
||||||
options: [
|
|
||||||
{ label: '快递', value: 'express' },
|
|
||||||
{ label: '无需发货', value: 'none' },
|
|
||||||
],
|
|
||||||
buttonStyle: 'solid',
|
|
||||||
optionType: 'button',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'logisticsId',
|
|
||||||
label: '物流公司',
|
|
||||||
component: 'ApiSelect',
|
|
||||||
componentProps: {
|
|
||||||
api: getSimpleDeliveryExpressList,
|
|
||||||
labelField: 'name',
|
|
||||||
valueField: 'id',
|
|
||||||
},
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['expressType'],
|
|
||||||
show: (values) => values.expressType === 'express',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'logisticsNo',
|
|
||||||
label: '物流单号',
|
|
||||||
component: 'Input',
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: ['expressType'],
|
|
||||||
show: (values) => values.expressType === 'express',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -101,7 +51,6 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
},
|
},
|
||||||
async onOpenChange(isOpen: boolean) {
|
async onOpenChange(isOpen: boolean) {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
formData.value = undefined;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 加载数据
|
// 加载数据
|
||||||
@@ -111,10 +60,10 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
}
|
}
|
||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
try {
|
try {
|
||||||
|
await formApi.setValues({ id: data.id });
|
||||||
if (data.logisticsId === 0) {
|
if (data.logisticsId === 0) {
|
||||||
await formApi.setValues({ expressType: 'none' });
|
await formApi.setValues({ expressType: 'none' });
|
||||||
}
|
}
|
||||||
// 设置到 values
|
|
||||||
} finally {
|
} finally {
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,558 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { MallDeliveryExpressApi } from '#/api/mall/trade/delivery/express';
|
|
||||||
import type { MallDeliveryPickUpStoreApi } from '#/api/mall/trade/delivery/pickUpStore';
|
|
||||||
import type { MallOrderApi } from '#/api/mall/trade/order';
|
|
||||||
|
|
||||||
import { onMounted, ref } from 'vue';
|
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
import { confirm, ContentWrap, Page, useVbenModal } from '@vben/common-ui';
|
|
||||||
import {
|
|
||||||
DeliveryTypeEnum,
|
|
||||||
DICT_TYPE,
|
|
||||||
TradeOrderStatusEnum,
|
|
||||||
} from '@vben/constants';
|
|
||||||
import { getDictLabel, getDictObj } from '@vben/hooks';
|
|
||||||
import { fenToYuan, formatDate } from '@vben/utils';
|
|
||||||
|
|
||||||
import {
|
|
||||||
ElDescriptions,
|
|
||||||
ElDescriptionsItem,
|
|
||||||
ElMessage,
|
|
||||||
ElTimeline,
|
|
||||||
ElTimelineItem,
|
|
||||||
} from 'element-plus';
|
|
||||||
|
|
||||||
import * as DeliveryExpressApi from '#/api/mall/trade/delivery/express';
|
|
||||||
import * as DeliveryPickUpStoreApi from '#/api/mall/trade/delivery/pickUpStore';
|
|
||||||
import * as TradeOrderApi from '#/api/mall/trade/order';
|
|
||||||
import { DictTag } from '#/components/dict-tag';
|
|
||||||
|
|
||||||
import OrderDeliveryForm from './delevery-form.vue';
|
|
||||||
import OrderUpdateAddressForm from './update-address-form.vue';
|
|
||||||
import OrderUpdatePriceForm from './update-price-form.vue';
|
|
||||||
import OrderUpdateRemarkForm from './update-remark-form.vue';
|
|
||||||
|
|
||||||
defineOptions({ name: 'TradeOrderDetail' });
|
|
||||||
|
|
||||||
// 查询参数
|
|
||||||
const props = defineProps({
|
|
||||||
id: {
|
|
||||||
type: Number,
|
|
||||||
default: undefined,
|
|
||||||
}, // 订单ID
|
|
||||||
showPickUp: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
}, // 显示核销按钮
|
|
||||||
});
|
|
||||||
|
|
||||||
const [OrderDeliveryFormModal, formModalApi] = useVbenModal({
|
|
||||||
connectedComponent: OrderDeliveryForm,
|
|
||||||
destroyOnClose: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [RemarkFormModal, remarkFormModalApi] = useVbenModal({
|
|
||||||
connectedComponent: OrderUpdateRemarkForm,
|
|
||||||
destroyOnClose: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [OrderUpdateAddressFormModal, addressFormModalApi] = useVbenModal({
|
|
||||||
connectedComponent: OrderUpdateAddressForm,
|
|
||||||
destroyOnClose: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [OrderUpdatePriceFormModal, priceFormModalApi] = useVbenModal({
|
|
||||||
connectedComponent: OrderUpdatePriceForm,
|
|
||||||
destroyOnClose: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 获得 userType 颜色 */
|
|
||||||
const getUserTypeColor = (type: number) => {
|
|
||||||
const dict = getDictObj(DICT_TYPE.USER_TYPE, type);
|
|
||||||
switch (dict?.colorType) {
|
|
||||||
case 'danger': {
|
|
||||||
return '#F56C6C';
|
|
||||||
}
|
|
||||||
case 'info': {
|
|
||||||
return '#909399';
|
|
||||||
}
|
|
||||||
case 'success': {
|
|
||||||
return '#67C23A';
|
|
||||||
}
|
|
||||||
case 'warning': {
|
|
||||||
return '#E6A23C';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '#409EFF';
|
|
||||||
};
|
|
||||||
|
|
||||||
// 订单详情
|
|
||||||
const formData = ref<MallOrderApi.Order>({
|
|
||||||
logs: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 各种操作 */
|
|
||||||
const remark = () => {
|
|
||||||
remarkFormModalApi.setData(formData.value).open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const delivery = () => {
|
|
||||||
formModalApi.setData(formData.value).open();
|
|
||||||
};
|
|
||||||
const updateAddress = () => {
|
|
||||||
addressFormModalApi.setData(formData.value).open();
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatePrice = () => {
|
|
||||||
priceFormModalApi.setData(formData.value).open();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 核销 */
|
|
||||||
const handlePickUp = async () => {
|
|
||||||
// 二次确认
|
|
||||||
await confirm(`确认核销订单吗?`);
|
|
||||||
await TradeOrderApi.pickUpOrder(formData.value.id!);
|
|
||||||
ElMessage.success('核销成功');
|
|
||||||
// 刷新列表
|
|
||||||
await getDetail();
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 获得详情 */
|
|
||||||
const { params } = useRoute();
|
|
||||||
const id = (params.id || props.id) as unknown as number;
|
|
||||||
const getDetail = async () => {
|
|
||||||
if (id) {
|
|
||||||
const res = (await TradeOrderApi.getOrder(id)) as MallOrderApi.Order;
|
|
||||||
// 没有表单信息则关闭页面返回
|
|
||||||
if (!res) {
|
|
||||||
ElMessage.error('交易订单不存在');
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
formData.value = res;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 关闭 tag */
|
|
||||||
const { push } = useRouter(); // 路由
|
|
||||||
const close = () => {
|
|
||||||
push({ name: 'TradeOrder' });
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 复制 */
|
|
||||||
const clipboardSuccess = () => {
|
|
||||||
ElMessage.success('复制成功');
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 初始化 */
|
|
||||||
const deliveryExpressList = ref<MallDeliveryExpressApi.SimpleDeliveryExpress[]>(
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
// 物流公司
|
|
||||||
const expressTrackList = ref<MallOrderApi.OrderExpressTrackRespDTO[]>([]); // 物流详情
|
|
||||||
const pickUpStore = ref<MallDeliveryPickUpStoreApi.PickUpStore>(
|
|
||||||
{} as MallDeliveryPickUpStoreApi.PickUpStore,
|
|
||||||
); // 自提门店
|
|
||||||
onMounted(async () => {
|
|
||||||
await getDetail();
|
|
||||||
// 如果配送方式为快递,则查询物流公司
|
|
||||||
if (formData.value.deliveryType === DeliveryTypeEnum.EXPRESS.type) {
|
|
||||||
deliveryExpressList.value =
|
|
||||||
await DeliveryExpressApi.getSimpleDeliveryExpressList();
|
|
||||||
if (formData.value.logisticsId) {
|
|
||||||
expressTrackList.value = await TradeOrderApi.getExpressTrackList(
|
|
||||||
formData.value.id!,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (
|
|
||||||
formData.value.deliveryType === DeliveryTypeEnum.PICK_UP.type &&
|
|
||||||
formData.value.pickUpStoreId
|
|
||||||
) {
|
|
||||||
pickUpStore.value = await DeliveryPickUpStoreApi.getDeliveryPickUpStore(
|
|
||||||
formData.value.pickUpStoreId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<Page auto-content-height>
|
|
||||||
<ContentWrap>
|
|
||||||
<!-- 订单信息 -->
|
|
||||||
<ElDescriptions title="订单信息">
|
|
||||||
<ElDescriptionsItem label="订单号: ">
|
|
||||||
{{ formData.no }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="买家: ">
|
|
||||||
{{ formData?.user?.nickname }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="订单类型: ">
|
|
||||||
<DictTag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="formData.type!" />
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="订单来源: ">
|
|
||||||
<DictTag :type="DICT_TYPE.TERMINAL" :value="formData.terminal!" />
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="买家留言: ">
|
|
||||||
{{ formData.userRemark }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="商家备注: ">
|
|
||||||
{{ formData.remark }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="支付单号: ">
|
|
||||||
{{ formData.payOrderId }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="付款方式: ">
|
|
||||||
<DictTag
|
|
||||||
:type="DICT_TYPE.PAY_CHANNEL_CODE"
|
|
||||||
:value="formData.payChannelCode!"
|
|
||||||
/>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem v-if="formData.brokerageUser" label="推广用户: ">
|
|
||||||
{{ formData.brokerageUser?.nickname }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
</ElDescriptions>
|
|
||||||
|
|
||||||
<!-- 订单状态 -->
|
|
||||||
<ElDescriptions :column="1" title="订单状态">
|
|
||||||
<ElDescriptionsItem label="订单状态: ">
|
|
||||||
<DictTag
|
|
||||||
:type="DICT_TYPE.TRADE_ORDER_STATUS"
|
|
||||||
:value="formData.status!"
|
|
||||||
/>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem
|
|
||||||
v-access:code="['trade:order:update']"
|
|
||||||
label-class-name="no-colon"
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
v-if="formData.status! === TradeOrderStatusEnum.UNPAID.status"
|
|
||||||
type="primary"
|
|
||||||
@click="updatePrice"
|
|
||||||
>
|
|
||||||
调整价格
|
|
||||||
</el-button>
|
|
||||||
<el-button type="primary" @click="remark">备注</el-button>
|
|
||||||
<!-- 待发货 -->
|
|
||||||
<template
|
|
||||||
v-if="formData.status! === TradeOrderStatusEnum.UNDELIVERED.status"
|
|
||||||
>
|
|
||||||
<!-- 快递发货 -->
|
|
||||||
<el-button
|
|
||||||
v-if="formData.deliveryType === DeliveryTypeEnum.EXPRESS.type"
|
|
||||||
type="primary"
|
|
||||||
@click="delivery"
|
|
||||||
>
|
|
||||||
发货
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="formData.deliveryType === DeliveryTypeEnum.EXPRESS.type"
|
|
||||||
type="primary"
|
|
||||||
@click="updateAddress"
|
|
||||||
>
|
|
||||||
修改地址
|
|
||||||
</el-button>
|
|
||||||
<!-- 到店自提 -->
|
|
||||||
<el-button
|
|
||||||
v-if="
|
|
||||||
formData.deliveryType === DeliveryTypeEnum.PICK_UP.type &&
|
|
||||||
showPickUp
|
|
||||||
"
|
|
||||||
type="primary"
|
|
||||||
@click="handlePickUp"
|
|
||||||
>
|
|
||||||
核销
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem>
|
|
||||||
<template #label>
|
|
||||||
<span style="color: red">提醒: </span>
|
|
||||||
</template>
|
|
||||||
<el-text>
|
|
||||||
买家付款成功后,货款将直接进入您的商户号(微信、支付宝)<br />
|
|
||||||
请及时关注你发出的包裹状态,确保可以配送至买家手中 <br />
|
|
||||||
如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商
|
|
||||||
</el-text>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
</ElDescriptions>
|
|
||||||
|
|
||||||
<!-- 商品信息 -->
|
|
||||||
<ElDescriptions title="商品信息">
|
|
||||||
<ElDescriptionsItem label-class-name="no-colon">
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="15">
|
|
||||||
<el-table :data="formData.items" border>
|
|
||||||
<el-table-column label="商品" prop="spuName" width="auto">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ row.spuName }}
|
|
||||||
<el-tag
|
|
||||||
v-for="property in row.properties"
|
|
||||||
:key="property.propertyId"
|
|
||||||
>
|
|
||||||
{{ property.propertyName }}: {{ property.valueName }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="商品原价" prop="price" width="150">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ fenToYuan(row.price) }}元
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="数量" prop="count" width="100" />
|
|
||||||
<el-table-column label="合计" prop="payPrice" width="150">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ fenToYuan(row.payPrice) }}元
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
label="售后状态"
|
|
||||||
prop="afterSaleStatus"
|
|
||||||
width="120"
|
|
||||||
>
|
|
||||||
<template #default="{ row }">
|
|
||||||
<DictTag
|
|
||||||
:type="DICT_TYPE.TRADE_ORDER_ITEM_AFTER_SALE_STATUS"
|
|
||||||
:value="row.afterSaleStatus"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10" />
|
|
||||||
</el-row>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
</ElDescriptions>
|
|
||||||
<ElDescriptions :column="4">
|
|
||||||
<!-- 第一层 -->
|
|
||||||
<ElDescriptionsItem label="商品总额: ">
|
|
||||||
{{ fenToYuan(formData.totalPrice!) }} 元
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="运费金额: ">
|
|
||||||
{{ fenToYuan(formData.deliveryPrice!) }} 元
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="订单调价: ">
|
|
||||||
{{ fenToYuan(formData.adjustPrice!) }} 元
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem
|
|
||||||
v-for="item in 1"
|
|
||||||
:key="item"
|
|
||||||
label-class-name="no-colon"
|
|
||||||
/>
|
|
||||||
<!-- 第二层 -->
|
|
||||||
<ElDescriptionsItem>
|
|
||||||
<template #label>
|
|
||||||
<span style="color: red">优惠劵优惠: </span>
|
|
||||||
</template>
|
|
||||||
{{ fenToYuan(formData.couponPrice!) }} 元
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem>
|
|
||||||
<template #label><span style="color: red">VIP 优惠: </span></template>
|
|
||||||
{{ fenToYuan(formData.vipPrice!) }} 元
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem>
|
|
||||||
<template #label><span style="color: red">活动优惠: </span></template>
|
|
||||||
{{ fenToYuan(formData.discountPrice!) }} 元
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem>
|
|
||||||
<template #label><span style="color: red">积分抵扣: </span></template>
|
|
||||||
{{ fenToYuan(formData.pointPrice!) }} 元
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<!-- 第三层 -->
|
|
||||||
<ElDescriptionsItem
|
|
||||||
v-for="item in 3"
|
|
||||||
:key="item"
|
|
||||||
label-class-name="no-colon"
|
|
||||||
/>
|
|
||||||
<ElDescriptionsItem label="应付金额: ">
|
|
||||||
{{ fenToYuan(formData.payPrice!) }} 元
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
</ElDescriptions>
|
|
||||||
|
|
||||||
<!-- 物流信息 -->
|
|
||||||
<ElDescriptions :column="4" title="收货信息">
|
|
||||||
<ElDescriptionsItem label="配送方式: ">
|
|
||||||
<DictTag
|
|
||||||
:type="DICT_TYPE.TRADE_DELIVERY_TYPE"
|
|
||||||
:value="formData.deliveryType!"
|
|
||||||
/>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="收货人: ">
|
|
||||||
{{ formData.receiverName }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="联系电话: ">
|
|
||||||
{{ formData.receiverMobile }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<!-- 快递配送 -->
|
|
||||||
<div v-if="formData.deliveryType === DeliveryTypeEnum.EXPRESS.type">
|
|
||||||
<ElDescriptionsItem
|
|
||||||
v-if="formData.receiverDetailAddress"
|
|
||||||
label="收货地址: "
|
|
||||||
>
|
|
||||||
{{ formData.receiverAreaName }} {{ formData.receiverDetailAddress }}
|
|
||||||
<el-link
|
|
||||||
v-clipboard:copy="
|
|
||||||
`${formData.receiverAreaName} ${formData.receiverDetailAddress}`
|
|
||||||
"
|
|
||||||
v-clipboard:success="clipboardSuccess"
|
|
||||||
icon="ep:document-copy"
|
|
||||||
type="primary"
|
|
||||||
/>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem v-if="formData.logisticsId" label="物流公司: ">
|
|
||||||
{{
|
|
||||||
deliveryExpressList.find(
|
|
||||||
(item) => item.id === formData.logisticsId,
|
|
||||||
)?.name
|
|
||||||
}}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem v-if="formData.logisticsId" label="运单号: ">
|
|
||||||
{{ formData.logisticsNo }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem v-if="formData.deliveryTime" label="发货时间: ">
|
|
||||||
{{ formatDate(formData.deliveryTime) }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem
|
|
||||||
v-for="item in 2"
|
|
||||||
:key="item"
|
|
||||||
label-class-name="no-colon"
|
|
||||||
/>
|
|
||||||
<ElDescriptionsItem
|
|
||||||
v-if="expressTrackList.length > 0"
|
|
||||||
label="物流详情: "
|
|
||||||
>
|
|
||||||
<ElTimeline>
|
|
||||||
<ElTimelineItem
|
|
||||||
v-for="(express, index) in expressTrackList"
|
|
||||||
:key="index"
|
|
||||||
:timestamp="formatDate(express.time)?.toString()"
|
|
||||||
>
|
|
||||||
{{ express.content }}
|
|
||||||
</ElTimelineItem>
|
|
||||||
</ElTimeline>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
</div>
|
|
||||||
<!-- 自提门店 -->
|
|
||||||
<div v-if="formData.deliveryType === DeliveryTypeEnum.PICK_UP.type">
|
|
||||||
<ElDescriptionsItem v-if="formData.pickUpStoreId" label="自提门店: ">
|
|
||||||
{{ pickUpStore?.name }}
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
</div>
|
|
||||||
</ElDescriptions>
|
|
||||||
|
|
||||||
<!-- 订单日志 -->
|
|
||||||
<ElDescriptions title="订单操作日志">
|
|
||||||
<ElDescriptionsItem label-class-name="no-colon">
|
|
||||||
<ElTimeline>
|
|
||||||
<ElTimelineItem
|
|
||||||
v-for="(log, index) in formData.logs"
|
|
||||||
:key="index"
|
|
||||||
:timestamp="formatDate(log.createTime!)!.toString()"
|
|
||||||
placement="top"
|
|
||||||
>
|
|
||||||
<div class="el-timeline-right-content">
|
|
||||||
{{ log.content }}
|
|
||||||
</div>
|
|
||||||
<template #dot>
|
|
||||||
<span
|
|
||||||
:style="{ backgroundColor: getUserTypeColor(log.userType!) }"
|
|
||||||
class="dot-node-style"
|
|
||||||
>
|
|
||||||
{{ getDictLabel(DICT_TYPE.USER_TYPE, log.userType)[0] }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</ElTimelineItem>
|
|
||||||
</ElTimeline>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
</ElDescriptions>
|
|
||||||
</ContentWrap>
|
|
||||||
|
|
||||||
<!-- 各种操作的弹窗 -->
|
|
||||||
<OrderDeliveryFormModal @success="getDetail" />
|
|
||||||
<OrderUpdateRemarkFormModal @success="getDetail" />
|
|
||||||
<OrderUpdateAddressFormModal @success="getDetail" />
|
|
||||||
<OrderUpdatePriceFormModal @success="getDetail" />
|
|
||||||
</Page>
|
|
||||||
</template>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
:deep(.el-descriptions) {
|
|
||||||
&:not(:nth-child(1)) {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-descriptions__title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
display: inline-block;
|
|
||||||
width: 3px;
|
|
||||||
height: 20px;
|
|
||||||
margin-right: 10px;
|
|
||||||
content: '';
|
|
||||||
background-color: #409eff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-descriptions-item__container {
|
|
||||||
margin: 0 10px;
|
|
||||||
|
|
||||||
.no-colon {
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 时间线样式调整
|
|
||||||
:deep(.el-timeline) {
|
|
||||||
margin: 10px 0 0 160px;
|
|
||||||
|
|
||||||
.el-timeline-item__wrapper {
|
|
||||||
position: relative;
|
|
||||||
top: -20px;
|
|
||||||
|
|
||||||
.el-timeline-item__timestamp {
|
|
||||||
position: absolute !important;
|
|
||||||
top: 10px;
|
|
||||||
left: -150px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 单独定义气泡样式,不使用嵌套 */
|
|
||||||
:deep(.el-timeline-right-content) {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 30px;
|
|
||||||
padding: 10px;
|
|
||||||
margin-left: 10px;
|
|
||||||
background-color: #f5f7fa; /* 使用明确的颜色替代变量 */
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-timeline-right-content)::before {
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
left: -16px;
|
|
||||||
content: '';
|
|
||||||
border-color: transparent #f5f7fa transparent transparent;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dot-node-style {
|
|
||||||
position: absolute;
|
|
||||||
left: -5px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
font-size: 10px;
|
|
||||||
color: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,21 +1,17 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MallOrderApi } from '#/api/mall/trade/order';
|
import type { MallOrderApi } from '#/api/mall/trade/order';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { updateOrderAddress } from '#/api/mall/trade/order';
|
import { updateOrderAddress } from '#/api/mall/trade/order';
|
||||||
import { getAreaTree } from '#/api/system/area';
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
import { useAddressFormSchema } from '../data';
|
||||||
|
|
||||||
const emit = defineEmits(['success']);
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const formData = ref<MallOrderApi.DeliveryRequest>();
|
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
const [Form, formApi] = useVbenForm({
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
componentProps: {
|
componentProps: {
|
||||||
@@ -25,56 +21,7 @@ const [Form, formApi] = useVbenForm({
|
|||||||
labelWidth: 120,
|
labelWidth: 120,
|
||||||
},
|
},
|
||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: [
|
schema: useAddressFormSchema(),
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'id',
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: [''],
|
|
||||||
show: () => false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// TODO @xingyu:发货默认选中第一个?
|
|
||||||
{
|
|
||||||
fieldName: 'receiverName',
|
|
||||||
label: '收件人',
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请输入收件人名称',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'receiverMobile',
|
|
||||||
label: '手机号',
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请输入收件人手机号',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'receiverAreaId',
|
|
||||||
label: '所在地',
|
|
||||||
component: 'ApiTreeSelect',
|
|
||||||
componentProps: {
|
|
||||||
api: () => getAreaTree(),
|
|
||||||
labelField: 'name',
|
|
||||||
valueField: 'id',
|
|
||||||
childrenField: 'children',
|
|
||||||
placeholder: '请选择收件人所在地',
|
|
||||||
treeDefaultExpandAll: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'receiverDetailAddress',
|
|
||||||
label: '详细地址',
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请输入收件人详细地址',
|
|
||||||
type: 'textarea',
|
|
||||||
rows: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -99,7 +46,6 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
},
|
},
|
||||||
async onOpenChange(isOpen: boolean) {
|
async onOpenChange(isOpen: boolean) {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
formData.value = undefined;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 加载数据
|
// 加载数据
|
||||||
@@ -116,7 +62,6 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
receiverAreaId: data.receiverAreaId,
|
receiverAreaId: data.receiverAreaId,
|
||||||
receiverDetailAddress: data.receiverDetailAddress,
|
receiverDetailAddress: data.receiverDetailAddress,
|
||||||
});
|
});
|
||||||
// 设置到 values
|
|
||||||
} finally {
|
} finally {
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
}
|
}
|
||||||
@@ -125,7 +70,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal class="w-1/3" title="发货">
|
<Modal class="w-1/3" title="修改地址">
|
||||||
<Form class="mx-4" />
|
<Form class="mx-4" />
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,22 +1,17 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MallOrderApi } from '#/api/mall/trade/order';
|
import type { MallOrderApi } from '#/api/mall/trade/order';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
import { floatToFixed2 } from '@vben/utils';
|
|
||||||
|
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { updateOrderPrice } from '#/api/mall/trade/order';
|
import { updateOrderPrice } from '#/api/mall/trade/order';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
import { usePriceFormSchema } from '../data';
|
||||||
|
|
||||||
const emit = defineEmits(['success']);
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const formData = ref<MallOrderApi.DeliveryRequest>();
|
|
||||||
const newPayPrice = ref<string>();
|
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
const [Form, formApi] = useVbenForm({
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
componentProps: {
|
componentProps: {
|
||||||
@@ -26,54 +21,7 @@ const [Form, formApi] = useVbenForm({
|
|||||||
labelWidth: 120,
|
labelWidth: 120,
|
||||||
},
|
},
|
||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: [
|
schema: usePriceFormSchema(),
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'id',
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: [''],
|
|
||||||
show: () => false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// TODO @xingyu:发货默认选中第一个?
|
|
||||||
{
|
|
||||||
fieldName: 'payPrice',
|
|
||||||
label: '应付金额(总)',
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请输入应付金额(总)',
|
|
||||||
disabled: true,
|
|
||||||
formatter: (value: string) => `${floatToFixed2(value)}元`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'adjustPrice',
|
|
||||||
label: '订单调价',
|
|
||||||
component: 'InputNumber',
|
|
||||||
componentProps: {
|
|
||||||
class: 'w-100%',
|
|
||||||
placeholder: '请输入订单调价',
|
|
||||||
step: 0.1,
|
|
||||||
precision: 2,
|
|
||||||
onChange: async (value: number) => {
|
|
||||||
const { payPrice } = await formApi.getValues();
|
|
||||||
await formApi.setValues({
|
|
||||||
newPayPrice: (payPrice + value * 100).toFixed(2),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: '订单调价。 正数,加价;负数,减价',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldName: 'newPayPrice',
|
|
||||||
label: '调价后',
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
disabled: true,
|
|
||||||
formatter: (value: string) => `${floatToFixed2(value)}元`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,9 +34,6 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const data = (await formApi.getValues()) as MallOrderApi.PriceRequest;
|
const data = (await formApi.getValues()) as MallOrderApi.PriceRequest;
|
||||||
if (data.adjustPrice) {
|
|
||||||
data.adjustPrice = data.adjustPrice * 100;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
await updateOrderPrice(data);
|
await updateOrderPrice(data);
|
||||||
// 关闭并提示
|
// 关闭并提示
|
||||||
@@ -101,7 +46,6 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
},
|
},
|
||||||
async onOpenChange(isOpen: boolean) {
|
async onOpenChange(isOpen: boolean) {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
formData.value = undefined;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 加载数据
|
// 加载数据
|
||||||
@@ -111,15 +55,11 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
}
|
}
|
||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
try {
|
try {
|
||||||
newPayPrice.value = data.payPrice?.toString();
|
|
||||||
data.adjustPrice = data.adjustPrice ? data.adjustPrice / 100 : 0;
|
|
||||||
await formApi.setValues({
|
await formApi.setValues({
|
||||||
id: data.id,
|
id: data.id,
|
||||||
payPrice: data.payPrice,
|
payPrice: data.payPrice,
|
||||||
adjustPrice: data.adjustPrice,
|
adjustPrice: data.adjustPrice ? data.adjustPrice / 100 : 0,
|
||||||
newPayPrice: newPayPrice.value,
|
|
||||||
});
|
});
|
||||||
// 设置到 values
|
|
||||||
} finally {
|
} finally {
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
}
|
}
|
||||||
@@ -128,7 +68,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal class="w-1/3" title="发货">
|
<Modal class="w-1/3" title="调整价格">
|
||||||
<Form class="mx-4" />
|
<Form class="mx-4" />
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MallOrderApi } from '#/api/mall/trade/order';
|
import type { MallOrderApi } from '#/api/mall/trade/order';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
@@ -10,11 +8,10 @@ import { ElMessage } from 'element-plus';
|
|||||||
import { useVbenForm } from '#/adapter/form';
|
import { useVbenForm } from '#/adapter/form';
|
||||||
import { updateOrderRemark } from '#/api/mall/trade/order';
|
import { updateOrderRemark } from '#/api/mall/trade/order';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
import { useRemarkFormSchema } from '../data';
|
||||||
|
|
||||||
const emit = defineEmits(['success']);
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const formData = ref<MallOrderApi.DeliveryRequest>();
|
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
const [Form, formApi] = useVbenForm({
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
componentProps: {
|
componentProps: {
|
||||||
@@ -24,26 +21,7 @@ const [Form, formApi] = useVbenForm({
|
|||||||
labelWidth: 120,
|
labelWidth: 120,
|
||||||
},
|
},
|
||||||
layout: 'horizontal',
|
layout: 'horizontal',
|
||||||
schema: [
|
schema: useRemarkFormSchema(),
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
fieldName: 'id',
|
|
||||||
dependencies: {
|
|
||||||
triggerFields: [''],
|
|
||||||
show: () => false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// TODO @xingyu:发货默认选中第一个?
|
|
||||||
{
|
|
||||||
fieldName: 'remark',
|
|
||||||
label: '备注',
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
type: 'textarea',
|
|
||||||
rows: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -68,7 +46,6 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
},
|
},
|
||||||
async onOpenChange(isOpen: boolean) {
|
async onOpenChange(isOpen: boolean) {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
formData.value = undefined;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 加载数据
|
// 加载数据
|
||||||
@@ -79,7 +56,6 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
try {
|
try {
|
||||||
await formApi.setValues({ id: data.id, remark: data.remark });
|
await formApi.setValues({ id: data.id, remark: data.remark });
|
||||||
// 设置到 values
|
|
||||||
} finally {
|
} finally {
|
||||||
modalApi.unlock();
|
modalApi.unlock();
|
||||||
}
|
}
|
||||||
@@ -88,7 +64,7 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal class="w-1/3" title="发货">
|
<Modal class="w-1/3" title="订单备注">
|
||||||
<Form class="mx-4" />
|
<Form class="mx-4" />
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user