0607.5
Some checks failed
Next.js CI/CD 流水线 / deploy (push) Failing after 21s

This commit is contained in:
2025-06-07 02:01:27 +08:00
parent eb79e416db
commit 4f6acafb2a
2 changed files with 174 additions and 85 deletions

View File

@@ -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);

View File

@@ -6,7 +6,7 @@
*/ */
import React, { useEffect, useState, useMemo, useCallback } from 'react'; import React, { useEffect, useState, useMemo, useCallback } from 'react';
import { Table, Button, Card, Tag, Tooltip 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 { IAfterSalesRecord } from '@/models/types';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useUserInfo } from '@/store/userStore'; import { useUserInfo } from '@/store/userStore';
@@ -15,7 +15,7 @@ import { useRouter } from 'next/router';
import { CheckCircleOutlined, ClockCircleOutlined, DownloadOutlined, FieldTimeOutlined, IdcardOutlined, MobileOutlined, SyncOutlined, UserOutlined, WechatOutlined import { CheckCircleOutlined, ClockCircleOutlined, DownloadOutlined, FieldTimeOutlined, IdcardOutlined, MobileOutlined, SyncOutlined, UserOutlined, WechatOutlined
, SearchOutlined , SearchOutlined
} from '@ant-design/icons'; } from '@ant-design/icons';
import { IconButton, Iconify } from '@/components/icon'; import { Iconify } from '@/components/icon';
import PaymentCodeImageComponent from '@/pages/components/PaymentCodeImage'; import PaymentCodeImageComponent from '@/pages/components/PaymentCodeImage';
import MultiAfterSalesModal from './MultiAfterSalesModal'; import MultiAfterSalesModal from './MultiAfterSalesModal';
import ShipModal from './ship-modal'; import ShipModal from './ship-modal';
@@ -23,6 +23,36 @@ import EditAfterSalesModal from './EditAfterSalesModal'; // 引入编辑售后
import ProductCardList from '@/components/product/ProductCardList'; // 引入产品卡片列表组件 import ProductCardList from '@/components/product/ProductCardList'; // 引入产品卡片列表组件
import MyTooltip from '@/components/tooltip/MyTooltip'; 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相关库 // 导出Excel相关库
//import * as XLSX from 'xlsx'; //import * as XLSX from 'xlsx';
//import { saveAs } from 'file-saver'; //import { saveAs } from 'file-saver';
@@ -212,6 +242,7 @@ const AfterSaleRecordPage = () => {
{ {
title: '客户信息', title: '客户信息',
width: 160, width: 160,
align: "center",
key: '客户信息', key: '客户信息',
// 增加filterDropdown用于尾号查询 // 增加filterDropdown用于尾号查询
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => ( filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
@@ -254,49 +285,61 @@ const AfterSaleRecordPage = () => {
return phoneTail.includes(searchVal); return phoneTail.includes(searchVal);
}, },
render: (record: IAfterSalesRecord) => { render: (record: IAfterSalesRecord) => {
// 将地址的各个部分拼接成一个字符串 const address = buildCustomerAddress(record..?.);
const address = record..?. const customerName = record..?. ?? "未知";
? `${record.... ?? ''} ${record.... ?? ''} ${record.... ?? ''} ${record.... ?? ''}` const unreceivedAmount = parseFloat((record.. || 0).toString());
: '未知'; const customerTagColor = getCustomerTagColor(unreceivedAmount);
const customerInfo = `姓名:${record..?. ?? '未知'}\n电话${record..?. ?? '未知'}\n地址${address}`;
const customerName = record..?. ?? '未知';
//显示账号编号
const accountNumber = record..?. ?? '未知'; const accountNumber = record..?. ?? '未知';
// 准备复制文本
const customerCopyText = `姓名:${customerName}\n电话${record..?. ?? "未知"}\n地址${address}`;
return ( return (
<div className="flex items-center"> <div style={{ display: "flex" }}>
{/* 左侧复制按钮 */}
<div style={{ marginRight: 8 }}>
{isAdmin && ( {isAdmin && (
<IconButton <Paragraph
className="text-gray" copyable={{
onClick={async () => { text: customerCopyText,
try { onCopy: () => message.success(`客户 ${customerName} 信息复制成功!`),
await navigator.clipboard.writeText(customerInfo); tooltips: ['复制客户信息', '复制成功'],
message.success(`客户 ${customerName} 信息复制成功!`); icon: <Iconify icon="eva:copy-fill" size={16} />
} catch (error) {
console.error('客户信息复制失败:', error);
message.error('客户信息复制失败');
}
}} }}
style={{ margin: 0, lineHeight: 0 }}
> >
<Iconify icon="eva:copy-fill" size={20} /> {/* 空内容,只显示复制按钮 */}
</IconButton> </Paragraph>
)} )}
<MyTooltip </div>
color="white"
title={record..?. ?? '未知'}> {/* 右侧标签信息,按用户要求布局 */}
<div> <MyTooltip color="white" title={customerName} placement="topLeft">
<Tag icon={<UserOutlined />} color="">{record..?. ?? '未知'}</Tag> <div style={COMMON_STYLES.flexColumn}>
<Tag icon={<FieldTimeOutlined />} color="">{record.. ? new Date(record..).toLocaleDateString() : '未知'}</Tag> {/* 客户名字 */}
<Tag icon={<MobileOutlined />} color="">{record..?. ? `****${record....slice(-4)}` : '未知'}</Tag> <Tag icon={<UserOutlined />} color={customerTagColor} style={COMMON_STYLES.tagContainer}>
{/*<div>状态:{record.销售记录?.订单状态?.[0]}</div>*/} {customerName}
{/* 将最后两个 Tag 放在一个 span 中,并使用 no-wrap 样式避免自动换行 */}
<span style={{ whiteSpace: 'nowrap' }}>
<Tag icon={<IdcardOutlined />} color="">
{record.?.?. ?? '未知'}
</Tag> </Tag>
<Tag icon={<WechatOutlined />} color="green">
{/* 客户尾号 */}
<Tag icon={<MobileOutlined />} color="green" style={COMMON_STYLES.tagContainer}>
{record..?. ? `${record....slice(-4)}` : "未知"}
</Tag>
{/* 成交日期 */}
<Tag icon={<FieldTimeOutlined />} color="purple" style={COMMON_STYLES.tagContainer}>
{record.. ? formatDate(record...toString()) : "未知"}
</Tag>
{/* accountNumber+导购姓名显示在一行 */}
<div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap' }}>
<Tag icon={<WechatOutlined />} color="geekblue" style={COMMON_STYLES.tagContainer}>
{accountNumber} {accountNumber}
</Tag> </Tag>
</span> <Tag icon={<IdcardOutlined />} color="cyan" style={COMMON_STYLES.tagContainer}>
{record.?.?. ?? '未知'}
</Tag>
</div>
</div> </div>
</MyTooltip> </MyTooltip>
</div> </div>
@@ -306,10 +349,21 @@ const AfterSaleRecordPage = () => {
{ {
title: '售后产品', title: '售后产品',
dataIndex: '原产品', dataIndex: '原产品',
//width: 260, width: 260, // 设置固定宽度,防止占用其他列空间
key: 'originalProducts', key: 'originalProducts',
render: (products: any[], record: IAfterSalesRecord) => { render: (products: any[], record: IAfterSalesRecord) => {
return <ProductCardList products={products} record={record} />; return (
<div style={{
width: '100%',
maxWidth: '270px',
overflowX: 'auto',
overflowY: 'hidden',
scrollbarWidth: 'thin',
scrollbarColor: '#d9d9d9 transparent',
}}>
<ProductCardList products={products} record={record} />
</div>
);
} }
}, },
@@ -333,6 +387,7 @@ const AfterSaleRecordPage = () => {
{ {
title: '售后信息', title: '售后信息',
key: 'reasonAndType', key: 'reasonAndType',
width: 200,
//筛选售后类型 //筛选售后类型
filters: [ filters: [
{ text: '退货', value: '退货' }, { text: '退货', value: '退货' },
@@ -363,9 +418,21 @@ const AfterSaleRecordPage = () => {
{ {
title: '替换产品', title: '替换产品',
dataIndex: '替换产品', dataIndex: '替换产品',
width: 260, // 设置固定宽度,防止占用其他列空间
key: 'replacementProducts', key: 'replacementProducts',
render: (products: any[], record: IAfterSalesRecord) => { render: (products: any[], record: IAfterSalesRecord) => {
return <ProductCardList products={products} record={record} />; return (
<div style={{
width: '100%',
maxWidth: '270px',
overflowX: 'auto',
overflowY: 'hidden',
scrollbarWidth: 'thin',
scrollbarColor: '#d9d9d9 transparent',
}}>
<ProductCardList products={products} record={record} />
</div>
);
} }
}, },
//财务信息 //财务信息
@@ -759,7 +826,7 @@ const AfterSaleRecordPage = () => {
sticky sticky
scroll={{ scroll={{
y: `calc(100vh - 300px)`, y: `calc(100vh - 300px)`,
//x: 'max-content' x: 'max-content' // 启用水平滚动,确保表格内容不会被挤压
}} }}
//pagination={false} // 禁用分页 //pagination={false} // 禁用分页
pagination={{ pagination={{