/* * @Author: code4eat awesomedema@gmail.com * @Date: 2023-03-03 11:30:33 * @LastEditors: code4eat awesomedema@gmail.com * @LastEditTime: 2025-02-28 15:18:53 * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ import { createFromIconfontCN } from '@ant-design/icons'; import { ModalForm, ProFormDependency, ProFormInstance, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form'; import { ActionType, ProColumns } from '@ant-design/pro-table'; import { Input, message, Popconfirm, Switch, Tooltip } from 'antd'; import { useEffect, useRef, useState } from 'react'; import 'moment/locale/zh-cn'; import { addData, applyBatchItemValueReq, delData, editData, generateTableDataReq, getCurrentHospAlldeps, getTableList } from './service'; import './style.less'; import React from 'react'; import generateTableData from './generateTableData'; import { useModel } from 'umi'; import KCTable from '@/components/kcTable'; const IconFont = createFromIconfontCN({ scriptUrl: '', }); //填报周期 export const DATAFILL_PERIODTYPE = [ { label: '月度', value: 1 }, { label: '季度', value: 2 }, { label: '年度', value: 3 }, { label: '变动时', value: 4 }, ]; //填报主体类型 export const DATAFILL_MAINTYPE = [ { label: '职能部门', value: 1 }, { label: '相关科室', value: 2 }, ]; //填报维度 export const DATAFILL_DIMENSIONTYPE = [ { label: '按全院 ', value: 1 }, { label: '按科室', value: 2 }, ]; type Data = { // 键为科室/部门编码,保持字符串类型 [key: string]: string; }; type LabelValue = { label: string; // value 需保持为字符串编码,避免多选时因 NaN 造成同值冲突 value: string; }; // 全局简单缓存,避免每次打开不同弹窗都重复请求 let cachedDeptOptions: LabelValue[] | null = null; export function transformToLabelValue(data: Data): LabelValue[] { const result: LabelValue[] = []; for (const key in data) { if (data.hasOwnProperty(key)) { result.push({ label: data[key], value: key, }); } } return result; } export const searchTree = (tree: any[], searchTerm: string) => { const searchTermLower = searchTerm.toLowerCase(); function searchNode(node: any) { const matchedChildren: any[] = []; if (node.children && node.children.length > 0) { node.children.forEach((child: any) => { const matchedChild = searchNode(child); if (matchedChild) { matchedChildren.push(matchedChild); } }); } if (node.responsibilityName.toLowerCase().includes(searchTermLower) || (node.responsibilityCode && node.responsibilityCode.toLowerCase().includes(searchTermLower))) { return { ...node, children: matchedChildren.length > 0 ? matchedChildren : node.children, }; } else if (matchedChildren.length > 0) { return { ...node, children: matchedChildren, }; } return null; } return tree.map((rootNode) => searchNode(rootNode)).filter((node) => node !== null); }; const defaultYear = new Date().getFullYear(); let table_columns: any[] = []; let total_tableDataSource: any[] = []; export default function FillingMana() { const { initialState, setInitialState } = useModel('@@initialState'); const [tableDataFilterParams, set_tableDataFilterParams] = useState<{ current: number; pageSize: number; name?: string; }>({ current: 1, pageSize: 10 }); const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState(''); const tableRef = useRef(); const detailTableRef = useRef(); const formRef = useRef(); const [tableDataSource, set_tableDataSource] = useState([]); const [tableColumns, set_tableColumns] = useState([]); const [currentEditRow, set_currentEditRow] = useState(undefined); const [actionType, set_actionType] = useState<'NORMAL' | 'DETAIL' | undefined>('NORMAL'); const [currentEditTableRow, set_currentEditTableRow] = useState(undefined); const [currentYear, set_currentYear] = useState(defaultYear); const [isFirstLoad, setIsFirstLoad] = useState(true); const tableColumns_default: ProColumns[] = [ { title: '操作', key: 'option', fixed: 'right', width: 80, valueType: 'option', render: (_: any, record: any) => { return ( { set_currentEditTableRow(record); }} > 编辑 ); }, }, ]; const columns: ProColumns[] = [ { title: '填报项目', ellipsis: true, dataIndex: 'name', }, { title: '填报周期', ellipsis: true, dataIndex: 'periodType', renderText(code, record, index, action) { const item = DATAFILL_PERIODTYPE.find((item) => item.value === code); return item ? item.label : ''; }, }, { title: '填报维度', ellipsis: true, dataIndex: 'dimensionType', renderText(code, record, index, action) { const item = DATAFILL_DIMENSIONTYPE.find((item) => item.value === code); return item ? item.label : ''; }, }, { title: '填报主体类型', ellipsis: true, dataIndex: 'type', renderText(code, record, index, action) { const item = DATAFILL_MAINTYPE.find((item) => item.value === code); return item ? item.label : ''; }, }, { title: '填报主体', ellipsis: true, dataIndex: 'typeName', renderText(_, record) { // 根据维度类型从 fillDeptList 提取名称并用逗号拼接 const list = Array.isArray(record?.fillDeptList) ? record.fillDeptList : []; const names = list .map((item: any) => { if (record?.dimensionType === 2) { return item?.dimensionTypeName ?? item?.departmentName ?? ''; } // 默认按全院/维度类型为 1 时取 departmentName return item?.departmentName ?? item?.dimensionTypeName ?? ''; }) .filter((s: string) => s); return names.join(','); }, }, { title: '填报单位', ellipsis: true, dataIndex: 'unit', }, { title: '填报说明', ellipsis: true, dataIndex: 'description', }, { title: '启用', width: 60, ellipsis: true, dataIndex: 'status', renderText(num, record) { return ( updateTable( { ...record, status: bool ? 1 : 0, fillDeptList: record?.fillDeptList.map((a: any) => ({ value: a.departmentCode, label: a.departmentName })), relateDeptList: record?.relateDeptList.map((a: any) => ({ value: a.departmentCode, label: a.departmentName })), }, 'EDIT', ) } /> ); }, }, { title: '操作', key: 'option', fixed: 'right', width: 120, valueType: 'option', render: (_: any, record: any) => { const { applyStatus } = record; return [ { set_currentEditRow(record); }} > 详情 , , delTableData(record)}> 删除 , ]; }, }, ]; const getGenerateTableData = async () => { const resp = await generateTableDataReq({ fillItemCode: currentEditRow?.code, dataYear: currentYear }); if (resp) { const { itemTitles, itemDatas } = resp; const { columns, dataSource } = generateTableData(itemTitles, itemDatas, [0]); table_columns = columns; total_tableDataSource = dataSource; set_tableColumns(columns); set_tableDataSource(dataSource); } }; const getTableData = async (params: any) => { const { current = 1, pageSize = 10, name } = params; const resp = await getTableList({ current, pageSize, name }); if (resp) { return { data: resp.list, success: true, total: resp.totalCount }; } return { data: [], success: false, total: 0 }; }; const delTableData = async (record: any) => { const resp = await delData(record.code); if (resp) { tableRef.current?.reload(); } }; const updateTable = async (data: any, type: 'ADD' | 'EDIT') => { try { const result = { name: data.name, type: data.type, dimensionType: data.type == 2 ? 2 : data.dimensionType, periodType: data.periodType, unit: data.unit, status: type == 'ADD' ? null : data.status, description: data.description, fillDeptList: data.fillDeptList instanceof Array ? data.fillDeptList.map((a: any) => ({ departmentCode: a.value, departmentName: a.label })) : [{ departmentCode: data.fillDeptList.value, departmentName: data.fillDeptList.label }], relateDeptList: data.type != 2 && data.dimensionType != 1 && data.relateDeptList ? data.relateDeptList.map((a: any) => ({ departmentCode: a.value, departmentName: a.label })) : [], }; if (type == 'ADD') { const resp = await addData(result); if (resp) { tableRef.current?.reload(); return true; } } if (type == 'EDIT') { const resp = await editData({ code: data.code, ...result }); if (resp) { tableRef.current?.reload(); } return true; } } catch (error) { console.log({ 'updateTable error': error }); } return false; }; const handleTableChange = (pagination: any) => { set_tableDataFilterParams({ ...tableDataFilterParams, current: pagination.current, pageSize: pagination.pageSize }); } const tableDataSearchHandle = (paramName: string) => { set_tableDataFilterParams({ ...tableDataFilterParams, current: 1, [`${paramName}`]: tableDataSearchKeywords }); } const detailtableDataSearchHandle = (paramName: string) => { const result = total_tableDataSource.filter((a: any) => a[`${paramName}`].indexOf(tableDataSearchKeywords) != -1); set_tableDataSource(result); }; const UpDataActBtn = ({ record, type, sideHandle }: { record: any; type: 'EDIT' | 'ADD'; sideHandle?: { [key: string]: any } }) => { const actType = type; const ref = React.createRef<{ save: any }>(); const [maintype, set_maintype] = useState(undefined); const [dimensionType, set_dimensionType] = useState(undefined); // 本地选项缓存,避免每次搜索触发远程过滤 const [deptOptions, set_deptOptions] = useState([]); const { commitResult } = sideHandle ? sideHandle : {}; useEffect(() => { if (type !== undefined) { formRef.current?.setFieldValue('fillDeptList', []); // 清空填报主体 } }, [maintype]); useEffect(() => { if (dimensionType !== undefined) { formRef.current?.setFieldValue('relateDeptList', []); // 清空填相关科室 } }, [dimensionType]); // 弹窗打开时才加载选项,并使用文件级缓存 const ensureDeptOptions = async () => { if (deptOptions && deptOptions.length > 0) return; if (cachedDeptOptions && cachedDeptOptions.length > 0) { set_deptOptions(cachedDeptOptions); return; } const depLists = await getCurrentHospAlldeps(); const opts = depLists ? transformToLabelValue(depLists) : []; cachedDeptOptions = opts; set_deptOptions(opts); }; return ( ({ label: a.departmentName, value: a.departmentCode })) || [], relateDeptList: record?.relateDeptList?.map((a: any) => ({ label: a.departmentName, value: a.departmentCode })) || [], } : { periodType: 1, type: 1, dimensionType: 1 } } trigger={ type == 'EDIT' ? ( ensureDeptOptions()}>编辑 ) : ( ensureDeptOptions()}>新增 ) } onFinish={(val) => { commitResult && commitResult(); return updateTable(type == 'EDIT' ? { ...val, status: record.status } : { ...val }, type); }} modalProps={{ destroyOnClose: true }} colProps={{ span: 24 }} grid > { <> ); }; useEffect(() => { if (!isFirstLoad) { getGenerateTableData(); } else { setIsFirstLoad(false); // 标记首次加载已完成 } }, [currentYear]); useEffect(() => { if (currentEditRow) { set_actionType('DETAIL'); getGenerateTableData(); } else { set_actionType('NORMAL'); } }, [currentEditRow]); return (
{actionType == 'DETAIL' && (
set_currentEditRow(undefined)}>
{currentEditRow?.name}
填报周期: {currentEditRow && `${DATAFILL_PERIODTYPE.find((item) => item.value === currentEditRow.periodType) ? DATAFILL_PERIODTYPE.find((item) => item.value === currentEditRow.periodType)?.label : ''}`} 填报维度: {currentEditRow && `${ DATAFILL_DIMENSIONTYPE.find((item) => item.value === currentEditRow.dimensionType) ? DATAFILL_DIMENSIONTYPE.find((item) => item.value === currentEditRow.dimensionType)?.label : '' }`} 填报单位:{currentEditRow?.unit}
{' '} 检索: detailtableDataSearchHandle('dimensionName')} />} onChange={(e) => { set_tableDataSearchKeywords(e.target.value); if (e.target.value.length == 0) { set_tableDataSource(total_tableDataSource); } }} onPressEnter={(e: any) => { const result = total_tableDataSource.filter((a: any) => a.dimensionName.indexOf(e.target.value) != -1); set_tableDataSource(result); }} />
{(currentEditRow?.periodType == 1 || currentEditRow?.periodType == 2) && (
set_currentYear(currentYear - 1)}>
{currentYear}
set_currentYear(currentYear + 1)}>
)}
[defaultDom.save, defaultDom.cancel], onSave: async (key, record, originRow, newLineConfig) => { let unEditableColum: any = []; const editableColumn = table_columns.filter((a: any) => { !a.editable && unEditableColum.push(a); return a.editable; }); const result = editableColumn.map((a: any) => ({ fillItemCode: record[`${unEditableColum[0].dataIndex}_fillItemCode`], dimensionCode: record[`${unEditableColum[0].dataIndex}_dimensionCode`], periodCode: a.key, value: record[`${a.key}`] ?? null, dataYear: currentYear, })); const resp = await applyBatchItemValueReq(result); if (resp) { set_currentEditTableRow(undefined); getGenerateTableData(); } return Promise.resolve(true); }, onCancel: (key, record, originRow, newLineConfig) => { set_currentEditTableRow(undefined); return Promise.resolve(true); }, }} />
)} {actionType != 'DETAIL' && (
{' '} 检索: tableDataSearchHandle('name')} />} onChange={(e) => { set_tableDataSearchKeywords(e.target.value); if (e.target.value.length == 0) { set_tableDataFilterParams({ ...tableDataFilterParams, current: 1, name: '', }); } }} onPressEnter={(e) => { set_tableDataFilterParams({ ...tableDataFilterParams, current: 1, name: (e.target as HTMLInputElement).value, }); }} />
getTableData(params)} onChange={handleTableChange} />
)}
); }