From 4d54b36a162e52a9454c06640cde9daa39a82180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=99=AF=E5=AD=A6?= <5412262+sun_jing_xue@user.noreply.gitee.com> Date: Fri, 27 Jun 2025 10:41:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BE=9B=E5=BA=94=E5=95=86=E9=80=80=E5=87=BA?= =?UTF-8?q?=E3=80=81=E5=87=86=E5=85=A5=E3=80=81=20=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CompanyInfo/_mock.ts | 343 --------------- .../CompanyInfo/component/BankFormModal.tsx | 193 +++++++++ .../CompanyInfo/component/BankInfoTab.tsx | 186 ++++++--- .../CompanyInfo/component/BaseInfoTab.tsx | 54 +-- .../component/InvoiceFormModal.tsx | 227 ++++++++++ .../CompanyInfo/component/InvoiceTab.tsx | 96 +++-- .../component/QualificationFormModal.tsx | 223 ++++++++++ .../component/QualificationTab.tsx | 96 +++-- src/components/CompanyInfo/index.tsx | 2 - src/components/CompanyInfo/services.ts | 191 +++++++-- .../components/CreateModal.tsx | 211 ++++++++++ .../components/SupplierSelector.tsx | 154 +++++++ .../components/ViewModal.tsx | 72 ++++ .../admission/SupplierCategoryEntry/index.tsx | 293 ++++++------- .../SupplierCategoryEntry/services.ts | 68 ++- .../components/ViewModal.tsx | 72 ++++ .../SupplierCategoryEntryReview/index.tsx | 391 ++++++------------ .../SupplierCategoryEntryReview/services.ts | 61 ++- .../components/ViewModal.tsx | 88 ++++ .../admission/SupplierEntryReview/index.tsx | 132 +++--- .../admission/SupplierEntryReview/services.ts | 6 +- .../components/CreateModal.tsx | 22 +- .../components/ResultModal.tsx | 390 ++++++++--------- .../admission/admissionManagement/index.tsx | 33 +- .../admission/admissionManagement/services.ts | 8 +- .../components/GroupLeaderModal.tsx | 46 ++- .../components/ResultModal.tsx | 125 ++++-- .../components/ViewModal.tsx | 86 ++++ .../admissionReviewManagement/index.tsx | 43 +- .../admissionReviewManagement/services.ts | 5 +- .../components/CreateBlacklistModal.tsx | 180 ++++++++ .../components/SupplierSelectModal.tsx | 226 ++++++++++ .../components/ViewBlacklistModal.tsx | 113 +++++ .../supplierExit/supplierExitAudit/index.tsx | 226 +++++----- .../supplierExitAudit/services.ts | 64 +++ .../components/CreateBlacklistModal.tsx | 167 +++++--- .../components/SupplierSelectModal.tsx | 219 +++++----- .../components/ViewBlacklistModal.tsx | 113 +++++ .../supplierExit/supplierExitManage/index.tsx | 88 ++-- .../supplierExitManage/services.ts | 64 +++ 40 files changed, 3746 insertions(+), 1631 deletions(-) delete mode 100644 src/components/CompanyInfo/_mock.ts create mode 100644 src/components/CompanyInfo/component/BankFormModal.tsx create mode 100644 src/components/CompanyInfo/component/InvoiceFormModal.tsx create mode 100644 src/components/CompanyInfo/component/QualificationFormModal.tsx create mode 100644 src/pages/supplier/admission/SupplierCategoryEntry/components/CreateModal.tsx create mode 100644 src/pages/supplier/admission/SupplierCategoryEntry/components/SupplierSelector.tsx create mode 100644 src/pages/supplier/admission/SupplierCategoryEntry/components/ViewModal.tsx create mode 100644 src/pages/supplier/admission/SupplierCategoryEntryReview/components/ViewModal.tsx create mode 100644 src/pages/supplier/admission/SupplierEntryReview/components/ViewModal.tsx create mode 100644 src/pages/supplier/admission/admissionReviewManagement/components/ViewModal.tsx create mode 100644 src/pages/supplier/supplierExit/supplierExitAudit/components/CreateBlacklistModal.tsx create mode 100644 src/pages/supplier/supplierExit/supplierExitAudit/components/SupplierSelectModal.tsx create mode 100644 src/pages/supplier/supplierExit/supplierExitAudit/components/ViewBlacklistModal.tsx create mode 100644 src/pages/supplier/supplierExit/supplierExitAudit/services.ts create mode 100644 src/pages/supplier/supplierExit/supplierExitManage/components/ViewBlacklistModal.tsx create mode 100644 src/pages/supplier/supplierExit/supplierExitManage/services.ts diff --git a/src/components/CompanyInfo/_mock.ts b/src/components/CompanyInfo/_mock.ts deleted file mode 100644 index a91db54..0000000 --- a/src/components/CompanyInfo/_mock.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { Request, Response } from 'express'; - -// const data = [ -// { -// title: 'Name', -// dataIndex: '评审项', -// key: '评审项', -// }, -// { -// title: 'Other', -// children: [ -// { -// title: 'Age', -// key: '人员A', -// }, -// { -// title: 'Address', -// key: '人员B', -// }, -// ] -// }, -// ] -const dataInvoiceInfo = [ - { - id: '1', - taxpayerType: '一般纳税人', - taxpayerCode: '91345678901234567X', - head: '北京某科技有限公司', - address: '北京市朝阳区XX路99号', - phone: '010-12345678', - bank: '中国银行北京分行', - account: '6228888888888888', - updateTime: '2025-06-17 10:20:00', - voided: false, - qualificationCertificate: 'https://example.com/cert1.pdf', - }, - { - id: '2', - taxpayerType: '小规模纳税人', - taxpayerCode: '91345678901234566Y', - head: '上海某信息技术有限公司', - address: '上海市浦东新区XX大厦8楼', - phone: '021-87654321', - bank: '工商银行上海分行', - account: '6229999999999999', - updateTime: '2025-06-16 15:30:00', - voided: true, - qualificationCertificate: '', - }, -] -const mockQualificationData = [ - { - id: '1', - certificateType: '建筑业企业资质证书', - name: '建筑工程施工总承包一级', - code: 'ZJ-A123456', - typeLevel: '一级', - authority: '住房和城乡建设部', - dateTime: '2023-03-01', - termOfValidity: '2028-03-01', - updateTime: '2025-06-17 10:30:00', - }, - { - id: '2', - certificateType: '安全生产许可证', - name: '施工企业安全生产许可证', - code: 'AQ-789012', - typeLevel: 'A级', - authority: '应急管理部', - dateTime: '2022-06-15', - termOfValidity: '2025-06-15', - updateTime: '2025-06-17 11:45:00', - }, -] -export const mockData = { - base: { - "id": "123456", - "supplierType": "dvs", - "licenceAccessory": "https://example.com/license.pdf", - "licenceDate": "2025-12-31", - "enterpriseType": "company", - "name": "深圳供应商有限公司", - "nameEn": "Shenzhen Supplier Co., Ltd.", - "socialCreditCode": "91440300MA5F3XXXXQ", - "range": "电子元器件、金属材料销售", - "regAddress": "广东省深圳市南山区科技园", - "workAddress": "广东省深圳市南山区软件产业基地", - "parentCompanyInvestor": "深圳控股集团有限公司", - "legalPerson": "李四", - "idCard": "440301199001015678", - "capital": 5000, - "contactsName": "王五", - "contactsPhone": "13800138000", - "contactsType": "法人代表", - "contactsEmail": "contact@supplier.com", - "telephone": "0755-12345678", - "nation": "新加坡", - "vat": "SG12345678VAT", - "taxpayerId": "SG-TAX-998877", - "currency": "SGD", - "personName": "张三", - "personPhone": "13812345678", - "personBank": "中国银行深圳分行", - "personAccount": "6222020200123456789", - "remark": "该供应商已完成初步审核", - "accessStatus": 1, - "blacklistStatus": 0, - "greylistStatus": 1, - "fillinStatus": 0, - "fillinBy": "", - "sapCode": "SAP998877", - "delFlag": "normal", - "createBy": "admin", - "createTime": "2024-06-01 10:00:00", - "updateBy": "admin", - "updateTime": "2025-06-01 11:00:00", - "lastUpdateTime": "2025-06-17 09:30:00" - }, - qualifications: [{ - "id": "cert-001", - "supplierId": "supplier-123456", - "certificateType": "安全生产许可证", - "name": "建筑施工总承包一级资质", - "code": "ZJ20230605001", - "typeLevel": "一级", - "authority": "住房和城乡建设部", - "dateTime": "2023-06-05", - "termOfValidity": "2026-06-05", - "accessory": "https://example.com/certificate.pdf", - "delFlag": "normal", - "createBy": "admin", - "createTime": "2023-06-01 10:00:00", - "updateBy": "admin", - "updateTime": "2024-06-01 11:00:00", - "lastUpdateTime": "2025-06-17 09:30:00" - }], - invoice: { - "id": "invoice-001", - "supplierId": "supplier-123456", - "taxpayerType": "general", - "taxpayerCode": "91440300MA5F3XXXXQ", - "phone": "0755-12345678", - "account": "6222020200123456789", - "head": "深圳供应商有限公司", - "address": "深圳市南山区科技园开票楼101号", - "bank": "中国银行深圳分行", - "qualificationCertificate": "https://example.com/tax-cert.pdf", - "delFlag": "normal", - "createBy": "admin", - "createTime": "2024-06-01 09:00:00", - "updateBy": "admin", - "updateTime": "2025-06-01 10:00:00", - "lastUpdateTime": "2025-06-17 08:30:00" - }, - bank: [{ - "id": "bank-001", - "supplierId": "supplier-123456", - "interbankNumber": "123456789012", - "bank": "中国银行深圳分行", - "swiftCode": "BKCHCNBJ45A", - "accountName": "Shenzhen Supplier Co., Ltd.", - "account": "6222020200123456789", - "currency": "CNY", - "nation": "中国", - "province": "广东省", - "city": "深圳市", - "delFlag": "normal", - "createBy": "admin", - "createTime": "2024-06-01 09:00:00", - "updateBy": "admin", - "updateTime": "2025-06-01 10:00:00", - "lastUpdateTime": "2025-06-17 08:30:00" - }], - survey: { - "supplierName": "深圳供应商有限公司", - "name": "李四", - "position": "采购经理", - "phone": "13800138000", - "email": "lisi@supplier.com", - "dateTime": "2025-06-17", - }, - questionReply: [ - { - "surveyQuestion": "法律法规:\n我们确保经营和提供的产品服务遵守国家及 各业务所在地的所有使用法律、法规", - "replyValue": "是", - },{ - "surveyQuestion": "健康和安全:\n我们为员工提供符合法律法规的安全且健康 的工作场所。我们建立安全管理体系,并向 员工传达工作场所或生活设施的健康和安全 标准,致力于减少工作对员工造成的伤害和 疾病。", - "replyValue": "符合", - },{ - "surveyQuestion": "环境:\n我们能够以环境友好的方式经营。我们遵守 适用的环境法律、法规和标准;并建立有效 的环境管理体系。\n我们遵守贵集团对相关产品或服务的部分附 加环境要求,这些要求和规定体现在设计与 产品规范的合同文档中。", - "replyValue": "符合", - },{ - "surveyQuestion": "监督和记录:\n我们保留记录遵守相关法律和此行为准则的必要文件,并根据要求为贵集团提供对文件的查看权。我们会允许贵集团在适当的时候,以验证行为准则执行为目的的现场勘查", - "replyValue": "符合", - } - ], - attachments: { - "attachmentsType": "commitment", - "fileName": "anti-bribery-commitment.pdf", - "fileType": "pdf", - "fileSize": "204800", - "filePath": "/data/files/anti-bribery-commitment.pdf", - "fileUrl": "http://example.com/files/anti-bribery-commitment.pdf", - } -}; -// 代码中会兼容本地 service mock 以及部署站点的静态数据 -export default { - // 供应商信息 - 'GET /api/system/coscoSupplier': (req: Request, res: Response) => { - res.json({ - code: 200, - data: mockData, - msg: '操作成功' - }); - }, - // - 'GET /api/system/qualifications': (req: Request, res: Response) => { - res.json({ code: 200, - data: mockQualificationData, - total: 2, - msg: '操作成功' - }); - }, - // - 'GET /api/system/invoice': (req: Request, res: Response) => { - res.json({ code: 200, - data: dataInvoiceInfo, - total: 2, - msg: '操作成功' - }); - }, - // - 'GET /api/system/bank': (req: Request, res: Response) => { - res.json({ code: 200, - data: [ - { - id: '1', - interbankNumber: '123456789', - bank: '中国银行', - accountName: '张三', - account: '6228480000000000000', - currency: '人民币', - nation: '中国', - province: '广东省', - city: '广州市', - updateTime: '2024-06-18', - }, - { - id: '2', - interbankNumber: '987654321', - bank: '工商银行', - accountName: '李四', - account: '6228480000000000001', - currency: '美元', - nation: '中国', - province: '江苏省', - city: '南京市', - updateTime: '2024-06-17', - }, - ], - total: 2, - msg: '操作成功' - }); - }, - // - 'GET /api/system/tianyancha': (req: Request, res: Response) => { - res.json({ code: 200, - data: [ - { - key: '1', - base: '京', - name: '北京科技有限公司', - legalPersonName: '张三', - legalPersonType: '1', - regNumber: '110108123456789', - industry: '信息技术', - companyOrgType: '有限责任公司', - regLocation: '北京市海淀区中关村', - estiblishTime: '2010-06-15', - fromTime: '2010-06-16', - toTime: '2025-06-15', - businessScope: '软件开发、技术咨询', - approvedTime: '2010-06-10', - regStatus: '存续', - regCapital: '5000万元', - regInstitute: '北京市工商局', - orgNumber: '1234567890', - creditCode: '91110108MA01A12345', - property3: 'Beijing Tech Co., Ltd.', - updatetime: '2025-06-15', - companyId: '1001', - taxNumber: '110108123456789', - email: 'contact@bjtech.com', - website: 'http://www.bjtech.com', - phoneNumber: '010-12345678', - lastUpdateTime: '2025-06-15 10:00:00', - }, - { - key: '2', - base: '沪', - name: '上海电子商务有限公司', - legalPersonName: '李四', - legalPersonType: '1', - regNumber: '310101987654321', - industry: '电子商务', - companyOrgType: '股份有限公司', - regLocation: '上海市浦东新区', - estiblishTime: '2015-03-20', - fromTime: '2015-03-21', - toTime: '2030-03-20', - businessScope: '电子商务平台运营、广告设计', - approvedTime: '2015-03-15', - regStatus: '存续', - regCapital: '1亿元', - regInstitute: '上海市工商局', - orgNumber: '0987654321', - creditCode: '91310101MA1AB23456', - property3: 'Shanghai E-commerce Co., Ltd.', - updatetime: '2025-06-15', - companyId: '1002', - taxNumber: '310101987654321', - email: 'info@shcommerce.com', - website: 'http://www.shcommerce.com', - phoneNumber: '021-87654321', - lastUpdateTime: '2025-06-15 09:30:00', - }, - ], - total: 2, - msg: '操作成功' }); - }, - - 'GET /api/500': (req: Request, res: Response) => { - res.status(500).send({ - timestamp: 1513932555104, - status: 500, - error: 'error', - message: 'error', - path: '/base/category/list', - }); - }, - - -}; diff --git a/src/components/CompanyInfo/component/BankFormModal.tsx b/src/components/CompanyInfo/component/BankFormModal.tsx new file mode 100644 index 0000000..bb1630b --- /dev/null +++ b/src/components/CompanyInfo/component/BankFormModal.tsx @@ -0,0 +1,193 @@ +import React, { useEffect, useState } from 'react'; +import { Modal, Form, Input, Button, Upload, message, Row, Col, Descriptions } from 'antd'; +import type { UploadProps } from 'antd'; +import { UploadOutlined } from '@ant-design/icons'; +import { uploadFile, bankView, bankAdd, bankEdit } from '../services'; +interface props { + visible: boolean; + onOk: () => void; + onCancel: () => void; + initialValues?: any; + readOnly?: boolean; +} +interface viewDataData { + id?: string | null; + account?: string; + accountName?: string; + bank?: string; + city?: string; + currency?: string; + interbankNumber?: string; + nation?: string; + province?: string; + supplierId?: string; + swiftCode?: null; + attachment?: { + uid: string; + name: string; + url: string; + status: string; + }[]; +} +const InvoiceFormModal: React.FC = ({ + visible, + onOk, + onCancel, + initialValues, + readOnly = false, +}) => { + // 新增与修改 + const [form] = Form.useForm(); + //查看 + const [viewData, setViewData] = useState({}); + useEffect(() => { + if (visible) { + if (initialValues) { + bankView(initialValues.id).then((res) => { + const { code, data } = res; + if (code === 200) { + const fields = { + ...data, + id: data.id ? data.id : null, + }; + form.setFieldsValue(fields); + setViewData(fields); + } + }); + } else { + form.resetFields(); // ✅ 只有无 initialValues 才重置 + } + } + }, [visible, initialValues]); + + // 提交 + const handleFinish = async () => { + try { + const values = await form.validateFields(); + const payload = { + ...values, + "supplierId": "9c12e8ea-a681-4184-81ba-5fa276299a00", + }; + + if (!values.id) { + bankAdd(payload).then((res) => { + if (res.code == 200) { + message.success('新增成功'); + onOk(); + } + }) + } else { + bankEdit(payload).then((res) => { + if (res.code == 200) { + message.success('修改成功'); + onOk(); + } + }) + } + + } catch (error) { + console.error('表单校验失败:', error); + } + }; + + //上传接口 + const uploadProps: UploadProps = { + name: 'file', + showUploadList: true, + customRequest: async ({ file, onSuccess, onError }) => { + try { + const realFile = file as File; + const res = await uploadFile(realFile); + const uploadedFile = { + uid: res.fileSize, + name: res.fileName, + status: 'done', + url: res.url, + response: res, + }; + onSuccess?.(uploadedFile, new XMLHttpRequest()) + message.success('上传成功'); + } catch (err: any) { + onError?.(err); + message.error(err.message || '上传失败'); + } + } + }; + + return ( + + {readOnly ? ( + + {viewData.account} + {viewData.accountName} + {viewData.bank} + {viewData.interbankNumber} + {viewData.province} + {viewData.city} + {viewData.nation} + {viewData.currency} + + ) : ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ )} +
+ ); +}; + +export default InvoiceFormModal; diff --git a/src/components/CompanyInfo/component/BankInfoTab.tsx b/src/components/CompanyInfo/component/BankInfoTab.tsx index e9f7410..165938e 100644 --- a/src/components/CompanyInfo/component/BankInfoTab.tsx +++ b/src/components/CompanyInfo/component/BankInfoTab.tsx @@ -1,77 +1,24 @@ import React, { useEffect, useState } from 'react'; -import { Table } from 'antd'; +import { Table, Button } from 'antd'; import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'; -import { bank } from '../services'; +import { bankGetPage } from '../services'; import { useIntl } from 'umi'; +import BankFormModal from './BankFormModal'; interface BankInfo { id: string; - interbankNumber: string; - bank: string; - accountName: string; account: string; + accountName: string; + bank: string; + city: string; currency: string; + interbankNumber: string; nation: string; province: string; - city: string; - updateTime: string; + supplierId: string; + swiftCode: null; } -// 表格头部 -const columns: ColumnsType = [ - { - title: 'page.workbench.bank.index', - dataIndex: 'index', - key: 'index', - width: 80, - align: 'center', - render: (_: any, __: any, index: number) => index + 1 - }, - { - title: 'page.workbench.bank.interbankNumber', - dataIndex: 'interbankNumber', - key: 'interbankNumber', - }, - { - title: 'page.workbench.bank.bank', - dataIndex: 'bank', - key: 'bank', - }, - { - title: 'page.workbench.bank.accountName', - dataIndex: 'accountName', - key: 'accountName', - }, - { - title: 'page.workbench.bank.account', - dataIndex: 'account', - key: 'account', - }, - { - title: 'page.workbench.bank.currency', - dataIndex: 'currency', - key: 'currency', - }, - { - title: 'page.workbench.bank.nation', - dataIndex: 'nation', - key: 'nation', - }, - { - title: 'page.workbench.bank.province', - dataIndex: 'province', - key: 'province', - }, - { - title: 'page.workbench.bank.city', - dataIndex: 'city', - key: 'city', - }, - { - title: 'page.workbench.bank.updateTime', - dataIndex: 'updateTime', - key: 'updateTime', - }, -]; + const BankInfoTab: React.FC = () => { //双语 const intl = useIntl(); @@ -82,25 +29,121 @@ const BankInfoTab: React.FC = () => { //列表分页 const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); //列表方法 - const getList = async (page: number = 1, pageSize: number = 10) => { + const getList = async (pageNo: number = 1, pageSize: number = 10) => { setLoading(true); try { - const { code, data, total } = await bank({page, pageSize}); + const { code, data } = await bankGetPage({pageNo, pageSize}); if (code === 200) { - setData(data); - setPagination({ current: page, pageSize, total }); + setData(data.records); + setPagination({ current: pageNo, pageSize, total:data.total }); } } finally { setLoading(false); } }; + + //增改查 + const [formVisible, setFormVisible] = useState(false); + const [editingRecord, setEditingRecord] = useState(null); + const [isViewMode, setIsViewMode] = useState(false); + const handleFormSubmit = () => { + setFormVisible(false); + getList(); + }; + const handleAdd = () => { + setEditingRecord(null); + setIsViewMode(false); + setFormVisible(true); + }; + + const handleEdit = (record: BankInfo) => { + setEditingRecord(record); + setIsViewMode(false); + setFormVisible(true); + }; + + const handleView = (record: BankInfo) => { + setEditingRecord(record); + setIsViewMode(true); + setFormVisible(true); + }; + //初始化 useEffect(() => { getList(); }, []); - + // 表格头部 + const columns: ColumnsType = [ + { + title: 'page.workbench.bank.index', + dataIndex: 'index', + key: 'index', + width: 80, + align: 'center', + render: (_: any, __: any, index: number) => index + 1 + }, + { + title: 'page.workbench.bank.interbankNumber', + dataIndex: 'interbankNumber', + key: 'interbankNumber', ellipsis: true + }, + { + title: 'page.workbench.bank.bank', + dataIndex: 'bank', + key: 'bank', ellipsis: true + }, + { + title: 'page.workbench.bank.accountName', + dataIndex: 'accountName', + key: 'accountName', ellipsis: true + }, + { + title: 'page.workbench.bank.account', + dataIndex: 'account', + key: 'account', ellipsis: true + }, + { + title: 'page.workbench.bank.currency', + dataIndex: 'currency', + key: 'currency', ellipsis: true + }, + { + title: 'page.workbench.bank.nation', + dataIndex: 'nation', + key: 'nation', ellipsis: true + }, + { + title: 'page.workbench.bank.province', + dataIndex: 'province', + key: 'province', ellipsis: true + }, + { + title: 'page.workbench.bank.city', + dataIndex: 'city', + key: 'city', ellipsis: true + }, + { + title: 'page.workbench.bank.updateTime', + dataIndex: 'updateTime', + key: 'updateTime', ellipsis: true + }, + { + title: 'page.workbench.attachments.action', + dataIndex: 'option', + width: 120, + render: (_: any, record: BankInfo) => ( + <> + handleView(record)}>查看 + handleEdit(record)}>修改 + + ), + }, + ]; return (
+
+ +
{ loading={loading} onChange={(pagination) => getList(pagination.current!, pagination.pageSize!)} /> + setFormVisible(false)} + initialValues={editingRecord || undefined} + readOnly={isViewMode} + /> ); }; diff --git a/src/components/CompanyInfo/component/BaseInfoTab.tsx b/src/components/CompanyInfo/component/BaseInfoTab.tsx index 9cf8058..f9e58f7 100644 --- a/src/components/CompanyInfo/component/BaseInfoTab.tsx +++ b/src/components/CompanyInfo/component/BaseInfoTab.tsx @@ -1,14 +1,16 @@ import React, { useEffect, useState } from 'react'; import { Descriptions } from 'antd'; -import { coscoSupplier } from '../services'; +import { coscoSupplierBase } from '../services'; import { useIntl } from 'umi'; + + const BaseInfoTab: React.FC = () => { const intl = useIntl(); - const [registerInfo, setRegisterInfo] = useState({ base: {} }); + const [registerInfo, setRegisterInfo] = useState(); const fetchData = async () => { - const res = await coscoSupplier({}); + const res = await coscoSupplierBase(); if (res.code === 200) { setRegisterInfo(res.data); } @@ -19,7 +21,7 @@ const BaseInfoTab: React.FC = () => { fetchData() }, []); - if (!registerInfo?.base) return
{intl.formatMessage({ id: 'component.globalModal.loading' })}...
; + if (!registerInfo?.coscoSupplierBase) return
{intl.formatMessage({ id: 'component.globalModal.loading' })}...
; return (
@@ -29,74 +31,74 @@ const BaseInfoTab: React.FC = () => { size="middle" style={{ background: '#fff', padding: '16px 0 0' }} > - {registerInfo.base.supplierType === 'dvs' && ( + {registerInfo.coscoSupplierBase.supplierType === 'dvs' && ( {intl.formatMessage({ id: 'component.globalModal.domesticEnterprise' })} )} - {registerInfo.base.name} + {registerInfo.coscoSupplierBase.name} - {registerInfo.base.nameEn} + {registerInfo.coscoSupplierBase.nameEn} - {registerInfo.base.supplierType !== 'dvs' && ( + {registerInfo.coscoSupplierBase.supplierType !== 'dvs' && ( <> - {registerInfo.base.nation} + {registerInfo.coscoSupplierBase.nation} - {registerInfo.base.vat} + {registerInfo.coscoSupplierBase.vat} - {registerInfo.base.taxpayerId} + {registerInfo.coscoSupplierBase.taxpayerId} - {registerInfo.base.currency} + {registerInfo.coscoSupplierBase.currency} )} - {registerInfo.base.socialCreditCode} + {registerInfo.coscoSupplierBase.socialCreditCode} - {registerInfo.base.range} + {registerInfo.coscoSupplierBase.range} - {registerInfo.base.regAddress} + {registerInfo.coscoSupplierBase.regAddress} - {registerInfo.base.workAddress} + {registerInfo.coscoSupplierBase.workAddress} - {registerInfo.base.parentCompanyInvestor} + {registerInfo.coscoSupplierBase.parentCompanyInvestor} - {registerInfo.base.legalPerson} + {registerInfo.coscoSupplierBase.legalPerson} - {registerInfo.base.idCard} + {registerInfo.coscoSupplierBase.idCard} - {registerInfo.base.capital} + {registerInfo.coscoSupplierBase.capital} - {registerInfo.base.enterpriseType} + {registerInfo.coscoSupplierBase.enterpriseType} - {registerInfo.base.contactsName} + {registerInfo.coscoSupplierBase.contactsName} - {registerInfo.base.contactsPhone} + {registerInfo.coscoSupplierBase.contactsPhone} - {registerInfo.base.contactsType} + {registerInfo.coscoSupplierBase.contactsType} - {registerInfo.base.contactsEmail} + {registerInfo.coscoSupplierBase.contactsEmail} - {registerInfo.base.telephone} + {registerInfo.coscoSupplierBase.telephone}
diff --git a/src/components/CompanyInfo/component/InvoiceFormModal.tsx b/src/components/CompanyInfo/component/InvoiceFormModal.tsx new file mode 100644 index 0000000..37b1aea --- /dev/null +++ b/src/components/CompanyInfo/component/InvoiceFormModal.tsx @@ -0,0 +1,227 @@ +import React, { useEffect, useState } from 'react'; +import { Modal, Form, Input, Select, Button, Upload, message, Row, Col, Descriptions } from 'antd'; +import type { UploadProps } from 'antd'; +import { UploadOutlined } from '@ant-design/icons'; +import { uploadFile, invoiceView, invoiceAdd, invoiceEdit } from '../services'; +import moment from 'moment'; +interface props { + visible: boolean; + onOk: () => void; + onCancel: () => void; + initialValues?: any; + readOnly?: boolean; +} +interface viewDataData { + id?: string | null; + account?: string; + address?: string; + bank?: string; + head?: string; + phone?: string; + qualificationCertificate?: string; + supplierId?: string; + taxpayerCode?: string; + taxpayerType?: string; + attachment?: { + uid: string; + name: string; + url: string; + status: string; + }[]; + } +const InvoiceFormModal: React.FC = ({ + visible, + onOk, + onCancel, + initialValues, + readOnly = false, +}) => { + // 新增与修改 + const [form] = Form.useForm(); + //查看 + const [viewData, setViewData] = useState({}); + useEffect(() => { + if (visible) { + if (initialValues) { + invoiceView(initialValues.id).then((res) => { + const { code, data } = res; + if (code === 200) { + const fields = { + ...data, + id: data.id ? data.id : null, + attachment: data.qualificationCertificate + ? [{ uid: '-1', name: data.qualificationCertificate, url: data.qualificationCertificate, status: 'done', response: { url: data.qualificationCertificate } }] + : [], + }; + console.log(fields,'fields'); + + form.setFieldsValue(fields); + setViewData(fields); + } + }); + } else { + form.resetFields(); // ✅ 只有无 initialValues 才重置 + } + } + }, [visible, initialValues]); + + // 提交 + const handleFinish = async () => { + try { + const values = await form.validateFields(); + const qualificationCertificate = values.attachment?.[0]?.response.url; // uploadFile 返回的 data + const payload = { + ...values, + qualificationCertificate, + "supplierId": "9c12e8ea-a681-4184-81ba-5fa276299a00", + }; + + console.log(values,'values'); + + if (!values.id) { + invoiceAdd(payload).then((res) => { + if (res.code == 200) { + message.success('新增成功'); + onOk(); + } + }) + } else { + invoiceEdit(payload).then((res) => { + if (res.code == 200) { + message.success('修改成功'); + onOk(); + } + }) + } + + } catch (error) { + console.error('表单校验失败:', error); + } + }; + + //上传接口 + const uploadProps: UploadProps = { + name: 'file', + showUploadList: true, + customRequest: async ({ file, onSuccess, onError }) => { + try { + const realFile = file as File; + const res = await uploadFile(realFile); + const uploadedFile = { + uid: res.fileSize, + name: res.fileName, + status: 'done', + url: res.url, + response: res, + }; + onSuccess?.(uploadedFile, new XMLHttpRequest()) + message.success('上传成功'); + } catch (err: any) { + onError?.(err); + message.error(err.message || '上传失败'); + } + } + }; + + return ( + + {readOnly ? ( + + {viewData.taxpayerType} + {viewData.taxpayerCode} + {viewData.phone} + {viewData.account} + {viewData.head} + {viewData.address} + {viewData.bank} + + {viewData.attachment?.[0]?.url ? ( + + {viewData.attachment[0].name || '查看附件'} + + ) : ( + '无' + )} + + + ) : (
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Array.isArray(e) ? e : e?.fileList} + rules={[{ required: true }]} + > + + + + + + + )} + + ); +}; + +export default InvoiceFormModal; diff --git a/src/components/CompanyInfo/component/InvoiceTab.tsx b/src/components/CompanyInfo/component/InvoiceTab.tsx index 776abaf..09c7a51 100644 --- a/src/components/CompanyInfo/component/InvoiceTab.tsx +++ b/src/components/CompanyInfo/component/InvoiceTab.tsx @@ -1,8 +1,9 @@ import React, { useEffect, useState } from 'react'; -import { Table } from 'antd'; +import { Table, Button } from 'antd'; import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'; -import { invoice } from '../services'; +import { invoiceGetPage } from '../services'; import { useIntl } from 'umi'; +import InvoiceFormModal from './InvoiceFormModal'; interface InvoiceInfo { id: string; @@ -17,23 +18,6 @@ interface InvoiceInfo { certificateUrl: string; } -const columns: ColumnsType = [ - { title: 'page.workbench.invoice.index', dataIndex: 'index', width: 80, key: 'index', render: (_: any, __: any, index: number) => index + 1 }, - { title: 'page.workbench.invoice.taxpayerType', dataIndex: 'taxpayerType' }, - { title: 'page.workbench.invoice.taxpayerCode', dataIndex: 'taxpayerCode' }, - { title: 'page.workbench.invoice.head', dataIndex: 'head' }, - { title: 'page.workbench.invoice.address', dataIndex: 'address' }, - { title: 'page.workbench.invoice.phone', dataIndex: 'phone' }, - { title: 'page.workbench.invoice.bank', dataIndex: 'bank' }, - { title: 'page.workbench.invoice.account', dataIndex: 'account' }, - { title: 'page.workbench.invoice.updateTime', dataIndex: 'updateTime' }, - { - title: 'page.workbench.invoice.qualificationCertificate', - width:'180px', - dataIndex: 'qualificationCertificate', - render: (val: string) => (val ? 查看附件 : '-'), - }, -]; const InvoiceTab: React.FC = () => { //语言切换 @@ -44,26 +28,85 @@ const InvoiceTab: React.FC = () => { const [loading, setLoading] = useState(false); //列表分页 const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); + //列表方法 - const getList = async (page = 1, pageSize = 10) => { + const getList = async (pageNo = 1, pageSize = 10) => { setLoading(true); try { - const { code, data, total } = await invoice({page, pageSize}); + const { code, data } = await invoiceGetPage({pageNo, pageSize}); if (code === 200) { - setData(data); - setPagination({ current: page, pageSize, total }); + setData(data.records); + setPagination({ current: pageNo, pageSize, total:data.total }); } } finally { setLoading(false); } }; + + //增改查 + const [formVisible, setFormVisible] = useState(false); + const [editingRecord, setEditingRecord] = useState(null); + const [isViewMode, setIsViewMode] = useState(false); + const handleFormSubmit = () => { + setFormVisible(false); + getList(); + }; + const handleAdd = () => { + setEditingRecord(null); + setIsViewMode(false); + setFormVisible(true); + }; + + const handleEdit = (record: InvoiceInfo) => { + setEditingRecord(record); + setIsViewMode(false); + setFormVisible(true); + }; + + const handleView = (record: InvoiceInfo) => { + setEditingRecord(record); + setIsViewMode(true); + setFormVisible(true); + }; + //初始化 useEffect(() => { getList(); }, []); + const columns: ColumnsType = [ + { title: 'page.workbench.invoice.index', dataIndex: 'index', width: 80, key: 'index', render: (_: any, __: any, index: number) => index + 1 }, + { title: 'page.workbench.invoice.taxpayerType', dataIndex: 'taxpayerType', ellipsis: true }, + { title: 'page.workbench.invoice.taxpayerCode', dataIndex: 'taxpayerCode', ellipsis: true }, + { title: 'page.workbench.invoice.head', dataIndex: 'head', ellipsis: true }, + { title: 'page.workbench.invoice.address', dataIndex: 'address', ellipsis: true }, + { title: 'page.workbench.invoice.phone', dataIndex: 'phone', ellipsis: true }, + { title: 'page.workbench.invoice.bank', dataIndex: 'bank', ellipsis: true }, + { title: 'page.workbench.invoice.account', dataIndex: 'account', ellipsis: true }, + { title: 'page.workbench.invoice.updateTime', dataIndex: 'updateTime', ellipsis: true }, + { + title: 'page.workbench.invoice.qualificationCertificate', + width:'180px', + dataIndex: 'qualificationCertificate', + render: (val: string) => (val ? 查看附件 : '-'), + }, + { + title: 'page.workbench.attachments.action', + dataIndex: 'option', + width: 120, + render: (_: any, record: InvoiceInfo) => ( + <> + handleView(record)}>查看 + handleEdit(record)}>修改 + + ), + }, + ]; return (
+
+ +
{ loading={loading} onChange={(pagination) => getList(pagination.current!, pagination.pageSize!)} /> + setFormVisible(false)} + initialValues={editingRecord || undefined} + readOnly={isViewMode} + /> ); }; diff --git a/src/components/CompanyInfo/component/QualificationFormModal.tsx b/src/components/CompanyInfo/component/QualificationFormModal.tsx new file mode 100644 index 0000000..444c268 --- /dev/null +++ b/src/components/CompanyInfo/component/QualificationFormModal.tsx @@ -0,0 +1,223 @@ +import React, { useEffect, useState } from 'react'; +import { Modal, Form, Input, DatePicker, Button, Upload, message, Row, Col, Descriptions } from 'antd'; +import type { UploadProps } from 'antd'; +import { UploadOutlined } from '@ant-design/icons'; +import { uploadFile, qualificationsView, qualificationsaAdd, qualificationsEdit } from '../services'; +import moment from 'moment'; +interface QualificationFormModalProps { + visible: boolean; + onOk: () => void; + onCancel: () => void; + initialValues?: any; + readOnly?: boolean; +} +interface QualificationData { + id?: string | null; + certificateType?: string; + name?: string; + code?: string; + typeLevel?: string; + authority?: string; + dateTime?: moment.Moment; + termOfValidity?: moment.Moment; + attachment?: { + uid: string; + name: string; + url: string; + status: string; + }[]; +} +const QualificationFormModal: React.FC = ({ + visible, + onOk, + onCancel, + initialValues, + readOnly = false, +}) => { + // 新增与修改 + const [form] = Form.useForm(); + //查看 + const [viewData, setViewData] = useState({}); + useEffect(() => { + if (visible) { + if (initialValues) { + qualificationsView(initialValues.id).then((res) => { + const { code, data } = res; + if (code === 200) { + const fields = { + ...data, + id: data.id ? data.id : null, + dateTime: data.dateTime ? moment(data.dateTime) : undefined, + termOfValidity: data.termOfValidity ? moment(data.termOfValidity) : undefined, + + attachment: data.accessory + ? [{ uid: '-1', name: data.accessory, url: data.accessory, status: 'done', response: { url: data.accessory } }] + : [], + }; + console.log(fields, 'fields'); + + form.setFieldsValue(fields); + setViewData(fields); + } + }); + } else { + form.resetFields(); // ✅ 只有无 initialValues 才重置 + } + } + }, [visible, initialValues]); + + // 提交 + const handleFinish = async () => { + try { + const values = await form.validateFields(); + console.log(values, 'values'); + + const accessory = values.attachment?.[0]?.response.url; // uploadFile 返回的 data + const payload = { + ...values, + dateTime: values.dateTime ? moment(values.dateTime) : undefined, + termOfValidity: values.termOfValidity ? moment(values.termOfValidity) : undefined, + accessory, + "supplierId": "9c12e8ea-a681-4184-81ba-5fa276299a00", + }; + if(!values.id) { + qualificationsaAdd(payload).then((res) => { + if (res.code == 200) { + message.success('新增成功'); + onOk(); + } + }) + } else { + qualificationsEdit(payload).then((res) => { + if (res.code == 200) { + message.success('修改成功'); + onOk(); + } + }) + } + + } catch (error) { + console.error('表单校验失败:', error); + } + }; + + //上传接口 + const uploadProps: UploadProps = { + name: 'file', + showUploadList: true, + customRequest: async ({ file, onSuccess, onError }) => { + try { + const realFile = file as File; + const res = await uploadFile(realFile); + const uploadedFile = { + uid: res.fileSize, + name: res.fileName, + status: 'done', + url: res.url, + response: res, + }; + onSuccess?.(uploadedFile, new XMLHttpRequest()) + message.success('上传成功'); + } catch (err: any) { + onError?.(err); + message.error(err.message || '上传失败'); + } + } + }; + + return ( + + {readOnly ? ( + + {viewData.certificateType} + {viewData.name} + {viewData.code} + {viewData.typeLevel} + {viewData.authority} + {viewData.dateTime ? moment(viewData.dateTime).format('YYYY-MM-DD') : ''} + {viewData.termOfValidity ? moment(viewData.termOfValidity).format('YYYY-MM-DD') : ''} + + {viewData.attachment?.[0]?.url ? ( + + {viewData.attachment[0].name || '查看附件'} + + ) : '无'} + + + ) : (
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Array.isArray(e) ? e : e?.fileList} + rules={[{ required: true }]} + > + + + + + + + )} + + ); +}; + +export default QualificationFormModal; diff --git a/src/components/CompanyInfo/component/QualificationTab.tsx b/src/components/CompanyInfo/component/QualificationTab.tsx index c5fddc4..aeb86a1 100644 --- a/src/components/CompanyInfo/component/QualificationTab.tsx +++ b/src/components/CompanyInfo/component/QualificationTab.tsx @@ -1,8 +1,9 @@ import React, { useEffect, useState } from 'react'; -import { Table } from 'antd'; +import { Table, Button, message } from 'antd'; import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'; -import { qualifications } from '../services'; +import { qualificationsGetPage } from '../services'; import { useIntl } from 'umi'; +import QualificationFormModal from './QualificationFormModal'; interface Qualification { id: string; @@ -15,61 +16,106 @@ interface Qualification { termOfValidity: string; updateTime: string; } -// 列表头部信息 -const columns: ColumnsType = [ - { title: 'page.workbench.certificateType', dataIndex: 'certificateType' }, - { title: 'page.workbench.certificateName', dataIndex: 'name' }, - { title: 'page.workbench.certificateCode', dataIndex: 'code' }, - { title: 'page.workbench.typeLevel', dataIndex: 'typeLevel' }, - { title: 'page.workbench.authority', dataIndex: 'authority' }, - { title: 'page.workbench.dateTime', dataIndex: 'dateTime' }, - { title: 'page.workbench.termOfValidity', dataIndex: 'termOfValidity' }, - { title: 'page.workbench.updateTime', dataIndex: 'updateTime' }, -]; const QualificationTab: React.FC = () => { - //语言切换 const intl = useIntl(); - //列表渲染数据 const [data, setData] = useState([]); - //列表加载 const [loading, setLoading] = useState(false); - //列表分页 const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); - //列表方法 - const getList = async (page = 1, pageSize = 10) => { + //增改查 + const [formVisible, setFormVisible] = useState(false); + const [editingRecord, setEditingRecord] = useState(null); + const [isViewMode, setIsViewMode] = useState(false); + + const getList = async (pageNo = 1, pageSize = 10) => { setLoading(true); try { - const { code, data, total } = await qualifications({page, pageSize}); + const { code, data } = await qualificationsGetPage({ pageNo, pageSize }); if (code === 200) { - setData(data); - setPagination({ current: page, pageSize, total }); + setData(data.records); + setPagination({ current: pageNo, pageSize, total: data.total }); } } finally { setLoading(false); } }; - //初始化 + useEffect(() => { getList(); }, []); + const handleAdd = () => { + setEditingRecord(null); + setIsViewMode(false); + setFormVisible(true); + }; + + const handleEdit = (record: Qualification) => { + setEditingRecord(record); + setIsViewMode(false); + setFormVisible(true); + }; + + const handleView = (record: Qualification) => { + setEditingRecord(record); + setIsViewMode(true); + setFormVisible(true); + }; + + const handleFormSubmit = () => { + setFormVisible(false); + getList(); + }; + + const columns: ColumnsType = [ + { title: 'page.workbench.certificateType', dataIndex: 'certificateType', ellipsis: true }, + { title: 'page.workbench.certificateName', dataIndex: 'name', ellipsis: true }, + { title: 'page.workbench.certificateCode', dataIndex: 'code', ellipsis: true }, + { title: 'page.workbench.typeLevel', dataIndex: 'typeLevel' }, + { title: 'page.workbench.authority', dataIndex: 'authority', ellipsis: true }, + { title: 'page.workbench.dateTime', dataIndex: 'dateTime', ellipsis: true }, + { title: 'page.workbench.termOfValidity', dataIndex: 'termOfValidity', ellipsis: true }, + { title: 'page.workbench.updateTime', dataIndex: 'updateTime', ellipsis: true }, + { + title: 'page.workbench.attachments.action', + dataIndex: 'option', + width: 120, + render: (_: any, record: Qualification) => ( + <> + handleView(record)}>查看 + handleEdit(record)}>修改 + + ), + }, + ]; + return (
+
+ +
({ ...column, - title: intl.formatMessage({ id: column.title as string }) + title: typeof column.title === 'string' ? intl.formatMessage({ id: column.title }) : column.title, }))} dataSource={data} pagination={pagination} loading={loading} + scroll={{ y: 400 }} onChange={(pagination) => getList(pagination.current!, pagination.pageSize!)} /> + setFormVisible(false)} + initialValues={editingRecord || undefined} + readOnly={isViewMode} + /> ); }; -export default QualificationTab; \ No newline at end of file +export default QualificationTab; diff --git a/src/components/CompanyInfo/index.tsx b/src/components/CompanyInfo/index.tsx index 24ac192..d54b379 100644 --- a/src/components/CompanyInfo/index.tsx +++ b/src/components/CompanyInfo/index.tsx @@ -8,7 +8,6 @@ import OtherAttachmentsTab from './component/OtherAttachmentsTab'; import ContactsInfoTab from './component/ContactsInfoTab'; import BankInfoTab from './component/BankInfoTab'; -import Supplier from '@/pages/supplier/register/supplier'; const { TabPane } = Tabs; @@ -21,7 +20,6 @@ const CompanyInfo: React.FC = () => { return ( - {/* */} diff --git a/src/components/CompanyInfo/services.ts b/src/components/CompanyInfo/services.ts index c0313b1..565bd1a 100644 --- a/src/components/CompanyInfo/services.ts +++ b/src/components/CompanyInfo/services.ts @@ -1,38 +1,173 @@ import request from '@/utils/request'; -export async function coscoSupplier(params:any) { - console.log(params,'params'); - - return request('/api/system/coscoSupplier', { - method: 'GET', - params - }); -} -export async function library(params:any) { - return request('/api/system/library', { - method: 'GET', - params - }); -} +/** +* 供应商基本信息 +*/ +export const coscoSupplierBase = () => request.get(`/coscoSupplierBase/9c12e8ea-a681-4184-81ba-5fa276299a00`); -export async function qualifications(params:any) { - return request('/api/system/qualifications', { - method: 'GET', - params - }); +/** +* 资质分页列表 +*/ +interface qualificationsGetPage { + pageNo: number; + pageSize: number; + supplierId?: string; } -export async function invoice(params:any) { - return request('/api/system/invoice', { - method: 'GET', - params - }); +export const qualificationsGetPage = (data: qualificationsGetPage) => request.post('/qualifications/getPage', { data }); + +/** +* 资质详情 +*/ +export const qualificationsView = (id: string) => request.get(`/qualifications/${id}`); +/** +* 资质新增 +*/ +interface qualificationsaAdd { + id: string; + accessory: string; + authority: string; + certificateType: string; + code: string; + dateTime: string; + name: string; + supplierId: string; + termOfValidity: string; + typeLevel: string; } -export async function bank(params:any) { - return request('/api/system/bank', { - method: 'GET', - params +export const qualificationsaAdd = (data: qualificationsaAdd) => request.post('/qualifications', { data }); +/** + * @param data + * @returns + * 资质修改 + */ +export const qualificationsEdit = (data: qualificationsaAdd) => request.put('/qualifications', { data }); +/** + * 上传文件 + * @param file 上传的文件对象 + * @returns 上传结果 + */ +export const uploadFile = async (file: File) => { + const formData = new FormData(); + formData.append('file', file); + return request('/fileConfig/files/upload', { + method: 'POST', + data: formData, + }); +}; + + +/** invoice +* 开票分页列表 +*/ +interface invoiceGetPage { + pageNo: number; + pageSize: number; + supplierId?: string; } +export const invoiceGetPage = (data: invoiceGetPage) => request.post('/invoice/getPage', { data }); + +/** +* 开票详情 +*/ +export const invoiceView = (id: string) => request.get(`/invoice/${id}`); +/** +* 开票新增 +*/ +interface invoiceAdd { + id: string; + account: string; + address: string; + bank: string; + head: string; + phone: string; + qualificationCertificate: string; + supplierId: string; + taxpayerCode: string; + taxpayerType: string; +} +export const invoiceAdd = (data: invoiceAdd) => request.post('/invoice', { data }); +/** + * @param data + * @returns + * 开票修改 + */ +export const invoiceEdit = (data: invoiceAdd) => request.put('/invoice', { data }); + + + +/** bank +* 开票分页列表 +*/ +interface bankGetPage { + pageNo: number; + pageSize: number; + supplierId?: string; +} +export const bankGetPage = (data: bankGetPage) => request.post('/bank/getPage', { data }); + +/** +* 开票详情 +*/ +export const bankView = (id: string) => request.get(`/bank/${id}`); +/** +* 开票新增 +*/ +interface bankAdd { + id: string; + account: string; + accountName: string; + bank: string; + city: string; + currency: string; + interbankNumber: string; + nation: string; + province: string; + supplierId: string; + swiftCode: null; + [property: string]: any; +} +export const bankAdd = (data: bankAdd) => request.post('/bank', { data }); +/** + * @param data + * @returns + * 开票修改 + */ +export const bankEdit = (data: bankAdd) => request.put('/bank', { data }); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pages/supplier/admission/SupplierCategoryEntry/components/CreateModal.tsx b/src/pages/supplier/admission/SupplierCategoryEntry/components/CreateModal.tsx new file mode 100644 index 0000000..1d49aa7 --- /dev/null +++ b/src/pages/supplier/admission/SupplierCategoryEntry/components/CreateModal.tsx @@ -0,0 +1,211 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Form, Select, Button, Tree, message, Input } from 'antd'; +//组件 +import SupplierSelector from './SupplierSelector'; +// 请求 +import { categoryTree, add } from '../services'; +const { Option } = Select; + +// 主体 +const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ visible, onCancel }) => { + + const [form] = Form.useForm(); + //品类选择 + const [checkedKeys, setCheckedKeys] = useState([]); + //供应商 + const [selectedSuppliers, setSelectedSuppliers] = useState([]); + //供应商弹出 + const [supplierModalVisible, setSupplierModalVisible] = useState(false); + //品类选择渲染数据 + const [categoriesTreeData, setCategoriesTreeData] = useState([]); + //品类选择数据中字段转换 + const convertTreeData = (data: any) => { + return data.map((item: any) => ({ + ...item, + title: item.categoryName, + key: item.id, + children: item.children ? convertTreeData(item.children) : undefined, + + })); + } + function findLeafKeys(treeData: any[]): string[] { + let leafKeys: string[] = []; + function dfs(nodes: any[]) { + nodes.forEach(node => { + if (!node.children || node.children.length === 0) { + leafKeys.push(node.key); + } else { + dfs(node.children); + } + }); + } + dfs(treeData); + return leafKeys; + } + //品类选择 + const onCheck = ( + checkedKeysValue: + | React.Key[] + | { checked: React.Key[]; halfChecked: React.Key[] } + ) => { + const keys = Array.isArray(checkedKeysValue) + ? checkedKeysValue + : checkedKeysValue.checked; + + // 只取叶子节点 key + const leafKeys = findLeafKeys(convertTreeData(categoriesTreeData)); + const onlyLeafChecked = keys.filter(key => leafKeys.includes(String(key))); + setCheckedKeys(keys); // UI 显示用,还是全量 + form.setFieldsValue({ categoryIds: onlyLeafChecked }); // 只存叶子到表单 + }; + + // 提交 + const onFinish = async (values: any) => { + const finalPayload: { + coscoAccessWork: { + accessWorkName: string; + deptId: string; + }; + categoryIds: string[]; + supplierIds: string[]; + } = { + coscoAccessWork: { + accessWorkName: '', + deptId: '', + }, + categoryIds: [], + supplierIds: [], + }; + //标题名称 + finalPayload.coscoAccessWork.accessWorkName = values.accessWorkName; + //准入部门 + finalPayload.coscoAccessWork.deptId = values.deptId; + //品类选择 + finalPayload.categoryIds = values.categoryIds; + //选择供应商 + if(values.supplier.length != 0) { + values.supplier.forEach((item: { id: string }) => { + finalPayload.supplierIds.push(item.id) + }) + } + console.log( finalPayload, values); + const res = await add(finalPayload); + if (res?.success) { + message.success('创建成功'); + form.resetFields(); + setCheckedKeys([]); + setSelectedSuppliers([]); + onCancel(); + } else { + message.error('创建失败'); + } + }; + //初始化 + useEffect(() => { + categoryTree().then((res) => { + const { code, data } = res; + if (code == 200) { + setCategoriesTreeData(data) + } + }) + }, [visible, form]); + return ( + { + form.resetFields(); + setCheckedKeys([]); + setSelectedSuppliers([]); + onCancel(); + }} + width="700px" + destroyOnClose + > +
+ + + + + + + + + + + + + + + + + + + + + + setSupplierModalVisible(false)} + onSelect={(selected) => { + setSelectedSuppliers(selected); + form.setFieldsValue({ supplier: selected }); + setSupplierModalVisible(false); + }} + /> +
+ ); +}; + +export default CreateModal; diff --git a/src/pages/supplier/admission/SupplierCategoryEntry/components/SupplierSelector.tsx b/src/pages/supplier/admission/SupplierCategoryEntry/components/SupplierSelector.tsx new file mode 100644 index 0000000..ba0bf4c --- /dev/null +++ b/src/pages/supplier/admission/SupplierCategoryEntry/components/SupplierSelector.tsx @@ -0,0 +1,154 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Input, Select, Row, Col, Table, Button, Form, Tooltip } from 'antd'; +import { RightOutlined, LeftOutlined } from '@ant-design/icons'; +import { coscoSupplierBase } from '../services'; + +const { Option } = Select; + +const SupplierSelector: React.FC<{ visible: boolean; onCancel: () => void; onSelect?: (selected: any[]) => void; }> = ({ visible, onCancel, onSelect }) => { + // 查询 + const [form] = Form.useForm(); + //列表渲染数据 + const [tableListData, setTableListData] = useState([]); + //列表分页 + const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); + //列表加载 + const [loading, setLoading] = useState(false); + //已选供应商 + const [leftSelected, setLeftSelected] = useState([]); + //选择供应商 + const [rightSelected, setRightSelected] = useState([]); + //确认 已选供应商 + const [chosenSuppliers, setChosenSuppliers] = useState([]); + //已选供应商 去重 + const filteredData = (chosenSuppliers:any, selected:any) => { + const ids = new Set(chosenSuppliers.map((item:any) => item.id)); + // 只把 selected 里没出现过的加进去 + const newSelected = selected.filter((item:any) => !ids.has(item.id)); + return [...chosenSuppliers, ...newSelected]; + }; + //获取已选供应商 + const moveToRight = () => { + const selected = tableListData.filter((item:any) => leftSelected.includes(item.id)); + const chosenSuppliersNew = filteredData(chosenSuppliers, selected); + setChosenSuppliers(chosenSuppliersNew); + setLeftSelected([]); + }; + // 删除已选供应商 + const moveToLeft = () => { + const remaining = chosenSuppliers.filter((item:any) => !rightSelected.includes(item.id)); + setChosenSuppliers(remaining); + setRightSelected([]); + }; + // 列表方法 + const getTableList = async (values: any = {}, pageNo: number = 1, pageSize: number = 10) => { + setLoading(true); + try { + const { code, data } = await coscoSupplierBase({ ...values, basePageRequest: { pageNo, pageSize} }); + if (code === 200) { + setTableListData(data.records); + setPagination({ current: pageNo, pageSize, total: data.total }); + } + } finally { + setLoading(false); + } + }; + // 初始化 + useEffect(() => { + if(visible) { + const values = form.getFieldsValue(); + getTableList(values,1 , 10) + } + }, [visible]) + //供应商名称 + const columns = [ + { title: '供应商名称', dataIndex: 'name', ellipsis: true, render: (name: string) => ( + + {name} + + ), }, + { title: '境内/境外', dataIndex: 'supplierType', render: (supplierType: string) => supplierType === 'dvs' ? '境内' : '境外'}, + ]; + return ( + + +
+ + + + + + + + + + + + + + + + +
+
待选供应商
+
{ + const values = form.getFieldsValue(); + getTableList(values, pagination.current!, pagination.pageSize!) + }} + scroll={{ y: 300 }} + /> + + + + +
+
+ + + + +
已选供应商
+
+ + + +
+ + +
+ + ); +}; + +export default SupplierSelector; diff --git a/src/pages/supplier/admission/SupplierCategoryEntry/components/ViewModal.tsx b/src/pages/supplier/admission/SupplierCategoryEntry/components/ViewModal.tsx new file mode 100644 index 0000000..b7b39b1 --- /dev/null +++ b/src/pages/supplier/admission/SupplierCategoryEntry/components/ViewModal.tsx @@ -0,0 +1,72 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Descriptions } from 'antd'; + +import { coscoAccessWorkCategory } from '../services' + +//数据接口 +interface Data { + coscoAccessWork: coscoAccessWorks; + coscoAccessSupplierList: coscoAccessSupplierLists[]; + coscoAccessCategoryList: coscoAccessCategoryLists[]; +} + +interface coscoAccessCategoryLists { + categoryName: string; + [property: string]: any; +} +interface coscoAccessSupplierLists { + supplierName: string; + [property: string]: any; +} +interface coscoAccessWorks { + deptId: string; + reviewStatusText: string; +} + +const ViewModal: React.FC<{ + visible: boolean; + record?: any; + onCancel: () => void; +}> = ({ visible, record = {}, onCancel }) => { + //渲染数据 + const [data, setData] = useState(null); + //初始化 + useEffect(() => { + if (record.id) { + coscoAccessWorkCategory(record.id).then((res) => { + const { code, data } = res; + if (code == 200) { + setData(data) + } + }) + } + }, [record]) + + return ( + + {data && ( + + {data.coscoAccessWork.deptId} + + {data.coscoAccessSupplierList.map((item) => { + return ( +
{item.supplierName}
+ ) + })} +
+ + {data.coscoAccessCategoryList.map((item) => { + return ( +
{item.categoryName}
+ ) + })} +
+ + {data.coscoAccessWork.reviewStatusText} +
+ )} +
+ ); +}; + +export default ViewModal; \ No newline at end of file diff --git a/src/pages/supplier/admission/SupplierCategoryEntry/index.tsx b/src/pages/supplier/admission/SupplierCategoryEntry/index.tsx index f53eda6..91568c0 100644 --- a/src/pages/supplier/admission/SupplierCategoryEntry/index.tsx +++ b/src/pages/supplier/admission/SupplierCategoryEntry/index.tsx @@ -1,207 +1,156 @@ -import React, { useEffect, useState } from 'react'; -import { Table, Form, Select, Button, Tag, message } from 'antd'; -import { SearchOutlined, ReloadOutlined } from '@ant-design/icons'; -;import { getApprovePage } from './services' -import type { ColumnsType } from 'antd/es/table'; +import React, { useState, useEffect } from 'react'; +import { Form, Select, Button, Table, Space, Modal, message } from 'antd'; +import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'; +//查看弹窗 +import ViewModal from './components/ViewModal'; +//发起准入 弹窗 +import CreateModal from './components/CreateModal'; +import { getPage, startApprove } from './services' -interface SupplierEntryReviewRecord { +const { Option } = Select; + +interface Data { id: string; - accessWorkName: string; // 准入工作 - deptId: string; // 准入部门ID - accessTypeText: string; // 准入方式 - reviewStatusText: string; // 流程状态 - categoryName: string; // 品类名称 - startTime: string; // 申请时间 - endTime: string; - createTime: string; // 创建时间 - updateTime: string; // 更新时间 - [key: string]: any; // 允许有其它字段 + deptId: string; + accessTypeText: string; + createTime: string; + approveStatus: string; } -const statusColorMap: Record = { - '未开始': 'default', - '进行中': 'processing', - '已完成': 'success', -}; - -const methodOptions = [ - { label: '全部', value: '' }, - { label: '线上准入', value: '线上准入' }, - { label: '线下准入', value: '线下准入' }, -]; - -const statusOptions = [ - { label: '全部', value: '' }, - { label: '未开始', value: '未开始' }, - { label: '进行中', value: '进行中' }, - { label: '已完成', value: '已完成' }, -]; - -const deptOptions = [ - { label: '全部', value: '' }, - { label: '采购部', value: 'DEPT001' }, - { label: '业务部', value: 'DEPT002' }, -]; - -const columns:ColumnsType = [ - { - title: '序号', - dataIndex: 'index', - width: 48, - align: 'center', - render: (_: any, __: any, idx: number) => idx + 1, - }, - { - title: '准入工作', - dataIndex: 'accessWorkName', - align: 'center', - ellipsis: true, - }, - { - title: '准入部门', - dataIndex: 'deptId', - align: 'center', - render: (deptId: string) => deptId === 'DEPT001' ? '采购部' : deptId === 'DEPT002' ? '业务部' : deptId, - }, - { - title: '准入方式', - dataIndex: 'accessTypeText', - align: 'center', - }, - { - title: '准入品类', - dataIndex: 'categoryName', - align: 'center', - ellipsis: true, - }, - { - title: '开始时间', - dataIndex: 'startTime', - align: 'center', - }, - { - title: '结束时间', - dataIndex: 'endTime', - align: 'center', - }, - { - title: '流程状态', - dataIndex: 'reviewStatusText', - align: 'center', - render: (text: string) => {text}, - }, -]; - const SupplierCategoryEntry: React.FC = () => { + // 查询 const [form] = Form.useForm(); - const [data, setData] = useState([]); - const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); + //列表渲染数据 + const [data, setData] = useState([]); + // 发起准入、查看、发起审批、审批记录、查看评审结果 显示哪个组件状态 + const [modalInfo, setModalInfo] = useState<{ type: string; visible: boolean; record?: any }>({ type: '', visible: false, }); + //列表分页 + const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); + //列表加载 const [loading, setLoading] = useState(false); - - // 查询数据 - const fetchData = async (params = {}) => { + // 列表方法 + const getList = async (values: any = {},pageNo: number = 1, pageSize: number = 10) => { setLoading(true); try { - const res = await getApprovePage({ - pageNo: pagination.current, - pageSize: pagination.pageSize, - ...form.getFieldsValue(), - ...params, - }); - if (res.code === 200) { - setData(res.data.records); - setPagination({ - ...pagination, - current: res.data.current, - total: res.data.total, - pageSize: res.data.size, - }); - } else { - setData([]); - setPagination({ ...pagination, total: 0 }); + const { code, data } = await getPage({ ...values, pageNo, pageSize }); + if (code === 200) { + setData(data.records); + setPagination({ current: pageNo, pageSize, total: data.total }); } - } catch (err) { - message.error('获取数据失败'); } finally { setLoading(false); } }; - + //初始化 useEffect(() => { - fetchData({ pageNo: 1 }); - // eslint-disable-next-line + const values = form.getFieldsValue(); + getList(values, 1, 10); }, []); - - // 表格分页切换 - const handleTableChange = (pag: any) => { - setPagination({ - ...pagination, - current: pag.current, - pageSize: pag.pageSize, - }); - fetchData({ - pageNo: pag.current, - pageSize: pag.pageSize, + //开启弹窗 + const openModal = (type: string, record?: any) => { + setModalInfo({ type, visible: true, record }); + }; + //关闭弹窗 + const closeModal = () => { + setModalInfo({ type: '', visible: false }); + const values = form.getFieldsValue(); + getList(values, 1, 10); + }; + const handleApproval = (accessWorkId: string) => { + Modal.confirm({ + title: '是否确认发起审批?', + onOk: async () => { + const res = await startApprove({ accessWorkId }); + if (res.code === 200) { + message.success('发起审批成功'); + const values = form.getFieldsValue(); + getList(values, 1, 10); + } + }, }); }; - - // 搜索 - const handleSearch = () => { - setPagination({ ...pagination, current: 1 }); - fetchData({ pageNo: 1 }); - }; - - // 重置 - const handleReset = () => { - form.resetFields(); - setPagination({ ...pagination, current: 1 }); - fetchData({ pageNo: 1 }); - }; + //列表头部数据 + const columns: ColumnsType = [ + { + title: '序号', + dataIndex: 'index', + render: (_: any, __: any, index: number) => index + 1, + }, + { title: '准入工作', dataIndex: 'accessWorkName' }, + { title: '准入单位', dataIndex: 'deptId' }, + { title: '准入部门', dataIndex: 'deptId' }, + { title: '准入方式', dataIndex: 'accessTypeText' }, + { title: '申请时间', dataIndex: 'createTime' }, + { title: '状态', dataIndex: 'approveStatusText' }, + { + title: '操作', + width: 140, + render: (_: any, record: any) => ( + + openModal('view', record)}>查看 + { ( !record.approveStatusText) && ( + handleApproval(record.id)}> + 发起审批 + + )} + + ), + }, + ]; return ( -
-
- - + + + - - + + + - - + + + + + + - - + + + + - +
+ +
{ + const values = form.getFieldsValue(); + getList(values, pagination.current!, pagination.pageSize!) }} - onChange={handleTableChange} - bordered /> - + {/* 弹窗区 */} + + + ); }; diff --git a/src/pages/supplier/admission/SupplierCategoryEntry/services.ts b/src/pages/supplier/admission/SupplierCategoryEntry/services.ts index 940d2b4..0759cc8 100644 --- a/src/pages/supplier/admission/SupplierCategoryEntry/services.ts +++ b/src/pages/supplier/admission/SupplierCategoryEntry/services.ts @@ -1,16 +1,64 @@ import request from '@/utils/request'; /** - * 品类准入审核列表 + * 品类准入管理列表 */ interface getPageData { - accessType?: string; - approveStatus?: string; - categoryId?: string; - deptId?: string; - pageNo: string; - pageSize: string; - reviewStatus?: string; - [property: string]: any; + pageNo: number; + pageSize: number; + deptId?: string; + accessType?: string; + reviewStatus?: string; + approveStatus?: string; + categoryId?: string; } -export const getApprovePage = (data: getPageData) => request.post('/coscoAccessWorkCategory/getPage', { data}); \ No newline at end of file +export const getPage = (data: getPageData) => request.post('/coscoAccessWorkCategory/getPage', { data }); + +/** + * 发起审批 + */ +interface startApproveData { + accessWorkId: string; +} +export const startApprove = (params: startApproveData) => request.get(`/coscoAccessWorkCategory/startApprove`, { params }); + +/** + * 供应商准入管理详情 + */ +export const coscoAccessWorkCategory = (id: string) => request.get(`/coscoAccessWorkCategory/${id}`); + +/** + * 供应商分页列表查询 + */ +interface coscoSupplierBaseData { + basePageRequest: basePageRequests; + accessStatus?: number; + name?: string; + supplierType?: string; +} +interface basePageRequests { + pageNo: number; + pageSize: number; +} +export const coscoSupplierBase = (data: coscoSupplierBaseData) => request.post('/coscoSupplierBase/getSupplierPage', { data }); +/** + * 的供应商分页列表查询 + */ +interface addInterface { + categoryIds: string[]; + coscoAccessWork: CoscoAccessWork; + supplierIds: string[]; + [property: string]: any; +} + +interface CoscoAccessWork { + accessWorkName: string; + deptId: string; + [property: string]: any; +} +export const add = (data: addInterface) => request.post('/coscoAccessWorkCategory/add', { data }); + +/** + * 品类选择查询树 + */ +export const categoryTree = () => request.get('/cosco/category/categoryTree'); diff --git a/src/pages/supplier/admission/SupplierCategoryEntryReview/components/ViewModal.tsx b/src/pages/supplier/admission/SupplierCategoryEntryReview/components/ViewModal.tsx new file mode 100644 index 0000000..b7b39b1 --- /dev/null +++ b/src/pages/supplier/admission/SupplierCategoryEntryReview/components/ViewModal.tsx @@ -0,0 +1,72 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Descriptions } from 'antd'; + +import { coscoAccessWorkCategory } from '../services' + +//数据接口 +interface Data { + coscoAccessWork: coscoAccessWorks; + coscoAccessSupplierList: coscoAccessSupplierLists[]; + coscoAccessCategoryList: coscoAccessCategoryLists[]; +} + +interface coscoAccessCategoryLists { + categoryName: string; + [property: string]: any; +} +interface coscoAccessSupplierLists { + supplierName: string; + [property: string]: any; +} +interface coscoAccessWorks { + deptId: string; + reviewStatusText: string; +} + +const ViewModal: React.FC<{ + visible: boolean; + record?: any; + onCancel: () => void; +}> = ({ visible, record = {}, onCancel }) => { + //渲染数据 + const [data, setData] = useState(null); + //初始化 + useEffect(() => { + if (record.id) { + coscoAccessWorkCategory(record.id).then((res) => { + const { code, data } = res; + if (code == 200) { + setData(data) + } + }) + } + }, [record]) + + return ( + + {data && ( + + {data.coscoAccessWork.deptId} + + {data.coscoAccessSupplierList.map((item) => { + return ( +
{item.supplierName}
+ ) + })} +
+ + {data.coscoAccessCategoryList.map((item) => { + return ( +
{item.categoryName}
+ ) + })} +
+ + {data.coscoAccessWork.reviewStatusText} +
+ )} +
+ ); +}; + +export default ViewModal; \ No newline at end of file diff --git a/src/pages/supplier/admission/SupplierCategoryEntryReview/index.tsx b/src/pages/supplier/admission/SupplierCategoryEntryReview/index.tsx index 04c5c89..d8c0bdd 100644 --- a/src/pages/supplier/admission/SupplierCategoryEntryReview/index.tsx +++ b/src/pages/supplier/admission/SupplierCategoryEntryReview/index.tsx @@ -1,284 +1,133 @@ import React, { useState, useEffect } from 'react'; -import ProTable from '@ant-design/pro-table'; -import type { ProColumns, ActionType } from '@ant-design/pro-table'; -import { Form, Select, Button, Row, Col, Tag, Space, DatePicker, Input } from 'antd'; -import { SearchOutlined, ReloadOutlined } from '@ant-design/icons'; -import { getApprovePage } from './services' +import { Form, Select, Button, Table, Space, Modal, message } from 'antd'; +import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'; +//查看弹窗 +import ViewModal from './components/ViewModal'; -const { RangePicker } = DatePicker; +import { getPage } from './services' -// 示例数据 -const tableData = [ - { - id: 1, - name: '中山市合创展包装材料有限公司', - region: '境内', - type: '民营企业', - category: '船用物料,添加剂', - time: '2025-03-03 09:30', - status: '未开始', - result: '', - }, - { - id: 2, - name: '深圳市欧阳华斯电源有限公司', - region: '境内', - type: '民营企业', - category: '绳机物料', - time: '2025-03-03 09:30', - status: '未开始', - result: '', - }, - { - id: 3, - name: '广东振兴塑胶机械有限公司', - region: '境内', - type: '民营企业', - category: '船用物料', - time: '2025-03-03 09:30', - status: '进行中', - result: '', - }, - { - id: 4, - name: '上海硕建建筑技术工程有限公司', - region: '境内', - type: '民营企业', - category: '绳机物料', - time: '2025-03-03 09:30', - status: '进行中', - result: '', - }, - { - id: 5, - name: '中山市合创展包装材料有限公司', - region: '境内', - type: '民营企业', - category: '船用物料', - time: '2025-03-03 09:30', - status: '进行中', - result: '', - }, - { - id: 6, - name: '深圳市欧阳华斯电源有限公司', - region: '境内', - type: '民营企业', - category: '绳机物料', - time: '2025-03-03 09:30', - status: '进行中', - result: '', - }, - { - id: 7, - name: '广东振兴塑胶机械有限公司', - region: '境内', - type: '民营企业', - category: '船用物料', - time: '2025-03-03 09:30', - status: '已结束', - result: '通过', - }, - { - id: 8, - name: '上海硕建建筑技术工程有限公司', - region: '境内', - type: '民营企业', - category: '绳机物料', - time: '2025-03-03 09:30', - status: '已结束', - result: '驳回', - }, - { - id: 9, - name: '广东振兴塑胶机械有限公司', - region: '境内', - type: '民营企业', - category: '船用物料', - time: '2025-03-03 09:30', - status: '已结束', - result: '驳回', - }, - { - id: 10, - name: '上海硕建建筑技术工程有限公司', - region: '境内', - type: '民营企业', - category: '绳机物料', - time: '2025-03-03 09:30', - status: '已结束', - result: '驳回', - }, -]; +const { Option } = Select; -const statusColorMap: Record = { - '未开始': 'default', - '进行中': 'processing', - '已结束': 'success', -}; - -const resultColorMap: Record = { - '通过': 'success', - '驳回': 'error', -}; - -const columns: ProColumns[] = [ - { - title: '序号', - dataIndex: 'index', - valueType: 'index', - width: 48, - align: 'center', - }, - { - title: '供应商名称', - dataIndex: 'name', - align: 'center', - ellipsis: true, - }, - { - title: '境内/境外', - dataIndex: 'region', - align: 'center', - }, - { - title: '企业类型', - dataIndex: 'type', - align: 'center', - }, - { - title: '准入品类', - dataIndex: 'category', - align: 'center', - ellipsis: true, - }, - { - title: '提交时间', - dataIndex: 'time', - align: 'center', - sorter: (a, b) => new Date(a.time).getTime() - new Date(b.time).getTime(), - }, - { - title: '流程状态', - dataIndex: 'status', - align: 'center', - render: (_, record) => - {record.status}, - }, - { - title: '审批结果', - dataIndex: 'result', - align: 'center', - render: (val: string) => - val ? {val} : null, - }, - { - title: '操作', - dataIndex: 'option', - align: 'center', - valueType: 'option', - render: (_, record) => ( - - 审批 - 审批记录 - - ), - }, -]; - -// 查询项选项 -const regionOptions = [ - { label: '请选择', value: '' }, - { label: '境内', value: '境内' }, - { label: '境外', value: '境外' }, -]; -const statusOptions = [ - { label: '请选择', value: '' }, - { label: '未开始', value: '未开始' }, - { label: '进行中', value: '进行中' }, - { label: '已结束', value: '已结束' }, -]; -const resultOptions = [ - { label: '请选择', value: '' }, - { label: '通过', value: '通过' }, - { label: '驳回', value: '驳回' }, -]; - -const SupplierCategoryEntry: React.FC = () => { - // const actionRef = useRef(); - - console.log(1); +interface Data { + id: string; + deptId: string; + accessTypeText: string; + createTime: string; + approveStatus: string; +} +const SupplierCategoryEntryReview: React.FC = () => { + // 查询 + const [form] = Form.useForm(); + //列表渲染数据 + const [data, setData] = useState([]); + // 发起准入、查看、发起审批、审批记录、查看评审结果 显示哪个组件状态 + const [modalInfo, setModalInfo] = useState<{ type: string; visible: boolean; record?: any }>({ type: '', visible: false, }); + //列表分页 + const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); + //列表加载 + const [loading, setLoading] = useState(false); + // 列表方法 + const getList = async (values: any = {},pageNo: number = 1, pageSize: number = 10) => { + setLoading(true); + try { + const { code, data } = await getPage({ ...values, pageNo, pageSize }); + if (code === 200) { + setData(data.records); + setPagination({ current: pageNo, pageSize, total: data.total }); + } + } finally { + setLoading(false); + } + }; + //初始化 useEffect(() => { - console.log(1); - - getApprovePage({ - pageNo: 1, - pageSize: 10, - }); - }, []) - // 查询区渲染 - const searchFormRender = ( -
- -
- - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + +
{ + const values = form.getFieldsValue(); + getList(values, pagination.current!, pagination.pageSize!) }} - options={false} - bordered - /> */} - + /> + {/* 弹窗区 */} + + ); }; -export default SupplierCategoryEntry; +export default SupplierCategoryEntryReview; diff --git a/src/pages/supplier/admission/SupplierCategoryEntryReview/services.ts b/src/pages/supplier/admission/SupplierCategoryEntryReview/services.ts index a779958..d37bc38 100644 --- a/src/pages/supplier/admission/SupplierCategoryEntryReview/services.ts +++ b/src/pages/supplier/admission/SupplierCategoryEntryReview/services.ts @@ -1,12 +1,61 @@ import request from '@/utils/request'; /** - * 列表 + * 品类准入管理列表 */ interface getPageData { - pageNo: number; - pageSize: number; - parentCode?: string; + pageNo: number; + pageSize: number; + deptId?: string; + accessType?: string; + reviewStatus?: string; + approveStatus?: string; + categoryId?: string; } -export const getApprovePage = (data: getPageData) => request.post('/coscoAccessWork/getApprovePage', { data}); - \ No newline at end of file +export const getPage = (data: getPageData) => request.post('/coscoAccessWorkCategory/getPage', { data }); + +/** + * 发起审批 + */ +interface startApproveData { + accessWorkId: string; +} +export const startApprove = (params: startApproveData) => request.get(`/coscoAccessWorkCategory/startApprove`, { params }); + +/** + * 供应商准入管理详情 + */ +export const coscoAccessWorkCategory = (id: string) => request.get(`/coscoAccessWorkCategory/${id}`); + +/** + * 供应商分页列表查询 + */ +interface coscoSupplierBaseData { + pageNo: number; + pageSize: number; + accessStatus?: number; + name?: string; + supplierType?: string; +} +export const coscoSupplierBase = (data: coscoSupplierBaseData) => request.post('/coscoSupplierBase/getSupplierPage', { data }); +/** + * 的供应商分页列表查询 + */ +interface addInterface { + categoryIds: string[]; + coscoAccessWork: CoscoAccessWork; + supplierIds: string[]; + [property: string]: any; +} + +interface CoscoAccessWork { + accessWorkName: string; + deptId: string; + [property: string]: any; +} +export const add = (data: addInterface) => request.post('/coscoAccessWorkCategory/add', { data }); + +/** + * 品类选择查询树 + */ +export const categoryTree = () => request.get('/cosco/category/categoryTree'); diff --git a/src/pages/supplier/admission/SupplierEntryReview/components/ViewModal.tsx b/src/pages/supplier/admission/SupplierEntryReview/components/ViewModal.tsx new file mode 100644 index 0000000..fa7f83e --- /dev/null +++ b/src/pages/supplier/admission/SupplierEntryReview/components/ViewModal.tsx @@ -0,0 +1,88 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Descriptions } from 'antd'; + +import { coscoAccessWork } from '../services' + +//数据接口 +interface Data { + coscoAccessWork: coscoAccessWorks; + coscoAccessSupplierList: coscoAccessSupplierLists[]; + coscoAccessCategoryList: coscoAccessCategoryLists[]; + coscoAccessUserls: coscoAccessUserl[]; +} +interface coscoAccessUserl { + deptId: string; + userId: string; +} +interface coscoAccessCategoryLists { + categoryName: string; + [property: string]: any; +} +interface coscoAccessSupplierLists { + supplierName: string; + [property: string]: any; +} +interface coscoAccessWorks { + deptId: string; + startTime: string; + endTime: string; + reviewStatusText: string; +} + +const ViewModal: React.FC<{ + visible: boolean; + record?: string | null; + onCancel: () => void; +}> = ({ visible, record, onCancel }) => { + //渲染数据 + const [data, setData] = useState(null); + //初始化 + useEffect(() => { + console.log(record,'record2'); + + if (record) { + coscoAccessWork(record).then((res) => { + const { code, data } = res; + if (code == 200) { + setData(data) + } + }) + } + }, [record]) + + return ( + + {data && ( + + {data.coscoAccessWork.deptId} + + {data.coscoAccessSupplierList.map((item) => { + return ( +
{item.supplierName}
+ ) + })} +
+ + {data.coscoAccessCategoryList.map((item) => { + return ( +
{item.categoryName}
+ ) + })} +
+ {data.coscoAccessWork.startTime} + {data.coscoAccessWork.endTime} + + {data.coscoAccessUserls.map((item) => { + return ( +
{item.deptId} - {item.userId}
+ ) + })} +
+ {data.coscoAccessWork.reviewStatusText} +
+ )} +
+ ); +}; + +export default ViewModal; \ No newline at end of file diff --git a/src/pages/supplier/admission/SupplierEntryReview/index.tsx b/src/pages/supplier/admission/SupplierEntryReview/index.tsx index 940650f..0dee325 100644 --- a/src/pages/supplier/admission/SupplierEntryReview/index.tsx +++ b/src/pages/supplier/admission/SupplierEntryReview/index.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useState } from 'react'; -import { Table, Form, Select, Button, Tag, message } from 'antd'; +import { Table, Form, Select, Button, Tag, message, Space } from 'antd'; import { SearchOutlined, ReloadOutlined } from '@ant-design/icons'; import { getApprovePage } from './services'; import type { ColumnsType } from 'antd/es/table'; - +import ViewModal from './components/ViewModal'; interface SupplierEntryReviewRecord { id: string; @@ -18,7 +18,11 @@ interface SupplierEntryReviewRecord { updateTime: string; // 更新时间 [key: string]: any; // 允许有其它字段 } - + +interface ModalInfo { + visible: boolean; + record: string | null; +} const statusColorMap: Record = { '未开始': 'default', '进行中': 'processing', @@ -44,61 +48,13 @@ const deptOptions = [ { label: '业务部', value: 'DEPT002' }, ]; -const columns:ColumnsType = [ - { - title: '序号', - dataIndex: 'index', - width: 48, - align: 'center', - render: (_: any, __: any, idx: number) => idx + 1, - }, - { - title: '准入工作', - dataIndex: 'accessWorkName', - align: 'center', - ellipsis: true, - }, - { - title: '准入部门', - dataIndex: 'deptId', - align: 'center', - render: (deptId: string) => deptId === 'DEPT001' ? '采购部' : deptId === 'DEPT002' ? '业务部' : deptId, - }, - { - title: '准入方式', - dataIndex: 'accessTypeText', - align: 'center', - }, - { - title: '准入品类', - dataIndex: 'categoryName', - align: 'center', - ellipsis: true, - }, - { - title: '开始时间', - dataIndex: 'startTime', - align: 'center', - }, - { - title: '结束时间', - dataIndex: 'endTime', - align: 'center', - }, - { - title: '流程状态', - dataIndex: 'reviewStatusText', - align: 'center', - render: (text: string) => {text}, - }, -]; const SupplierEntryReview: React.FC = () => { const [form] = Form.useForm(); const [data, setData] = useState([]); const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); const [loading, setLoading] = useState(false); - + const [modalInfo, setModalInfo] = useState({ visible: false, record: null }); // 查询数据 const fetchData = async (params = {}) => { setLoading(true); @@ -158,7 +114,72 @@ const SupplierEntryReview: React.FC = () => { setPagination({ ...pagination, current: 1 }); fetchData({ pageNo: 1 }); }; - + const openModal = (record: string) => { + setModalInfo({visible: true, record}); + }; + const closeModal = () => { + setModalInfo({ visible: false, record: null }); + }; + const columns:ColumnsType = [ + { + title: '序号', + dataIndex: 'index', + width: 48, + align: 'center', + render: (_: any, __: any, idx: number) => idx + 1, + }, + { + title: '准入工作', + dataIndex: 'accessWorkName', + align: 'center', + ellipsis: true, + }, + { + title: '准入部门', + dataIndex: 'deptId', + align: 'center', + render: (deptId: string) => deptId === 'DEPT001' ? '采购部' : deptId === 'DEPT002' ? '业务部' : deptId, + }, + { + title: '准入方式', + dataIndex: 'accessTypeText', + align: 'center', + }, + { + title: '准入品类', + dataIndex: 'categoryName', + align: 'center', + ellipsis: true, + }, + { + title: '开始时间', + dataIndex: 'startTime', + align: 'center', + }, + { + title: '结束时间', + dataIndex: 'endTime', + align: 'center', + }, + { + title: '流程状态', + dataIndex: 'reviewStatusText', + align: 'center', + }, + { + title: '操作', + width: 120, + render: (_: any, record: any) => { + console.log(record,'record'); + return ( + + openModal(record.id)}>查看 + + ) + + }, + }, + ]; return (
{ onChange={handleTableChange} bordered /> +
); }; diff --git a/src/pages/supplier/admission/SupplierEntryReview/services.ts b/src/pages/supplier/admission/SupplierEntryReview/services.ts index c7399f6..1c0748a 100644 --- a/src/pages/supplier/admission/SupplierEntryReview/services.ts +++ b/src/pages/supplier/admission/SupplierEntryReview/services.ts @@ -14,4 +14,8 @@ interface getPageData { [property: string]: any; } export const getApprovePage = (data: getPageData) => request.post('/coscoAccessWork/getApprovePage', { data}); - \ No newline at end of file + +/** + * 供应商准入管理详情 + */ +export const coscoAccessWork = (id: string) => request.get(`/coscoAccessWork/${id}`); \ No newline at end of file diff --git a/src/pages/supplier/admission/admissionManagement/components/CreateModal.tsx b/src/pages/supplier/admission/admissionManagement/components/CreateModal.tsx index 718ef44..728d7c5 100644 --- a/src/pages/supplier/admission/admissionManagement/components/CreateModal.tsx +++ b/src/pages/supplier/admission/admissionManagement/components/CreateModal.tsx @@ -3,7 +3,6 @@ import { Modal, Form, Select, Button, Tree, message, DatePicker, Radio, Upload, // import { UploadOutlined } from '@ant-design/icons'; import type { UploadFile } from 'antd/es/upload/interface'; -import moment from 'moment'; //组件 import SupplierSelector from './SupplierSelector'; import ReviewerSelector from './ReviewerSelector'; @@ -14,10 +13,10 @@ const { Option } = Select; const { RangePicker } = DatePicker; //selected 类型 interface Reviewer { - key: string; + userId: string; name: string; id: string; - dept: string; + deptId: string; } // 传入的人接口 interface ReviewerSelectorData { @@ -85,7 +84,7 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi // 只取叶子节点 key const leafKeys = findLeafKeys(convertTreeData(categoriesTreeData)); - const onlyLeafChecked = keys.filter(key => leafKeys.includes(key)); + const onlyLeafChecked = keys.filter(key => leafKeys.includes(String(key))); setCheckedKeys(keys); // UI 显示用,还是全量 form.setFieldsValue({ categoryIds: onlyLeafChecked }); // 只存叶子到表单 @@ -138,7 +137,20 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi }; // 提交 const onFinish = async (values: any) => { - const finalPayload = { + const finalPayload: { + coscoAccessWork: { + startTime: string; + endTime: string; + accessType: string; + accessWorkName: string; + deptId: string; + }; + categoryIds: string[]; + supplierIds: string[]; + coscoAccessUserls: { userId: string; deptId: string; isLeader: number }[]; + coscoAccessItems: { itemName: string; reviewBy: string[] }[]; + coscoAccessWorkAttachments: any; + } = { coscoAccessWork: { startTime: '', endTime: '', diff --git a/src/pages/supplier/admission/admissionManagement/components/ResultModal.tsx b/src/pages/supplier/admission/admissionManagement/components/ResultModal.tsx index 8cc64f5..d7d641e 100644 --- a/src/pages/supplier/admission/admissionManagement/components/ResultModal.tsx +++ b/src/pages/supplier/admission/admissionManagement/components/ResultModal.tsx @@ -1,201 +1,223 @@ -import React from 'react'; -import { Modal, Table, Tag, Typography, Button } from 'antd'; +import React, { useEffect, useState } from 'react'; +import { Modal, Table, Button, Select, Spin, message } from 'antd'; +import { reviewInfoData } from '../services'; -const { Link } = Typography; - -const dataSource = [ - { - key: '1', - item: '供应商信息登记表', - companyA_zhangsan: '合格', - companyA_lisi: '合格', - companyB_zhangsan: '合格', - companyB_lisi: '合格', - }, - { - key: '2', - item: '供应商反商业贿赂承诺书', - companyA_zhangsan: '合格', - companyA_lisi: '合格', - companyB_zhangsan: '合格', - companyB_lisi: '合格', - }, - { - key: '3', - item: '供应商社会准则符合性自审问卷', - companyA_zhangsan: '合格', - companyA_lisi: '合格', - companyB_zhangsan: '合格', - companyB_lisi: '合格', - }, - { - key: '4', - item: '是否为禁止使用供应商', - companyA_zhangsan: '合格', - companyA_lisi: '合格', - companyB_zhangsan: '合格', - companyB_lisi: '合格', - }, - { - key: '5', - item: '3年内经营活动中没有重大违法记录的书面声明', - companyA_zhangsan: '合格', - companyA_lisi: '合格', - companyB_zhangsan: '合格', - companyB_lisi: '合格', - }, - { - key: '6', - item: '企业存续状态审核(营业执照等)', - companyA_zhangsan: '合格', - companyA_lisi: '合格', - companyB_zhangsan: '合格', - companyB_lisi: '不合格', - companyB_lisiRemark: '查看备注', - }, - { - key: '7', - item: '行业资质、认证情况(按需)', - companyA_zhangsan: '合格', - companyA_lisi: '合格', - companyB_zhangsan: '合格', - companyB_lisi: '合格', - }, - { - key: '8', - item: '现场考察、产品试用情况(按需)', - companyA_zhangsan: '合格', - companyA_zhangsanRemark: '查看备注', - companyA_lisi: '合格', - companyA_lisiRemark: '查看备注', - companyB_zhangsan: '合格', - companyB_zhangsanRemark: '查看备注', - companyB_lisi: '合格', - companyB_lisiRemark: '查看备注', - }, -]; - -const columns = [ - { - title: '序号', - dataIndex: 'key', - width: 60, - }, - { - title: '评审项', - dataIndex: 'item', - width: 260, - }, - { - title: ( -
-
中山市合创展包装材料有限公司
-
- ), - children: [ - { - title: '张三', - dataIndex: 'companyA_zhangsan', - width: 100, - render: (text: string, record: any) => renderStatus(text, record.companyA_zhangsanRemark), - }, - { - title: '李四', - dataIndex: 'companyA_lisi', - width: 100, - render: (text: string, record: any) => renderStatus(text, record.companyA_lisiRemark), - }, - ], - }, - { - title: ( -
-
广东振兴塑胶机械有限公司
-
- ), - children: [ - { - title: '张三', - dataIndex: 'companyB_zhangsan', - width: 100, - render: (text: string, record: any) => renderStatus(text, record.companyB_zhangsanRemark), - }, - { - title: '李四', - dataIndex: 'companyB_lisi', - width: 100, - render: (text: string, record: any) => renderStatus(text, record.companyB_lisiRemark), - }, - ], - }, -]; - -function renderStatus(text: string, remark?: string) { - const color = text === '合格' ? 'green' : text === '不合格' ? 'red' : undefined; - return ( -
- - {text} - - {remark && ( - alert('备注内容')}> - {remark} - - )} -
- ); +interface ResultModalProps { + visible: boolean; + record?: { id?: string; [key: string]: any } | null; + onCancel: () => void; } -const ResultModal: React.FC<{ +// 只读备注弹窗 +const RemarkViewModal: React.FC<{ visible: boolean; - record?: any; onCancel: () => void; -}> = ({ visible, onCancel }) => { + remark: string; + file?: any; +}> = ({ visible, onCancel, remark, file }) => ( + +
+
+ 备注:{remark || '无'} +
+ {file && file.fileUrl && ( +
+ 附件: + + {file.fileName} + +
+ )} +
+
+); + +const ResultModal: React.FC = ({ + visible, + record, + onCancel, +}) => { + const [loading, setLoading] = useState(false); + const [suppliers, setSuppliers] = useState([]); + const [items, setItems] = useState([]); + const [groupSummaryResult, setGroupSummaryResult] = useState<{ [k: string]: '0' | '1' | undefined }>({}); + // 查看备注弹窗 + const [remarkModal, setRemarkModal] = useState({ open: false, remark: '', file: undefined as any }); + + // 拉取数据 + useEffect(() => { + if (visible && record?.id) { + setLoading(true); + reviewInfoData({ id: record.id }) + .then((res: any) => { + const supplierList = res?.data || []; + setSuppliers(supplierList); + // 所有项,取第一家公司 + const allItems = (supplierList[0]?.coscoAccessItemList || []); + // 非summary项 + setItems(allItems.filter((item: any) => item.itemType !== 'summary')); + // summary 行初始化 + const summaryMap: { [k: string]: '0' | '1' | undefined } = {}; + supplierList.forEach((sup: any) => { + // summary 行 + const summaryItem = (sup.coscoAccessItemList || []).find((i: any) => i.itemType === 'summary'); + console.log(summaryItem,'summaryItem'); + summaryMap[sup.supplierId] = summaryItem.coscoAccessUserItemList[0]?.reviewResult; + }); + setGroupSummaryResult(summaryMap); + }) + .finally(() => setLoading(false)); + } else if (!visible) { + setSuppliers([]); + setItems([]); + setGroupSummaryResult({}); + } + }, [visible, record]); + + + + // 构造二级表头 + const columns: any[] = [ + { + title: '评审项', + dataIndex: 'itemName', + key: 'itemName', + width: 180, + fixed: 'left', + }, + ...suppliers.map(sup => { + // 当前公司所有人员(所有非summary项,取 coscoAccessUserItemList 多个) + const reviewerSet = new Set(); + (sup.coscoAccessItemList || []).forEach((item: any) => { + if (item.itemType !== 'summary' && Array.isArray(item.coscoAccessUserItemList)) { + item.coscoAccessUserItemList.forEach((u: any) => { + reviewerSet.add(u.reviewBy); + }); + } + }); + const reviewers = Array.from(reviewerSet); + return { + title: ( +
+
{sup.supplierName}
+
+ ), + children: reviewers.map((reviewBy: string) => ({ + title: reviewBy, + dataIndex: `${sup.supplierId}_${reviewBy}`, + key: `${sup.supplierId}_${reviewBy}`, + width: 100, + align: 'center', + render: (_: any, row: any) => { + // 在sup.coscoAccessItemList里找该itemName下该人员 + const item = (sup.coscoAccessItemList || []).find((it: any) => it.itemName === row.itemName && it.itemType !== 'summary'); + if (!item) return null; + const userItem = (item.coscoAccessUserItemList || []).find((u: any) => u.reviewBy === reviewBy); + if (!userItem) return null; + return ( +
+ {userItem.reviewResult === '0' + ? 合格 + : userItem.reviewResult === '1' + ? 不合格 + : ''} + {userItem.remark && ( + + )} +
+ ); + } + })) + } + }) + ]; + + // 组装表格行数据 + const tableData = items.map(item => { + const row: any = { + key: item.id, + itemName: item.itemName + }; + suppliers.forEach(sup => { + // 每个人员一格 + const reviewerSet = new Set(); + (sup.coscoAccessItemList || []).forEach((it: any) => { + if (it.itemType !== 'summary' && Array.isArray(it.coscoAccessUserItemList)) { + it.coscoAccessUserItemList.forEach((u: any) => { + reviewerSet.add(u.reviewBy); + }); + } + }); + const reviewers = Array.from(reviewerSet); + reviewers.forEach((reviewBy: string) => { + row[`${sup.supplierId}_${reviewBy}`] = null; // 具体显示用render + }); + }); + return row; + }); + + // summary 行 + const summaryRow = ( + + 结果汇总 + {suppliers.map((sup, index) => { + // 统计reviewer个数 + const reviewerSet = new Set(); + (sup.coscoAccessItemList || []).forEach((item: any) => { + if (item.itemType !== 'summary' && Array.isArray(item.coscoAccessUserItemList)) { + item.coscoAccessUserItemList.forEach((u: any) => { + reviewerSet.add(u.reviewBy); + }); + } + }); + const colSpan = reviewerSet.size || 1; + + return ( + + {groupSummaryResult[sup.supplierId] === '0'? '合格': '不合格'} + + ) + })} + + ); + return ( 关 闭, + ]} width={1000} bodyStyle={{ maxHeight: '60vh', overflowY: 'auto' }} centered + destroyOnClose > -
{ - // 汇总结果示例,模拟图片底部汇总 - return ( - - - 结果汇总 - - - 合格 - - - 不合格 - - - ); - }} + +
summaryRow} + scroll={{ x: 300 * suppliers.length + 200 }} + /> + + setRemarkModal({ open: false, remark: '', file: undefined })} + remark={remarkModal.remark} + file={remarkModal.file} /> -
- - - - -
); }; diff --git a/src/pages/supplier/admission/admissionManagement/index.tsx b/src/pages/supplier/admission/admissionManagement/index.tsx index 52102b9..4b9ef3b 100644 --- a/src/pages/supplier/admission/admissionManagement/index.tsx +++ b/src/pages/supplier/admission/admissionManagement/index.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { Form, Select, Button, Table, Space } from 'antd'; +import { Form, Select, Button, Table, Space, Modal, message } from 'antd'; import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'; //查看弹窗 import ViewModal from './components/ViewModal'; @@ -12,7 +12,7 @@ import ResultModal from './components/ResultModal'; //发起准入 弹窗 import CreateModal from './components/CreateModal'; -import { getPage } from './services' +import { getPage, startApprove } from './services' const { Option } = Select; @@ -60,6 +60,21 @@ const AccessManagement: React.FC = () => { //关闭弹窗 const closeModal = () => { setModalInfo({ type: '', visible: false }); + const values = form.getFieldsValue(); + getList(values, 1, 10); + }; + const handleApproval = (id: string) => { + Modal.confirm({ + title: '是否确认发起审批?', + onOk: async () => { + const res = await startApprove({ id }); + if (res.code === 200) { + message.success('发起审批成功'); + const values = form.getFieldsValue(); + getList(values, 1, 10); + } + }, + }); }; //列表头部数据 const columns: ColumnsType = [ @@ -76,11 +91,21 @@ const AccessManagement: React.FC = () => { { title: '状态', dataIndex: 'reviewStatusText' }, { title: '操作', + width: 200, render: (_: any, record: any) => ( openModal('view', record)}>查看 - {/* openModal('approve', record)}>发起审批 */} - openModal('result', record)}>查看评审结果 + { (record.reviewStatus === '3' && !record.approveStatusText) && ( + handleApproval(record.id)}> + 发起审批 + + )} + { record.reviewStatus === '3' && ( + <> + openModal('result', record)}>评审结果 + + )} + ), }, diff --git a/src/pages/supplier/admission/admissionManagement/services.ts b/src/pages/supplier/admission/admissionManagement/services.ts index 9351c5c..99838d9 100644 --- a/src/pages/supplier/admission/admissionManagement/services.ts +++ b/src/pages/supplier/admission/admissionManagement/services.ts @@ -92,7 +92,11 @@ export const uploadFile = async (file: File) => { interface startApproveData { id: string; } -export const startApprove = (params: startApproveData) => request.get(`/coscoAccessWork/`, { params }); - +export const startApprove = (params: startApproveData) => request.get(`/coscoAccessWork/startApprove`, { params }); + +/** + * 查看评审结果 + */ +export const reviewInfoData = (params: startApproveData) => request.get(`/coscoAccessWork/reviewInfoData`, { params }); diff --git a/src/pages/supplier/admission/admissionReviewManagement/components/GroupLeaderModal.tsx b/src/pages/supplier/admission/admissionReviewManagement/components/GroupLeaderModal.tsx index 8ce5bad..61b949f 100644 --- a/src/pages/supplier/admission/admissionReviewManagement/components/GroupLeaderModal.tsx +++ b/src/pages/supplier/admission/admissionReviewManagement/components/GroupLeaderModal.tsx @@ -4,6 +4,7 @@ import { reviewInfo, update } from '../services'; interface ResultModalProps { visible: boolean; + view: boolean; record?: { id?: string; [key: string]: any } | null; onCancel: () => void; onSubmit: () => void; @@ -42,6 +43,7 @@ const RemarkViewModal: React.FC<{ const GroupLeaderModal: React.FC = ({ visible, record, + view, onCancel, onSubmit, }) => { @@ -49,7 +51,7 @@ const GroupLeaderModal: React.FC = ({ const [suppliers, setSuppliers] = useState([]); const [items, setItems] = useState([]); // groupSummaryResult: { [supplierId]: 0|1 } - const [groupSummaryResult, setGroupSummaryResult] = useState<{ [k: string]: 0 | 1 | undefined }>({}); + const [groupSummaryResult, setGroupSummaryResult] = useState<{ [k: string]: '0' | '1' | undefined }>({}); // 查看备注弹窗 const [remarkModal, setRemarkModal] = useState({ open: false, remark: '', file: undefined as any }); @@ -66,11 +68,12 @@ const GroupLeaderModal: React.FC = ({ // 非summary项 setItems(allItems.filter((item: any) => item.itemType !== 'summary')); // summary 行初始化 - const summaryMap: { [k: string]: 0 | 1 | undefined } = {}; + const summaryMap: { [k: string]: '0' | '1' | undefined } = {}; supplierList.forEach((sup: any) => { // summary 行 const summaryItem = (sup.coscoAccessItemList || []).find((i: any) => i.itemType === 'summary'); - summaryMap[sup.supplierId] = summaryItem?.reviewResult; + // summaryMap[sup.supplierId] = summaryItem?.reviewResult; + summaryMap[sup.supplierId] = summaryItem.coscoAccessUserItemList[0]?.reviewResult; }); setGroupSummaryResult(summaryMap); }) @@ -83,7 +86,7 @@ const GroupLeaderModal: React.FC = ({ }, [visible, record]); // 处理summary下拉变更 - const handleSummaryChange = (supplierId: string, value: 0 | 1) => { + const handleSummaryChange = (supplierId: string, value: '0' | '1') => { setGroupSummaryResult(prev => ({ ...prev, [supplierId]: value, @@ -217,16 +220,21 @@ const GroupLeaderModal: React.FC = ({ const colSpan = reviewerSet.size || 1; return ( - handleSummaryChange(sup.supplierId, val)} + options={[ + { label: '合格', value: '0' }, + { label: '不合格', value: '1' } + ]} + /> + )} ) })} @@ -239,8 +247,14 @@ const GroupLeaderModal: React.FC = ({ visible={visible} onCancel={onCancel} footer={[ - , - + , + !view && ( + + ) ]} width={1000} bodyStyle={{ maxHeight: '60vh', overflowY: 'auto' }} diff --git a/src/pages/supplier/admission/admissionReviewManagement/components/ResultModal.tsx b/src/pages/supplier/admission/admissionReviewManagement/components/ResultModal.tsx index 6eda462..bdb14e0 100644 --- a/src/pages/supplier/admission/admissionReviewManagement/components/ResultModal.tsx +++ b/src/pages/supplier/admission/admissionReviewManagement/components/ResultModal.tsx @@ -5,6 +5,7 @@ import type { ColumnsType } from 'antd/es/table'; //主体参数接口 interface ResultModalProps { visible: boolean; + view: boolean; record?: { id?: string; [key: string]: any } | null; onCancel: () => void; onSubmit: () => void; @@ -15,13 +16,46 @@ interface RowData { // 其他如有 } type CellValue = { - reviewResult?: 0 | 1; + reviewResult?: '0' | '1'; remark?: string; file?: any; }; + +// 只读备注弹窗 +const RemarkViewModal: React.FC<{ + visible: boolean; + onCancel: () => void; + remark: string; + file?: any; +}> = ({ visible, onCancel, remark, file }) => ( + +
+
+ 备注:{remark || '无'} +
+ {file && file.fileUrl && ( +
+ 附件: + + {file.fileName} + +
+ )} +
+
+); + + //主体 const ResultModal: React.FC = ({ visible, + view, record, onCancel, onSubmit @@ -34,7 +68,8 @@ const ResultModal: React.FC = ({ // userItemId为唯一key const [cellData, setCellData] = useState<{ [userItemId: string]: CellValue }>({}); const [loading, setLoading] = useState(false); - +// 查看备注弹窗 + const [remarkModal, setRemarkModal] = useState({ open: false, remark: '', file: undefined as any }); // 备注弹窗 const [remarksModalVisible, setRemarksModalVisible] = useState(false); const [remarks, setRemarks] = useState(''); @@ -98,7 +133,7 @@ const ResultModal: React.FC = ({ ...prev, [userItemId]: { ...prev[userItemId], - reviewResult: value === '合格' ? 0 : 1 + reviewResult: value === '合格' ? '0' : '1' } })); }; @@ -185,7 +220,7 @@ const ResultModal: React.FC = ({ accessWorkId = record?.id } // 提交审核 - update( {coscoAccessUserItemList: result, accessWorkId }).then((res) => { + update( {coscoAccessUserItemList: result, accessWorkId }).then((res) => { if(res.code == 200) { message.success('提交成功'); onSubmit() @@ -212,32 +247,48 @@ const ResultModal: React.FC = ({ if (!userItem) return null; // 无userItem不渲染 const v = cellData[userItem.id] || {}; return ( -
- handleRadioChange(userItem.id, e.target.value)} - > - 合格 - 不合格 - - - {v.remark && ( - 已备注 + <> + + {view && ( + <> + {v.reviewResult === '0'? '合格': '不合格'} + + )} - {v.file && ( - - 已上传 - + + + { !view && ( +
+ handleRadioChange(userItem.id, e.target.value)} + > + 合格 + 不合格 + + + {v.remark && ( + 已备注 + )} + {v.file && ( + + 已上传 + + )} +
)} -
+ + ); } })) @@ -250,17 +301,20 @@ const ResultModal: React.FC = ({ })); return ( + <> - 取消 + {view ? '关闭' : '取消'} , - + !view && ( + + ) ]} width={1000} bodyStyle={{ maxHeight: '60vh', overflowY: 'auto' }} @@ -301,6 +355,13 @@ const ResultModal: React.FC = ({ + setRemarkModal({ open: false, remark: '', file: undefined })} + remark={remarkModal.remark} + file={remarkModal.file} + /> + ); }; diff --git a/src/pages/supplier/admission/admissionReviewManagement/components/ViewModal.tsx b/src/pages/supplier/admission/admissionReviewManagement/components/ViewModal.tsx new file mode 100644 index 0000000..aa4b4a4 --- /dev/null +++ b/src/pages/supplier/admission/admissionReviewManagement/components/ViewModal.tsx @@ -0,0 +1,86 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Descriptions } from 'antd'; + +import { coscoAccessWork } from '../services' + +//数据接口 +interface Data { + coscoAccessWork: coscoAccessWorks; + coscoAccessSupplierList: coscoAccessSupplierLists[]; + coscoAccessCategoryList: coscoAccessCategoryLists[]; + coscoAccessUserls: coscoAccessUserl[]; +} +interface coscoAccessUserl { + deptId: string; + userId: string; +} +interface coscoAccessCategoryLists { + categoryName: string; + [property: string]: any; +} +interface coscoAccessSupplierLists { + supplierName: string; + [property: string]: any; +} +interface coscoAccessWorks { + deptId: string; + startTime: string; + endTime: string; + reviewStatusText: string; +} + +const ViewModal: React.FC<{ + visible: boolean; + record?: any; + onCancel: () => void; +}> = ({ visible, record = {}, onCancel }) => { + //渲染数据 + const [data, setData] = useState(null); + //初始化 + useEffect(() => { + if (record.id) { + coscoAccessWork(record.id).then((res) => { + const { code, data } = res; + if (code == 200) { + setData(data) + } + }) + } + }, [record]) + + return ( + + {data && ( + + {data.coscoAccessWork.deptId} + + {data.coscoAccessSupplierList.map((item) => { + return ( +
{item.supplierName}
+ ) + })} +
+ + {data.coscoAccessCategoryList.map((item) => { + return ( +
{item.categoryName}
+ ) + })} +
+ {data.coscoAccessWork.startTime} + {data.coscoAccessWork.endTime} + + {data.coscoAccessUserls.map((item) => { + return ( +
{item.deptId} - {item.userId}
+ ) + })} +
+ {data.coscoAccessWork.reviewStatusText} +
+ )} +
+ ); +}; + +export default ViewModal; \ No newline at end of file diff --git a/src/pages/supplier/admission/admissionReviewManagement/index.tsx b/src/pages/supplier/admission/admissionReviewManagement/index.tsx index 3cb9ac2..092562a 100644 --- a/src/pages/supplier/admission/admissionReviewManagement/index.tsx +++ b/src/pages/supplier/admission/admissionReviewManagement/index.tsx @@ -7,6 +7,7 @@ import { getPage } from './services'; //查看评审结果 弹窗 import ResultModal from './components/ResultModal'; import GroupLeaderModal from './components/GroupLeaderModal'; +import ViewModal from './components/ViewModal'; interface Data { deptName: string; @@ -17,26 +18,26 @@ interface Data { } interface ModalInfo { - type: 'teamMembers' | 'groupLeader' | null; + type: 'teamMembers' | 'groupLeader' | 'view' | null; visible: boolean; record: Data | null; + view: boolean; } - const CooperateEnterprise: React.FC = () => { const [searchForm] = Form.useForm(); const intl = useIntl(); const [data, setData] = useState([]); const [loading, setLoading] = useState(false); const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); - const [modalInfo, setModalInfo] = useState({ type: null, visible: false, record: null }); + const [modalInfo, setModalInfo] = useState({ type: null, visible: false, record: null, view:false }); - const openModal = (type: 'teamMembers' | 'groupLeader', record: Data) => { - setModalInfo({ type, visible: true, record }); + const openModal = (type: 'teamMembers' | 'groupLeader' | 'view', record: Data, view = false ) => { + setModalInfo({ type, visible: true, record, view }); }; //提交关闭审核 const closeModal = () => { - setModalInfo({ type: null, visible: false, record: null }); + setModalInfo({ type: null, visible: false, record: null, view:false }); }; //提交审核 const submitModal = () => { @@ -121,19 +122,30 @@ const CooperateEnterprise: React.FC = () => { title: '评审状态', dataIndex: 'reviewStatusText', key: 'reviewStatusText', + width: 120, }, { title: '操作', + width: 120, render: (_: any, record: any) => { + // 已完成 3 、结果汇总中 2 、进行中1 、 未开始0 + // 显示评审 按钮 const showAudit = ( - (['未开始', '进行中'].includes(record.reviewStatusText) && record.isLeader === '0') || - (['结果汇总中'].includes(record.reviewStatusText) && record.isLeader === '1') + (['0', '1'].includes(record.reviewStatus) && record.isLeader === '0') || + (['2'].includes(record.reviewStatus) && record.isLeader === '1') ); - const type = ['未开始', '进行中'].includes(record.reviewStatusText)? 'teamMembers': 'groupLeader'; + // 进行中1 、未开始0 弹出组员组件 否则弹出组长组件 + const type = ['0', '1'].includes(record.reviewStatus)? 'teamMembers': 'groupLeader'; + + //评审结果 结果汇总中2 弹出组员组件, 已完成3弹出组长组件 + const isLeader = (record.reviewStatus === '2' && record.isLeader === '0')? 'teamMembers': + (record.reviewStatus === '3' && record.isLeader === '1')? 'groupLeader':''; return ( - {showAudit && openModal(type, record)}>审核} - + {showAudit && openModal(type, record)}>评审} + openModal('view', record)}>查看 + { isLeader != '' && openModal(isLeader, record, true)}>评审结果} + ) }, @@ -171,6 +183,7 @@ const CooperateEnterprise: React.FC = () => { { modalInfo.type && modalInfo.type === 'teamMembers' && ( { { modalInfo.type && modalInfo.type === 'groupLeader' && ( )} + { modalInfo.type && modalInfo.type === 'view' && ( + + )} ); diff --git a/src/pages/supplier/admission/admissionReviewManagement/services.ts b/src/pages/supplier/admission/admissionReviewManagement/services.ts index 167aeb2..7a6587d 100644 --- a/src/pages/supplier/admission/admissionReviewManagement/services.ts +++ b/src/pages/supplier/admission/admissionReviewManagement/services.ts @@ -33,7 +33,10 @@ export const uploadFile = async (file: File) => { }); }; - +/** + * 供应商准入管理详情 + */ +export const coscoAccessWork = (id: string) => request.get(`/coscoAccessWork/${id}`); /** * 组员评审 */ diff --git a/src/pages/supplier/supplierExit/supplierExitAudit/components/CreateBlacklistModal.tsx b/src/pages/supplier/supplierExit/supplierExitAudit/components/CreateBlacklistModal.tsx new file mode 100644 index 0000000..a765123 --- /dev/null +++ b/src/pages/supplier/supplierExit/supplierExitAudit/components/CreateBlacklistModal.tsx @@ -0,0 +1,180 @@ +import React, { useEffect , useState } from "react"; +import { Modal, Button, Select, Input, Table, message, Form } from "antd"; +import SupplierSelectModal from "./SupplierSelectModal"; +import { add } from "../services"; +import type { ColumnsType } from 'antd/es/table'; +const { Option } = Select; +interface Supplier { + id: number; // 作为 rowKey 用于唯一标识 + supplierName: string; // 供应商名称 + unit: string; // 准入部门 + accessTime: string; // 准入时间 + categoryName: string; // 准入品类 + lastEval: string; // 最近一次评价 + lastEvalDate: string; // 评价时间 + supplierId: string; + categoryId: string; +} + +interface CreateBlacklistModalProps { + visible: boolean; + onOk: () => void; + onCancel: () => void; +} + +const DEPT_OPTIONS = [ + { value: "DEPT001", label: "部门A" }, + { value: "DEPT002", label: "部门B" }, +]; + +const CreateBlacklistModal: React.FC = ({ + visible, + onOk, + onCancel, +}) => { + const [selectVisible, setSelectVisible] = useState(false); + const [suppliers, setSuppliers] = useState([]); + const [form] = Form.useForm(); + + const removeSupplier = (id: number) => { + setSuppliers(suppliers.filter((s) => s.id !== id)); + }; + + const handleSelectOk = (selected: Supplier[]) => { + setSuppliers(selected); + setSelectVisible(false); + }; + + const handleSubmit = async () => { + try { + const values = await form.validateFields(); + if (suppliers.length === 0) { + message.error("请至少选择一个供应商"); + return; + } + + const payload: { + coscoSupplierexit: { + exitTheme: string; + exitReason: string; + deptId: string; + }, + supplierIdList: string[], + coscoSupplierexitSupplierCategoryList: { supplierId: string; categoryId: string; }[]; + + } = { + coscoSupplierexit: {...values}, + supplierIdList: suppliers.map((item) => item.supplierId), + coscoSupplierexitSupplierCategoryList: suppliers.map((item) => ({ supplierId: item.supplierId, categoryId: item.categoryId })) + } + const res = await add(payload); + if (res?.success) { + message.success("提交成功"); + onOk(); + } else { + message.error("提交失败"); + } + } catch (err) { + // 校验失败 + } + }; + useEffect(() => { + if (visible) { + setSuppliers([]); + form.resetFields(); + } + }, [visible]); + const columns: ColumnsType = [ + { title: "供应商名称", dataIndex: "supplierName", align: "center" }, + { title: "准入部门", dataIndex: "unit", align: "center" }, + { title: "准入时间", dataIndex: "accessTime", align: "center", render: () => "2023-04-20 13:00" }, + { title: "准入品类", dataIndex: "categoryName", align: "center" }, + { title: "最近一次评价", dataIndex: "lastEval", align: "center" }, + { title: "评价时间", dataIndex: "lastEvalDate", align: "center" }, + { + title: "操作", + dataIndex: "option", + align: "center", + render: (_: any, record: Supplier) => ( + + ), + }, + ]; + + return ( + <> + + + +
+ +
+ + + + + + + + + + + + + +
+ +
+ + +
+ + + setSelectVisible(false)} + /> + + ); +}; + +export default CreateBlacklistModal; diff --git a/src/pages/supplier/supplierExit/supplierExitAudit/components/SupplierSelectModal.tsx b/src/pages/supplier/supplierExit/supplierExitAudit/components/SupplierSelectModal.tsx new file mode 100644 index 0000000..67d3747 --- /dev/null +++ b/src/pages/supplier/supplierExit/supplierExitAudit/components/SupplierSelectModal.tsx @@ -0,0 +1,226 @@ +import React, { useEffect, useState } from "react"; +import { + Modal, Table, Button, Checkbox, Row, Col, Input, Select, Form, Space, message +} from "antd"; +import { getSupplierCategoryPage } from '../services'; + +const { Option } = Select; + +interface Supplier { + id: number; + supplierId: string; + categoryId: string; + supplierName: string; + + unit: string; // 准入部门 + accessTime: string; // 准入时间 + categoryName: string; // 准入品类 + lastEval: string; // 最近一次评价 + lastEvalDate: string; // 评价时间 + +} + +interface SupplierSelectModalProps { + visible: boolean; + selectedSuppliers: Supplier[]; + onOk: (suppliers: Supplier[]) => void; + onCancel: () => void; +} + + +const SupplierSelectModal: React.FC = ({ + visible, + selectedSuppliers, + onOk, + onCancel, +}) => { + const [form] = Form.useForm(); + const [leftSelected, setLeftSelected] = useState([]); + const [rightSelected, setRightSelected] = useState([]); + const [rightData, setRightData] = useState([]); + const [data, setData] = useState([]); + const [pagination, setPagination] = useState({ current: 1, pageSize: 5, total: 0 }); + const [loading, setLoading] = useState(false); + + useEffect(() => { + if (visible) { + setRightData(selectedSuppliers || []); + fetchData(); + } + }, [visible]); + + const fetchData = async (params: any = {}, pageNo = 1, pageSize = 5) => { + setLoading(true); + try { + const res = await getSupplierCategoryPage({ ...params, pageNo, pageSize }); + if (res.code === 200) { + setData(res.data.records); + setPagination({ current: pageNo, pageSize: pageSize, total: res.data.total }); + } else { + message.error('获取数据失败'); + } + } catch { + message.error('获取数据异常'); + } finally { + setLoading(false); + } + }; + + const handleSearch = () => { + const values = form.getFieldsValue(); + fetchData(values, 1, pagination.pageSize); + }; + + const handleReset = () => { + form.resetFields(); + fetchData({}, 1, pagination.pageSize); + }; + + const handleAdd = () => { + const added = data.filter(s => leftSelected.includes(s.id)); + const combined = [...rightData, ...added.filter(i => !rightData.some(r => r.id === i.id))]; + setRightData(combined); + setLeftSelected([]); + }; + + const handleRemove = () => { + setRightData(rightData.filter(i => !rightSelected.includes(i.id))); + setRightSelected([]); + }; + + const handleOk = () => { + onOk(rightData); + }; + + const columns = [ + { + title: 0} + indeterminate={leftSelected.length > 0 && leftSelected.length < data.length} + onChange={e => { + setLeftSelected(e.target.checked ? data.map(i => i.id) : []); + }} + >全选, + dataIndex: "select", + width: 80, + render: (_: any, record: Supplier) => ( + { + setLeftSelected(e.target.checked + ? [...leftSelected, record.id] + : leftSelected.filter(id => id !== record.id)); + }} + >选择 + ) + }, + { title: "供应商名称", dataIndex: "supplierName" }, + { title: "准入单位", dataIndex: "deptId" }, + { title: "准入部门", dataIndex: "deptId" }, + { title: "准入品类", dataIndex: "categoryName" } + ]; + + const rightColumns = [ + { + title: 0} + indeterminate={rightSelected.length > 0 && rightSelected.length < rightData.length} + onChange={e => { + setRightSelected(e.target.checked ? rightData.map(i => i.id) : []); + }} + >全选, + dataIndex: "select", + width: 80, + render: (_: any, record: Supplier) => ( + { + setRightSelected(e.target.checked + ? [...rightSelected, record.id] + : rightSelected.filter(id => id !== record.id)); + }} + >选择 + ) + }, + { title: "供应商名称", dataIndex: "supplierName" }, + { title: "准入单位", dataIndex: "deptId" }, + { title: "准入部门", dataIndex: "deptId" }, + { title: "准入品类", dataIndex: "categoryName" } + ]; + + return ( + +
+ + + + + + + + + + + + + + + + + + +
+
备选供应商
+
{ + const values = form.getFieldsValue(); + fetchData(values, pag.current!, pag.pageSize!); + }} + size="small" + bordered + /> + + + + + + +
已选供应商
+
+ + + + ); +}; + +export default SupplierSelectModal; diff --git a/src/pages/supplier/supplierExit/supplierExitAudit/components/ViewBlacklistModal.tsx b/src/pages/supplier/supplierExit/supplierExitAudit/components/ViewBlacklistModal.tsx new file mode 100644 index 0000000..ce7c606 --- /dev/null +++ b/src/pages/supplier/supplierExit/supplierExitAudit/components/ViewBlacklistModal.tsx @@ -0,0 +1,113 @@ +import React, { useEffect, useState } from "react"; +import { Modal, Button, Table, Descriptions, Spin, message } from "antd"; +import {coscoSupplierexit } from "../services"; // 假设的接口 +import type { ColumnsType } from 'antd/es/table'; + +interface Supplier { + id: number; // 作为 rowKey 用于唯一标识 + supplierName: string; // 供应商名称 + unit: string; // 准入部门 + accessTime: string; // 准入时间 + categoryName: string; // 准入品类 + lastEval: string; // 最近一次评价 + lastEvalDate: string; // 评价时间 + supplierId: string; + categoryId: string; + } +interface DetailData { + exitTheme: string; + deptName: string; + deptId: string; + exitReason: string; +} + +interface ViewBlacklistModalProps { + visible: boolean; + onCancel: () => void; + recordId: string; // 用于查询详情数据 +} + +const ViewBlacklistModal: React.FC = ({ + visible, + onCancel, + recordId, +}) => { + const [loading, setLoading] = useState(false); + const [detail, setDetail] = useState(null); + const [suppliers, setSuppliers] = useState([]); + + const fetchData = async () => { + setLoading(true); + try { + const { code, data } = await coscoSupplierexit(recordId) + if (code == 200) { + setDetail(data.coscoSupplierexit); + } else { + message.error("获取详情失败"); + } + + if (code == 200) { + setSuppliers(data.coscoSupplierexitSupplierCategoryList || []); + } else { + message.error("获取供应商列表失败"); + } + } catch (error) { + message.error("获取数据异常"); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + if (visible && recordId) { + fetchData(); + } + }, [visible, recordId]); + + const columns:ColumnsType = [ + { title: "供应商名称", dataIndex: "supplierName", align: "center" }, + { title: "准入部门", dataIndex: "unit", align: "center" }, + { title: "准入时间", dataIndex: "accessTime", align: "center" }, + { title: "准入品类", dataIndex: "categoryName", align: "center" }, + { title: "最近一次评价", dataIndex: "lastEval", align: "center" }, + { title: "评价时间", dataIndex: "lastEvalDate", align: "center" }, + ]; + + return ( + 关闭} + destroyOnClose + bodyStyle={{ padding: "36px 36px 16px" }} + > + + {detail && ( + + {detail.exitTheme} + {detail.deptId} + {detail.exitReason} + + )} + +
+ + + ); +}; + +export default ViewBlacklistModal; diff --git a/src/pages/supplier/supplierExit/supplierExitAudit/index.tsx b/src/pages/supplier/supplierExit/supplierExitAudit/index.tsx index a809dae..4426445 100644 --- a/src/pages/supplier/supplierExit/supplierExitAudit/index.tsx +++ b/src/pages/supplier/supplierExit/supplierExitAudit/index.tsx @@ -1,167 +1,131 @@ import React, { useEffect, useState } from "react"; -import { Form, Button, Table, Select, Input, Space, DatePicker, message } from "antd"; -import { SearchOutlined, ReloadOutlined } from '@ant-design/icons'; -// 类型定义 -import type { ColumnsType, TablePaginationConfig } from 'antd/es/table'; - -// Mock数据 -const MOCK_DATA = Array.from({ length: 188 }).map((_, idx) => ({ - id: idx + 1, - subject: `${idx % 2 ? '中山市合创展包装材料有限公司' : '上海硕建建筑技术工程有限公司'}等黑灰名单申请`, - unit: idx % 3 === 0 ? '中远海运特运' : idx % 3 === 1 ? '中远海运散运' : '中远海运广州公司', - dept: '采购部', - applyTime: `2024-10-${String(26 - (idx % 5)).padStart(2, "0")} ${idx % 2 ? '9:00' : '10:00'}`, - status: idx < 3 ? '未开始' : idx < 7 ? '进行中' : '已结束', - result: idx < 8 ? '' : (idx % 2 ? '通过' : '驳回'), -})); - -// 状态、结果选项 -const statusOptions = [ - { label: "请选择", value: "" }, - { label: "未开始", value: "未开始" }, - { label: "进行中", value: "进行中" }, - { label: "已结束", value: "已结束" }, -]; -const resultOptions = [ - { label: "请选择", value: "" }, - { label: "通过", value: "通过" }, - { label: "驳回", value: "驳回" }, -]; - -// 列表类型 -interface DataType { - id: number; - subject: string; - unit: string; - dept: string; - applyTime: string; - status: string; - result: string; +import { Form, Button, Table, Select, Input, DatePicker, Space, message } from "antd"; +import { SearchOutlined, ReloadOutlined, PlusOutlined } from "@ant-design/icons"; +import type { ColumnsType } from 'antd/es/table'; +import CreateBlacklistModal from './components/CreateBlacklistModal' +import ViewBlacklistModal from './components/ViewBlacklistModal'; +import { getPage } from './services' +interface ExitRecord { + exitTheme: string; // 申请主题 + deptId: string; // 发起单位/部门(两列共用) + createTime: string; // 发起时间 + accessType: string; // 审批记录状态 } +// mock 数据与服务(实际请换为接口) +const orgOptions = [ + { label: "请选择", value: "" }, + { label: "中远海运特运", value: "中远海运特运" }, + { label: "中远海运散运", value: "中远海运散运" }, + { label: "中远海运物流", value: "中远海运物流" }, + { label: "中远海运广州公司", value: "中远海运广州公司" }, + ]; + // 查询记录状态 +const recordStatusOptions = [ + { label: "请选择", value: "" }, + { label: "未开始", value: "未开始" }, + { label: "进行中", value: "进行中" }, + { label: "已结束", value: "已结束" }, + ]; + const supplierExitAudit: React.FC = () => { - // 搜索表单 - const [form] = Form.useForm(); - // 列表数据 - const [data, setData] = useState([]); - // 加载 - const [loading, setLoading] = useState(false); - // 分页 - const [pagination, setPagination] = useState({ - current: 1, - pageSize: 10, - total: MOCK_DATA.length, - }); - + const [form] = Form.useForm(); + const [data, setData] = useState([]); + const [loading, setLoading] = useState(false); + const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); + const [createVisible, setCreateVisible] = useState(false); + const [viewVisible, setViewVisible] = useState(false); + const [selectedRecordId, setSelectedRecordId] = useState(null); + // 查询接口 + const getList = async (pageNo = 1, pageSize = 10) => { + setLoading(true); + // 可传查询条件 form.getFieldsValue() + const { code, data } = await getPage({ pageNo, pageSize }); + if (code === 200) { + setData(data.records); + setPagination(prev => ({ ...prev, current: pageNo, pageSize, total: data.total })); + } + setLoading(false); + }; + // 查询 const handleSearch = () => { setPagination({ ...pagination, current: 1 }); getList(1, pagination.pageSize); }; - // 重置 const handleReset = () => { form.resetFields(); setPagination({ ...pagination, current: 1 }); getList(1, pagination.pageSize); }; - - // 获取列表(模拟接口,支持分页和部分筛选) - const getList = async (page: number = 1, pageSize: number = 10) => { - setLoading(true); - setTimeout(() => { - let filtered = MOCK_DATA; - const values = form.getFieldsValue(); - if (values.subject) { - filtered = filtered.filter(item => item.subject.includes(values.subject)); - } - if (values.unit) { - filtered = filtered.filter(item => item.unit === values.unit); - } - if (values.status) { - filtered = filtered.filter(item => item.status === values.status); - } - if (values.result) { - filtered = filtered.filter(item => item.result === values.result); - } - // 日期筛选略 - setData(filtered.slice((page - 1) * pageSize, page * pageSize)); - setPagination({ current: page, pageSize, total: filtered.length }); - setLoading(false); - }, 300); + // 分页 + const handleTableChange = (pageConf: any) => { + getList(pageConf.current, pageConf.pageSize); }; - - // 初始化 - useEffect(() => { + // 发起申请 + const handleApply = () => { + setCreateVisible(true) + }; + const handleSelectOk = () => { getList(); - }, []); + setCreateVisible(false); + }; + useEffect(() => { + getList(); + }, []); - // 列 - const columns: ColumnsType = [ + const columns: ColumnsType = [ { title: "序号", dataIndex: "index", key: "index", align: "center", width: 60, - render: (_: any, __: any, idx: number) => - (pagination.current! - 1) * pagination.pageSize! + idx + 1, + render: (_: any, __: any, idx: number) => idx + 1, }, - { title: "申请主题", dataIndex: "subject", key: "subject", align: "center", ellipsis: true }, - { title: "发起单位", dataIndex: "unit", key: "unit", align: "center" }, - { title: "发起部门", dataIndex: "dept", key: "dept", align: "center" }, - { title: "申请时间", dataIndex: "applyTime", key: "applyTime", align: "center" }, - { title: "流程状态", dataIndex: "status", key: "status", align: "center" }, - { title: "审批结果", dataIndex: "result", key: "result", align: "center" }, + { title: "申请主题", dataIndex: "exitTheme", key: "exitTheme", align: "center" }, + { title: "发起单位", dataIndex: "deptId", key: "deptId", align: "center" }, + { title: "发起部门", dataIndex: "deptId", key: "deptId", align: "center" }, + { title: "发起时间", dataIndex: "createTime", key: "createTime", align: "center" }, + { title: "审批记录状态", dataIndex: "approveStatusText", key: "approveStatusText", align: "center" }, { title: "操作", key: "option", align: "center", - render: (record: DataType) => ( - - 审批 - 审批记录 - + render: (record: any) => ( + { + setSelectedRecordId(record.id); + setViewVisible(true); + }} + > + 查看 + ), }, ]; - // 单元下拉(mock示例) - const unitOptions = [ - { label: "请选择", value: "" }, - { label: "中远海运特运", value: "中远海运特运" }, - { label: "中远海运散运", value: "中远海运散运" }, - { label: "中远海运广州公司", value: "中远海运广州公司" }, - ]; - return ( -
- {/* 搜索区 */} + <> + + {/* 查询表单 */}
- - + + - - + + + + - - - - - - - - + + {/* 表格 */} @@ -174,13 +138,19 @@ const supplierExitAudit: React.FC = () => { ...pagination, showQuickJumper: true, showSizeChanger: true, - showTotal: t => `共${t}条`, - onChange: (current, pageSize) => getList(current, pageSize), + showTotal: total => `共${total}条`, }} + onChange={handleTableChange} bordered - style={{ background: '#fff' }} /> -
+ + setCreateVisible(false)} onOk={handleSelectOk} /> + setViewVisible(false)} + /> + ); }; diff --git a/src/pages/supplier/supplierExit/supplierExitAudit/services.ts b/src/pages/supplier/supplierExit/supplierExitAudit/services.ts new file mode 100644 index 0000000..5144c97 --- /dev/null +++ b/src/pages/supplier/supplierExit/supplierExitAudit/services.ts @@ -0,0 +1,64 @@ +import request from '@/utils/request'; + +/** + * 品类准入管理列表 + */ +interface getPageData { + pageNo: number; + pageSize: number; + deptId?: string; + accessType?: string; + reviewStatus?: string; + approveStatus?: string; + categoryId?: string; +} +export const getPage = (data: getPageData) => request.post('/coscoSupplierexit/getPage', { data }); +/** + * 供应商分页列表查询 + */ +interface getSupplierCategoryPageData { + pageNo: number; + pageSize: number; + supplierName?: number; + categoryId?: string; + reviewResult?: string; +} + +export const getSupplierCategoryPage = (data: getSupplierCategoryPageData) => request.post('/coscoSupplierexit/getSupplierCategoryPage', { data }); + + +/** + * 的供应商分页列表查询 + */ +export interface addInterface { + coscoSupplierexit: CoscoSupplierexit; + coscoSupplierexitSupplierCategoryList: CoscoSupplierexitSupplierCategoryList[]; + supplierIdList: string[]; + [property: string]: any; +} + +export interface CoscoSupplierexit { + deptId: string; + exitReason: string; + exitTheme: string; + [property: string]: any; +} + +export interface CoscoSupplierexitSupplierCategoryList { + categoryId: string; + supplierId: string; + [property: string]: any; +} + +export const add = (data: addInterface) => request.post('/coscoSupplierexit/add', { data }); + + + +/** + * 退出详情页(没分页) + */ +export const coscoSupplierexit = (id: string) => request.get(`/coscoSupplierexit/${id}`); + + + + diff --git a/src/pages/supplier/supplierExit/supplierExitManage/components/CreateBlacklistModal.tsx b/src/pages/supplier/supplierExit/supplierExitManage/components/CreateBlacklistModal.tsx index e8ca2d4..a765123 100644 --- a/src/pages/supplier/supplierExit/supplierExitManage/components/CreateBlacklistModal.tsx +++ b/src/pages/supplier/supplierExit/supplierExitManage/components/CreateBlacklistModal.tsx @@ -1,15 +1,19 @@ -import React, { useState } from "react"; -import { Modal, Button, Select, Input, Table, message } from "antd"; -import SupplierSelectModal from "./SupplierSelectModal"; // 上面生成的组件 - +import React, { useEffect , useState } from "react"; +import { Modal, Button, Select, Input, Table, message, Form } from "antd"; +import SupplierSelectModal from "./SupplierSelectModal"; +import { add } from "../services"; +import type { ColumnsType } from 'antd/es/table'; const { Option } = Select; - interface Supplier { - id: number; - name: string; - unit: string; - dept: string; - category: string; + id: number; // 作为 rowKey 用于唯一标识 + supplierName: string; // 供应商名称 + unit: string; // 准入部门 + accessTime: string; // 准入时间 + categoryName: string; // 准入品类 + lastEval: string; // 最近一次评价 + lastEvalDate: string; // 评价时间 + supplierId: string; + categoryId: string; } interface CreateBlacklistModalProps { @@ -18,77 +22,89 @@ interface CreateBlacklistModalProps { onCancel: () => void; } -const initialSuppliers: Supplier[] = [ - { - id: 1, - name: "中山市合创展包装材料有限公司", - unit: "采购部", - dept: "采购部", - category: "船用燃油", - lastEval: "D", - lastEvalDate: "2025-02-20", - }, - { - id: 2, - name: "广东振兴塑胶机械有限公司", - unit: "采购部", - dept: "采购部", - category: "船用燃油", - lastEval: "D", - lastEvalDate: "2025-02-20", - } +const DEPT_OPTIONS = [ + { value: "DEPT001", label: "部门A" }, + { value: "DEPT002", label: "部门B" }, ]; const CreateBlacklistModal: React.FC = ({ - visible, onOk, onCancel + visible, + onOk, + onCancel, }) => { const [selectVisible, setSelectVisible] = useState(false); - const [suppliers, setSuppliers] = useState(initialSuppliers); - const [type, setType] = useState("黑名单"); - const [reason, setReason] = useState(""); + const [suppliers, setSuppliers] = useState([]); + const [form] = Form.useForm(); - // 删除已选供应商 const removeSupplier = (id: number) => { - setSuppliers(suppliers.filter(s => s.id !== id)); + setSuppliers(suppliers.filter((s) => s.id !== id)); }; - // 选择供应商 const handleSelectOk = (selected: Supplier[]) => { setSuppliers(selected); setSelectVisible(false); }; - // 提交 - const handleSubmit = () => { - if (!reason.trim()) { - message.error("请输入黑灰名单原因!"); - return; - } - message.success("提交成功(此处为前端示例)"); - onOk?.(); - }; + const handleSubmit = async () => { + try { + const values = await form.validateFields(); + if (suppliers.length === 0) { + message.error("请至少选择一个供应商"); + return; + } - const columns = [ - { title: "供应商名称", dataIndex: "name", align: "center" }, + const payload: { + coscoSupplierexit: { + exitTheme: string; + exitReason: string; + deptId: string; + }, + supplierIdList: string[], + coscoSupplierexitSupplierCategoryList: { supplierId: string; categoryId: string; }[]; + + } = { + coscoSupplierexit: {...values}, + supplierIdList: suppliers.map((item) => item.supplierId), + coscoSupplierexitSupplierCategoryList: suppliers.map((item) => ({ supplierId: item.supplierId, categoryId: item.categoryId })) + } + const res = await add(payload); + if (res?.success) { + message.success("提交成功"); + onOk(); + } else { + message.error("提交失败"); + } + } catch (err) { + // 校验失败 + } + }; + useEffect(() => { + if (visible) { + setSuppliers([]); + form.resetFields(); + } + }, [visible]); + const columns: ColumnsType = [ + { title: "供应商名称", dataIndex: "supplierName", align: "center" }, { title: "准入部门", dataIndex: "unit", align: "center" }, { title: "准入时间", dataIndex: "accessTime", align: "center", render: () => "2023-04-20 13:00" }, - { title: "准入品类", dataIndex: "category", align: "center" }, + { title: "准入品类", dataIndex: "categoryName", align: "center" }, { title: "最近一次评价", dataIndex: "lastEval", align: "center" }, { title: "评价时间", dataIndex: "lastEvalDate", align: "center" }, { - title: "选择", + title: "操作", dataIndex: "option", align: "center", render: (_: any, record: Supplier) => ( - ) - } + ), + }, ]; return ( <> 供应商黑灰名单申请} + title="供应商退出" visible={visible} onCancel={onCancel} width={900} @@ -99,6 +115,7 @@ const CreateBlacklistModal: React.FC = ({ +
= ({ pagination={false} /> - -
- setReason(e.target.value)} - style={{ width: "100%", marginTop: 8 }} - /> +
+
+ + + + + + + + + + + +
+
+ ({ - id: i + 1, - name: `XXXX${i + 1}有限公司`, - unit: "散运三级单位", - dept: "采购部", - category: ["燃油", "润滑油", "备件"][i % 3], - evalLevel: ["A", "B", "C", "D"][i % 4], -})); +interface Supplier { + id: number; + supplierId: string; + categoryId: string; + supplierName: string; -const evalOptions = [ - { value: "", label: "请选择" }, - { value: "A", label: "A" }, - { value: "B", label: "B" }, - { value: "C", label: "C" }, - { value: "D", label: "D" }, -]; + unit: string; // 准入部门 + accessTime: string; // 准入时间 + categoryName: string; // 准入品类 + lastEval: string; // 最近一次评价 + lastEvalDate: string; // 评价时间 + +} -const categoryOptions = [ - { value: "", label: "请选择" }, - { value: "燃油", label: "燃油" }, - { value: "润滑油", label: "润滑油" }, - { value: "备件", label: "备件" }, -]; +interface SupplierSelectModalProps { + visible: boolean; + selectedSuppliers: Supplier[]; + onOk: (suppliers: Supplier[]) => void; + onCancel: () => void; +} -const PAGE_SIZE = 5; -const SupplierSelectModal = ({ +const SupplierSelectModal: React.FC = ({ visible, + selectedSuppliers, onOk, onCancel, - selectedSuppliers, }) => { - // 查询表单 const [form] = Form.useForm(); - // 选中 - const [leftSelected, setLeftSelected] = useState([]); - const [rightSelected, setRightSelected] = useState([]); - const [rightData, setRightData] = useState(selectedSuppliers || []); - const [leftPage, setLeftPage] = useState(1); - const [query, setQuery] = useState({}); - - // 数据过滤 - const filteredSuppliers = mockSuppliers.filter(item => { - const { name = "", evalLevel = "", category = "" } = query; - return ( - (!name || item.name.includes(name)) && - (!evalLevel || item.evalLevel === evalLevel) && - (!category || item.category === category) - ); - }); - const pagedSuppliers = filteredSuppliers.slice((leftPage - 1) * PAGE_SIZE, leftPage * PAGE_SIZE); + const [leftSelected, setLeftSelected] = useState([]); + const [rightSelected, setRightSelected] = useState([]); + const [rightData, setRightData] = useState([]); + const [data, setData] = useState([]); + const [pagination, setPagination] = useState({ current: 1, pageSize: 5, total: 0 }); + const [loading, setLoading] = useState(false); useEffect(() => { - setRightData(selectedSuppliers || []); - }, [selectedSuppliers, visible]); + if (visible) { + setRightData(selectedSuppliers || []); + fetchData(); + } + }, [visible]); - // 查询 - const handleSearch = () => { - setQuery(form.getFieldsValue()); - setLeftPage(1); - setLeftSelected([]); + const fetchData = async (params: any = {}, pageNo = 1, pageSize = 5) => { + setLoading(true); + try { + const res = await getSupplierCategoryPage({ ...params, pageNo, pageSize }); + if (res.code === 200) { + setData(res.data.records); + setPagination({ current: pageNo, pageSize: pageSize, total: res.data.total }); + } else { + message.error('获取数据失败'); + } + } catch { + message.error('获取数据异常'); + } finally { + setLoading(false); + } }; - // 重置 + + const handleSearch = () => { + const values = form.getFieldsValue(); + fetchData(values, 1, pagination.pageSize); + }; + const handleReset = () => { form.resetFields(); - setQuery({}); - setLeftPage(1); + fetchData({}, 1, pagination.pageSize); + }; + + const handleAdd = () => { + const added = data.filter(s => leftSelected.includes(s.id)); + const combined = [...rightData, ...added.filter(i => !rightData.some(r => r.id === i.id))]; + setRightData(combined); setLeftSelected([]); }; - const leftColumns = [ + const handleRemove = () => { + setRightData(rightData.filter(i => !rightSelected.includes(i.id))); + setRightSelected([]); + }; + + const handleOk = () => { + onOk(rightData); + }; + + const columns = [ { title: 0} - indeterminate={leftSelected.length > 0 && leftSelected.length < pagedSuppliers.length} + checked={leftSelected.length === data.length && data.length > 0} + indeterminate={leftSelected.length > 0 && leftSelected.length < data.length} onChange={e => { - setLeftSelected(e.target.checked ? pagedSuppliers.map(i => i.id) : []); + setLeftSelected(e.target.checked ? data.map(i => i.id) : []); }} >全选, dataIndex: "select", - width: 60, - render: (_: any, record) => ( + width: 80, + render: (_: any, record: Supplier) => ( { @@ -96,14 +114,12 @@ const SupplierSelectModal = ({ >选择 ) }, - { title: "供应商名称", dataIndex: "name" }, - { title: "准入单位", dataIndex: "unit" }, - { title: "准入部门", dataIndex: "dept" }, - { title: "准入品类", dataIndex: "category" }, - { title: "最近一次评价等级", dataIndex: "evalLevel" } + { title: "供应商名称", dataIndex: "supplierName" }, + { title: "准入单位", dataIndex: "deptId" }, + { title: "准入部门", dataIndex: "deptId" }, + { title: "准入品类", dataIndex: "categoryName" } ]; - // 已选表格 const rightColumns = [ { title: 全选, dataIndex: "select", - width: 60, - render: (_: any, record) => ( + width: 80, + render: (_: any, record: Supplier) => ( { @@ -126,31 +142,12 @@ const SupplierSelectModal = ({ >选择 ) }, - { title: "供应商名称", dataIndex: "name" }, - { title: "准入单位", dataIndex: "unit" }, - { title: "准入部门", dataIndex: "dept" }, - { title: "准入品类", dataIndex: "category" } + { title: "供应商名称", dataIndex: "supplierName" }, + { title: "准入单位", dataIndex: "deptId" }, + { title: "准入部门", dataIndex: "deptId" }, + { title: "准入品类", dataIndex: "categoryName" } ]; - // 添加 - const handleAdd = () => { - const added = pagedSuppliers.filter(s => leftSelected.includes(s.id)); - const combined = [...rightData, ...added.filter(i => !rightData.some(r => r.id === i.id))]; - setRightData(combined); - setLeftSelected([]); - }; - - // 移除 - const handleRemove = () => { - setRightData(rightData.filter(i => !rightSelected.includes(i.id))); - setRightSelected([]); - }; - - // 确认 - const handleOk = () => { - onOk(rightData); - }; - return ( - {/* 查询区 */}
- + {['A', 'B', 'C', 'D'].map(level => ( + + ))} - + {['燃油', '润滑油', '备件'].map(cat => ( + + ))} @@ -185,26 +185,23 @@ const SupplierSelectModal = ({ +
-
备选供应商 {filteredSuppliers.length}
+
备选供应商
{ + const values = form.getFieldsValue(); + fetchData(values, pag.current!, pag.pageSize!); + }} size="small" bordered /> -
- -
@@ -213,9 +210,9 @@ const SupplierSelectModal = ({
已选供应商
void; + recordId: string; // 用于查询详情数据 +} + +const ViewBlacklistModal: React.FC = ({ + visible, + onCancel, + recordId, +}) => { + const [loading, setLoading] = useState(false); + const [detail, setDetail] = useState(null); + const [suppliers, setSuppliers] = useState([]); + + const fetchData = async () => { + setLoading(true); + try { + const { code, data } = await coscoSupplierexit(recordId) + if (code == 200) { + setDetail(data.coscoSupplierexit); + } else { + message.error("获取详情失败"); + } + + if (code == 200) { + setSuppliers(data.coscoSupplierexitSupplierCategoryList || []); + } else { + message.error("获取供应商列表失败"); + } + } catch (error) { + message.error("获取数据异常"); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + if (visible && recordId) { + fetchData(); + } + }, [visible, recordId]); + + const columns:ColumnsType = [ + { title: "供应商名称", dataIndex: "supplierName", align: "center" }, + { title: "准入部门", dataIndex: "unit", align: "center" }, + { title: "准入时间", dataIndex: "accessTime", align: "center" }, + { title: "准入品类", dataIndex: "categoryName", align: "center" }, + { title: "最近一次评价", dataIndex: "lastEval", align: "center" }, + { title: "评价时间", dataIndex: "lastEvalDate", align: "center" }, + ]; + + return ( + 关闭} + destroyOnClose + bodyStyle={{ padding: "36px 36px 16px" }} + > + + {detail && ( + + {detail.exitTheme} + {detail.deptId} + {detail.exitReason} + + )} + +
+ + + ); +}; + +export default ViewBlacklistModal; diff --git a/src/pages/supplier/supplierExit/supplierExitManage/index.tsx b/src/pages/supplier/supplierExit/supplierExitManage/index.tsx index b79bbfa..256c518 100644 --- a/src/pages/supplier/supplierExit/supplierExitManage/index.tsx +++ b/src/pages/supplier/supplierExit/supplierExitManage/index.tsx @@ -1,11 +1,16 @@ import React, { useEffect, useState } from "react"; import { Form, Button, Table, Select, Input, DatePicker, Space, message } from "antd"; import { SearchOutlined, ReloadOutlined, PlusOutlined } from "@ant-design/icons"; - +import type { ColumnsType } from 'antd/es/table'; import CreateBlacklistModal from './components/CreateBlacklistModal' - -// mock 数据和选项省略(和上面一致) - +import ViewBlacklistModal from './components/ViewBlacklistModal'; +import { getPage } from './services' +interface ExitRecord { + exitTheme: string; // 申请主题 + deptId: string; // 发起单位/部门(两列共用) + createTime: string; // 发起时间 + accessType: string; // 审批记录状态 +} // mock 数据与服务(实际请换为接口) const orgOptions = [ { label: "请选择", value: "" }, @@ -14,37 +19,7 @@ const orgOptions = [ { label: "中远海运物流", value: "中远海运物流" }, { label: "中远海运广州公司", value: "中远海运广州公司" }, ]; - const statusOptions = [ - { label: "请选择", value: "" }, - { label: "未开始", value: "未开始" }, - { label: "进行中", value: "进行中" }, - { label: "已结束", value: "已结束" }, - ]; - -// mock接口 -const mockGetList = async ({ page = 1, pageSize = 10 }) => { - // 生成数据 - const list = Array.from({ length: pageSize }).map((_, i) => { - const idx = (page - 1) * pageSize + i + 1; - return { - id: idx, - topic: ["中山市合创展包装材料有限公司等黑灰名单申请", "深圳市欧阳华斯电源有限公司等黑灰名单申请", "广东振兴塑胶机械有限公司等黑灰名单申请", "上海硕建建筑技术工程有限公司等黑灰名单申请"][i % 4], - org: ["中远海运特运", "中远海运散运", "中远海运广州公司"][i % 3], - dept: "采购部", - time: `2024-10-2${6 - (i % 3)} 9:00`, - status: ["未开始", "进行中", "已结束"][i % 3], - } - }); - return new Promise(resolve => { - setTimeout(() => { - resolve({ - code: 200, - data: list, - total: 188, - }); - }, 300); - }); - }; + // 查询记录状态 const recordStatusOptions = [ { label: "请选择", value: "" }, @@ -59,14 +34,16 @@ const supplierExitManage: React.FC = () => { const [loading, setLoading] = useState(false); const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); const [createVisible, setCreateVisible] = useState(false); + const [viewVisible, setViewVisible] = useState(false); + const [selectedRecordId, setSelectedRecordId] = useState(null); // 查询接口 - const getList = async (page = 1, pageSize = 10) => { + const getList = async (pageNo = 1, pageSize = 10) => { setLoading(true); // 可传查询条件 form.getFieldsValue() - const { code, data: list, total } = await mockGetList({ page, pageSize }); + const { code, data } = await getPage({ pageNo, pageSize }); if (code === 200) { - setData(list); - setPagination(prev => ({ ...prev, current: page, pageSize, total })); + setData(data.records); + setPagination(prev => ({ ...prev, current: pageNo, pageSize, total: data.total })); } setLoading(false); }; @@ -90,12 +67,15 @@ const supplierExitManage: React.FC = () => { const handleApply = () => { setCreateVisible(true) }; - + const handleSelectOk = () => { + getList(); + setCreateVisible(false); + }; useEffect(() => { getList(); }, []); - const columns = [ + const columns: ColumnsType = [ { title: "序号", dataIndex: "index", @@ -104,17 +84,24 @@ const supplierExitManage: React.FC = () => { width: 60, render: (_: any, __: any, idx: number) => idx + 1, }, - { title: "申请主题", dataIndex: "topic", key: "topic", align: "center" }, - { title: "发起单位", dataIndex: "org", key: "org", align: "center" }, - { title: "发起部门", dataIndex: "dept", key: "dept", align: "center" }, - { title: "发起时间", dataIndex: "time", key: "time", align: "center" }, - { title: "审批记录状态", dataIndex: "status", key: "status", align: "center" }, + { title: "申请主题", dataIndex: "exitTheme", key: "exitTheme", align: "center" }, + { title: "发起单位", dataIndex: "deptId", key: "deptId", align: "center" }, + { title: "发起部门", dataIndex: "deptId", key: "deptId", align: "center" }, + { title: "发起时间", dataIndex: "createTime", key: "createTime", align: "center" }, + { title: "审批记录状态", dataIndex: "approveStatusText", key: "approveStatusText", align: "center" }, { title: "操作", key: "option", align: "center", render: (record: any) => ( - message.error('123')}>查看 + { + setSelectedRecordId(record.id); + setViewVisible(true); + }} + > + 查看 + ), }, ]; @@ -163,7 +150,12 @@ const supplierExitManage: React.FC = () => { bordered /> - setCreateVisible(false)} onOk={() => setCreateVisible(false)} /> + setCreateVisible(false)} onOk={handleSelectOk} /> + setViewVisible(false)} + /> ); }; diff --git a/src/pages/supplier/supplierExit/supplierExitManage/services.ts b/src/pages/supplier/supplierExit/supplierExitManage/services.ts new file mode 100644 index 0000000..5144c97 --- /dev/null +++ b/src/pages/supplier/supplierExit/supplierExitManage/services.ts @@ -0,0 +1,64 @@ +import request from '@/utils/request'; + +/** + * 品类准入管理列表 + */ +interface getPageData { + pageNo: number; + pageSize: number; + deptId?: string; + accessType?: string; + reviewStatus?: string; + approveStatus?: string; + categoryId?: string; +} +export const getPage = (data: getPageData) => request.post('/coscoSupplierexit/getPage', { data }); +/** + * 供应商分页列表查询 + */ +interface getSupplierCategoryPageData { + pageNo: number; + pageSize: number; + supplierName?: number; + categoryId?: string; + reviewResult?: string; +} + +export const getSupplierCategoryPage = (data: getSupplierCategoryPageData) => request.post('/coscoSupplierexit/getSupplierCategoryPage', { data }); + + +/** + * 的供应商分页列表查询 + */ +export interface addInterface { + coscoSupplierexit: CoscoSupplierexit; + coscoSupplierexitSupplierCategoryList: CoscoSupplierexitSupplierCategoryList[]; + supplierIdList: string[]; + [property: string]: any; +} + +export interface CoscoSupplierexit { + deptId: string; + exitReason: string; + exitTheme: string; + [property: string]: any; +} + +export interface CoscoSupplierexitSupplierCategoryList { + categoryId: string; + supplierId: string; + [property: string]: any; +} + +export const add = (data: addInterface) => request.post('/coscoSupplierexit/add', { data }); + + + +/** + * 退出详情页(没分页) + */ +export const coscoSupplierexit = (id: string) => request.get(`/coscoSupplierexit/${id}`); + + + +