diff --git a/src/api/mall/trade/afterSale/index.ts b/src/api/mall/trade/afterSale/index.ts new file mode 100644 index 00000000..a109ee6b --- /dev/null +++ b/src/api/mall/trade/afterSale/index.ts @@ -0,0 +1,75 @@ +import request from '@/config/axios' + +export interface TradeAfterSaleVO { + id?: number | null // 售后编号,主键自增 + no?: string // 售后单号 + status?: number | null // 退款状态 + way?: number | null // 售后方式 + type?: number | null // 售后类型 + userId?: number | null // 用户编号 + applyReason?: string // 申请原因 + applyDescription?: string // 补充描述 + applyPicUrls?: string[] // 补充凭证图片 + orderId?: number | null // 交易订单编号 + orderNo?: string // 订单流水号 + orderItemId?: number | null // 交易订单项编号 + spuId?: number | null // 商品 SPU 编号 + spuName?: string // 商品 SPU 名称 + skuId?: number | null // 商品 SKU 编号 + properties?: ProductPropertiesVO[] // 属性数组 + picUrl?: string // 商品图片 + count?: number | null // 退货商品数量 + auditTime?: Date // 审批时间 + auditUserId?: number | null // 审批人 + auditReason?: string // 审批备注 + refundPrice?: number | null // 退款金额,单位:分。 + payRefundId?: number | null // 支付退款编号 + refundTime?: Date // 退款时间 + logisticsId?: number | null // 退货物流公司编号 + logisticsNo?: string // 退货物流单号 + deliveryTime?: Date // 退货时间 + receiveTime?: Date // 收货时间 + receiveReason?: string // 收货备注 +} + +export interface ProductPropertiesVO { + propertyId?: number | null // 属性的编号 + propertyName?: string // 属性的名称 + valueId?: number | null //属性值的编号 + valueName?: string // 属性值的名称 +} + +// 获得交易售后分页 +export const getAfterSalePage = async (params) => { + return await request.get({ url: `/trade/after-sale/page`, params }) +} + +// 获得交易售后详情 +export const getAfterSale = async (id: any) => { + return await request.get({ url: `/trade/after-sale/get-detail?id=${id}` }) +} + +// 同意售后 +export const agree = async (id: any) => { + return await request.put({ url: `/trade/after-sale/agree?id=${id}` }) +} + +// 拒绝售后 +export const disagree = async (data: any) => { + return await request.put({ url: `/trade/after-sale/disagree`, data }) +} + +// 确认收货 +export const receive = async (id: any) => { + return await request.put({ url: `/trade/after-sale/receive?id=${id}` }) +} + +// 拒绝收货 +export const refuse = async (id: any) => { + return await request.put({ url: `/trade/after-sale/refuse?id=${id}` }) +} + +// 确认退款 +export const refund = async (id: any) => { + return await request.put({ url: `/trade/after-sale/refund?id=${id}` }) +} diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 504a6e9e..c6c95e80 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -195,23 +195,6 @@ const remainingRouter: AppRouteRecordRaw[] = [ noTagsView: true } }, - { - path: '/trade/order', - component: Layout, - name: 'order', - meta: { - hidden: true - }, - children: [ - { - path: 'detail', - name: 'TradeOrderDetail', - // component: () => import('@/views/mall/trade/order/tradeOrderDetail.vue'), - component: () => import('@/views/mall/trade/order/detail/index.vue'), - meta: { title: '订单详情', hidden: true } - } - ] - }, { path: '/403', component: () => import('@/views/Error/403.vue'), @@ -357,7 +340,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ children: [ { path: 'spu/add', - component: () => import('@/views/mall/product/spu/addForm.vue'), + component: () => import('@/views/mall/product/spu/form/index.vue'), name: 'ProductSpuAdd', meta: { noCache: true, @@ -370,7 +353,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ }, { path: 'spu/edit/:spuId(\\d+)', - component: () => import('@/views/mall/product/spu/addForm.vue'), + component: () => import('@/views/mall/product/spu/form/index.vue'), name: 'ProductSpuEdit', meta: { noCache: true, @@ -383,7 +366,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ }, { path: 'spu/detail/:spuId(\\d+)', - component: () => import('@/views/mall/product/spu/addForm.vue'), + component: () => import('@/views/mall/product/spu/form/index.vue'), name: 'ProductSpuDetail', meta: { noCache: true, @@ -410,18 +393,24 @@ const remainingRouter: AppRouteRecordRaw[] = [ ] }, { - path: '/trade/order', + path: '/trade', component: Layout, - name: 'Detail', + name: 'Order', meta: { hidden: true }, children: [ { - path: 'detail/:orderId(\\d+)', + path: 'order/detail/:orderId(\\d+)', component: () => import('@/views/mall/trade/order/detail/index.vue'), - name: 'TradeOrderDetailForm', + name: 'TradeOrderDetail', meta: { title: '订单详情', icon: '', activeMenu: '/trade/trade/order' } + }, + { + path: 'after-sale/detail/:orderId(\\d+)', + component: () => import('@/views/mall/trade/afterSale/detail/index.vue'), + name: 'TradeAfterSaleDetail', + meta: { title: '退款详情', icon: '', activeMenu: '/trade/trade/after-sale' } } ] }, diff --git a/src/views/mall/product/spu/components/index.ts b/src/views/mall/product/spu/components/index.ts index 405dfde5..8f793c51 100644 --- a/src/views/mall/product/spu/components/index.ts +++ b/src/views/mall/product/spu/components/index.ts @@ -1,12 +1,5 @@ -import BasicInfoForm from './BasicInfoForm.vue' -import DescriptionForm from './DescriptionForm.vue' -import OtherSettingsForm from './OtherSettingsForm.vue' -import ProductAttributes from './ProductAttributes.vue' -import ProductPropertyAddForm from './ProductPropertyAddForm.vue' import SkuList from './SkuList.vue' -import { Spu } from '@/api/mall/product/spu' - interface PropertyAndValues { id: number name: string @@ -29,42 +22,4 @@ interface RuleConfig { message: string } -/** - * 获得商品的规格列表 - * - * @param spu - * @return PropertyAndValues 规格列表 - */ -const getPropertyList = (spu: Spu): PropertyAndValues[] => { - // 直接拿返回的 skus 属性逆向生成出 propertyList - const properties: PropertyAndValues[] = [] - // 只有是多规格才处理 - if (spu.specType) { - spu.skus?.forEach((sku) => { - sku.properties?.forEach(({ propertyId, propertyName, valueId, valueName }) => { - // 添加属性 - if (!properties?.some((item) => item.id === propertyId)) { - properties.push({ id: propertyId!, name: propertyName!, values: [] }) - } - // 添加属性值 - const index = properties?.findIndex((item) => item.id === propertyId) - if (!properties[index].values?.some((value) => value.id === valueId)) { - properties[index].values?.push({ id: valueId!, name: valueName! }) - } - }) - }) - } - return properties -} - -export { - BasicInfoForm, - DescriptionForm, - OtherSettingsForm, - ProductAttributes, - ProductPropertyAddForm, - SkuList, - getPropertyList, - PropertyAndValues, - RuleConfig -} +export { SkuList, PropertyAndValues, RuleConfig } diff --git a/src/views/mall/product/spu/components/BasicInfoForm.vue b/src/views/mall/product/spu/form/BasicInfoForm.vue similarity index 88% rename from src/views/mall/product/spu/components/BasicInfoForm.vue rename to src/views/mall/product/spu/form/BasicInfoForm.vue index 501295b4..678b564d 100644 --- a/src/views/mall/product/spu/components/BasicInfoForm.vue +++ b/src/views/mall/product/spu/form/BasicInfoForm.vue @@ -175,13 +175,17 @@ import { propTypes } from '@/utils/propTypes' import { checkSelectedNode, defaultProps, handleTree, treeToString } from '@/utils/tree' import { createImageViewer } from '@/components/ImageViewer' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -import { UploadImg, UploadImgs } from '@/components/UploadFile' -import { getPropertyList, ProductAttributes, ProductPropertyAddForm, SkuList } from './index' +import { PropertyAndValues, SkuList } from '@/views/mall/product/spu/components/index.ts' +import ProductAttributes from './ProductAttributes.vue' +import ProductPropertyAddForm from './ProductPropertyAddForm.vue' import { basicInfoSchema } from './spu.data' import type { Spu } from '@/api/mall/product/spu' import * as ProductCategoryApi from '@/api/mall/product/category' -import { getSimpleBrandList } from '@/api/mall/product/brand' -import { getSimpleTemplateList } from '@/api/mall/trade/delivery/expressTemplate/index' +import * as ProductBrandApi from '@/api/mall/product/brand' +import * as ExpressTemplateApi from '@/api/mall/trade/delivery/expressTemplate' + +defineOptions({ name: 'ProductSpuBasicInfoForm' }) + // ====== 商品详情相关操作 ====== const { allSchemas } = useCrudSchemas(basicInfoSchema) /** 商品图预览 */ @@ -198,9 +202,36 @@ const imagePreview = (args) => { urlList }) } -// ====== end ====== -defineOptions({ name: 'ProductSpuBasicInfoForm' }) +/** + * 获得商品的规格列表 + * + * @param spu + * @return PropertyAndValues 规格列表 + */ +const getPropertyList = (spu: Spu): PropertyAndValues[] => { + // 直接拿返回的 skus 属性逆向生成出 propertyList + const properties: PropertyAndValues[] = [] + // 只有是多规格才处理 + if (spu.specType) { + spu.skus?.forEach((sku) => { + sku.properties?.forEach(({ propertyId, propertyName, valueId, valueName }) => { + // 添加属性 + if (!properties?.some((item) => item.id === propertyId)) { + properties.push({ id: propertyId!, name: propertyName!, values: [] }) + } + // 添加属性值 + const index = properties?.findIndex((item) => item.id === propertyId) + if (!properties[index].values?.some((value) => value.id === valueId)) { + properties[index].values?.push({ id: valueId!, name: valueName! }) + } + }) + }) + } + return properties +} + +// ====== end ====== const message = useMessage() // 消息弹窗 @@ -346,8 +377,8 @@ onMounted(async () => { const data = await ProductCategoryApi.getCategoryList({}) categoryList.value = handleTree(data, 'id', 'parentId') // 获取商品品牌列表 - brandList.value = await getSimpleBrandList() + brandList.value = await ProductBrandApi.getSimpleBrandList() // 获取运费模版 - deliveryTemplateList.value = await getSimpleTemplateList() + deliveryTemplateList.value = await ExpressTemplateApi.getSimpleTemplateList() }) diff --git a/src/views/mall/product/spu/components/DescriptionForm.vue b/src/views/mall/product/spu/form/DescriptionForm.vue similarity index 100% rename from src/views/mall/product/spu/components/DescriptionForm.vue rename to src/views/mall/product/spu/form/DescriptionForm.vue diff --git a/src/views/mall/product/spu/components/OtherSettingsForm.vue b/src/views/mall/product/spu/form/OtherSettingsForm.vue similarity index 100% rename from src/views/mall/product/spu/components/OtherSettingsForm.vue rename to src/views/mall/product/spu/form/OtherSettingsForm.vue diff --git a/src/views/mall/product/spu/components/ProductAttributes.vue b/src/views/mall/product/spu/form/ProductAttributes.vue similarity index 100% rename from src/views/mall/product/spu/components/ProductAttributes.vue rename to src/views/mall/product/spu/form/ProductAttributes.vue diff --git a/src/views/mall/product/spu/components/ProductPropertyAddForm.vue b/src/views/mall/product/spu/form/ProductPropertyAddForm.vue similarity index 98% rename from src/views/mall/product/spu/components/ProductPropertyAddForm.vue rename to src/views/mall/product/spu/form/ProductPropertyAddForm.vue index 243cd7a0..a3e09fef 100644 --- a/src/views/mall/product/spu/components/ProductPropertyAddForm.vue +++ b/src/views/mall/product/spu/form/ProductPropertyAddForm.vue @@ -80,6 +80,8 @@ const submitForm = async () => { if (res[0].values === null) { res[0].values = [] } + // 不需要属性值 + res[0].values = [] attributeList.value.push(res[0]) // 因为只用一个 } message.success(t('common.createSuccess')) diff --git a/src/views/mall/product/spu/addForm.vue b/src/views/mall/product/spu/form/index.vue similarity index 97% rename from src/views/mall/product/spu/addForm.vue rename to src/views/mall/product/spu/form/index.vue index 910bad4a..db5b0445 100644 --- a/src/views/mall/product/spu/addForm.vue +++ b/src/views/mall/product/spu/form/index.vue @@ -39,13 +39,12 @@ + diff --git a/src/views/mall/trade/afterSale/form/AfterSaleDisagreeForm.vue b/src/views/mall/trade/afterSale/form/AfterSaleDisagreeForm.vue new file mode 100644 index 00000000..1fa2b0f5 --- /dev/null +++ b/src/views/mall/trade/afterSale/form/AfterSaleDisagreeForm.vue @@ -0,0 +1,70 @@ + + diff --git a/src/views/mall/trade/afterSale/index.vue b/src/views/mall/trade/afterSale/index.vue new file mode 100644 index 00000000..d22e5295 --- /dev/null +++ b/src/views/mall/trade/afterSale/index.vue @@ -0,0 +1,268 @@ + + diff --git a/src/views/mall/trade/order/detail/index.vue b/src/views/mall/trade/order/detail/index.vue index f43bccd2..ef2d9958 100644 --- a/src/views/mall/trade/order/detail/index.vue +++ b/src/views/mall/trade/order/detail/index.vue @@ -208,10 +208,10 @@ import * as TradeOrderApi from '@/api/mall/trade/order' import { floatToFixed2 } from '@/utils' import { DICT_TYPE } from '@/utils/dict' -import OrderUpdateRemarkForm from '@/views/mall/trade/order/components/OrderUpdateRemarkForm.vue' -import OrderDeliveryForm from '@/views/mall/trade/order/components/OrderDeliveryForm.vue' -import OrderUpdateAddressForm from '@/views/mall/trade/order/components/OrderUpdateAddressForm.vue' -import OrderUpdatePriceForm from '@/views/mall/trade/order/components/OrderUpdatePriceForm.vue' +import OrderUpdateRemarkForm from '@/views/mall/trade/order/form/OrderUpdateRemarkForm.vue' +import OrderDeliveryForm from '@/views/mall/trade/order/form/OrderDeliveryForm.vue' +import OrderUpdateAddressForm from '@/views/mall/trade/order/form/OrderUpdateAddressForm.vue' +import OrderUpdatePriceForm from '@/views/mall/trade/order/form/OrderUpdatePriceForm.vue' defineOptions({ name: 'TradeOrderDetailForm' }) diff --git a/src/views/mall/trade/order/components/OrderDeliveryForm.vue b/src/views/mall/trade/order/form/OrderDeliveryForm.vue similarity index 94% rename from src/views/mall/trade/order/components/OrderDeliveryForm.vue rename to src/views/mall/trade/order/form/OrderDeliveryForm.vue index 6d4a07c4..14f9411d 100644 --- a/src/views/mall/trade/order/components/OrderDeliveryForm.vue +++ b/src/views/mall/trade/order/form/OrderDeliveryForm.vue @@ -34,7 +34,6 @@ import * as DeliveryExpressApi from '@/api/mall/trade/delivery/express' import * as TradeOrderApi from '@/api/mall/trade/order' import { copyValueToTarget } from '@/utils' -// TODO @puhui999:要不 Form 保持和别的模块一样,和 index.vue 放在一个目录下,不作为 components;components 更多要支持给多个模块使用哈。 defineOptions({ name: 'OrderDeliveryForm' }) const { t } = useI18n() // 国际化 diff --git a/src/views/mall/trade/order/components/OrderUpdateAddressForm.vue b/src/views/mall/trade/order/form/OrderUpdateAddressForm.vue similarity index 100% rename from src/views/mall/trade/order/components/OrderUpdateAddressForm.vue rename to src/views/mall/trade/order/form/OrderUpdateAddressForm.vue diff --git a/src/views/mall/trade/order/components/OrderUpdatePriceForm.vue b/src/views/mall/trade/order/form/OrderUpdatePriceForm.vue similarity index 100% rename from src/views/mall/trade/order/components/OrderUpdatePriceForm.vue rename to src/views/mall/trade/order/form/OrderUpdatePriceForm.vue diff --git a/src/views/mall/trade/order/components/OrderUpdateRemarkForm.vue b/src/views/mall/trade/order/form/OrderUpdateRemarkForm.vue similarity index 98% rename from src/views/mall/trade/order/components/OrderUpdateRemarkForm.vue rename to src/views/mall/trade/order/form/OrderUpdateRemarkForm.vue index cbb7dbe9..bbc45a2c 100644 --- a/src/views/mall/trade/order/components/OrderUpdateRemarkForm.vue +++ b/src/views/mall/trade/order/form/OrderUpdateRemarkForm.vue @@ -49,7 +49,6 @@ const submitForm = async () => { formLoading.value = true try { const data = unref(formData) - console.log(data) await TradeOrderApi.updateRemark(data) message.success(t('common.updateSuccess')) dialogVisible.value = false diff --git a/src/views/mall/trade/order/index.vue b/src/views/mall/trade/order/index.vue index 89200465..1f89e1de 100644 --- a/src/views/mall/trade/order/index.vue +++ b/src/views/mall/trade/order/index.vue @@ -64,10 +64,17 @@ /> - - + + + + + + - + -