From 96373deb2f07413a4fa87ba72b2b2a5a9540c58a Mon Sep 17 00:00:00 2001 From: wurenzhi Date: Wed, 18 Mar 2026 21:02:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=94=AE=E5=90=8E?= =?UTF-8?q?=E9=80=86=E5=90=91=E6=B5=81=E7=A8=8B=E5=92=8C=E7=89=A9=E6=B5=81?= =?UTF-8?q?=E7=AD=96=E7=95=A5=E9=97=AD=E7=8E=AF=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor: 移除不再使用的提示文件和文档副本 docs: 更新开发进度文档,补充前端任务完成情况 --- .prompts/README.md | 39 - .prompts/V32-ThinkPad.Modelfile | 12 - .prompts/v32-audit.prompt | 14 - .prompts/v32-service.prompt | 14 - .../src/pages/AfterSales/CustomerService.tsx | 508 + client/src/pages/AfterSales/RefundProcess.tsx | 390 + client/src/pages/AfterSales/ReturnApply.tsx | 399 + .../src/pages/Blacklist/BlacklistManage.tsx | 470 + client/src/pages/Blacklist/RiskMonitor.tsx | 475 + .../src/pages/Logistics/LogisticsSelect.tsx | 485 + .../src/pages/Logistics/LogisticsTracking.tsx | 441 + .../Logistics/ShippingCostCalculator.tsx | 384 + dashboard/src/.umi/appData.json | 24481 +++++++++++++++- docs/00_Business/Business_ClosedLoops.md | 878 + docs/00_Business/Task_Overview.md | 721 +- docs/Development_Progress.md | 19 +- docs/临时修改建议 copy.MD | 745 - 17 files changed, 29574 insertions(+), 901 deletions(-) delete mode 100644 .prompts/README.md delete mode 100644 .prompts/V32-ThinkPad.Modelfile delete mode 100644 .prompts/v32-audit.prompt delete mode 100644 .prompts/v32-service.prompt create mode 100644 client/src/pages/AfterSales/CustomerService.tsx create mode 100644 client/src/pages/AfterSales/RefundProcess.tsx create mode 100644 client/src/pages/AfterSales/ReturnApply.tsx create mode 100644 client/src/pages/Blacklist/BlacklistManage.tsx create mode 100644 client/src/pages/Blacklist/RiskMonitor.tsx create mode 100644 client/src/pages/Logistics/LogisticsSelect.tsx create mode 100644 client/src/pages/Logistics/LogisticsTracking.tsx create mode 100644 client/src/pages/Logistics/ShippingCostCalculator.tsx diff --git a/.prompts/README.md b/.prompts/README.md deleted file mode 100644 index d8f1dc8..0000000 --- a/.prompts/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Prompts - 提示文件 - -## 📋 项目简介 - -本目录包含 AI 提示文件,用于指导 AI 模型生成代码和文档。 - -## 🚀 核心提示文件 - -### 1. 模型文件 -- **文件**: `V32-ThinkPad.Modelfile` -- **功能**: 定义 AI 模型的配置和行为 - -### 2. 审计提示 -- **文件**: `v32-audit.prompt` -- **功能**: 指导 AI 进行代码审计 - -### 3. 服务提示 -- **文件**: `v32-service.prompt` -- **功能**: 指导 AI 生成服务代码 - -## 📁 项目结构 - -``` -.prompts/ -├── V32-ThinkPad.Modelfile # 模型配置文件 -├── v32-audit.prompt # 审计提示文件 -├── v32-service.prompt # 服务提示文件 -└── README.md # 项目说明 -``` - -## 🔧 使用规范 - -- 提示文件应遵循清晰、具体的原则 -- 提示文件应包含足够的上下文信息 -- 提示文件应定期更新以适应项目需求 - -## 🤝 贡献 - -欢迎贡献提示文件和提出建议!请先阅读项目文档,然后提交 Pull Request。 diff --git a/.prompts/V32-ThinkPad.Modelfile b/.prompts/V32-ThinkPad.Modelfile deleted file mode 100644 index 71c6351..0000000 --- a/.prompts/V32-ThinkPad.Modelfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM qwen2.5-coder:14b -# 强制开启 16k 上下文窗口 -PARAMETER num_ctx 16384 -# 设置较低的温度,保证代码逻辑严谨 -PARAMETER temperature 0.2 -# 针对 V32.0 规格的系统提示词 -SYSTEM """ -你是一个顶级全栈架构师。在编写代码时,必须遵守以下原则: -1. 必须在 LegacyTableInitializer.ts 中检查物理表注册。 -2. 所有 AGI 建议必须通过 DecisionExplainabilityEngine 记录因果链。 -3. 严禁使用 Mock 数据,严格遵守 Zero-Mock Policy。 -""" diff --git a/.prompts/v32-audit.prompt b/.prompts/v32-audit.prompt deleted file mode 100644 index 93db29b..0000000 --- a/.prompts/v32-audit.prompt +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: v32-audit -description: 执行 V32.0 规格与物理表注册审计 ---- - -你是一个顶级全栈架构师。请针对以下输入代码执行 V32.0 规格审计: - -1. **物理表校验**:检查是否在 [LegacyTableInitializer.ts](file:///d:/trae_projects/crawlful-hub/server/src/core/runtime/LegacyTableInitializer.ts) 中注册了 initTable()。 -2. **因果链校验**:确保使用了 `DecisionExplainabilityEngine.logDecision`。 -3. **零 Mock 校验**:严禁硬编码数据。 -4. **规格匹配**:对比 [task-specifications.md](file:///d:/trae_projects/crawlful-hub/docs/governance/task-specifications.md) 确认逻辑闭环。 - -代码内容: -{{{ input }}} diff --git a/.prompts/v32-service.prompt b/.prompts/v32-service.prompt deleted file mode 100644 index f1f1488..0000000 --- a/.prompts/v32-service.prompt +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: v32-service -description: 编写符合 V32.0 规范的后端 Service 逻辑 ---- - -你是一个顶级后端架构师。请根据以下要求编写 Service: - -1. **命名规范**:遵循 project_rules.md,使用 TypeScript,禁止 any。 -2. **初始化逻辑**:必须包含 `static async initTable()`,并使用 `db.schema.hasTable` 保证幂等。 -3. **业务闭环**:实现逻辑必须与 [task-specifications.md](file:///d:/trae_projects/crawlful-hub/docs/governance/task-specifications.md) 中的原子规格 100% 对应。 -4. **日志与审计**:关键业务变更必须调用 `AuditService`。 - -上下文背景: -{{{ input }}} diff --git a/client/src/pages/AfterSales/CustomerService.tsx b/client/src/pages/AfterSales/CustomerService.tsx new file mode 100644 index 0000000..82df1ed --- /dev/null +++ b/client/src/pages/AfterSales/CustomerService.tsx @@ -0,0 +1,508 @@ +import React, { useState, useEffect } from 'react'; +import { + Card, + Table, + Button, + Modal, + Form, + Input, + Select, + TextArea, + message, + Spin, + Row, + Col, + Typography, + Divider, + Space, + Tag, + Descriptions, + Badge, +} from 'antd'; +import { + MessageOutlined, + PhoneOutlined, + MailOutlined, + UserOutlined, + ClockCircleOutlined, + CheckCircleOutlined, + CloseCircleOutlined, + QuestionCircleOutlined, + MessageSquareOutlined, +} from '@ant-design/icons'; + +const { Option } = Select; +const { Title, Text, Paragraph } = Typography; + +// 模拟客户服务数据 +const mockCustomerServices = [ + { + id: 'CS-20260318-001', + customerName: '张三', + customerId: 'CUST-001', + contactInfo: '13800138001', + serviceType: 'PRODUCT_ISSUE', + subject: '商品质量问题', + description: '购买的iPhone 15 Pro屏幕出现闪烁问题', + status: 'PENDING', + priority: 'HIGH', + createdAt: '2026-03-18T10:00:00Z', + updatedAt: '2026-03-18T10:00:00Z', + assignedTo: '客服专员A', + messages: [ + { + id: 'MSG-001', + sender: 'CUSTOMER', + content: '购买的iPhone 15 Pro屏幕出现闪烁问题', + timestamp: '2026-03-18T10:00:00Z', + }, + ], + }, + { + id: 'CS-20260318-002', + customerName: '李四', + customerId: 'CUST-002', + contactInfo: '13900139002', + serviceType: 'ORDER_ISSUE', + subject: '订单发货问题', + description: '订单已经付款但一直未发货', + status: 'PROCESSING', + priority: 'MEDIUM', + createdAt: '2026-03-17T15:30:00Z', + updatedAt: '2026-03-18T09:00:00Z', + assignedTo: '客服专员B', + messages: [ + { + id: 'MSG-002', + sender: 'CUSTOMER', + content: '订单已经付款但一直未发货', + timestamp: '2026-03-17T15:30:00Z', + }, + { + id: 'MSG-003', + sender: 'SUPPORT', + content: '您好,我们正在核实您的订单情况,稍后会给您回复', + timestamp: '2026-03-18T09:00:00Z', + }, + ], + }, + { + id: 'CS-20260318-003', + customerName: '王五', + customerId: 'CUST-003', + contactInfo: '13700137003', + serviceType: 'REFUND_ISSUE', + subject: '退款未到账', + description: '退款申请已经通过但钱还没到账', + status: 'COMPLETED', + priority: 'HIGH', + createdAt: '2026-03-16T14:00:00Z', + updatedAt: '2026-03-17T10:00:00Z', + assignedTo: '客服专员A', + messages: [ + { + id: 'MSG-004', + sender: 'CUSTOMER', + content: '退款申请已经通过但钱还没到账', + timestamp: '2026-03-16T14:00:00Z', + }, + { + id: 'MSG-005', + sender: 'SUPPORT', + content: '您好,退款通常需要1-3个工作日到账,请耐心等待', + timestamp: '2026-03-16T15:00:00Z', + }, + { + id: 'MSG-006', + sender: 'CUSTOMER', + content: '已经收到退款了,谢谢', + timestamp: '2026-03-17T10:00:00Z', + }, + ], + }, +]; + +// 服务类型选项 +const serviceTypes = [ + { value: 'PRODUCT_ISSUE', label: '商品问题' }, + { value: 'ORDER_ISSUE', label: '订单问题' }, + { value: 'REFUND_ISSUE', label: '退款问题' }, + { value: 'SHIPPING_ISSUE', label: '物流问题' }, + { value: 'ACCOUNT_ISSUE', label: '账户问题' }, + { value: 'OTHER', label: '其他问题' }, +]; + +// 优先级选项 +const priorities = [ + { value: 'LOW', label: '低', color: 'blue' }, + { value: 'MEDIUM', label: '中', color: 'orange' }, + { value: 'HIGH', label: '高', color: 'red' }, +]; + +// 状态选项 +const statuses = [ + { value: 'PENDING', label: '待处理' }, + { value: 'PROCESSING', label: '处理中' }, + { value: 'COMPLETED', label: '已完成' }, + { value: 'CLOSED', label: '已关闭' }, +]; + +const CustomerService: React.FC = () => { + const [services, setServices] = useState(mockCustomerServices); + const [selectedService, setSelectedService] = useState(null); + const [isModalVisible, setIsModalVisible] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [form] = Form.useForm(); + const [messageForm] = Form.useForm(); + const [newMessage, setNewMessage] = useState(''); + + // 处理服务详情查看 + const handleServiceView = (service: any) => { + setSelectedService(service); + setIsModalVisible(true); + }; + + // 处理消息发送 + const handleMessageSend = async () => { + if (!newMessage.trim()) return; + + setIsLoading(true); + try { + // 模拟API调用 + await new Promise(resolve => setTimeout(resolve, 500)); + + const updatedServices = services.map(service => { + if (service.id === selectedService.id) { + const updatedService = { + ...service, + messages: [ + ...service.messages, + { + id: `MSG-${Date.now()}`, + sender: 'SUPPORT', + content: newMessage, + timestamp: new Date().toISOString(), + }, + ], + updatedAt: new Date().toISOString(), + }; + return updatedService; + } + return service; + }); + + setServices(updatedServices); + setSelectedService(updatedServices.find(s => s.id === selectedService.id)); + setNewMessage(''); + message.success('消息发送成功'); + } catch (error) { + message.error('消息发送失败'); + } finally { + setIsLoading(false); + } + }; + + // 处理服务状态更新 + const handleStatusUpdate = async (values: any) => { + setIsLoading(true); + try { + // 模拟API调用 + await new Promise(resolve => setTimeout(resolve, 1000)); + + const updatedServices = services.map(service => { + if (service.id === selectedService.id) { + return { + ...service, + status: values.status, + priority: values.priority, + updatedAt: new Date().toISOString(), + }; + } + return service; + }); + + setServices(updatedServices); + setSelectedService(updatedServices.find(s => s.id === selectedService.id)); + message.success('服务状态更新成功'); + } catch (error) { + message.error('服务状态更新失败'); + } finally { + setIsLoading(false); + } + }; + + // 获取服务类型标签 + const getServiceTypeTag = (type: string) => { + const serviceType = serviceTypes.find(t => t.value === type); + return serviceType ? {serviceType.label} : {type}; + }; + + // 获取优先级标签 + const getPriorityTag = (priority: string) => { + const p = priorities.find(p => p.value === priority); + return p ? {p.label} : {priority}; + }; + + // 获取状态标签 + const getStatusTag = (status: string) => { + switch (status) { + case 'PENDING': + return 待处理; + case 'PROCESSING': + return 处理中; + case 'COMPLETED': + return 已完成; + case 'CLOSED': + return 已关闭; + default: + return {status}; + } + }; + + // 服务表格列 + const serviceColumns = [ + { + title: '服务ID', + dataIndex: 'id', + key: 'id', + }, + { + title: '客户信息', + key: 'customer', + render: (_, record: any) => ( +
+
{record.customerName}
+
{record.contactInfo}
+
+ ), + }, + { + title: '服务类型', + dataIndex: 'serviceType', + key: 'serviceType', + render: (type: string) => getServiceTypeTag(type), + }, + { + title: '主题', + dataIndex: 'subject', + key: 'subject', + }, + { + title: '优先级', + dataIndex: 'priority', + key: 'priority', + render: (priority: string) => getPriorityTag(priority), + }, + { + title: '状态', + dataIndex: 'status', + key: 'status', + render: (status: string) => getStatusTag(status), + }, + { + title: '创建时间', + dataIndex: 'createdAt', + key: 'createdAt', + render: (date: string) => new Date(date).toLocaleString(), + }, + { + title: '操作', + key: 'action', + render: (_: any, record: any) => ( + + ), + }, + ]; + + return ( +
+ + 客户服务管理 + 售后逆向流程第三步 +
+ } + extra={ + + } + > + 服务工单 + + + + {/* 客户服务详情模态框 */} + {selectedService && ( + setIsModalVisible(false)} + footer={null} + width={1000} + > + + + + {selectedService.id} + {selectedService.customerName} + {selectedService.customerId} + {selectedService.contactInfo} + {getServiceTypeTag(selectedService.serviceType)} + {selectedService.subject} + {selectedService.description} + {getPriorityTag(selectedService.priority)} + {getStatusTag(selectedService.status)} + + {new Date(selectedService.createdAt).toLocaleString()} + + + {new Date(selectedService.updatedAt).toLocaleString()} + + {selectedService.assignedTo} + + + + +
+ + + + + + + + + +