From 20990a419ccc1adb9e6e8b5fd4001a478b3a0c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A6=82=E5=88=9D?= <3236758982@qq.com> Date: Thu, 12 Mar 2026 17:43:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=94=AE=E5=90=8E=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=89=8D=E7=AB=AF=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/aftersale/aftersaleanalysis/index.ts | 58 +++ src/api/aftersale/aftersaleprocess/index.ts | 57 +++ src/api/aftersale/aftersaleregister/index.ts | 56 +++ src/api/aftersale/aftersalesvisit/index.ts | 53 +++ .../aftersale/aftersaleanalysis/index.vue | 265 ++++++++++++ .../aftersaleprocess/AfterSaleProcessForm.vue | 407 ++++++++++++++++++ .../aftersale/aftersaleprocess/index.vue | 405 +++++++++++++++++ .../AfterSaleRegisterForm.vue | 307 +++++++++++++ .../aftersale/aftersaleregister/index.vue | 391 +++++++++++++++++ .../aftersalesvisit/AfterSalesVisitForm.vue | 267 ++++++++++++ src/views/aftersale/aftersalesvisit/index.vue | 306 +++++++++++++ 11 files changed, 2572 insertions(+) create mode 100644 src/api/aftersale/aftersaleanalysis/index.ts create mode 100644 src/api/aftersale/aftersaleprocess/index.ts create mode 100644 src/api/aftersale/aftersaleregister/index.ts create mode 100644 src/api/aftersale/aftersalesvisit/index.ts create mode 100644 src/views/aftersale/aftersaleanalysis/index.vue create mode 100644 src/views/aftersale/aftersaleprocess/AfterSaleProcessForm.vue create mode 100644 src/views/aftersale/aftersaleprocess/index.vue create mode 100644 src/views/aftersale/aftersaleregister/AfterSaleRegisterForm.vue create mode 100644 src/views/aftersale/aftersaleregister/index.vue create mode 100644 src/views/aftersale/aftersalesvisit/AfterSalesVisitForm.vue create mode 100644 src/views/aftersale/aftersalesvisit/index.vue diff --git a/src/api/aftersale/aftersaleanalysis/index.ts b/src/api/aftersale/aftersaleanalysis/index.ts new file mode 100644 index 0000000..dd8bc76 --- /dev/null +++ b/src/api/aftersale/aftersaleanalysis/index.ts @@ -0,0 +1,58 @@ +import request from '@/config/axios' + +export interface AnalysisQueryParams { + registerCreateTime?: string[] + processFinishTime?: string[] + visitCreateTime?: string[] + pageSize?: number +} + +export interface DistItem { + name: string + value: number +} + +export interface RegisterSummary { + total: number + pending: number + approved: number + rejected: number +} + +export interface ProcessSummary { + total: number + processing: number + completed: number + failed: number +} + +export interface VisitSummary { + total: number + avgRating: number + fiveStar: number + highRepurchase: number +} + +export interface RegisterAnalysisResponse { + registerSummary?: RegisterSummary + registerTypeDist?: DistItem[] + registerStatusDist?: DistItem[] +} + +export interface ProcessAnalysisResponse { + processSummary?: ProcessSummary + processTypeDist?: DistItem[] + processStatusDist?: DistItem[] +} + +export interface VisitAnalysisResponse { + visitSummary?: VisitSummary + visitRatingDist?: DistItem[] + visitRepurchaseDist?: DistItem[] +} + +export const AfterSaleAnalysisApi = { + getAnalysis: async (params: AnalysisQueryParams) => { + return await request.post({ url: '/erp/after-sale/analysis', data: params }) + } +} diff --git a/src/api/aftersale/aftersaleprocess/index.ts b/src/api/aftersale/aftersaleprocess/index.ts new file mode 100644 index 0000000..7136b1f --- /dev/null +++ b/src/api/aftersale/aftersaleprocess/index.ts @@ -0,0 +1,57 @@ +import request from '@/config/axios' +import type { Dayjs } from 'dayjs'; + +/** ERP 售后处理信息 */ +export interface AfterSaleProcess { + id: number; // 处理记录编号 + afterSaleId?: number; // 关联售后登记编号 + processType?: number; // 处理类型:1-退货入库,2-换货出库,3-维修处理,4-退款处理,5-取消处理,6-其他 + processCount?: number; // 处理数量(与售后类型对应:退货数量/换货数量/维修数量等) + processResult?: string; // 处理结果描述 + processEvidence: string; // 处理凭证(图片/文件URL,多个用逗号分隔) + relatedOrderId: number; // 关联业务订单编号(如换货对应的新销售订单号、退款对应的财务订单号) + processStatus?: number; // 处理状态:1-处理中,2-处理完成,3-处理失败 + processFailReason: string; // 处理失败原因 + processUser?: string; // 处理人 + processTime?: string | Dayjs; // 处理时间 + finishTime: string | Dayjs; // 处理完成时间 + userRating?: number; // 用户评价评分(0-10) + } + +// ERP 售后处理 API +export const AfterSaleProcessApi = { + // 查询ERP 售后处理分页 + getAfterSaleProcessPage: async (params: any) => { + return await request.get({ url: `/erp/after-sale-process/page`, params }) + }, + + // 查询ERP 售后处理详情 + getAfterSaleProcess: async (id: number) => { + return await request.get({ url: `/erp/after-sale-process/get?id=` + id }) + }, + + // 新增ERP 售后处理 + createAfterSaleProcess: async (data: AfterSaleProcess) => { + return await request.post({ url: `/erp/after-sale-process/create`, data }) + }, + + // 修改ERP 售后处理 + updateAfterSaleProcess: async (data: AfterSaleProcess) => { + return await request.put({ url: `/erp/after-sale-process/update`, data }) + }, + + // 删除ERP 售后处理 + deleteAfterSaleProcess: async (id: number) => { + return await request.delete({ url: `/erp/after-sale-process/delete?id=` + id }) + }, + + /** 批量删除ERP 售后处理 */ + deleteAfterSaleProcessList: async (ids: number[]) => { + return await request.delete({ url: `/erp/after-sale-process/delete-list?ids=${ids.join(',')}` }) + }, + + // 导出ERP 售后处理 Excel + exportAfterSaleProcess: async (params) => { + return await request.download({ url: `/erp/after-sale-process/export-excel`, params }) + } +} diff --git a/src/api/aftersale/aftersaleregister/index.ts b/src/api/aftersale/aftersaleregister/index.ts new file mode 100644 index 0000000..a6851a5 --- /dev/null +++ b/src/api/aftersale/aftersaleregister/index.ts @@ -0,0 +1,56 @@ +import request from '@/config/axios' +import type { Dayjs } from 'dayjs'; + +/** ERP 售后登记信息 */ +export interface AfterSaleRegister { + id: number; // 售后登记编号 + orderId?: number; // 关联销售订单编号 + orderItemId?: number; // 关联销售订单项编号 + afterSaleType?: number; // 售后类型:1-退货,2-换货,3-维修,4-退款 + applyReason?: string; // 申请原因 + contactName?: string; // 联系人 + contactPhone?: string; // 联系电话 + applyStatus?: number; // 申请状态:1-待审核,2-审核通过,3-审核驳回,4-已取消 + rejectReason: string; // 驳回原因(审核驳回时填写) + applicant?: string; // 申请人 + auditUser: string; // 审核人 + auditTime: string | Dayjs; // 审核时间 + } + +// ERP 售后登记 API +export const AfterSaleRegisterApi = { + // 查询ERP 售后登记分页 + getAfterSaleRegisterPage: async (params: any) => { + return await request.get({ url: `/erp/after-sale-register/page`, params }) + }, + + // 查询ERP 售后登记详情 + getAfterSaleRegister: async (id: number) => { + return await request.get({ url: `/erp/after-sale-register/get?id=` + id }) + }, + + // 新增ERP 售后登记 + createAfterSaleRegister: async (data: AfterSaleRegister) => { + return await request.post({ url: `/erp/after-sale-register/create`, data }) + }, + + // 修改ERP 售后登记 + updateAfterSaleRegister: async (data: AfterSaleRegister) => { + return await request.put({ url: `/erp/after-sale-register/update`, data }) + }, + + // 删除ERP 售后登记 + deleteAfterSaleRegister: async (id: number) => { + return await request.delete({ url: `/erp/after-sale-register/delete?id=` + id }) + }, + + /** 批量删除ERP 售后登记 */ + deleteAfterSaleRegisterList: async (ids: number[]) => { + return await request.delete({ url: `/erp/after-sale-register/delete-list?ids=${ids.join(',')}` }) + }, + + // 导出ERP 售后登记 Excel + exportAfterSaleRegister: async (params) => { + return await request.download({ url: `/erp/after-sale-register/export-excel`, params }) + } +} \ No newline at end of file diff --git a/src/api/aftersale/aftersalesvisit/index.ts b/src/api/aftersale/aftersalesvisit/index.ts new file mode 100644 index 0000000..6c556a6 --- /dev/null +++ b/src/api/aftersale/aftersalesvisit/index.ts @@ -0,0 +1,53 @@ +import request from '@/config/axios' +import type { Dayjs } from 'dayjs'; + +/** 售后回访信息 */ +export interface AfterSalesVisit { + id: number; // 主键ID + customerName?: string; // 客户名称 + contactInfo?: string; // 联系方式 + customerUsage: string; // 客户用途 + productName?: string; // 产品名称 + productEvaluation: string; // 产品评价 + customerType?: string; // 客户类型:大型食品厂/中小型加工厂/经销商/餐饮连锁/机关单位/其他 + repurchaseIntention?: string; // 重复采购意愿:一定会/应该会/不确定/可能不会/肯定不会 + serviceRating?: number; // 服务评分(0~5星) + } + +// 售后回访 API +export const AfterSalesVisitApi = { + // 查询售后回访分页 + getAfterSalesVisitPage: async (params: any) => { + return await request.get({ url: `/erp/after-sales-visit/page`, params }) + }, + + // 查询售后回访详情 + getAfterSalesVisit: async (id: number) => { + return await request.get({ url: `/erp/after-sales-visit/get?id=` + id }) + }, + + // 新增售后回访 + createAfterSalesVisit: async (data: AfterSalesVisit) => { + return await request.post({ url: `/erp/after-sales-visit/create`, data }) + }, + + // 修改售后回访 + updateAfterSalesVisit: async (data: AfterSalesVisit) => { + return await request.put({ url: `/erp/after-sales-visit/update`, data }) + }, + + // 删除售后回访 + deleteAfterSalesVisit: async (id: number) => { + return await request.delete({ url: `/erp/after-sales-visit/delete?id=` + id }) + }, + + /** 批量删除售后回访 */ + deleteAfterSalesVisitList: async (ids: number[]) => { + return await request.delete({ url: `/erp/after-sales-visit/delete-list?ids=${ids.join(',')}` }) + }, + + // 导出售后回访 Excel + exportAfterSalesVisit: async (params) => { + return await request.download({ url: `/erp/after-sales-visit/export-excel`, params }) + } +} \ No newline at end of file diff --git a/src/views/aftersale/aftersaleanalysis/index.vue b/src/views/aftersale/aftersaleanalysis/index.vue new file mode 100644 index 0000000..f8244b9 --- /dev/null +++ b/src/views/aftersale/aftersaleanalysis/index.vue @@ -0,0 +1,265 @@ + + + + + + + 统计 + + + + + + + + + + 售后登记统计 + + + + + + + + + 售后类型分布 + + + + 申请状态分布 + + + + + + + 售后处理统计 + + + + + + + + + 处理类型分布 + + + + 处理状态分布 + + + + + + + 售后回访统计 + + + + + + + + + 评分分布 + + + + 复购意愿分布 + + + + + + + + diff --git a/src/views/aftersale/aftersaleprocess/AfterSaleProcessForm.vue b/src/views/aftersale/aftersaleprocess/AfterSaleProcessForm.vue new file mode 100644 index 0000000..a038425 --- /dev/null +++ b/src/views/aftersale/aftersaleprocess/AfterSaleProcessForm.vue @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 确 定 + 取 消 + + + + + + + + + + + + + + + + + + + 搜索 + + + + 重置 + + + + + + + + + + + + + + + + {{ formatAfterSaleType(row.afterSaleType) }} + + + + + + + + + + + diff --git a/src/views/aftersale/aftersaleprocess/index.vue b/src/views/aftersale/aftersaleprocess/index.vue new file mode 100644 index 0000000..cf3a6e3 --- /dev/null +++ b/src/views/aftersale/aftersaleprocess/index.vue @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 搜索 + 重置 + + 新增 + + + 导出 + + + 批量删除 + + + + + + + + + + + + + + + + + + + + + + + + + + 详情 + + 编辑 + + + 处理完成 + + + 删除 + + + + + + + + + + + + + + + {{ detailRow.afterSaleId }} + {{ formatProcessType(detailRow, null as any, detailRow.processType as any) }} + {{ detailRow.processCount ?? '-' }} + {{ detailRow.relatedOrderId ?? '-' }} + {{ detailRow.processResult ?? '-' }} + {{ detailRow.processFailReason ?? '-' }} + {{ formatProcessStatus(detailRow, null as any, detailRow.processStatus as any) }} + {{ detailRow.processUser ?? '-' }} + {{ dateFormatter(detailRow, null as any, detailRow.processTime as any) }} + {{ dateFormatter(detailRow, null as any, detailRow.finishTime as any) }} + + + + + + + + {{ dateFormatter(detailRow, null as any, (detailRow as any).createTime) }} + + + 关闭 + + + + + diff --git a/src/views/aftersale/aftersaleregister/AfterSaleRegisterForm.vue b/src/views/aftersale/aftersaleregister/AfterSaleRegisterForm.vue new file mode 100644 index 0000000..29367ae --- /dev/null +++ b/src/views/aftersale/aftersaleregister/AfterSaleRegisterForm.vue @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 确 定 + 取 消 + + + + + + + + + + + + + + 搜索 + + + + 重置 + + + + + + + + + + + + + + + + + + + + diff --git a/src/views/aftersale/aftersaleregister/index.vue b/src/views/aftersale/aftersaleregister/index.vue new file mode 100644 index 0000000..b315f83 --- /dev/null +++ b/src/views/aftersale/aftersaleregister/index.vue @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 搜索 + 重置 + + 新增 + + + 导出 + + + 批量删除 + + + + + + + + + + + + + + + + + + 详情 + + 编辑 + + + 审核通过 + + + 删除 + + + + + + + + + + + + + + + {{ detailRow.orderId }} + {{ formatAfterSaleType(detailRow, null as any, detailRow.afterSaleType as any) }} + {{ detailRow.applyReason ?? '-' }} + {{ detailRow.contactName ?? '-' }} + {{ detailRow.contactPhone ?? '-' }} + {{ formatApplyStatus(detailRow, null as any, detailRow.applyStatus as any) }} + {{ detailRow.rejectReason ?? '-' }} + {{ detailRow.applicant ?? '-' }} + {{ detailRow.auditUser ?? '-' }} + {{ dateFormatter(detailRow, null as any, detailRow.auditTime as any) }} + {{ dateFormatter(detailRow, null as any, (detailRow as any).createTime) }} + + + 关闭 + + + + + diff --git a/src/views/aftersale/aftersalesvisit/AfterSalesVisitForm.vue b/src/views/aftersale/aftersalesvisit/AfterSalesVisitForm.vue new file mode 100644 index 0000000..e29393c --- /dev/null +++ b/src/views/aftersale/aftersalesvisit/AfterSalesVisitForm.vue @@ -0,0 +1,267 @@ + + + + + 客户信息 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 产品信息 + + + + + + + + + + + + + + + 服务评价 + + + + + + + + + + + + + + + + + 取消 + + 确定 + + + + + diff --git a/src/views/aftersale/aftersalesvisit/index.vue b/src/views/aftersale/aftersalesvisit/index.vue new file mode 100644 index 0000000..f06cb8e --- /dev/null +++ b/src/views/aftersale/aftersalesvisit/index.vue @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 搜索 + + + 重置 + + + + + + + + 新增 + + + 导出 + + + 批量删除 + + + + + + + + + + + + + + + {{ getCustomerTypeLabel(scope.row.customerType) }} + + + + + + + {{ getRepurchaseLabel(scope.row.repurchaseIntention) }} + + + + + + + + + + + + + 编辑 + + + 删除 + + + + + + + + + + + + +