diff --git a/src/api/mall/trade/afterSale/index.ts b/src/api/mall/trade/afterSale/index.ts new file mode 100644 index 00000000..cc97d628 --- /dev/null +++ b/src/api/mall/trade/afterSale/index.ts @@ -0,0 +1,54 @@ +import request from '@/config/axios' + +// 定义 TradeAfterSaleDTO 接口,映射 TradeAfterSaleDO +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 function getAfterSale(id) { + return request({ + url: '/trade/after-sale/get?id=' + id, + method: 'get' + }) +} + +// 获得交易售后分页 +export const getAfterSalePage = async (params) => { + return await request.get({ url: `/trade/after-sale/page`, params }) +} diff --git a/src/views/mall/trade/afterSale/index.vue b/src/views/mall/trade/afterSale/index.vue new file mode 100644 index 00000000..b96fc93d --- /dev/null +++ b/src/views/mall/trade/afterSale/index.vue @@ -0,0 +1,215 @@ +<template> + <!-- 搜索 --> + <ContentWrap> + <el-form ref="queryFormRef" :inline="true" :model="queryParams" label-width="68px"> + <el-form-item label="商品名称" prop="spuName"> + <el-input + v-model="queryParams.spuName" + clearable + placeholder="请输入商品 SPU 名称" + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="退款编号" prop="no"> + <el-input + v-model="queryParams.no" + clearable + placeholder="请输入退款编号" + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="订单编号" prop="orderNo"> + <el-input + v-model="queryParams.orderNo" + clearable + placeholder="请输入订单编号" + @keyup.enter="handleQuery" + /> + </el-form-item> + <el-form-item label="售后状态" prop="status"> + <el-select v-model="queryParams.status" clearable placeholder="请选择售后状态"> + <el-option label="全部" value="0" /> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.TRADE_AFTER_SALE_STATUS)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="售后方式" prop="way"> + <el-select v-model="queryParams.way" clearable placeholder="请选择售后方式"> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.TRADE_AFTER_SALE_WAY)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="售后类型" prop="type"> + <el-select v-model="queryParams.type" clearable placeholder="请选择售后类型"> + <el-option + v-for="dict in getDictOptions(DICT_TYPE.TRADE_AFTER_SALE_TYPE)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="创建时间" prop="createTime"> + <el-date-picker + v-model="queryParams.createTime" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-280px" + end-placeholder="自定义时间" + start-placeholder="自定义时间" + type="daterange" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery"> + <Icon class="mr-5px" icon="ep:search" /> + 搜索 + </el-button> + <el-button @click="resetQuery"> + <Icon class="mr-5px" icon="ep:refresh" /> + 重置 + </el-button> + </el-form-item> + </el-form> + </ContentWrap> + <ContentWrap> + <el-tabs v-model="queryParams.status" @tab-click="tabClick"> + <el-tab-pane + v-for="item in statusTabs" + :key="item.label" + :label="item.label" + :name="item.value" + /> + </el-tabs> + <!-- 列表 --> + <el-table v-loading="loading" :data="list"> + <el-table-column align="center" label="退款编号" prop="no" /> + <el-table-column align="center" label="订单编号" prop="orderNo" /> + <!-- TODO 芋艿:未来要加个订单链接 --> + <el-table-column align="center" label="商品信息" min-width="300" prop="spuName" width="auto"> + <!-- TODO @小红:样式不太对,辛苦改改 --> + <!-- <div v-slot="{ row }" class="goods-info">--> + <!-- <img :src="row.picUrl"/>--> + <!-- <span class="ellipsis-2" :title="row.name">{{row.name}}</span>--> + <!-- </div>--> + </el-table-column> + <el-table-column align="center" label="订单金额" prop="refundPrice"> + <template #default="scope"> + <span>¥{{ (scope.row.refundPrice / 100.0).toFixed(2) }}</span> + </template> + </el-table-column> + <el-table-column align="center" label="买家" prop="user.nickname" /> + <!-- TODO 芋艿:未来要加个会员链接 --> + <el-table-column align="center" label="申请时间" prop="createTime" width="180"> + <template #default="scope"> + <span>{{ formatDate(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column align="center" label="售后状态"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.TRADE_AFTER_SALE_STATUS" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column align="center" label="售后方式"> + <template #default="scope"> + <dict-tag :type="DICT_TYPE.TRADE_AFTER_SALE_WAY" :value="scope.row.way" /> + </template> + </el-table-column> + <el-table-column align="center" fixed="right" label="操作" width="160"> + <template #default> + <el-button icon="el-icon-thumb" link type="primary">处理退款</el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页 --> + <Pagination + v-model:limit="queryParams.pageSize" + v-model:page="queryParams.pageNo" + :total="total" + @pagination="getList" + /> + </ContentWrap> +</template> +<script lang="ts" setup> +import * as AfterSaleApi from '@/api/mall/trade/afterSale/index' +import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { formatDate } from '@/utils/formatTime' +import { TabsPaneContext } from 'element-plus' +import { cloneDeep } from 'lodash-es' + +defineOptions({ name: 'TradeAfterSale' }) + +const loading = ref(true) // 列表的加载中 +const total = ref(0) // 列表的总页数 +const list = ref<AfterSaleApi.TradeAfterSaleVO[]>([]) // 列表的数据 +const statusTabs = ref([ + { + label: '全部', + value: '0' + } +]) +const queryFormRef = ref() // 搜索的表单 +// 查询参数 +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + no: null, + status: '0', + orderNo: null, + spuName: null, + createTime: [], + way: null, + type: null +}) +/** 查询列表 */ +const getList = async () => { + loading.value = true + try { + const data = cloneDeep(queryParams) + // 处理掉全部的状态,不传就是全部 + if (data.status === '0') { + delete data.status + } + // 执行查询 + const res = (await AfterSaleApi.getAfterSalePage(data)) as AfterSaleApi.TradeAfterSaleVO[] + list.value = res.list + total.value = res.total + } finally { + loading.value = false + } +} +/** 搜索按钮操作 */ +const handleQuery = async () => { + queryParams.pageNo = 1 + await getList() +} +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value?.resetFields() + handleQuery() +} +/** tab 切换 */ +const tabClick = async (tab: TabsPaneContext) => { + queryParams.status = tab.paneName + await getList() +} + +onMounted(async () => { + await getList() + // 设置 statuses 过滤 + for (const dict of getDictOptions(DICT_TYPE.TRADE_AFTER_SALE_STATUS)) { + statusTabs.value.push({ + label: dict.label, + value: dict.value + }) + } +}) +</script> diff --git a/src/views/mall/trade/order/index.vue b/src/views/mall/trade/order/index.vue index d4bb6642..bcbbff5f 100644 --- a/src/views/mall/trade/order/index.vue +++ b/src/views/mall/trade/order/index.vue @@ -146,10 +146,10 @@ </template> <template #default="scope"> <el-table + :border="true" :data="scope.row.items" :header-cell-style="headerStyle" :span-method="spanMethod" - :border="true" style="width: 100%" > <el-table-column min-width="300" prop="spuName"> @@ -173,8 +173,8 @@ :value="scope.row.payChannelCode" class="mr-20px" /> - <v-else class="mr-20px" v-else>未支付</v-else> - <span class="mr-20px" v-if="scope.row.payTime"> + <v-else v-else class="mr-20px">未支付</v-else> + <span v-if="scope.row.payTime" class="mr-20px"> 支付时间:{{ formatDate(scope.row.payTime) }} </span> <span>订单类型:</span> @@ -280,7 +280,8 @@ 发货 </el-dropdown-item> <el-dropdown-item command="remark"> - <Icon icon="ep:chat-line-square" /> 备注 + <Icon icon="ep:chat-line-square" /> + 备注 </el-dropdown-item> </el-dropdown-menu> </template> @@ -306,7 +307,7 @@ <OrderUpdateRemarkForm ref="updateRemarkForm" @success="getList" /> </template> -<script lang="ts" name="Order" setup> +<script lang="ts" setup> import type { FormInstance, TableColumnCtx } from 'element-plus' import OrderDeliveryForm from './components/OrderDeliveryForm.vue' import OrderUpdateRemarkForm from './components/OrderUpdateRemarkForm.vue' @@ -318,6 +319,8 @@ import { floatToFixed2 } from '@/utils' import { createImageViewer } from '@/components/ImageViewer' import * as DeliveryExpressApi from '@/api/mall/trade/delivery/express' +defineOptions({ name: 'TradeOrder' }) + const { currentRoute, push } = useRouter() // 路由跳转 const loading = ref(true) // 列表的加载中