封装选择供应商组件; 丰富选择品类库 说明文档

This commit is contained in:
linxd
2025-06-24 14:49:45 +08:00
parent 6f4efad67b
commit 9a45e65db1
13 changed files with 1153 additions and 559 deletions

View File

@ -190,8 +190,8 @@ const SupplierEvaluateResult: React.FC = () => {
},
{
title: '评价品类',
dataIndex: 'category',
key: 'category',
dataIndex: 'categoryName',
key: 'categoryName',
width: 120,
ellipsis: {
showTitle: false,

View File

@ -212,8 +212,8 @@ const SupplierEvaluateResultInfo: React.FC = () => {
},
{
title: '品类',
dataIndex: 'category',
key: 'category',
dataIndex: 'categoryName',
key: 'categoryName',
width: 120,
},
{

View File

@ -22,7 +22,6 @@ interface TemplateItem {
const BasicInfoStep = forwardRef<any, BasicInfoStepProps>(({ formData, onFormDataChange }, ref) => {
const [form] = Form.useForm();
const [templates, setTemplates] = useState<TemplateItem[]>([]);
const [selectedCategoryId, setSelectedCategoryId] = useState<string | undefined>(undefined);
const [loading, setLoading] = useState<boolean>(false);
// 暴露表单方法给父组件
@ -64,11 +63,6 @@ const BasicInfoStep = forwardRef<any, BasicInfoStepProps>(({ formData, onFormDat
// 初始化表单数据
if (formData) {
form.setFieldsValue(formData);
// 设置已选品类
if (formData.categoryId) {
setSelectedCategoryId(formData.categoryId);
}
}
}, []);
@ -78,6 +72,7 @@ const BasicInfoStep = forwardRef<any, BasicInfoStepProps>(({ formData, onFormDat
if (changedValues.templateId) {
const template = templates.find((t) => t.id === changedValues.templateId);
if (template) {
// 更新品类限制类型
form.setFieldsValue({
categoryLimitation: template.categoryLimitation || '0',
});
@ -87,16 +82,10 @@ const BasicInfoStep = forwardRef<any, BasicInfoStepProps>(({ formData, onFormDat
form.setFieldsValue({
categoryId: undefined,
});
setSelectedCategoryId(undefined);
}
}
}
// 处理品类变更
if (changedValues.categoryId) {
setSelectedCategoryId(changedValues.categoryId?.[0]);
}
// 默认设置weightStatus为0
const formattedValues = {
...allValues,
@ -122,11 +111,6 @@ const BasicInfoStep = forwardRef<any, BasicInfoStepProps>(({ formData, onFormDat
return categoryLimitation === CategoryLimitationType.LIMITED;
}, [form]);
// 处理品类选择变化
const handleCategoryChange = useCallback((value: string | string[]) => {
const categoryId = Array.isArray(value) ? value[0] : value;
setSelectedCategoryId(categoryId);
}, []);
return (
<div className={styles.basicInfoStep}>
@ -212,7 +196,7 @@ const BasicInfoStep = forwardRef<any, BasicInfoStepProps>(({ formData, onFormDat
name="categoryId"
rules={[{ required: true, message: '请选择品类' }]}
>
<CategorySelector onChange={handleCategoryChange} />
<CategorySelector multiple={false} />
</Form.Item>
</Col>
)}

View File

@ -1,9 +1,7 @@
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import { Card, Row, Col, Input, Select, Radio, Table, Button, Space, Pagination, Form } from 'antd';
import { SearchOutlined, ArrowRightOutlined } from '@ant-design/icons';
import React, { forwardRef, useImperativeHandle } from 'react';
import { Card, Form } from 'antd';
import styles from '../supplierTaskManageAdd.less';
const { Option } = Select;
import SupplierSelector from '@/components/SupplierSelector';
interface SupplierSelectStepProps {
formData: any;
@ -11,28 +9,13 @@ interface SupplierSelectStepProps {
}
interface SupplierItem {
key: string;
supplierName: string;
socialCreditCode: string;
category: string;
id: string;
name: string;
supplierType: string;
[key: string]: any;
}
const SupplierSelectStep = forwardRef<any, SupplierSelectStepProps>(({ formData, onFormDataChange }, ref) => {
const [filterForm] = Form.useForm();
const [categoryKeyword, setCategoryKeyword] = useState<string>('');
const [selectedCategory, setSelectedCategory] = useState<string | undefined>(undefined);
const [hasPaymentLastYear, setHasPaymentLastYear] = useState<string>('是');
const [department, setDepartment] = useState<string | undefined>(undefined);
const [pendingSuppliers, setPendingSuppliers] = useState<SupplierItem[]>([]);
const [selectedSuppliers, setSelectedSuppliers] = useState<SupplierItem[]>([]);
const [pendingKeyword, setPendingKeyword] = useState<string>('');
const [selectedKeyword, setSelectedKeyword] = useState<string>('');
const [pendingSelectedRowKeys, setPendingSelectedRowKeys] = useState<React.Key[]>([]);
const [selectedSelectedRowKeys, setSelectedSelectedRowKeys] = useState<React.Key[]>([]);
// 暴露表单方法给父组件
useImperativeHandle(ref, () => ({
validateFields: () => {
@ -41,372 +24,37 @@ const SupplierSelectStep = forwardRef<any, SupplierSelectStepProps>(({ formData,
},
getFieldsValue: () => {
return {
selectedSuppliers,
supplierIds: selectedSuppliers.map(supplier => ({ id: supplier.key }))
selectedSuppliers: formData.selectedSuppliers || [],
supplierIds: (formData.selectedSuppliers || []).map((supplier: SupplierItem) => ({ id: supplier.id }))
};
},
setFieldsValue: (values: any) => {
if (values.selectedSuppliers) {
setSelectedSuppliers(values.selectedSuppliers);
onFormDataChange({
...formData,
selectedSuppliers: values.selectedSuppliers
});
}
},
}));
// 初始化数据
useEffect(() => {
// 从formData中恢复已选供应商
if (formData.selectedSuppliers) {
setSelectedSuppliers(formData.selectedSuppliers);
}
// 初始化筛选表单
filterForm.setFieldsValue({
category: selectedCategory,
categoryKeyword: categoryKeyword,
categoryRange: undefined,
hasPaymentLastYear: hasPaymentLastYear,
department: department
});
// 模拟获取待选供应商列表
const mockPendingSuppliers: SupplierItem[] = [
{ key: '1', supplierName: '供应商A', socialCreditCode: '2425322525', category: '润滑油' },
{ key: '2', supplierName: '供应商B', socialCreditCode: '2425322525', category: '燃油' },
{ key: '3', supplierName: '供应商C', socialCreditCode: '2425322525', category: '备件' },
{ key: '4', supplierName: '供应商D', socialCreditCode: '2425322525', category: '润滑油' },
{ key: '5', supplierName: '供应商E', socialCreditCode: '2425322525', category: '燃油' },
{ key: '6', supplierName: '供应商F', socialCreditCode: '2425322525', category: '备件' },
{ key: '7', supplierName: '供应商G', socialCreditCode: '2425322525', category: '润滑油' },
{ key: '8', supplierName: '供应商H', socialCreditCode: '2425322525', category: '燃油' },
{ key: '9', supplierName: '供应商I', socialCreditCode: '2425322525', category: '备件' },
{ key: '10', supplierName: '供应商J', socialCreditCode: '2425322525', category: '计算机' },
];
// 模拟已选供应商列表
const mockSelectedSuppliers: SupplierItem[] = [
{ key: '11', supplierName: '供应商A', socialCreditCode: '4636373737', category: '润滑油' },
{ key: '12', supplierName: '供应商B', socialCreditCode: '4636373737', category: '燃油' },
{ key: '13', supplierName: '供应商C', socialCreditCode: '4636373737', category: '备件' },
{ key: '14', supplierName: '供应商D', socialCreditCode: '4636373737', category: '润滑油' },
{ key: '15', supplierName: '供应商E', socialCreditCode: '4636373737', category: '燃油' },
{ key: '16', supplierName: '供应商F', socialCreditCode: '4636373737', category: '备件' },
{ key: '17', supplierName: '供应商G', socialCreditCode: '4636373737', category: '润滑油' },
{ key: '18', supplierName: '供应商H', socialCreditCode: '4636373737', category: '燃油' },
{ key: '19', supplierName: '供应商I', socialCreditCode: '4636373737', category: '备件' },
{ key: '20', supplierName: '供应商J', socialCreditCode: '4636373737', category: '计算机' },
];
setPendingSuppliers(mockPendingSuppliers);
// 如果没有从formData中恢复则使用模拟数据
if (!formData.selectedSuppliers) {
setSelectedSuppliers(mockSelectedSuppliers);
}
}, [formData]);
// 更新表单数据
const updateFormData = (suppliers: SupplierItem[]) => {
// 处理供应商选择
const handleSupplierSelect = (suppliers: SupplierItem[]) => {
onFormDataChange({
...formData,
selectedSuppliers: suppliers,
supplierIds: suppliers.map(supplier => ({ id: supplier.key }))
supplierIds: suppliers.map(supplier => ({ id: supplier.id }))
});
};
// 处理筛选条件变化
const handleFilterChange = (changedValues: any, allValues: any) => {
if ('category' in changedValues) {
setSelectedCategory(changedValues.category);
}
if ('categoryKeyword' in changedValues) {
setCategoryKeyword(changedValues.categoryKeyword);
}
if ('hasPaymentLastYear' in changedValues) {
setHasPaymentLastYear(changedValues.hasPaymentLastYear);
}
if ('department' in changedValues) {
setDepartment(changedValues.department);
}
// 这里可以添加筛选逻辑,根据筛选条件更新待选供应商列表
};
// 处理添加供应商
const handleAddSuppliers = () => {
if (pendingSelectedRowKeys.length === 0) return;
// 找出选中的供应商
const suppliersToAdd = pendingSuppliers.filter(item =>
pendingSelectedRowKeys.includes(item.key)
);
// 更新已选供应商列表
const newSelectedSuppliers = [...selectedSuppliers, ...suppliersToAdd];
setSelectedSuppliers(newSelectedSuppliers);
// 从待选列表中移除
const newPendingSuppliers = pendingSuppliers.filter(item =>
!pendingSelectedRowKeys.includes(item.key)
);
setPendingSuppliers(newPendingSuppliers);
// 清空选中状态
setPendingSelectedRowKeys([]);
// 更新表单数据
updateFormData(newSelectedSuppliers);
};
// 处理移除供应商
const handleRemoveSuppliers = () => {
if (selectedSelectedRowKeys.length === 0) return;
// 找出选中的供应商
const suppliersToRemove = selectedSuppliers.filter(item =>
selectedSelectedRowKeys.includes(item.key)
);
// 更新待选供应商列表
const newPendingSuppliers = [...pendingSuppliers, ...suppliersToRemove];
setPendingSuppliers(newPendingSuppliers);
// 从已选列表中移除
const newSelectedSuppliers = selectedSuppliers.filter(item =>
!selectedSelectedRowKeys.includes(item.key)
);
setSelectedSuppliers(newSelectedSuppliers);
// 清空选中状态
setSelectedSelectedRowKeys([]);
// 更新表单数据
updateFormData(newSelectedSuppliers);
};
// 过滤待选供应商
const filteredPendingSuppliers = pendingSuppliers.filter(item => {
// 按关键词过滤
const matchKeyword = pendingKeyword ?
(item.supplierName.includes(pendingKeyword) ||
item.socialCreditCode.includes(pendingKeyword)) : true;
return matchKeyword;
});
// 过滤已选供应商
const filteredSelectedSuppliers = selectedSuppliers.filter(item => {
// 按关键词过滤
const matchKeyword = selectedKeyword ?
(item.supplierName.includes(selectedKeyword) ||
item.socialCreditCode.includes(selectedKeyword)) : true;
return matchKeyword;
});
// 表格列定义
const columns = [
{
title: '供应商名称',
dataIndex: 'supplierName',
key: 'supplierName',
},
{
title: '统一社会信用代码',
dataIndex: 'socialCreditCode',
key: 'socialCreditCode',
},
{
title: '准入品类',
dataIndex: 'category',
key: 'category',
}
];
// 待选表格行选择配置
const pendingRowSelection = {
selectedRowKeys: pendingSelectedRowKeys,
onChange: (selectedRowKeys: React.Key[]) => {
setPendingSelectedRowKeys(selectedRowKeys);
}
};
// 已选表格行选择配置
const selectedRowSelection = {
selectedRowKeys: selectedSelectedRowKeys,
onChange: (selectedRowKeys: React.Key[]) => {
setSelectedSelectedRowKeys(selectedRowKeys);
}
};
// 部门选项
const departmentOptions = [
{ value: '1', label: '采购部' },
{ value: '2', label: '技术部' },
{ value: '3', label: '质量部' },
{ value: '4', label: '生产部' },
];
// 类别选项
const categoryOptions = [
{ value: '润滑油', label: '润滑油' },
{ value: '燃油', label: '燃油' },
{ value: '备件', label: '备件' },
{ value: '计算机', label: '计算机' },
];
return (
<div className={styles.supplierSelectStep}>
<Card title="筛选条件" bordered={false} className="inner-card">
<Form
form={filterForm}
layout="horizontal"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
onValuesChange={handleFilterChange}
>
<Row gutter={24}>
<Col span={8}>
<Form.Item label="选择类别" name="category">
<Select
placeholder="请选择"
allowClear
>
{categoryOptions.map(option => (
<Option key={option.value} value={option.value}>{option.label}</Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item label="品类关键字" name="categoryKeyword">
<Input placeholder="请输入" allowClear />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item label="品类范围" name="categoryRange">
<Input placeholder="请输入" allowClear />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item label="近一年有付款" name="hasPaymentLastYear" initialValue="是">
<Radio.Group>
<Radio value="是"></Radio>
<Radio value="否"></Radio>
</Radio.Group>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item label="准入部门" name="department">
<Select
placeholder="请选择"
allowClear
>
{departmentOptions.map(option => (
<Option key={option.value} value={option.value}>{option.label}</Option>
))}
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item wrapperCol={{ offset: 6, span: 18 }}>
<Button type="primary" onClick={() => filterForm.submit()}>
</Button>
<Button style={{ marginLeft: 8 }} onClick={() => filterForm.resetFields()}>
</Button>
</Form.Item>
</Col>
</Row>
</Form>
<Card title="供应商选择" bordered={false} className="inner-card">
<SupplierSelector
onSelect={handleSupplierSelect}
selectedSuppliers={formData.selectedSuppliers || []}
/>
</Card>
<Row gutter={24} style={{ marginTop: '16px' }}>
<Col span={11}>
<Card
title="待选列表"
bordered={false}
className="inner-card"
extra={<span>2/50</span>}
>
<div className="search-bar">
<Input
placeholder="输入关键词"
prefix={<SearchOutlined />}
value={pendingKeyword}
onChange={e => setPendingKeyword(e.target.value)}
allowClear
/>
</div>
<Table
rowSelection={pendingRowSelection}
columns={columns}
dataSource={filteredPendingSuppliers}
pagination={false}
size="middle"
rowKey="key"
/>
<div className="pagination-container">
<Pagination
size="small"
total={50}
current={1}
pageSize={10}
showSizeChanger={false}
/>
</div>
</Card>
</Col>
<Col span={2} style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<Space direction="vertical">
<Button
type="primary"
icon={<ArrowRightOutlined />}
onClick={handleAddSuppliers}
disabled={pendingSelectedRowKeys.length === 0}
/>
<Button
icon={<ArrowRightOutlined style={{ transform: 'rotate(180deg)' }} />}
onClick={handleRemoveSuppliers}
disabled={selectedSelectedRowKeys.length === 0}
/>
</Space>
</Col>
<Col span={11}>
<Card
title="已选列表"
bordered={false}
className="inner-card"
extra={<span>2/50</span>}
>
<div className="search-bar">
<Input
placeholder="输入关键词"
prefix={<SearchOutlined />}
value={selectedKeyword}
onChange={e => setSelectedKeyword(e.target.value)}
allowClear
/>
</div>
<Table
rowSelection={selectedRowSelection}
columns={columns}
dataSource={filteredSelectedSuppliers}
pagination={false}
size="middle"
rowKey="key"
/>
<div className="pagination-container">
<Pagination
size="small"
total={50}
current={1}
pageSize={10}
showSizeChanger={false}
/>
</div>
</Card>
</Col>
</Row>
</div>
);
});

View File

@ -11,7 +11,7 @@ import styles from './supplierTaskManageAdd.less';
const { Step } = Steps;
const SupplierTaskManageAdd: React.FC = () => {
const [currentStep, setCurrentStep] = useState<number>(0);
const [currentStep, setCurrentStep] = useState<number>(1);
const [loading, setLoading] = useState<boolean>(false);
const [formData, setFormData] = useState<Partial<SupplierEvaluate.TaskAddRequest>>({});