diff --git a/src/pages/api/paymentCodeImage/[id].ts b/src/pages/api/paymentCodeImage/[id].ts new file mode 100644 index 0000000..905a131 --- /dev/null +++ b/src/pages/api/paymentCodeImage/[id].ts @@ -0,0 +1,22 @@ +import { NextApiRequest, NextApiResponse } from 'next'; +import connectDB from '@/utils/connectDB'; +import { CustomerPaymentCode } from '@/models'; + +const handler = async (req: NextApiRequest, res: NextApiResponse) => { + const { id } = req.query; + + try { + const paymentCode = await CustomerPaymentCode.findById(id); + + if (!paymentCode) { + return res.status(404).json({ message: '收款码未找到' }); + } + + res.status(200).send(paymentCode.收款码); + } catch (error) { + console.error('Error fetching payment code image:', error); + res.status(500).json({ message: '服务器错误' }); + } +}; + +export default connectDB(handler); diff --git a/src/pages/team/AfterSaleRecord/index.tsx b/src/pages/team/AfterSaleRecord/index.tsx index 1681a0c..f43b419 100644 --- a/src/pages/team/AfterSaleRecord/index.tsx +++ b/src/pages/team/AfterSaleRecord/index.tsx @@ -6,7 +6,7 @@ */ import React, { useEffect, useState, useMemo, useCallback } from 'react'; import { Table, Button, Card, Tag, Tooltip - , Input, Space, DatePicker, App } from 'antd'; + , Input, Space, DatePicker, App, Typography } from 'antd'; import { IAfterSalesRecord } from '@/models/types'; import dayjs from 'dayjs'; import { useUserInfo } from '@/store/userStore'; @@ -15,7 +15,7 @@ import { useRouter } from 'next/router'; import { CheckCircleOutlined, ClockCircleOutlined, DownloadOutlined, FieldTimeOutlined, IdcardOutlined, MobileOutlined, SyncOutlined, UserOutlined, WechatOutlined , SearchOutlined } from '@ant-design/icons'; -import { IconButton, Iconify } from '@/components/icon'; +import { Iconify } from '@/components/icon'; import PaymentCodeImageComponent from '@/pages/components/PaymentCodeImage'; import MultiAfterSalesModal from './MultiAfterSalesModal'; import ShipModal from './ship-modal'; @@ -23,6 +23,36 @@ import EditAfterSalesModal from './EditAfterSalesModal'; // 引入编辑售后 import ProductCardList from '@/components/product/ProductCardList'; // 引入产品卡片列表组件 import MyTooltip from '@/components/tooltip/MyTooltip'; +const { Paragraph } = Typography; + +// 通用样式 +const COMMON_STYLES = { + tagContainer: { margin: 0 }, + flexColumn: { display: "flex", flexDirection: "column" as const, alignItems: "flex-start", gap: "4px" }, + flexRow: { display: "flex", gap: "8px" } +}; + +// 工具函数 +const formatDate = (dateString: string): string => { + if (!dateString) return "未知"; + const date = new Date(dateString); + return date.toLocaleDateString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }).replace(/\//g, '-'); +}; + + +const getCustomerTagColor = (unreceivedAmount: number): string => { + return unreceivedAmount > 0 ? "#cd201f" : "blue"; +}; + +const buildCustomerAddress = (address: any): string => { + if (!address) return "未知"; + return `${address.省份 ?? ""} ${address.城市 ?? ""} ${address.区县 ?? ""} ${address.详细地址 ?? ""}`.trim(); +}; + // 导出Excel相关库 //import * as XLSX from 'xlsx'; //import { saveAs } from 'file-saver'; @@ -212,91 +242,104 @@ const AfterSaleRecordPage = () => { { title: '客户信息', width: 160, + align: "center", key: '客户信息', - // 增加filterDropdown用于尾号查询 - filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => ( -
- setSelectedKeys(e.target.value ? [e.target.value] : [])} - onPressEnter={() => confirm()} - style={{ marginBottom: 8, display: 'block' }} - /> - - - - -
- ), - filterIcon: filtered => ( - - ), - onFilter: (value, record: IAfterSalesRecord) => { - const phoneTail = record.销售记录.客户?.电话 - ? record.销售记录.客户.电话.slice(-4) - : ''; - const searchVal = String(value); - return phoneTail.includes(searchVal); - }, + // 增加filterDropdown用于尾号查询 + filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => ( +
+ setSelectedKeys(e.target.value ? [e.target.value] : [])} + onPressEnter={() => confirm()} + style={{ marginBottom: 8, display: 'block' }} + /> + + + + +
+ ), + filterIcon: filtered => ( + + ), + onFilter: (value, record: IAfterSalesRecord) => { + const phoneTail = record.销售记录.客户?.电话 + ? record.销售记录.客户.电话.slice(-4) + : ''; + const searchVal = String(value); + return phoneTail.includes(searchVal); + }, render: (record: IAfterSalesRecord) => { - // 将地址的各个部分拼接成一个字符串 - const address = record.销售记录.客户?.地址 - ? `${record.销售记录.客户.地址.省份 ?? ''} ${record.销售记录.客户.地址.城市 ?? ''} ${record.销售记录.客户.地址.区县 ?? ''} ${record.销售记录.客户.地址.详细地址 ?? ''}` - : '未知'; - const customerInfo = `姓名:${record.销售记录.客户?.姓名 ?? '未知'}\n电话:${record.销售记录.客户?.电话 ?? '未知'}\n地址:${address}`; - const customerName = record.销售记录.客户?.姓名 ?? '未知'; - //显示账号编号 + const address = buildCustomerAddress(record.销售记录.客户?.地址); + const customerName = record.销售记录.客户?.姓名 ?? "未知"; + const unreceivedAmount = parseFloat((record.销售记录.待收款 || 0).toString()); + const customerTagColor = getCustomerTagColor(unreceivedAmount); const accountNumber = record.销售记录.订单来源?.账号编号 ?? '未知'; + + // 准备复制文本 + const customerCopyText = `姓名:${customerName}\n电话:${record.销售记录.客户?.电话 ?? "未知"}\n地址:${address}`; + return ( -
- {isAdmin && ( - { - try { - await navigator.clipboard.writeText(customerInfo); - message.success(`客户 ${customerName} 信息复制成功!`); - } catch (error) { - console.error('客户信息复制失败:', error); - message.error('客户信息复制失败'); - } - }} - > - - - )} - -
- } color="">{record.销售记录.客户?.姓名 ?? '未知'} - } color="">{record.销售记录.成交日期 ? new Date(record.销售记录.成交日期).toLocaleDateString() : '未知'} - } color="">{record.销售记录.客户?.电话 ? `****${record.销售记录.客户.电话.slice(-4)}` : '未知'} - {/*
状态:{record.销售记录?.订单状态?.[0]}
*/} - {/* 将最后两个 Tag 放在一个 span 中,并使用 no-wrap 样式避免自动换行 */} - - } color=""> - {record.销售记录?.导购?.姓名 ?? '未知'} - - } color="green"> +
+ {/* 左侧复制按钮 */} +
+ {isAdmin && ( + message.success(`客户 ${customerName} 信息复制成功!`), + tooltips: ['复制客户信息', '复制成功'], + icon: + }} + style={{ margin: 0, lineHeight: 0 }} + > + {/* 空内容,只显示复制按钮 */} + + )} +
+ + {/* 右侧标签信息,按用户要求布局 */} + +
+ {/* 客户名字 */} + } color={customerTagColor} style={COMMON_STYLES.tagContainer}> + {customerName} + + + {/* 客户尾号 */} + } color="green" style={COMMON_STYLES.tagContainer}> + {record.销售记录.客户?.电话 ? `${record.销售记录.客户.电话.slice(-4)}` : "未知"} + + + {/* 成交日期 */} + } color="purple" style={COMMON_STYLES.tagContainer}> + {record.销售记录.成交日期 ? formatDate(record.销售记录.成交日期.toString()) : "未知"} + + + {/* accountNumber+导购姓名显示在一行 */} +
+ } color="geekblue" style={COMMON_STYLES.tagContainer}> {accountNumber} - + } color="cyan" style={COMMON_STYLES.tagContainer}> + {record.销售记录?.导购?.姓名 ?? '未知'} + +
@@ -306,10 +349,21 @@ const AfterSaleRecordPage = () => { { title: '售后产品', dataIndex: '原产品', - //width: 260, + width: 260, // 设置固定宽度,防止占用其他列空间 key: 'originalProducts', render: (products: any[], record: IAfterSalesRecord) => { - return ; + return ( +
+ +
+ ); } }, @@ -333,6 +387,7 @@ const AfterSaleRecordPage = () => { { title: '售后信息', key: 'reasonAndType', + width: 200, //筛选售后类型 filters: [ { text: '退货', value: '退货' }, @@ -363,9 +418,21 @@ const AfterSaleRecordPage = () => { { title: '替换产品', dataIndex: '替换产品', + width: 260, // 设置固定宽度,防止占用其他列空间 key: 'replacementProducts', render: (products: any[], record: IAfterSalesRecord) => { - return ; + return ( +
+ +
+ ); } }, //财务信息 @@ -759,7 +826,7 @@ const AfterSaleRecordPage = () => { sticky scroll={{ y: `calc(100vh - 300px)`, - //x: 'max-content' + x: 'max-content' // 启用水平滚动,确保表格内容不会被挤压 }} //pagination={false} // 禁用分页 pagination={{