import React, { useRef, useState } from 'react'; import { Button, Form, Image, message, Modal, Select, Tag, Typography } from 'antd'; import { DeleteOutlined, PlusOutlined } from '@ant-design/icons'; import XinTable from '@/components/XinTable'; import AuthButton from '@/components/AuthButton'; import type { XinTableColumn, XinTableInstance, XinTableProps } from '@/components/XinTable/typings.ts'; import type IHomeSpecial from '@/domain/iHomeSpecial.ts'; import { HOME_SPECIAL_STATUS_MAP } from '@/domain/iHomeSpecial.ts'; import type IProduct from '@/domain/iProduct.ts'; import { PRODUCT_STATUS_MAP } from '@/domain/iProduct.ts'; import { getProductOptions } from '@/api/product/goods.ts'; import { batchAddSpecials, batchDeleteSpecials } from '@/api/client/special.ts'; const { Title, Text } = Typography; /** * 特价推荐商品配置(小程序首页) * * 仅标记推荐商品,不设特价字段:小程序端按门店客户等级价展示; * 推荐停用或商品下架后不展示,排序越小越靠前。 */ const HomeSpecialPage: React.FC = () => { const tableRef = useRef | null>(null); // ===== 批量删除 ===== const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [batchDeleting, setBatchDeleting] = useState(false); /** 批量删除(成功后清空勾选并刷新列表) */ const handleBatchDelete = () => { window.$modal?.confirm({ title: `确定要删除选中的 ${selectedRowKeys.length} 条推荐吗?`, okText: '删除', okButtonProps: { danger: true }, cancelText: '取消', onOk: async () => { setBatchDeleting(true); try { await batchDeleteSpecials(selectedRowKeys); message.success('批量删除成功'); setSelectedRowKeys([]); await tableRef.current?.reload(); } finally { setBatchDeleting(false); } }, }); }; // ===== 批量添加 ===== const [addOpen, setAddOpen] = useState(false); const [addSaving, setAddSaving] = useState(false); const [addForm] = Form.useForm(); const [productOptions, setProductOptions] = useState([]); /** 打开添加弹窗(首次打开时加载上架商品选项) */ const openAdd = () => { addForm.resetFields(); setAddOpen(true); if (productOptions.length === 0) { getProductOptions().then((res) => setProductOptions(res.data.data ?? [])); } }; /** 提交批量添加(重复推荐后端自动跳过) */ const handleAddSave = async (values: { product_ids: number[] }) => { setAddSaving(true); try { const res = await batchAddSpecials(values.product_ids); const { added = 0, skipped = 0 } = res.data.data ?? {}; message.success(`已添加 ${added} 件推荐商品${skipped > 0 ? `,${skipped} 件已在推荐中自动跳过` : ''}`); setAddOpen(false); await tableRef.current?.reload(); } finally { setAddSaving(false); } }; const columns: XinTableColumn[] = [ { title: 'ID', dataIndex: 'id', hideInForm: true, hideInSearch: true, width: 70, align: 'center', }, { title: '商品图片', dataIndex: 'image', hideInForm: true, hideInSearch: true, align: 'center', width: 100, render: (_, record) => { const url = record.product?.images_arr?.[0]?.preview_url; if (!url) return '-'; return ( ); }, }, { title: '商品名称', dataIndex: 'keyword', hideInForm: true, valueType: 'text', fieldProps: { placeholder: '按商品名称搜索' }, render: (_, record) => { const product = record.product; if (!product) return '-'; return `${product.name}${product.spec ? `(${product.spec})` : ''}`; }, }, { title: '市场', dataIndex: 'market', hideInForm: true, hideInSearch: true, align: 'center', render: (_, record) => record.product?.market || '-', }, { title: '计价单位', dataIndex: 'unit', hideInForm: true, hideInSearch: true, align: 'center', width: 90, render: (_, record) => record.product?.unit || '-', }, { title: '商品状态', dataIndex: 'product_status', hideInForm: true, hideInSearch: true, align: 'center', width: 100, render: (_, record) => { const item = PRODUCT_STATUS_MAP[record.product?.status ?? 1]; return {item?.text}; }, }, { title: '排序', dataIndex: 'sort', valueType: 'digit', hideInSearch: true, initialValue: 0, fieldProps: { min: 0, precision: 0 }, align: 'center', width: 80, }, { title: '状态', dataIndex: 'status', valueType: 'radioButton', initialValue: 1, fieldProps: { options: [ { value: 1, label: '正常' }, { value: 0, label: '停用' }, ], }, render: (_, record) => { const item = HOME_SPECIAL_STATUS_MAP[record.status ?? 1]; return {item?.text}; }, align: 'center', width: 90, }, { title: '创建时间', dataIndex: 'created_at', hideInForm: true, hideInSearch: true, align: 'center', }, ]; const tableProps: XinTableProps = { api: '/client/special', columns, rowKey: 'id', accessName: 'client.special', tableRef, addShow: false, rowSelection: { selectedRowKeys, onChange: (keys) => setSelectedRowKeys(keys.map(Number)), }, actionBarRender: (dom) => [ dom.search, , , ], formProps: { grid: true, colProps: { span: 12 }, layout: 'vertical', }, modalProps: { width: 640 }, }; return ( <>
特价推荐 小程序首页「特价推荐」区展示的商品;价格按门店客户等级价展示,推荐停用或商品下架后不展示,排序越小越靠前。
{...tableProps} /> setAddOpen(false)} onOk={() => addForm.submit()} confirmLoading={addSaving} okText="添加" destroyOnHidden >