From 6c5c5528cba3f7d72f3f592f909c11f6fec04672 Mon Sep 17 00:00:00 2001 From: linxd <544554903@qq.com> Date: Mon, 30 Jun 2025 20:44:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BB=9F=E8=AE=A1=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=BC=80=E5=8F=91=E5=AF=B9=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/router.config.ts | 45 +++ src/dicts/dataStatistics.ts | 57 ++++ .../supplierAnnualStatistics.less | 0 .../supplierAnnualStatistics.tsx | 283 ++++++++++++++++ .../supplierEvaluateStatistics.less | 7 + .../supplierEvaluateStatistics.tsx | 304 +++++++++++++++++ .../supplierExitStatistics.less | 0 .../supplierExitStatistics.tsx | 285 ++++++++++++++++ ...upplierQualificationWarningStatistics.less | 0 ...supplierQualificationWarningStatistics.tsx | 319 ++++++++++++++++++ src/servers/api/dataStatistics.ts | 179 ++++++++++ src/servers/dao/dataStatistics.d.ts | 195 +++++++++++ 12 files changed, 1674 insertions(+) create mode 100644 src/dicts/dataStatistics.ts create mode 100644 src/pages/dataStatistics/supplierAnnualStatistics/supplierAnnualStatistics.less create mode 100644 src/pages/dataStatistics/supplierAnnualStatistics/supplierAnnualStatistics.tsx create mode 100644 src/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics.less create mode 100644 src/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics.tsx create mode 100644 src/pages/dataStatistics/supplierExitStatistics/supplierExitStatistics.less create mode 100644 src/pages/dataStatistics/supplierExitStatistics/supplierExitStatistics.tsx create mode 100644 src/pages/dataStatistics/supplierQualificationWarningStatistics/supplierQualificationWarningStatistics.less create mode 100644 src/pages/dataStatistics/supplierQualificationWarningStatistics/supplierQualificationWarningStatistics.tsx create mode 100644 src/servers/api/dataStatistics.ts create mode 100644 src/servers/dao/dataStatistics.d.ts diff --git a/config/router.config.ts b/config/router.config.ts index 75f2db8..818bce1 100644 --- a/config/router.config.ts +++ b/config/router.config.ts @@ -202,6 +202,51 @@ export default [ // } ] }, + //数据统计 + { + name: 'dataStatistics', + path: '/dataStatistics', + meta: { + title: '数据统计', + icon: 'icon-fenlei', + }, + component: '@/layouts/MainLayout', + routes: [ + { + name: 'supplierEvaluateStatistics', + path: '/dataStatistics/supplierEvaluateStatistics', + meta: { + title: '供应商评价情况统计', + icon: 'icon-fenlei', + }, + component: '@/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics', + }, { + name: 'supplierAnnualStatistics', + path: '/dataStatistics/supplierAnnualStatistics', + meta: { + title: '供应商年审情况统计', + icon: 'icon-fenlei', + }, + component: '@/pages/dataStatistics/supplierAnnualStatistics/supplierAnnualStatistics', + }, { + name: 'supplierQualificationWarningStatistics', + path: '/dataStatistics/supplierQualificationWarningStatistics', + meta: { + title: '供应商资质预警统计', + icon: 'icon-fenlei', + }, + component: '@/pages/dataStatistics/supplierQualificationWarningStatistics/supplierQualificationWarningStatistics', + }, { + name: 'supplierExitStatistics', + path: '/dataStatistics/supplierExitStatistics', + meta: { + title: '供应商清退情况统计', + icon: 'icon-fenlei', + }, + component: '@/pages/dataStatistics/supplierExitStatistics/supplierExitStatistics', + } + ] + }, // 供应商年审分组 { name: 'supplierAnnual', diff --git a/src/dicts/dataStatistics.ts b/src/dicts/dataStatistics.ts new file mode 100644 index 0000000..26eec18 --- /dev/null +++ b/src/dicts/dataStatistics.ts @@ -0,0 +1,57 @@ +// 数据统计模块字典 + +// 评价等级字典 +export const EvaluateLevelText = { + 'A': 'A级', + 'B': 'B级', + 'C': 'C级', + 'D': 'D级', +}; + +// 评价等级对应颜色 +export const EvaluateLevelColor = { + 'A': 'green', + 'B': 'blue', + 'C': 'orange', + 'D': 'red', +}; + +// 供应商类型 +export const SupplierTypeText = { + 'DOMESTIC': '境内', + 'FOREIGN': '境外', +}; + +// 评价年度列表 +export const EvaluateYears = [ + { label: '2023年', value: '2023' }, + { label: '2022年', value: '2022' }, + { label: '2021年', value: '2021' }, +]; + +// 年审结果字典 +export const AnnualReviewResultText = { + '1': '合格', + '2': '不合格', +}; + +// 年审结果对应颜色 +export const AnnualReviewResultColor = { + '1': 'green', + '2': 'red', +}; + +// 年审年度列表 +export const AnnualReviewYears = [ + { label: '2023年', value: '2023' }, + { label: '2022年', value: '2022' }, + { label: '2021年', value: '2021' }, +]; + +// 数据统计类型 +export const StatisticsType = { + 'EVALUATE': 'evaluate', // 评价情况统计 + 'ANNUAL': 'annual', // 年度考核统计 + 'EXIT': 'exit', // 退出情况统计 + 'QUALIFICATION': 'qualification', // 资质预警统计 +}; diff --git a/src/pages/dataStatistics/supplierAnnualStatistics/supplierAnnualStatistics.less b/src/pages/dataStatistics/supplierAnnualStatistics/supplierAnnualStatistics.less new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/dataStatistics/supplierAnnualStatistics/supplierAnnualStatistics.tsx b/src/pages/dataStatistics/supplierAnnualStatistics/supplierAnnualStatistics.tsx new file mode 100644 index 0000000..541efb0 --- /dev/null +++ b/src/pages/dataStatistics/supplierAnnualStatistics/supplierAnnualStatistics.tsx @@ -0,0 +1,283 @@ +import React, { useState, useEffect } from 'react'; +import { + Button, + Table, + Space, + Input, + Select, + Form, + Tooltip, + Tag, + DatePicker, + message +} from 'antd'; +import type { TablePaginationConfig } from 'antd'; +import { + SearchOutlined, + DeleteOutlined, + ExportOutlined +} from '@ant-design/icons'; +import CategorySelector from '@/components/CategorySelector/CategorySelector'; +import { AnnualReviewYears, AnnualReviewResultText, AnnualReviewResultColor, SupplierTypeText } from '@/dicts/dataStatistics'; +import { getSupplierAnnualReviewStatistics, exportSupplierAnnualReviewStatistics } from '@/servers/api/dataStatistics'; +import './supplierAnnualStatistics.less'; + +const { Option } = Select; + +const SupplierAnnualStatistics: React.FC = () => { + const [loading, setLoading] = useState(false); + const [form] = Form.useForm(); + + const [statisticsData, setStatisticsData] = useState([]); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + }); + const [searchParams, setSearchParams] = useState({}); + + // 准入单位下拉选项 - 假数据 + const companyOptions = [ + { label: '中山市合创展包装材料有限公司', value: '中山市合创展包装材料有限公司' }, + { label: '广州市科技发展有限公司', value: '广州市科技发展有限公司' }, + { label: '深圳市创新科技有限公司', value: '深圳市创新科技有限公司' }, + { label: '东莞市制造业有限公司', value: '东莞市制造业有限公司' }, + ]; + + // 年审结果选项 + const annualResultOptions = Object.entries(AnnualReviewResultText).map(([key, value]) => ({ + label: value, + value: key, + })); + + // 获取数据 + const fetchStatisticsData = async ( + current = 1, + pageSize = 10, + params: DataStatistics.AnnualReviewStatisticsSearchParams = searchParams, + ) => { + if (params !== searchParams) { + setSearchParams(params); + } + + setLoading(true); + try { + // 构建请求参数 + const requestParams: DataStatistics.AnnualReviewStatisticsRequest = { + basePageRequest: { + pageNo: current, + pageSize: pageSize, + }, + ...params, + }; + + // 调用接口 + const response = await getSupplierAnnualReviewStatistics(requestParams); + + if (response.success && response.data) { + setStatisticsData(response.data.records); + setPagination({ + ...pagination, + current: response.data.current, + pageSize: response.data.size, + total: response.data.total, + }); + } else { + message.error(response.message || '获取年审统计数据失败'); + } + } catch (error) { + console.error('获取年审统计数据失败:', error); + message.error('获取年审统计数据失败'); + } finally { + setLoading(false); + } + }; + + // 首次加载获取数据 + useEffect(() => { + fetchStatisticsData(pagination.current, pagination.pageSize, {}); + }, []); + + // 处理表格分页变化 + const handleTableChange = (newPagination: TablePaginationConfig) => { + fetchStatisticsData(newPagination.current, newPagination.pageSize, searchParams); + }; + + // 获取年审结果标签 + const getResultTag = (result: string) => { + const color = AnnualReviewResultColor[result as keyof typeof AnnualReviewResultColor] || 'default'; + const text = AnnualReviewResultText[result as keyof typeof AnnualReviewResultText] || result; + return {text}; + }; + + const columns = [ + { + title: '序号', + render: (_: any, __: DataStatistics.AnnualReviewStatisticsRecord, index: number) => + (pagination.current! - 1) * pagination.pageSize! + index + 1, + width: 80, + }, + { + title: '供应商名称', + dataIndex: 'supplierName', + key: 'supplierName', + width: 180, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '境内/境外', + dataIndex: 'area', + key: 'area', + width: 100, + }, + { + title: '品类', + dataIndex: 'categoryName', + key: 'categoryName', + width: 120, + }, + { + title: '准入单位', + dataIndex: 'accessUnit', + key: 'accessUnit', + width: 180, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '准入部门', + dataIndex: 'accessDept', + key: 'accessDept', + width: 120, + }, + { + title: '年度', + dataIndex: 'annualreviewYear', + key: 'annualreviewYear', + width: 100, + render: (year: string) => `${year}年` + }, + { + title: '年审结果', + dataIndex: 'annualStatisticsResult', + key: 'annualStatisticsResult', + width: 100, + render: (result: string) => getResultTag(result), + }, + ]; + + // 处理搜索 + const handleSearch = (values: any) => { + fetchStatisticsData(1, pagination.pageSize, values); + }; + + // 导出功能 + const handleExport = () => { + const values = form.getFieldsValue(); + exportSupplierAnnualReviewStatistics(values) + .then(response => { + // 创建a标签进行下载 + const url = window.URL.createObjectURL(new Blob([response])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', `供应商年审情况统计_${new Date().getTime()}.xlsx`); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }) + .catch(error => { + console.error('导出失败:', error); + message.error('导出失败'); + }); + }; + + return ( +
+
+
+ + + + + + + + + + + + + + + + +
+
+ +
+
+ +
+ + + + ); +}; + +export default SupplierAnnualStatistics; diff --git a/src/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics.less b/src/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics.less new file mode 100644 index 0000000..c3cd0cc --- /dev/null +++ b/src/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics.less @@ -0,0 +1,7 @@ + +.supplier-evaluate-statistics { + // 评价等级样式 + .evaluate-level { + font-weight: 500; + } +} diff --git a/src/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics.tsx b/src/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics.tsx new file mode 100644 index 0000000..383186d --- /dev/null +++ b/src/pages/dataStatistics/supplierEvaluateStatistics/supplierEvaluateStatistics.tsx @@ -0,0 +1,304 @@ +import React, { useState, useEffect } from 'react'; +import { + Button, + Table, + Space, + Input, + Select, + Form, + Tooltip, + Tag, + DatePicker, + message +} from 'antd'; +import type { TablePaginationConfig } from 'antd'; +import { + SearchOutlined, + DeleteOutlined, + ExportOutlined +} from '@ant-design/icons'; +import CategorySelector from '@/components/CategorySelector/CategorySelector'; +import { EvaluateLevelText, EvaluateLevelColor, EvaluateYears, SupplierTypeText } from '@/dicts/dataStatistics'; +import { getSupplierEvaluateStatistics, exportSupplierEvaluateStatistics } from '@/servers/api/dataStatistics'; +import { getAllEvaluateRules } from '@/servers/api/supplierEvaluate'; +import type { EvaluateRuleItem } from '@/servers/dao/supplierEvaluateTask'; +import './supplierEvaluateStatistics.less'; + +const { Option } = Select; +const { RangePicker } = DatePicker; + +const SupplierEvaluateStatistics: React.FC = () => { + const [loading, setLoading] = useState(false); + const [form] = Form.useForm(); + + const [statisticsData, setStatisticsData] = useState([]); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + }); + const [searchParams, setSearchParams] = useState({}); + // 评价等级列表 + const [evaluateRules, setEvaluateRules] = useState([]); + + // 准入单位下拉选项 - 假数据 + const companyOptions = [ + { label: '中山市合创展包装材料有限公司', value: '中山市合创展包装材料有限公司' }, + { label: '广州市科技发展有限公司', value: '广州市科技发展有限公司' }, + { label: '深圳市创新科技有限公司', value: '深圳市创新科技有限公司' }, + { label: '东莞市制造业有限公司', value: '东莞市制造业有限公司' }, + ]; + + // 获取评价规则列表 + const fetchEvaluateRules = async () => { + try { + const response = await getAllEvaluateRules(); + if (response.success && response.data) { + setEvaluateRules(response.data); + } else { + message.error(response.message || '获取评价规则列表失败'); + } + } catch (error) { + console.error('获取评价规则列表失败:', error); + message.error('获取评价规则列表失败'); + } + }; + + // 首次加载获取评价规则列表 + useEffect(() => { + fetchEvaluateRules(); + }, []); + + // 更新fetchStatisticsData方法实现真实接口调用 + const fetchStatisticsData = async ( + current = 1, + pageSize = 10, + params: DataStatistics.EvaluateStatisticsSearchParams = searchParams, + ) => { + if (params !== searchParams) { + setSearchParams(params); + } + + setLoading(true); + try { + // 构建请求参数 + const requestParams: DataStatistics.EvaluateStatisticsRequest = { + basePageRequest: { + pageNo: current, + pageSize: pageSize, + }, + ...params, + }; + + // 调用接口 + const response = await getSupplierEvaluateStatistics(requestParams); + + if (response.success && response.data) { + setStatisticsData(response.data.records); + setPagination({ + ...pagination, + current: response.data.current, + pageSize: response.data.size, + total: response.data.total, + }); + } else { + message.error(response.message || '获取评价统计数据失败'); + } + } catch (error) { + console.error('获取评价统计数据失败:', error); + message.error('获取评价统计数据失败'); + } finally { + setLoading(false); + } + }; + + // 首次加载获取数据 + useEffect(() => { + fetchStatisticsData(pagination.current, pagination.pageSize, {}); + }, []); + + // 处理表格分页变化 + const handleTableChange = (newPagination: TablePaginationConfig) => { + fetchStatisticsData(newPagination.current, newPagination.pageSize, searchParams); + }; + + // 获取评级标签 + const getLevelTag = (level: string) => { + const color = EvaluateLevelColor[level as keyof typeof EvaluateLevelColor] || 'default'; + const text = EvaluateLevelText[level as keyof typeof EvaluateLevelText] || '未知等级'; + return {text}; + }; + + const columns = [ + { + title: '序号', + render: (_: any, __: DataStatistics.EvaluateStatisticsRecord, index: number) => + (pagination.current! - 1) * pagination.pageSize! + index + 1, + width: 80, + }, + { + title: '供应商名称', + dataIndex: 'supplierName', + key: 'supplierName', + width: 180, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '境内/境外', + dataIndex: 'area', + key: 'area', + width: 100, + }, + { + title: '品类', + dataIndex: 'categoryName', + key: 'categoryName', + width: 120, + }, + { + title: '准入单位', + dataIndex: 'accessUnit', + key: 'accessUnit', + width: 180, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '准入部门', + dataIndex: 'accessDept', + key: 'accessDept', + width: 120, + }, + { + title: '评价年度', + dataIndex: 'evaluateYear', + key: 'evaluateYear', + width: 100, + render: (year: string | null) => year ? `${year}年` : '-' + }, + { + title: '评价等级', + dataIndex: 'evaluateResult', + key: 'evaluateResult', + width: 100, + render: (level: string) => getLevelTag(level), + }, + ]; + + // 处理搜索 + const handleSearch = (values: any) => { + fetchStatisticsData(1, pagination.pageSize, values); + }; + + // 更新handleExport方法实现真实导出功能 + const handleExport = () => { + const values = form.getFieldsValue(); + exportSupplierEvaluateStatistics(values) + .then(response => { + // 创建a标签进行下载 + const url = window.URL.createObjectURL(new Blob([response])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', `供应商评价情况统计_${new Date().getTime()}.xlsx`); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }) + .catch(error => { + console.error('导出失败:', error); + message.error('导出失败'); + }); + }; + + return ( +
+
+
+ + + + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ + + ); +}; + +export default SupplierEvaluateStatistics; \ No newline at end of file diff --git a/src/pages/dataStatistics/supplierExitStatistics/supplierExitStatistics.less b/src/pages/dataStatistics/supplierExitStatistics/supplierExitStatistics.less new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/dataStatistics/supplierExitStatistics/supplierExitStatistics.tsx b/src/pages/dataStatistics/supplierExitStatistics/supplierExitStatistics.tsx new file mode 100644 index 0000000..c29f413 --- /dev/null +++ b/src/pages/dataStatistics/supplierExitStatistics/supplierExitStatistics.tsx @@ -0,0 +1,285 @@ +import React, { useState, useEffect } from 'react'; +import { + Button, + Table, + Space, + Input, + Select, + Form, + Tooltip, + Tag, + DatePicker, + message +} from 'antd'; +import type { TablePaginationConfig } from 'antd'; +import { + SearchOutlined, + DeleteOutlined, + ExportOutlined +} from '@ant-design/icons'; +import CategorySelector from '@/components/CategorySelector/CategorySelector'; +import { SupplierTypeText } from '@/dicts/dataStatistics'; +import { getSupplierExitStatistics, exportSupplierExitStatistics } from '@/servers/api/dataStatistics'; +import moment from 'moment'; +import './supplierExitStatistics.less'; + +const { Option } = Select; +const { RangePicker } = DatePicker; + +const SupplierExitStatistics: React.FC = () => { + const [loading, setLoading] = useState(false); + const [form] = Form.useForm(); + + const [statisticsData, setStatisticsData] = useState([]); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + }); + const [searchParams, setSearchParams] = useState({}); + + // 退出单位下拉选项 - 假数据 + const companyOptions = [ + { label: '中山市合创展包装材料有限公司', value: '中山市合创展包装材料有限公司' }, + { label: '广州市科技发展有限公司', value: '广州市科技发展有限公司' }, + { label: '深圳市创新科技有限公司', value: '深圳市创新科技有限公司' }, + { label: '东莞市制造业有限公司', value: '东莞市制造业有限公司' }, + ]; + + // 年度下拉选项 + const yearOptions = [ + { label: '2023年', value: '2023' }, + { label: '2022年', value: '2022' }, + { label: '2021年', value: '2021' }, + { label: '2020年', value: '2020' }, + ]; + + // 获取数据 + const fetchStatisticsData = async ( + current = 1, + pageSize = 10, + params: DataStatistics.ExitStatisticsSearchParams = searchParams, + ) => { + if (params !== searchParams) { + setSearchParams(params); + } + + setLoading(true); + try { + // 处理日期范围 + const { applyTimeRange, ...otherParams } = params; + + const requestParams: DataStatistics.ExitStatisticsRequest = { + basePageRequest: { + pageNo: current, + pageSize: pageSize, + }, + ...otherParams + }; + + // 如果有日期范围,转换为开始和结束日期 + if (applyTimeRange && applyTimeRange.length === 2) { + requestParams.applyTimeStart = applyTimeRange[0]; + requestParams.applyTimeEnd = applyTimeRange[1]; + } + + // 调用接口 + const response = await getSupplierExitStatistics(requestParams); + + if (response.success && response.data) { + setStatisticsData(response.data.records); + setPagination({ + ...pagination, + current: response.data.current, + pageSize: response.data.size, + total: response.data.total, + }); + } else { + message.error(response.message || '获取退出统计数据失败'); + } + } catch (error) { + console.error('获取退出统计数据失败:', error); + message.error('获取退出统计数据失败'); + } finally { + setLoading(false); + } + }; + + // 首次加载获取数据 + useEffect(() => { + fetchStatisticsData(pagination.current, pagination.pageSize, {}); + }, []); + + // 处理表格分页变化 + const handleTableChange = (newPagination: TablePaginationConfig) => { + fetchStatisticsData(newPagination.current, newPagination.pageSize, searchParams); + }; + + // 格式化日期 + const formatDate = (dateStr: string) => { + return moment(dateStr).format('YYYY-MM-DD HH:mm:ss'); + }; + + const columns = [ + { + title: '序号', + render: (_: any, __: DataStatistics.ExitStatisticsRecord, index: number) => + (pagination.current! - 1) * pagination.pageSize! + index + 1, + width: 80, + }, + { + title: '供应商名称', + dataIndex: 'supplierName', + key: 'supplierName', + width: 180, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '境内/境外', + dataIndex: 'area', + key: 'area', + width: 100, + }, + { + title: '退出品类', + dataIndex: 'categoryName', + key: 'categoryName', + width: 120, + }, + { + title: '退出单位', + dataIndex: 'accessUnit', + key: 'accessUnit', + width: 150, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '退出部门', + dataIndex: 'accessDept', + key: 'accessDept', + width: 120, + }, + { + title: '退出申请人', + dataIndex: 'applyUser', + key: 'applyUser', + width: 100, + }, + { + title: '退出时间', + dataIndex: 'applyTime', + key: 'applyTime', + width: 160, + render: (text: string) => formatDate(text), + }, + ]; + + // 处理搜索 + const handleSearch = (values: any) => { + fetchStatisticsData(1, pagination.pageSize, values); + }; + + // 导出功能 + const handleExport = () => { + const values = form.getFieldsValue(); + exportSupplierExitStatistics(values) + .then(response => { + // 创建a标签进行下载 + const url = window.URL.createObjectURL(new Blob([response])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', `供应商退出情况统计_${new Date().getTime()}.xlsx`); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }) + .catch(error => { + console.error('导出失败:', error); + message.error('导出失败'); + }); + }; + + return ( +
+
+
+ + + + + + + + + + + + + + +
+ +
+
+ +
+
record.supplierName + record.applyTime} + dataSource={statisticsData} + pagination={pagination} + loading={loading} + onChange={handleTableChange} + scroll={{ x: 1200 }} + /> + + + ); +}; + +export default SupplierExitStatistics; diff --git a/src/pages/dataStatistics/supplierQualificationWarningStatistics/supplierQualificationWarningStatistics.less b/src/pages/dataStatistics/supplierQualificationWarningStatistics/supplierQualificationWarningStatistics.less new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/dataStatistics/supplierQualificationWarningStatistics/supplierQualificationWarningStatistics.tsx b/src/pages/dataStatistics/supplierQualificationWarningStatistics/supplierQualificationWarningStatistics.tsx new file mode 100644 index 0000000..0ac6a72 --- /dev/null +++ b/src/pages/dataStatistics/supplierQualificationWarningStatistics/supplierQualificationWarningStatistics.tsx @@ -0,0 +1,319 @@ +import React, { useState, useEffect } from 'react'; +import { + Button, + Table, + Space, + Input, + Select, + Form, + Tooltip, + Tag, + DatePicker, + message +} from 'antd'; +import type { TablePaginationConfig } from 'antd'; +import { + SearchOutlined, + DeleteOutlined, + ExportOutlined +} from '@ant-design/icons'; +import CategorySelector from '@/components/CategorySelector/CategorySelector'; +import { SupplierTypeText } from '@/dicts/dataStatistics'; +import { getSupplierQualificationExpire, exportSupplierQualificationExpire } from '@/servers/api/dataStatistics'; +import moment from 'moment'; +import './supplierQualificationWarningStatistics.less'; + +const { Option } = Select; +const { RangePicker } = DatePicker; + +const SupplierQualificationWarningStatistics: React.FC = () => { + const [loading, setLoading] = useState(false); + const [form] = Form.useForm(); + + const [statisticsData, setStatisticsData] = useState([]); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 10, + total: 0, + showSizeChanger: true, + showQuickJumper: true, + showTotal: (total) => `共 ${total} 条记录`, + }); + const [searchParams, setSearchParams] = useState({}); + + // 准入单位下拉选项 - 假数据 + const companyOptions = [ + { label: '中山市合创展包装材料有限公司', value: '中山市合创展包装材料有限公司' }, + { label: '广州市科技发展有限公司', value: '广州市科技发展有限公司' }, + { label: '深圳市创新科技有限公司', value: '深圳市创新科技有限公司' }, + { label: '东莞市制造业有限公司', value: '东莞市制造业有限公司' }, + ]; + + // 境内/境外选项 + const areaOptions = [ + { label: '境内', value: 'dvs' }, + { label: '境外', value: 'ovs' }, + ]; + + // 获取数据 + const fetchStatisticsData = async ( + current = 1, + pageSize = 10, + params: DataStatistics.QualificationExpireSearchParams = searchParams, + ) => { + if (params !== searchParams) { + setSearchParams(params); + } + + setLoading(true); + try { + // 处理日期范围 + const { termOfValidityRange, ...otherParams } = params; + + const requestParams: DataStatistics.QualificationExpireRequest = { + basePageRequest: { + pageNo: current, + pageSize: pageSize, + }, + ...otherParams + }; + + // 如果有日期范围,转换为开始和结束日期 + if (termOfValidityRange && termOfValidityRange.length === 2) { + requestParams.termOfValidityStart = termOfValidityRange[0]; + requestParams.termOfValidityEnd = termOfValidityRange[1]; + } + + // 调用接口 + const response = await getSupplierQualificationExpire(requestParams); + + if (response.success && response.data) { + setStatisticsData(response.data.records); + setPagination({ + ...pagination, + current: response.data.current, + pageSize: response.data.size, + total: response.data.total, + }); + } else { + message.error(response.message || '获取资质预警统计数据失败'); + } + } catch (error) { + console.error('获取资质预警统计数据失败:', error); + message.error('获取资质预警统计数据失败'); + } finally { + setLoading(false); + } + }; + + // 首次加载获取数据 + useEffect(() => { + fetchStatisticsData(pagination.current, pagination.pageSize, {}); + }, []); + + // 处理表格分页变化 + const handleTableChange = (newPagination: TablePaginationConfig) => { + fetchStatisticsData(newPagination.current, newPagination.pageSize, searchParams); + }; + + // 格式化日期 + const formatDate = (dateStr: string) => { + return moment(dateStr).format('YYYY-MM-DD'); + }; + + // 获取境内/境外显示文本 + const getAreaText = (areaCode: string) => { + const area = areaOptions.find(item => item.value === areaCode); + return area ? area.label : areaCode; + }; + + const columns = [ + { + title: '序号', + render: (_: any, __: DataStatistics.QualificationExpireRecord, index: number) => + (pagination.current! - 1) * pagination.pageSize! + index + 1, + width: 80, + }, + { + title: '供应商名称', + dataIndex: 'supplierName', + key: 'supplierName', + width: 180, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '境内/境外', + dataIndex: 'area', + key: 'area', + width: 100, + render: (text: string) => getAreaText(text), + }, + { + title: '品类', + dataIndex: 'categoryName', + key: 'categoryName', + width: 120, + }, + { + title: '准入单位', + dataIndex: 'accessUnit', + key: 'accessUnit', + width: 150, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '准入部门', + dataIndex: 'accessDept', + key: 'accessDept', + width: 120, + }, + { + title: '资质名称', + dataIndex: 'qualificationName', + key: 'qualificationName', + width: 150, + ellipsis: { + showTitle: false, + }, + render: (text: string) => ( + + {text} + + ), + }, + { + title: '资质到期时间', + dataIndex: 'termOfValidity', + key: 'termOfValidity', + width: 120, + render: (text: string) => formatDate(text), + }, + ]; + + // 处理搜索 + const handleSearch = (values: any) => { + // 处理日期范围 + const formattedValues = { ...values }; + if (values.termOfValidityRange && values.termOfValidityRange.length === 2) { + formattedValues.termOfValidityRange = [ + values.termOfValidityRange[0].format('YYYY-MM-DD'), + values.termOfValidityRange[1].format('YYYY-MM-DD'), + ]; + } + + fetchStatisticsData(1, pagination.pageSize, formattedValues); + }; + + // 导出功能 + const handleExport = () => { + const values = form.getFieldsValue(); + // 处理日期范围 + const exportParams = { ...values }; + if (values.termOfValidityRange && values.termOfValidityRange.length === 2) { + exportParams.termOfValidityRange = [ + values.termOfValidityRange[0].format('YYYY-MM-DD'), + values.termOfValidityRange[1].format('YYYY-MM-DD'), + ]; + } + + exportSupplierQualificationExpire(exportParams) + .then(response => { + // 创建a标签进行下载 + const url = window.URL.createObjectURL(new Blob([response])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', `供应商资质预警统计_${new Date().getTime()}.xlsx`); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }) + .catch(error => { + console.error('导出失败:', error); + message.error('导出失败'); + }); + }; + + return ( +
+
+
+ + + + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ + + ); +}; + +export default SupplierQualificationWarningStatistics; diff --git a/src/servers/api/dataStatistics.ts b/src/servers/api/dataStatistics.ts new file mode 100644 index 0000000..7aebc39 --- /dev/null +++ b/src/servers/api/dataStatistics.ts @@ -0,0 +1,179 @@ +import request from '@/utils/request'; +import { getAllEvaluateRules } from './supplierEvaluate'; + +// 数据统计模块api + +// 评价情况统计列表查询 +export async function getEvaluateStatisticsList(params: DataStatistics.EvaluateStatisticsRequest) { + return request('/api/dataStatistics/evaluateStatistics/list', { + method: 'POST', + data: params, + }); +} + +// 评价情况统计数据导出 +export async function exportEvaluateStatistics(params: DataStatistics.EvaluateStatisticsSearchParams) { + return request('/api/dataStatistics/evaluateStatistics/export', { + method: 'POST', + data: params, + responseType: 'blob', + }); +} + +// 年度考核统计列表查询 +export async function getAnnualStatisticsList(params: any) { + return request('/api/dataStatistics/annualStatistics/list', { + method: 'POST', + data: params, + }); +} + +// 年度考核统计数据导出 +export async function exportAnnualStatistics(params: any) { + return request('/api/dataStatistics/annualStatistics/export', { + method: 'POST', + data: params, + responseType: 'blob', + }); +} + +// 供应商退出统计列表查询 +export async function getExitStatisticsList(params: any) { + return request('/api/dataStatistics/exitStatistics/list', { + method: 'POST', + data: params, + }); +} + +// 供应商退出统计数据导出 +export async function exportExitStatistics(params: any) { + return request('/api/dataStatistics/exitStatistics/export', { + method: 'POST', + data: params, + responseType: 'blob', + }); +} + +// 资质预警统计列表查询 +export async function getQualificationWarningStatisticsList(params: any) { + return request('/api/dataStatistics/qualificationWarningStatistics/list', { + method: 'POST', + data: params, + }); +} + +// 资质预警统计数据导出 +export async function exportQualificationWarningStatistics(params: any) { + return request('/api/dataStatistics/qualificationWarningStatistics/export', { + method: 'POST', + data: params, + responseType: 'blob', + }); +} + +// ----------------- 供应商评价情况统计 ----------------- +/** + * 获取供应商评价情况统计列表 + * @param params 查询参数 + * @returns Promise + */ +export async function getSupplierEvaluateStatistics(params: DataStatistics.EvaluateStatisticsRequest) { + return request>>('/dataStatistics/getSupplierEvaluateStatistics', { + method: 'POST', + data: params, + }); +} + +/** + * 导出供应商评价情况统计 + * @param params 查询参数 + * @returns Promise + */ +export async function exportSupplierEvaluateStatistics(params: DataStatistics.EvaluateStatisticsSearchParams) { + return request('/dataStatistics/exportSupplierEvaluateStatistics', { + method: 'GET', + params, + responseType: 'blob', + }); +} + +// ----------------- 供应商年审统计 ----------------- +/** + * 获取供应商年审统计列表 + * @param params 查询参数 + * @returns Promise + */ +export async function getSupplierAnnualReviewStatistics(params: DataStatistics.AnnualReviewStatisticsRequest) { + return request>>('/dataStatistics/getSupplierAnnualReviewStatistics', { + method: 'POST', + data: params, + }); +} + +/** + * 导出供应商年审列表 + * @param params 查询参数 + * @returns Promise + */ +export async function exportSupplierAnnualReviewStatistics(params: DataStatistics.AnnualReviewStatisticsSearchParams) { + return request('/dataStatistics/exportSupplierAnnualReviewStatistics', { + method: 'GET', + params, + responseType: 'blob', + }); +} + +// ----------------- 供应商退出统计 ----------------- +/** + * 获取供应商退出统计列表 + * @param params 查询参数 + * @returns Promise + */ +export async function getSupplierExitStatistics(params: DataStatistics.ExitStatisticsRequest) { + return request>>('/dataStatistics/getSupplierExitStatistics', { + method: 'POST', + data: params, + }); +} + +/** + * 导出供应商退出列表 + * @param params 查询参数 + * @returns Promise + */ +export async function exportSupplierExitStatistics(params: DataStatistics.ExitStatisticsSearchParams) { + return request('/dataStatistics/exportSupplierExitStatistics', { + method: 'GET', + params, + responseType: 'blob', + }); +} + +// ----------------- 供应商资质过期统计 ----------------- +/** + * 获取供应商资质过期列表 + * @param params 查询参数 + * @returns Promise + */ +export async function getSupplierQualificationExpire(params: DataStatistics.QualificationExpireRequest) { + return request>>('/dataStatistics/getSupplierQualificationExpire', { + method: 'POST', + data: params, + }); +} + +/** + * 导出供应商资质列表 + * @param params 查询参数 + * @returns Promise + */ +export async function exportSupplierQualificationExpire(params: DataStatistics.QualificationExpireSearchParams) { + return request('/dataStatistics/exportSupplierQualificationExpire', { + method: 'GET', + params, + responseType: 'blob', + }); +} + +// 导出方法 - 用于兼容老代码 +export { getAllEvaluateRules }; diff --git a/src/servers/dao/dataStatistics.d.ts b/src/servers/dao/dataStatistics.d.ts new file mode 100644 index 0000000..65ad461 --- /dev/null +++ b/src/servers/dao/dataStatistics.d.ts @@ -0,0 +1,195 @@ +// 数据统计大模块 + +// 数据统计模块类型定义 +declare namespace DataStatistics { + // 通用分页请求参数 + export interface BasePageRequest { + pageNo: number; + pageSize: number; + } + + // 通用分页响应 + export interface PageResponse { + records: T[]; + total: number; + size: number; + current: number; + orders?: any[]; + optimizeCountSql?: boolean; + hitCount?: boolean; + countId?: null; + maxLimit?: null; + searchCount?: boolean; + pages?: number; + } + + // 评价情况统计 - 记录 + export interface EvaluateStatisticsRecord { + id: string; + area: string; // 境内/境外 + categoryName: string | null; // 品类 + supplierName: string; // 供应商名称 + accessUnit: string; // 准入单位 + accessDept: string; // 准入部门 + evaluateYear: string | null; // 评价年度 + evaluateResult: string; // 评价结果/等级 + basePageRequest: null; + } + + // 评价情况统计 - 查询参数 + export interface EvaluateStatisticsSearchParams { + supplierName?: string; + evaluateYear?: string; + accessUnit?: string; + evaluateResult?: string; + area?: string; + categoryName?: string; + accessDept?: string; + } + + // 评价情况统计 - 请求参数 + export interface EvaluateStatisticsRequest { + basePageRequest: BasePageRequest; + supplierName?: string; + evaluateYear?: string; + accessUnit?: string; + evaluateResult?: string; + area?: string; + categoryName?: string; + accessDept?: string; + } + + // 年审统计 - 记录 + export interface AnnualReviewStatisticsRecord { + id: string; + area: string; // 境内/境外 + categoryName: string | null; // 品类 + supplierName: string; // 供应商名称 + accessUnit: string; // 准入单位 + accessDept: string; // 准入部门 + annualreviewYear: string; // 年审年度 + annualStatisticsResult: string; // 年审结果 + basePageRequest: null; + } + + // 年审统计 - 查询参数 + export interface AnnualReviewStatisticsSearchParams { + supplierName?: string; + annualreviewYear?: string; + accessUnit?: string; + annualStatisticsResult?: string; + area?: string; + categoryName?: string; + accessDept?: string; + } + + // 年审统计 - 请求参数 + export interface AnnualReviewStatisticsRequest { + basePageRequest: BasePageRequest; + supplierName?: string; + annualreviewYear?: string; + accessUnit?: string; + annualStatisticsResult?: string; + area?: string; + categoryName?: string; + accessDept?: string; + } + + // 退出统计 - 记录 + export interface ExitStatisticsRecord { + area: string; // 境内/境外 + categoryName: string | null; // 品类 + supplierName: string; // 供应商名称 + accessUnit: string; // 退出单位 + accessDept: string; // 退出部门 + applyUser: string; // 申请人 + applyTime: string; // 申请时间 + basePageRequest: null; + } + + // 退出统计 - 查询参数 + export interface ExitStatisticsSearchParams { + supplierName?: string; + accessUnit?: string; + area?: string; + categoryName?: string; + accessDept?: string; + applyUser?: string; + applyTimeRange?: string[]; + } + + // 退出统计 - 请求参数 + export interface ExitStatisticsRequest { + basePageRequest: BasePageRequest; + supplierName?: string; + accessUnit?: string; + area?: string; + categoryName?: string; + accessDept?: string; + applyUser?: string; + applyTimeStart?: string; + applyTimeEnd?: string; + } + + // 资质过期 - 记录 + export interface QualificationExpireRecord { + id: string; + authority: string; // 发证机构 + termOfValidity: string; // 有效期限 + supplierName: string; // 供应商名称 + area: string; // 境内/境外 + accessUnit: string; // 准入单位 + accessDept: string; // 准入部门 + categoryName: string | null; // 品类 + basePageRequest: null; + } + + // 资质过期 - 查询参数 + export interface QualificationExpireSearchParams { + supplierName?: string; + accessUnit?: string; + area?: string; + categoryName?: string; + accessDept?: string; + authority?: string; + termOfValidityRange?: string[]; + } + + // 资质过期 - 请求参数 + export interface QualificationExpireRequest { + basePageRequest: BasePageRequest; + supplierName?: string; + accessUnit?: string; + area?: string; + categoryName?: string; + accessDept?: string; + authority?: string; + termOfValidityStart?: string; + termOfValidityEnd?: string; + } + + // 导出功能 - 通用响应 + export interface ExportResponse { + id: string; + name: string; + deptName: string; + categoryName: string; + libraryId: string; + area: string; + supplierName: null; + applyUser: string; + applyTime: string; + approveStatus: string; + processStatusName: null; + approveResult: null; + basePageRequest: null; + coscoCategoryLibrarySupplierVos: { + name: string; + area: string; + unifiedSocialCreditCode: string; + supplierCategory: string; + id: string; + selected: boolean; + }[] + } +}