code4eat 2 роки тому
батько
коміт
03ea6ec3c2

+ 2 - 2
src/components/BMSTable/style.less

@@ -52,7 +52,7 @@
         .bms-ant-table-thead {
             .bms-ant-table-cell {
                 border-bottom: none !important;
-                padding: 9px 8px !important;
+                padding: 8px 8px !important;
                 //border-top:1px solid #dae2f2 !important ;
                 background: rgb(238 243 250 / 100%) !important;
                 //border-right: 1px solid  #dae2f2 !important;
@@ -99,7 +99,7 @@
                     // font-weight: 500;
 
                     color: #17181A;
-                    padding: 9px 8px !important; 
+                    padding: 8px 8px !important; 
                     border-bottom: none !important;
 
                     &>.bms-ant-typography {

+ 3 - 3
src/global.less

@@ -53,9 +53,9 @@ textarea {
         padding: 16px !important;
 
         .bms-ant-modal-body {
-            // max-height: 528px;
-            // overflow-y: scroll;
-            // overflow-x: hidden;
+            max-height: 600px;
+            overflow-y: scroll;
+            overflow-x: hidden;
             padding: 0;
 
             .bms-ant-modal-confirm-body-wrapper {

+ 309 - 36
src/pages/budgetMana/monthlyDataCheck/index.tsx

@@ -4,7 +4,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-16 09:42:52
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-06-27 15:35:49
+ * @LastEditTime: 2023-06-30 19:40:58
  * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -16,7 +16,7 @@ import BMSPagecontainer from '@/components/BMSPageContainer';
 import { useEffect, useRef, useState } from 'react';
 import './style.less';
 
-import { Tree, TreeProps, Tabs, Input, Modal, Transfer, Divider, Select, Popconfirm, message, Button, Skeleton, Popover, Tooltip } from 'antd';
+import { Tree, TreeProps, Tabs, Input, Modal, Transfer, Divider, Select, Popconfirm, message, Button, Skeleton, Popover, Tooltip, InputNumber } from 'antd';
 import { DataNode } from 'antd/es/tree';
 
 import expandedIcon from '../../../../static/treenode_open.png';
@@ -24,7 +24,7 @@ import closeIcon from '../../../../static/treenode_collapse.png';
 import { BMSTable } from '@/components/BMSTable';
 import { ActionType, ModalForm, ProColumns, ProColumnType, ProForm, ProFormDependency, ProFormDigit, ProFormInstance, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
 import { createFromIconfontCN } from '@ant-design/icons';
-import { addTableData, checkMonthlyReq, delTableDataRequest, downloadTemplateReq, editCheckProject, editManaIndexTableData, editTableData, editTableSalaryRequest, generateCheckProjectTableData, getCheckItemCalcStatus, getCheckProjectTableData, getCostData, getDepLists, getEmps, getHesuanUnits, getIncomeData, getManaIndexGroup, getManaIndexTableData, getManaIndicatorJiangchengCoefficient, getNoCheckTableData, getPageCheckStatus, getProjects, getSalaryInfoTableData, importMonthlyperformanceRelaFiles } from './service';
+import { addTableData, checkMonthlyReq, delTableDataRequest, downloadTemplateReq, editCheckProject, editManaIndexTableData, editTableData, editTableSalaryRequest, editUnitCostTableData, generateCheckProjectTableData, generateUnitCostTableData, getCheckItemCalcStatus, getCheckProjectTableData, getCostData, getDepLists, getEmps, getHesuanUnits, getIncomeData, getManaIndexGroup, getManaIndexTableData, getManaIndicatorJiangchengCoefficient, getNoCheckTableData, getPageCheckStatus, getProjects, getSalaryInfoTableData, getUnitCostTableData, importMonthlyperformanceRelaFiles } from './service';
 
 
 import editIcon from '../../../../static/editIcon.png';
@@ -40,6 +40,7 @@ import { getDeepestTreeData } from '@/utils/tooljs';
 
 
 import '../../../utils/zhongtaiA'
+import { formatMoneyNumber } from '@/utils/format';
 
 const IconFont = createFromIconfontCN({
     scriptUrl: '',
@@ -82,7 +83,7 @@ const MonthlyDataCheck: React.FC = () => {
 
     const [currentEditRecord, set_currentEditRecord] = useState<undefined | any>(undefined);
 
-    const [inputSalaryNum, set_inputSalaryNum] = useState(0);  //固定工资金额
+    const [inputSalaryNum, set_inputSalaryNum] = useState<undefined|number>(undefined);  //固定工资金额
 
     const [checkItemvalNum, set_checkItemvalNum] = useState(0); //考核项目数值
 
@@ -94,16 +95,18 @@ const MonthlyDataCheck: React.FC = () => {
 
     const [computeMethod, set_computeMethod] = useState('1'); //1按考核分级 2按总分
 
+    const [unitCostComputeData,set_unitCostComputeData] = useState({unitCostTotal:0,unitCostCtrlTotal:0})
+
     const [manaIndexGroups, set_manaIndexGroups] = useState<{
-        depiction: any; id: number, groupCode: string, groupName: string, hospId: number 
-}[]>([]); //管理指标分组
+        depiction: any; id: number, groupCode: string, groupName: string, hospId: number
+    }[]>([]); //管理指标分组
     const [currentSelectedManaGroup, set_currentSelectedManaGroup] = useState<{ id: number, groupCode: string, groupName: string, hospId: number }>();
 
     const formRef = useRef<ProFormInstance>();
 
     const tableRef = useRef<ActionType>();
 
-    const tableColumnOne:ProColumns[] = [
+    const tableColumnOne: ProColumns[] = [
         {
             title: '职类',
             dataIndex: 'unitTypeName',
@@ -272,6 +275,56 @@ const MonthlyDataCheck: React.FC = () => {
         //     align: 'center'
         // },
     ]
+    const tableColumnSeven = [
+        {
+            title: '项目名称',
+            dataIndex: 'name',
+        },
+        {
+            title: '项目类型',
+            dataIndex: 'costType',
+        },
+        {
+            title: '金额',
+            dataIndex: 'amount',
+            width: 200,
+            render: (text: any, record: any) => {
+            
+                return (
+                    <div style={{ display: 'flex', flexDirection: 'row', width: '100%', justifyContent: 'flex-start', alignItems: 'center' }}>
+
+                        <div style={{ width: '80px', height: 16, display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center' }}>
+                            {
+                                (currentEditRecord ? currentEditRecord.id : -1) == record.id ? <InputNumber size='small' defaultValue={record.amount} placeholder='请输入' onChange={(value) => { console.log({value}); set_currentEditRecord({...currentEditRecord,amount:value})}} style={{ width: '80px' }} /> : <span>{formatMoneyNumber(text)}</span>
+                            }
+                        </div>
+                        {(auditType == '0'&&record.summaryFlag == 0) && <img onClick={() => editHandle(record, '7')} style={{ width: 16, height: 16, cursor: 'pointer', marginLeft: 8 }} src={(currentEditRecord ? currentEditRecord.id : -1) == record.id ? conformIcon : editIcon} alt="" />}
+                    </div>
+                )
+            }
+        },
+        {
+            title: '汇总',
+            dataIndex: 'summaryFlag',
+            render: (num: any, record: any) => {
+                return record.summaryFlag == 0 ?'否':'是'
+            }
+        },
+        {
+            title: '统计',
+            dataIndex: 'statFlag',
+            render: (num: any, record: any) => {
+                return num == 0 ?'否':'是'
+            }
+        },
+        {
+            title: '可控',
+            dataIndex: 'ctrlFlag',
+            render: (num: any, record: any) => {
+                  return num == 0 ?'否':'是'
+            }
+        }
+    ]
 
     let inervalhander = undefined;
 
@@ -283,9 +336,9 @@ const MonthlyDataCheck: React.FC = () => {
     const onSelectHandle: TreeProps['onSelect'] = (selectedKeys, info) => {
 
         const { node } = info;
-        //set_tableDataFilterParams({...tableDataFilterParams,current:1})
-        set_currentSelectedTreeNode(node);
-
+        if(!node.children){
+            set_currentSelectedTreeNode(node);
+        }
     };
 
 
@@ -296,20 +349,33 @@ const MonthlyDataCheck: React.FC = () => {
 
 
     //固定金额编辑金额
-    const editHandle = async (record: any) => {
+    const editHandle = async (record: any, curTabKey: string) => {
         const { id, deptCode, salaryType, unitCode, userId } = record;
         if (id == editTableCellId) {
             //保存
-            // console.log({ inputSalaryNum,currentSelectedTreeNode });
+            //console.log({currentEditRecord,curTabKey });
+            
+            if (inputSalaryNum != undefined) {
 
-            if (inputSalaryNum) {
+                if (curTabKey == '1') {
+                    const resp = await editTableSalaryRequest({
+                        computeDate: currentComputeDate as string,
+                        unitCode,
+                        deptCode, salaryType,
+                        salary: inputSalaryNum,
+                        userId: `${userId}`,
+                        id
 
-                const resp = await editTableSalaryRequest({
-                    computeDate: currentComputeDate as string,
-                    unitCode,
-                    deptCode, salaryType,
-                    salary: inputSalaryNum,
-                    userId: `${userId}`,
+                    });
+                    if (resp) {
+                        tableRef.current?.reload();
+                    }
+                }
+            }
+
+            if (curTabKey == '7') {
+                const resp = await editUnitCostTableData({
+                    amount: currentEditRecord.amount,
                     id
 
                 });
@@ -319,9 +385,11 @@ const MonthlyDataCheck: React.FC = () => {
             }
 
             set_editTableCellId(undefined);
+            set_currentEditRecord(undefined);
         } else {
             //编辑
             set_editTableCellId(id);
+            set_currentEditRecord(record);
         }
 
     }
@@ -465,7 +533,7 @@ const MonthlyDataCheck: React.FC = () => {
 
     const func = (str: string) => str && str.replace(/(?:\.0*|(\.\d+?)0+)$/, '$1') + '%';
 
-    const getTableData = async (type: '1' | '2' | '3' | '4' | '5' | '6', params: any, sort: any, filter: any) => {
+    const getTableData = async (type: '1' | '2' | '3' | '4' | '5' | '6' | '7', params: any, sort: any, filter: any) => {
 
         if (currentComputeDate) {
             if (type == '1') {
@@ -585,7 +653,7 @@ const MonthlyDataCheck: React.FC = () => {
                             key: 'level',
                             width: 100,
                             fixed: 'right',
-                            hideInTable:computeMethod == '2'?true:false
+                            hideInTable: computeMethod == '2' ? true : false
                         },
                         {
                             title: '系数',
@@ -659,6 +727,52 @@ const MonthlyDataCheck: React.FC = () => {
                     }
                 }
             }
+            if (type == '7'&&currentSelectedTreeNode) {
+                const resp = await getUnitCostTableData({
+                    unitCode: currentSelectedTreeNode.code,
+                    ...params
+                });
+
+                let unitCostTotal = 0;
+                let unitCostCtrlTotal = 0;
+
+                const traverseTree = (node:any) => {
+                    if(node == null) return;
+
+                    if(!node.summaryFlag){
+                        //summaryFlag 汇总
+                        unitCostTotal = unitCostTotal + node.amount
+                        if(node.ctrlFlag){
+                            unitCostCtrlTotal = unitCostCtrlTotal + node.amount
+                        }
+                    }
+                     
+                    if(node.children) {
+                      node.children.forEach(traverseTree);
+                    }
+                }
+
+                
+                
+                resp.forEach((a:any) => {
+                    traverseTree(a);
+                });
+
+                set_unitCostComputeData({
+                    unitCostTotal,unitCostCtrlTotal
+                })
+
+                if (resp) {
+
+                    return {
+                        data: resp,
+                        success: true,
+                        total:0,
+                        pageSize:10,
+                        totalPage:0,
+                    }
+                }
+            }
         }
 
         return []
@@ -756,6 +870,20 @@ const MonthlyDataCheck: React.FC = () => {
             return Promise.resolve(true);
 
         }
+        if (index == 7) {
+            const resp = await generateUnitCostTableData(
+                currentComputeDate as string,
+                currentSelectedTreeNode.code
+            );
+
+            set_loading(false);
+
+            if (resp) {
+                tableRef.current?.reload();
+            }
+            return Promise.resolve(true);
+
+        }
     }
 
     const generateFunc = (index: number, others?: any) => {
@@ -763,17 +891,16 @@ const MonthlyDataCheck: React.FC = () => {
          * index 获取的表格类型下标
          */
 
-        if (index == 3 && !loading) {
+        if ((index == 3||index == 7) && !loading) {
             Modal.confirm({
                 title: '注意',
                 cancelText: '',
                 okText: '确定',
                 closable: true,
-                content: others ? '获取单个操作会覆盖上次获取的该核算单元的数据,确定要继续操作?' : '获取所有操作会覆盖所有已获取的数据,确定要继续操作?',
+                content: others ? '获取单个操作会覆盖上次获取的该核算单元的数据,确定要继续操作?' : `${index == 7?'获取':'获取所有'}操作会覆盖所有已获取的数据,确定要继续操作?`,
                 onOk: () => { set_loading(true); confirmGenerateHandle(index, others) }
             })
         }
-
     }
 
     const onVisibleChangeHandle = (bool: boolean) => {
@@ -935,9 +1062,16 @@ const MonthlyDataCheck: React.FC = () => {
                     const { importFile: { fileList } } = values;
 
                     let formData = new FormData();
-                    formData.append('file', fileList[0].originFileObj);
-                    formData.append('computeDate', currentComputeDate as string);
-                    formData.append('groupId', currentSelectedManaGroup?.id as any);
+                    if (index == 7) {
+                        formData.append('file', fileList[0].originFileObj);
+                        formData.append('computeDate', currentComputeDate as string);
+                        formData.append('unitCode', currentSelectedTreeNode.code);
+                    }else{
+                        formData.append('file', fileList[0].originFileObj);
+                        formData.append('computeDate', currentComputeDate as string);
+                        formData.append('groupId', currentSelectedManaGroup?.id as any);
+                    }
+                    
 
                     const resp = await importMonthlyperformanceRelaFiles(index, formData);
 
@@ -949,7 +1083,7 @@ const MonthlyDataCheck: React.FC = () => {
                 }}
             >
                 <FormItem name={'importFile'}>
-                    <BMSUpload downloadTemplateFile={auditType == '0' ? () => index == 4 ? downloadTemplate(index, currentSelectedManaGroup?.id) : downloadTemplate(index) : () => { }} />
+                    <BMSUpload downloadTemplateFile={auditType == '0' ? () => index == 4 || index == 7 ? downloadTemplate(index, index == 7 ? currentSelectedTreeNode.code : currentSelectedManaGroup?.id) : downloadTemplate(index) : () => { }} />
                 </FormItem>
 
             </ModalForm>
@@ -998,10 +1132,10 @@ const MonthlyDataCheck: React.FC = () => {
 
     const getComputeMethod = async () => {
         const resp = await getManaIndicatorJiangchengCoefficient();
-        if(resp){
-            const need = resp.list.filter((a:any)=>(a.code == '1670618922728169472'));
-            if(need.length>0){
-                 set_computeMethod(need[0].value);
+        if (resp) {
+            const need = resp.list.filter((a: any) => (a.code == '1670618922728169472'));
+            if (need.length > 0) {
+                set_computeMethod(need[0].value);
             }
         }
     }
@@ -1032,7 +1166,7 @@ const MonthlyDataCheck: React.FC = () => {
 
 
     useEffect(() => {
-        console.log({ currentSelectedManaGroup });
+
         set_tableDataFilterParams({
             ...tableDataFilterParams,
             id: currentSelectedManaGroup?.id,
@@ -1069,9 +1203,25 @@ const MonthlyDataCheck: React.FC = () => {
         if (currentSelectedTabKey == '6') {
             set_tableColumn(tableColumnFive as ProColumns[]);
         }
+        if (currentSelectedTabKey == '7') {
+            if (currentComputeDate) {
+                getCheckUnitTreeDataFunc(currentComputeDate as string);
+            }
+            set_tableColumn(tableColumnSeven as ProColumns[]);
+        }
 
     }, [currentSelectedTabKey]);
 
+    useEffect(()=>{
+        if (currentSelectedTabKey == '7') {
+            if (currentComputeDate) {
+                getCheckUnitTreeDataFunc(currentComputeDate as string);
+            }
+            set_tableColumn(tableColumnSeven as ProColumns[]);
+        }
+
+    },[currentEditRecord,auditType])
+
 
 
     useEffect(() => {
@@ -1308,6 +1458,10 @@ const MonthlyDataCheck: React.FC = () => {
                                             label: `固定工资`,
                                             key: '1',
                                         },
+                                        {
+                                            label: `单元成本数据`,
+                                            key: '7',
+                                        },
                                         {
                                             label: `非考核项目`,
                                             key: '2',
@@ -1378,7 +1532,7 @@ const MonthlyDataCheck: React.FC = () => {
                                                                         editTableCellId == record.id ? <Input size='small' defaultValue={record.salary} placeholder='请输入' onChange={(e) => { set_inputSalaryNum(Number(e.target.value)) }} style={{ width: '80px' }} /> : <span>{text}</span>
                                                                     }
                                                                 </div>
-                                                                {auditType == '0' && <img onClick={() => editHandle(record)} style={{ width: 16, height: 16, cursor: 'pointer', marginLeft: 8 }} src={editTableCellId == record.id ? conformIcon : editIcon} alt="" />}
+                                                                {auditType == '0' && <img onClick={() => editHandle(record, '1')} style={{ width: 16, height: 16, cursor: 'pointer', marginLeft: 8 }} src={editTableCellId == record.id ? conformIcon : editIcon} alt="" />}
                                                             </div>
                                                         )
                                                     }
@@ -1419,7 +1573,7 @@ const MonthlyDataCheck: React.FC = () => {
                                                                             editTableCellId == record.id ? <Input size='small' defaultValue={record.salary} placeholder='请输入' onChange={(e) => { set_inputSalaryNum(Number(e.target.value)) }} style={{ width: '80px' }} /> : <span>{text}</span>
                                                                         }
                                                                     </div>
-                                                                    {auditType == '0' && <img onClick={() => editHandle(record)} style={{ width: 16, height: 16, cursor: 'pointer', marginLeft: 8 }} src={editTableCellId == record.id ? conformIcon : editIcon} alt="" />}
+                                                                    {auditType == '0' && <img onClick={() => editHandle(record, '1')} style={{ width: 16, height: 16, cursor: 'pointer', marginLeft: 8 }} src={editTableCellId == record.id ? conformIcon : editIcon} alt="" />}
                                                                 </div>
                                                             )
                                                         }
@@ -1653,7 +1807,7 @@ const MonthlyDataCheck: React.FC = () => {
                                                         {
                                                             manaIndexGroups.map((item, index) => {
                                                                 return (
-                                                                    <Tooltip placement="top" title={item.depiction?item.depiction:item.groupName}>
+                                                                    <Tooltip placement="top" title={item.depiction ? item.depiction : item.groupName}>
                                                                         <div key={index} className={currentSelectedManaGroup?.id == item.id ? 'tab on' : 'tab'} onClick={() => onManaIndexGroupClick(item)}>{item.groupName}</div>
                                                                     </Tooltip>
                                                                 )
@@ -1768,6 +1922,125 @@ const MonthlyDataCheck: React.FC = () => {
                                         </div>
                                     )
                                 }
+                                {
+                                    currentSelectedTabKey == '7' && (
+                                        <div className='tabContent'>
+
+                                            <div className='tabContentInner'>
+                                                <div className='leftTree'>
+                                                    <div className='search'>
+                                                        <Input className='searchInput' allowClear onChange={onTreeSearchKeyChange} placeholder="请输入名称" suffix={
+                                                            <IconFont type="iconsousuo" />
+                                                        } />
+                                                    </div>
+                                                    <div className='treeWrap'>
+                                                        {
+                                                            treeData && treeData.length > 0 && currentSelectedTreeNode && (
+                                                                <DirectoryTree
+                                                                    fieldNames={{ title: 'name', key: 'code', children: 'child' }}
+                                                                    rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
+                                                                    onSelect={onSelectHandle}
+                                                                    onExpand={onExpand}
+                                                                    expandedKeys={expandedKeys}
+                                                                    autoExpandParent={autoExpandParent}
+                                                                    selectedKeys={[currentSelectedTreeNode.code]}
+                                                                    blockNode={true}
+                                                                    icon={() => null}
+                                                                    titleRender={
+                                                                        (nodeData: any) => {
+                                                                            const strTitle = nodeData.name as string;
+                                                                            const index = strTitle.indexOf(searchValue);
+                                                                            const beforeStr = strTitle.substring(0, index);
+                                                                            const afterStr = strTitle.slice(index + searchValue.length);
+                                                                            const title =
+                                                                                index > -1 ? (
+                                                                                    <span>
+                                                                                        {beforeStr}
+                                                                                        <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
+                                                                                        {afterStr}
+                                                                                    </span>
+                                                                                ) : (
+                                                                                    <span className='strTitle'>{strTitle}</span>
+                                                                                );
+                                                                            return <div style={{
+                                                                                display: 'flex', flexDirection: 'row',
+                                                                                width: '100%',
+                                                                                justifyContent: 'flex-start', alignItems: 'center', height: 32,
+                                                                                borderRadius: '4px',
+                                                                                overflow: 'hidden',
+                                                                                color: '#17181A',
+                                                                                textOverflow: 'ellipsis',
+                                                                                whiteSpace: 'nowrap'
+
+                                                                            }}>{title}</div>
+                                                                        }
+                                                                    }
+                                                                    defaultSelectedKeys={[treeData[0].child[0].code]}
+                                                                    treeData={treeData as unknown as DataNode[]}
+                                                                    // treeData={treeDataNew}
+                                                                    switcherIcon={(props: any) => {
+                                                                        const { expanded } = props;
+                                                                        return !expanded ? <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} /> : <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
+                                                                    }}
+                                                                />
+                                                            )
+                                                        }
+                                                    </div>
+                                                </div>
+                                                <div className='rightTable'>
+                                                    <div className='tableToolbar'>
+                                                        <div className='filter'>
+                                                            {/* <div className='search' style={{ marginRight: 24 }}>
+                                                        <span>类型:</span><Input className='searchInput' allowClear placeholder="请输入" onChange={(e) => {
+                                                            set_tableDataSearchKeywords(e.target.value);
+                                                            if (e.target.value.length == 0) {
+                                                                set_tableDataFilterParams({
+                                                                    ...tableDataFilterParams,
+                                                                    itemType: ''
+                                                                });
+                                                            }
+                                                        }} suffix={
+                                                            <IconFont type="iconsousuo" onClick={() => tableDataSearchHandle('itemType')} />
+                                                        } />
+                                                    </div> */}
+                                                            <div className='search'>
+                                                                <span>项目名称:</span><Input className='searchInput' allowClear placeholder="请输入" onChange={(e) => {
+                                                                    set_tableDataSearchKeywords(e.target.value);
+                                                                    if (e.target.value.length == 0) {
+                                                                        set_tableDataFilterParams({
+                                                                            ...tableDataFilterParams,
+                                                                            itemName: ''
+                                                                        });
+                                                                    }
+                                                                }} suffix={
+                                                                    <IconFont type="iconsousuo" onClick={() => tableDataSearchHandle('itemName')} />
+                                                                } />
+                                                            </div>
+                                                        </div>
+                                                        <>
+                                                        {/* <span className='compelted'>已分配总额: <i>{pageData.completedTotal}</i></span>
+                                <span className='left'>剩余分配总额: <i>{pageData.leftTotal}</i></span> */}
+                                                        <div className='count'><span className='compelted' style={{display:'inline-block',marginRight:20}}>总成本:<i>{unitCostComputeData.unitCostTotal}</i></span><span className='left'>可控成本:<i>{unitCostComputeData.unitCostCtrlTotal}</i></span></div>
+                                                        <Popover open={ifShowTip} content={'当前处于审核中,无法操作!'} >
+                                                            <div className={auditType == '1' || loading ? 'btnGroup disabled' : 'btnGroup'}
+                                                                onMouseEnter={() => auditType == '0' ? set_ifShowTip(false) : set_ifShowTip(true)}
+                                                                onMouseLeave={() => set_ifShowTip(false)}
+                                                            >
+                                                                <span key="1" onClick={auditType == '0' ? () => generateFunc(7,false) : () => { }}>获取</span>
+                                                                <>{importData(7, '成本')}</>
+                                                            </div>
+                                                        </Popover>
+                                                        </>
+                                                        
+                                                    </div>
+                                                    {currentComputeDate && <BMSTable actionRef={tableRef} loading={{ spinning: loading, tip: '正在获取数据...' }} rowKey='id' params={tableDataFilterParams} columns={[...tableColumn]} pagination={false} request={(params, sort, filter) => getTableData('7', params, sort, filter)} />}
+                                                </div>
+
+                                            </div>
+
+                                        </div>
+                                    )
+                                }
 
 
                             </BMSPagecontainer>

+ 55 - 3
src/pages/budgetMana/monthlyDataCheck/service.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-21 11:13:51
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-06-27 13:36:28
+ * @LastEditTime: 2023-06-30 10:53:11
  * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlyInfoCheck/service.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -34,7 +34,7 @@ import axios from 'axios';
 
 
 
-//获取人员信息表格数据
+//获取固定工资表格数据
 
 export type SalaryInfoTableDataRequestParamsType = {
     computeDate: string; //核算年月
@@ -72,6 +72,50 @@ export const getSalaryInfoTableData = (params: SalaryInfoTableDataRequestParamsT
 
 }
 
+//获取单元成本数据
+
+export type UnitCostTableDataRequestParamsType = {
+    unitCode:string,
+    itemName?:string
+}
+
+
+
+export const getUnitCostTableData = (params: UnitCostTableDataRequestParamsType) => {
+
+    return request('/performance/kpi/getUnitCostList', {
+        method: 'GET',
+        params: params
+    })
+
+}
+
+//编辑单元成本
+export const editUnitCostTableData = (data:{id:number,amount:number}) => {
+
+    return request('/performance/kpi/editUnitCost', {
+        method: 'POST',
+        params:data
+    })
+
+}
+
+//获取按钮生成单元成本数据
+export const generateUnitCostTableData = (compute_date:string,unit_code:string) => {
+
+    return request('/performance/kpi/generateUnitCost', {
+        method: 'POST',
+        data:{
+            parameter:{
+                compute_date,
+                unit_code
+            }
+        }
+    })
+
+}
+
+
 
 //获取非考核项目表格数据
 
@@ -484,6 +528,12 @@ export const importMonthlyperformanceRelaFiles = (index: number, data: any) => {
             data
         })
     }
+    if (index == 7) {
+        return request('/performance/kpi/importUnitCost', {
+            method: 'POST',
+            data
+        })
+    }
 
 
 }
@@ -492,7 +542,6 @@ export const importMonthlyperformanceRelaFiles = (index: number, data: any) => {
 
 export const downloadTemplateReq = (index: number,id?:number|string) => {
 
-    console.log({index,id});
 
     let path = '';
 
@@ -511,6 +560,9 @@ export const downloadTemplateReq = (index: number,id?:number|string) => {
     if(index == 6){
         path = `/gateway/performance/kpi/exportCost`
     }
+    if(index == 7){
+        path = `/gateway/performance/kpi/exportUnitCost?unitCode=${id}`
+    }
 
     const userData = localStorage.getItem('userData');
     const { token = '' } = JSON.parse(userData as any);

+ 89 - 16
src/pages/budgetMana/monthlyDataCheck/style.less

@@ -8,22 +8,22 @@
 
     .maskCover {
         position: absolute;
-        top:0;
+        top: 0;
         left: 0;
-        width:100%;
-        height:100%;
+        width: 100%;
+        height: 100%;
         z-index: 9;
-        background: rgba(0,0,0,0.2);
+        background: rgba(0, 0, 0, 0.2);
     }
 
     .ManaIndextable {
         .bms-ant-table-thead {
             background-color: #37F !important;
 
-            &>tr:last-child{
-                 .bms-ant-table-cell {
-                       border-top: 1px solid #dae2f2 !important;
-                 }
+            &>tr:last-child {
+                .bms-ant-table-cell {
+                    border-top: 1px solid #dae2f2 !important;
+                }
             }
         }
     }
@@ -33,12 +33,14 @@
         height: 100%;
         padding: 16px;
         background: #FFF;
+        max-height: calc(100vh - 50px);
+        overflow-y: scroll;
 
         .checkBtn {
             position: absolute;
             cursor: pointer;
             top: 0;
-            right:0;
+            right: 0;
             padding: 0 14px;
             height: 24px;
             line-height: 24px;
@@ -93,8 +95,8 @@
 
             .totalCount {
                 position: absolute;
-                bottom:16px;
-                left: 16px;
+                bottom: 13px;
+                left: 13px;
                 z-index: 9;
                 height: 16px;
                 font-size: 16px;
@@ -130,7 +132,7 @@
                         .tab {
                             text-align: center;
                             line-height: 24px;
-                            min-width:48px;
+                            min-width: 48px;
                             height: 24px;
                             padding: 0 8px;
                             color: #525866;
@@ -179,6 +181,76 @@
                     }
                 }
 
+                .count {
+                    span {
+                        font-size: 14px;
+                        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                        font-weight: 400;
+                        color: #17181A;
+                        margin-right: 24px;
+
+                        &.total {
+                            i {
+                                font-style: normal;
+                                font-size: 14px;
+                                font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+                                font-weight: 500;
+                                color: #17181A;
+                            }
+                        }
+
+                        &.compelted {
+                            i {
+                                font-style: normal;
+                                font-size: 14px;
+                                font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+                                font-weight: 500;
+                                color: #2E6BE6;
+                            }
+
+                            &::before {
+                                position: relative;
+                                top: 2px;
+                                display: inline-block;
+                                content: '';
+                                width: 12px;
+                                height: 12px;
+                                margin-right: 4px;
+                                background: url('../../../../static//bingzhuantu.png');
+                                background-size: cover;
+
+                            }
+                        }
+
+                        &.left {
+                            i {
+                                font-style: normal;
+                                font-size: 14px;
+                                font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+                                font-weight: 500;
+                                color: #14CC8F;
+                            }
+
+                            &::before {
+                                position: relative;
+                                top: 2px;
+                                display: inline-block;
+                                content: '';
+                                width: 12px;
+                                height: 12px;
+                                margin-right: 4px;
+                                background: url('../../../../static/bingzhuantu_green.png');
+                                background-size: cover;
+
+                            }
+                        }
+
+                        &:last-child {
+                            margin-right: 0;
+                        }
+                    }
+                }
+
                 .btnGroup {
                     &>span {
                         display: inline-block;
@@ -199,9 +271,9 @@
 
                     &.disabled {
                         &>span {
-                            cursor:not-allowed;
+                            cursor: not-allowed;
                             color: rgb(0 0 0 / 50%);
-                            background-color:#f0f2f5;
+                            background-color: #f0f2f5;
                         }
                     }
                 }
@@ -228,7 +300,7 @@
                             border: 1px solid #CFD7E6;
                         }
 
-                       
+
 
                         &>span {
                             font-size: 14px;
@@ -248,7 +320,8 @@
                         border: 1px solid #DAE2F2;
                         overflow: hidden;
 
-                        .bms-ant-tree.bms-ant-tree-directory .bms-ant-tree-treenode-selected:hover::before,.bms-ant-tree.bms-ant-tree-directory .bms-ant-tree-treenode-selected::before {
+                        .bms-ant-tree.bms-ant-tree-directory .bms-ant-tree-treenode-selected:hover::before,
+                        .bms-ant-tree.bms-ant-tree-directory .bms-ant-tree-treenode-selected::before {
                             border-radius: 4px;
                             background: rgb(240 242 245 / 100%);
                         }

+ 10 - 23
src/pages/setting/manaPerformanceSet/indicGroupWeightSet/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 11:30:33
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-06-27 10:14:22
+ * @LastEditTime: 2023-07-05 14:11:19
  * @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
  */
@@ -68,7 +68,7 @@ export default function IndicGroupWeightSet() {
         {
             title: '分组名称',
             dataIndex: 'groupName',
-            width: 80
+            width: 150
         },
         {
             title: '组内单元名称',
@@ -101,14 +101,14 @@ export default function IndicGroupWeightSet() {
             }
         },
         {
-            title: '总分限',
-            dataIndex: 'ceiling',
+            title: '总分限',
+            dataIndex: 'floor',
             width: 80
         },
         {
-            title: '说明',
-            dataIndex: 'depiction',
-            ellipsis: true,
+            title: '总分上限',
+            dataIndex: 'ceiling',
+            width: 80
         },
         {
             title: '操作',
@@ -497,21 +497,8 @@ export default function IndicGroupWeightSet() {
                         return updateTable({ ...record, ...val }, type)
                     }
                     if (type == 'INDICATOR') {
-            
-                        // const total = indicatorData.reduce((prev:any,cur:any)=>{
-                        //         return math.add(Number(prev).toFixed(2),cur['weight'])
-                        // },0);
-                        
-                        // if(total != 1){
-                        //       Modal.confirm({
-                        //          title:'占比加总必须是1!'
-                        //       });
-                        //       return Promise.resolve(false);
-                        // }else{
-                            
-                        // }
-
-                        return updateTable({ id: record.id, indicatorWeights: indicatorData }, type);
+        
+                        return updateTable({ id: record.id, indicatorWeights: indicatorData.map(a=>({...a,indicatorCode:`${a.indicatorCode}`})) }, type);
                     }
 
                     return Promise.resolve(true);
@@ -556,7 +543,7 @@ export default function IndicGroupWeightSet() {
                                                 if (resp) {
                                                     return resp.list.map((a: any) => ({
                                                         label: a.name,
-                                                        value: Number(a.code)
+                                                        value: a.code
                                                     }))
                                                 }
                                                 return []

+ 85 - 24
src/pages/setting/projectSetting/checkUnitProjectSet/index.tsx

@@ -4,7 +4,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-16 09:42:52
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-06-29 15:56:47
+ * @LastEditTime: 2023-06-30 20:41:30
  * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -33,7 +33,7 @@ import 'dayjs/locale/zh-cn';
 
 import React from 'react';
 import DirectoryTree from 'antd/es/tree/DirectoryTree';
-import { getDeepestTreeData } from '@/utils/tooljs';
+import { findAllParents, getDeepestTreeData, getNodesWithChildren } from '@/utils/tooljs';
 import { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
 import { difference } from 'lodash';
 import { getBillProjectData } from '../bilingProjectMana/service';
@@ -60,6 +60,29 @@ export type TableListItem = {
 };
 
 
+interface TreeNode {
+    id: number;
+    name: string;
+    code?: string;
+    children?: TreeNode[];
+}
+
+function getAllLeafCodes(data: TreeNode[]): string[] {
+    let result: string[] = [];
+
+    for (let i = 0; i < data.length; i++) {
+        const node = data[i];
+        if (node.children) {
+            result = result.concat(getAllLeafCodes(node.children));
+        } else if (node.code) {
+            result.push(node.code);
+        }
+    }
+
+    return result;
+}
+
+
 const CheckUnitProjectSet: React.FC = () => {
 
     const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
@@ -460,6 +483,7 @@ const CheckUnitProjectSet: React.FC = () => {
         const [showList, set_showList] = useState<any[]>([]);
         const [tableParams, set_tableParams] = useState<any>({});
         const [keywords, set_keywords] = useState('');
+        const [allParentsNode,set_allParentsNode] = useState<any[]>([]);
 
         //获取表格数据
         const getFuncList = async () => {
@@ -472,29 +496,63 @@ const CheckUnitProjectSet: React.FC = () => {
                 }
             } else {
                 //成本项目添加
-                const resp = await getCostProjectTable();
-                if (resp) {
-                    //const filteredData = resp.filter((a:any)=>a.code != currentSelectedTreeNode.code);
-                    set_datasource(resp);
-                    set_showList(resp);
-                }
+                const resp2 = await getCostItemsTableData({
+                    unitCode: currentSelectedTreeNode.code,
+                });
 
+                if (resp2) {
+                    const resp = await getCostProjectTable();
+                    if (resp) {
+                        //const filteredData = resp.filter((a:any)=>a.code != currentSelectedTreeNode.code);
+                        set_datasource(resp);
+                        set_showList(resp);
+                        const parents = getNodesWithChildren(resp2);
+                        let codes = getAllLeafCodes(resp2);
+                        let _codes = Array.from(new Set(codes.map(obj => JSON.stringify(obj)))).map(str => JSON.parse(str));
+                        console.log({parents,_codes})
+                        setSelectedKeys(_codes);
+                        set_allParentsNode(parents);
+                    
+                    }
+                }
             }
 
         }
+    
+        const onSelectHandle = (record: any, selected:boolean, selectedRows:any[], nativeEvent: any) => {
+            let data = [...datasource];
+            let parent = record.parentCode != 0 ? findAllParents([...data],`${record.parentCode}`):undefined;
+            
+            parent = parent?parent.filter(obj => Object.keys(obj).length !== 0):[];
+
+            set_allParentsNode([...allParentsNode,...parent]);
 
+            let result = [...selectedRows,...parent];
 
-        const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: any) => {
-            setSelectedKeys([...newSelectedRowKeys]);
-            set_selectedRows(selectedRows);
+            result = result.filter(obj => Object.keys(obj).length !== 0);
+
+            const _result = Array.from(new Set(result.map(obj => JSON.stringify(obj)))).map(str => JSON.parse(str));
+
+            setSelectedKeys([...selectedRows.map((a: { code: any; })=>a.code)]);
+            set_selectedRows([...selectedRows,..._result]);
 
         };
 
         const save = async () => {
             if (!isCopy && currentSelectedTabKey == '4') {
-                //console.log({selectedKeys,selectedRows});
+                
+                //const _selectedRows = Array.from(new Set([...allParentsNode,...selectedRows].map(obj => JSON.stringify(obj)))).map(str => JSON.parse(str));
+                
+
+                let _selectedRows = Object.values([...allParentsNode,...selectedRows].reduce((acc, cur) => {
+                    acc[cur.code] = cur; // 如果 id 相同,后来的元素将替换前者
+                    return acc;
+                  }, {}));
+
+            
+        
                 const result = {
-                    itemList: selectedRows.map((a: any) => ({
+                    itemList: _selectedRows.map((a: any) => ({
                         code: a.code,
                         ctrlFlag: a.ctrlFlag,
                         itemType: a.itemType,
@@ -550,7 +608,7 @@ const CheckUnitProjectSet: React.FC = () => {
                     }
                     style={{ marginBottom: 8 }}
                     onChange={(e) => {
-                        if (currentSelectedTabKey != '4') {
+                        if (isCopy) {
                             if (e.target.value.length != 0) {
                                 const result = datasource.filter(item => item.unitName.indexOf(e.target.value) != -1);
                                 set_showList(result);
@@ -558,7 +616,7 @@ const CheckUnitProjectSet: React.FC = () => {
                                 set_showList(datasource);
                             }
                         }
-                        if (currentSelectedTabKey == '4') {
+                        if (!isCopy) {
                             //set_keywords(e.target.value);
                             const search: any = (data: any, name: string) => {
                                 let result = [];
@@ -566,29 +624,30 @@ const CheckUnitProjectSet: React.FC = () => {
                                 for (let i = 0; i < data.length; i++) {
                                     const item = data[i];
                                     if (item.name.indexOf(name) != -1) {
-                                      result.push(item);
+                                        result.push(item);
                                     }
                                     if (item.children) {
-                                      result.push(...search(item.children, name));
+                                        result.push(...search(item.children, name));
                                     }
-                                  }
+                                }
 
                                 return result;
                             }
 
-                            if(e.target.value.length>0){
-                                const foundItem = search(datasource,e.target.value);
+                            if (e.target.value.length > 0) {
+                                const foundItem = search(datasource, e.target.value);
                                 set_showList(foundItem);
-                            }else{
+                            } else {
                                 set_showList(datasource);
                             }
-                            
+
                         }
 
                     }}
 
 
                 />
+                <div className='wrapper' style={{maxHeight:'491px',overflowY:'scroll'}}>
                 <BMSTable columns={tableSelecterColumn}
                     options={{
                         density: true,
@@ -602,12 +661,14 @@ const CheckUnitProjectSet: React.FC = () => {
                     rowSelection={{
                         // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
                         // 注释该行则默认不显示下拉选项
-                        onChange: onSelectChange,
+                        selectedRowKeys:selectedKeys,
+                        onSelect: onSelectHandle,
                         checkStrictly: false
                     }}
-                    pagination={{ showSizeChanger: false, pageSize: 10, simple: true, showTitle: false }}
+                    pagination={false}
                     dataSource={showList}
                 />
+                </div>
                 <div className='footer'>
                     <span className='cancel' onClick={() => set_ifShowModal(false)}>取消</span>
                     <span className='ok' onClick={() => save()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>

+ 1 - 1
src/pages/setting/projectSetting/checkUnitProjectSet/style.less

@@ -8,7 +8,7 @@
          margin-top: 15px;
          span {
              display: inline-block;
-             width: 56px;
+             width: 60px;
              height: 24px;  
              font-size: 14px;
              line-height: 23px;

+ 341 - 77
src/pages/setting/reportSet/reportListMana/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 11:30:33
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-06-28 16:08:20
+ * @LastEditTime: 2023-06-30 18:21:06
  * @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
  */
@@ -14,17 +14,18 @@ import BMSPagecontainer from '@/components/BMSPageContainer';
 import { BMSTable } from '@/components/BMSTable';
 import { createFromIconfontCN } from '@ant-design/icons';
 
-import { ActionType, ProFormRadio } from '@ant-design/pro-components';
+import { ActionType, ProFormCheckbox, ProFormRadio } from '@ant-design/pro-components';
 import { ModalForm, ProFormDependency, ProFormDigit, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
 import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm } from 'antd';
 import { useEffect, useRef, useState } from 'react';
 
-import { addData, delData, editData, getManaIndic, getReportListTableData, getReportListType } from './service';
+import { addChildReportList, addData, delData, editData, getChildReportList, getManaIndic, getReportListTableData, getReportListType } from './service';
 
 import './style.less';
 
 import '../../../../utils/zhongtaiB';
+import React from 'react';
 const IconFont = createFromIconfontCN({
     scriptUrl: '',
 });
@@ -36,6 +37,11 @@ export default function ReportListMana() {
     const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
     const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
     const tableRef = useRef<ActionType>();
+    const [currentEditRow, set_currentEditRow] = useState<any | undefined>(undefined);
+
+    const [ifShowModal, set_ifShowModal] = useState(false);
+
+    const ref = React.createRef<{ save: any; getSelectedKeys: any }>();
 
     const columns: ProColumns[] = [
 
@@ -72,11 +78,14 @@ export default function ReportListMana() {
             title: '子列',
             width: 300,
             ellipsis: true,
-            dataIndex: 'sql',
+            dataIndex: 'childColumnList',
             render: (_: any, record: any) => {
-
-                if (record.sql) return record.sql;
-                if (record.indicatorCodeName) return record.indicatorCodeName
+                if (record.childColumnList){
+                    return record.childColumnList.reduce((prev:any,cur:any)=>{
+                        return `${prev.length>0?prev+'|':prev}${cur.headerText}`
+                    },'')
+                }
+            
             }
         },
         {
@@ -86,6 +95,7 @@ export default function ReportListMana() {
             valueType: 'option',
             render: (_: any, record: any) => {
                 return [
+                    <a key='edit_child' onClick={() => { set_currentEditRow(record); set_ifShowModal(true) }}>子列</a>,
                     <UpDataActBtn key={'act'} record={record} type='EDIT' />,
                     <Popconfirm
                         title="是否确认删除?"
@@ -100,6 +110,19 @@ export default function ReportListMana() {
 
     ]
 
+    const tableSelecterColumn: ProColumns[] = [
+        {
+            title: '列名称',
+            dataIndex: 'name',
+            // render:(_:any)=>_ == 1?'指标':'自定义SQL'
+        },
+        {
+            title: '列标题',
+            dataIndex: 'headerText',
+            // render:(_:any)=>_ == 1?'指标':'自定义SQL'
+        },
+    ]
+
 
     const getTableData = async (params: any) => {
         const resp = await getReportListTableData(params);
@@ -124,7 +147,7 @@ export default function ReportListMana() {
         }
     }
 
-    const updateTable = async (formVal: any, type: 'EDIT' | "ADD"|'EDIT_CHILD') => {
+    const updateTable = async (formVal: any, type: 'EDIT' | "ADD" | 'EDIT_CHILD') => {
 
         if (type == 'ADD') {
             if (formVal.dataSource == 1) {
@@ -134,7 +157,8 @@ export default function ReportListMana() {
                     headerText: formVal.headerText,
                     dataSource: formVal.dataSource,
                     columnType: formVal.columnType,
-                    sql:'',
+                    dataType: formVal.dataType,
+                    sql: '',
                     indicatorCode: formVal.indicatorCode.key,
                     indicatorCodeName: formVal.indicatorCode.label,
                 }
@@ -146,16 +170,17 @@ export default function ReportListMana() {
                 }
 
             }
-            if(formVal.dataSource == 2){
+            if (formVal.dataSource == 2) {
                 //sql
                 let result = {
                     name: formVal.name,
                     headerText: formVal.headerText,
                     dataSource: formVal.dataSource,
                     columnType: formVal.columnType,
+                    dataType: formVal.dataType,
                     sql: formVal.sql,
-                    indicatorCode:'',
-                    indicatorCodeName:''
+                    indicatorCode: '',
+                    indicatorCodeName: ''
                 }
 
                 const resp = await addData({ ...result });
@@ -170,7 +195,7 @@ export default function ReportListMana() {
         }
         if (type == 'EDIT') {
 
-            if (formVal.dataSource == 1){
+            if (formVal.dataSource == 1) {
                 //指标
                 const result = {
                     id: formVal.id,
@@ -178,7 +203,8 @@ export default function ReportListMana() {
                     headerText: formVal.headerText,
                     dataSource: formVal.dataSource,
                     columnType: formVal.columnType,
-                    sql:'',
+                    dataType: formVal.dataType,
+                    sql: '',
                     indicatorCode: formVal.indicatorCode.key,
                     indicatorCodeName: formVal.indicatorCode.label,
                 }
@@ -190,7 +216,7 @@ export default function ReportListMana() {
 
             }
 
-            if(formVal.dataSource == 2){
+            if (formVal.dataSource == 2) {
                 //sql
                 const result = {
                     id: formVal.id,
@@ -198,9 +224,10 @@ export default function ReportListMana() {
                     headerText: formVal.headerText,
                     dataSource: formVal.dataSource,
                     columnType: formVal.columnType,
+                    dataType: formVal.dataType,
                     sql: formVal.sql,
-                    indicatorCode:'',
-                    indicatorCodeName:''
+                    indicatorCode: '',
+                    indicatorCodeName: ''
                 }
                 const resp = await editData({ ...result });
                 if (resp) {
@@ -209,7 +236,7 @@ export default function ReportListMana() {
                 }
             }
 
-            
+
         }
         return true;
 
@@ -217,7 +244,7 @@ export default function ReportListMana() {
 
     const formRef = useRef();
 
-    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' | 'EDIT_CHILD' }) => {
 
         return (
             <ModalForm
@@ -226,82 +253,190 @@ export default function ReportListMana() {
                 formRef={formRef}
                 initialValues={type == 'EDIT' ? { ...record, indicatorCode: { label: record.indicatorCodeName, value: record.indicatorCode } } : {}}
                 trigger={
-                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
+                    type == 'EDIT_CHILD' ? <a key="edit_child" >子列</a> : type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
                 }
                 onFinish={(val) => {
-                    console.log({ val });
                     return updateTable(type == 'EDIT' ? { ...record, ...val, sql: val.sql ? val.sql : '', } : { ...val }, type);
                 }}
                 colProps={{ span: 24 }}
                 modalProps={{
-                    destroyOnClose:true
+                    destroyOnClose: true
                 }}
                 grid
             >
+                {
+                    (type != 'EDIT_CHILD') && (
+                        <>
+                            <ProFormText
+                                name="name"
+                                label="列名称:"
+                                placeholder="请输入"
+                                rules={[{ required: true, message: '列名称不能为空!' }]}
+                            />
+                            <ProFormText
+                                name="headerText"
+                                label="列标题:"
+                                placeholder="请输入"
+                                rules={[{ required: true, message: '列标题不能为空!' }]}
+                            />
+                            <ProFormSelect
+                                name="columnType"
+                                label="列类型:"
+                                placeholder="请选择"
+                                request={async () => {
+                                    const resp = await getReportListType();
+                                    if (resp) {
+                                        return resp.list.map((a: any) => ({ label: a.name, value: a.code }))
+                                    }
+                                }}
+                                rules={[{ required: true, message: '列类型不能为空!' }]}
+                            />
+
+
+                            <ProFormRadio.Group
+                                name="dataType"
+                                label="取数格式:"
+                                options={[
+                                    {
+                                        label: '文本',
+                                        value: 1,
+                                    },
+                                    {
+                                        label: '金额',
+                                        value: 2,
+                                    },
+                                    {
+                                        label: '数值',
+                                        value: 3,
+                                    },
+                                    {
+                                        label: '百分比',
+                                        value: 4,
+                                    },
+                                ]}
+                                rules={[{ required: true, message: '取数格式不能为空!' }]}
+                            />
 
-                <ProFormText
-                    name="name"
-                    label="列名称:"
-                    placeholder="请输入"
-                    rules={[{ required: true, message: '列名称不能为空!' }]}
-                />
-                <ProFormText
-                    name="headerText"
-                    label="列标题:"
-                    placeholder="请输入"
-                    rules={[{ required: true, message: '列标题不能为空!' }]}
-                />
-                <ProFormSelect
-                    name="columnType"
-                    label="列类型:"
-                    placeholder="请选择"
-                    request={async () => {
-                        const resp = await getReportListType();
-                        if (resp) {
-                            return resp.list.map((a: any) => ({ label: a.name, value: a.code }))
-                        }
-                    }}
-                    rules={[{ required: true, message: '列类型不能为空!' }]}
-                />
 
-                <ProFormSelect
-                    name="dataSource"
-                    label="取数类型:"
-                    placeholder="请选择"
-                    options={[
-                        { label: '指标', value: 1 },
-                        { label: '自定义SQL', value: 2 }
-                    ]}
-                    rules={[{ required: true, message: '取数类型不能为空!' }]}
-                />
-                <ProFormDependency name={['dataSource']}>
-                    {
-                        ({ dataSource }) => dataSource == 1 && (
                             <ProFormSelect
-                                name="indicatorCode"
-                                label="取数来源:"
+                                name="dataSource"
+                                label="取数类型:"
+                                placeholder="请选择"
+                                options={[
+                                    { label: '指标', value: 1 },
+                                    { label: '自定义SQL', value: 2 }
+                                ]}
+                                rules={[{ required: true, message: '取数类型不能为空!' }]}
+                            />
+                            <ProFormDependency name={['dataSource']}>
+                                {
+                                    ({ dataSource }) => dataSource == 1 && (
+                                        <ProFormSelect
+                                            name="indicatorCode"
+                                            label="取数来源:"
+                                            placeholder="请选择"
+                                            fieldProps={{
+                                                labelInValue: true
+                                            }}
+                                            request={async () => {
+                                                const resp = await getManaIndic();
+                                                if (resp) {
+                                                    return resp.map((a: any) => ({ label: a.name, value: a.code }))
+                                                }
+                                            }}
+                                            rules={[{ required: true, message: '数据来源不能为空!' }]}
+                                        />
+                                    )
+                                }
+                            </ProFormDependency>
+                            <ProFormDependency name={['dataSource']}>
+                                {
+                                    ({ dataSource }) => dataSource == 2 && (
+                                        <ProFormTextArea name={'sql'} label='SQL:' rules={[{ required: true, message: 'SQL不能为空!' }]} />
+                                    )
+                                }
+                            </ProFormDependency>
+                        </>
+                    )
+                }
+                {/* {
+                    (type == 'EDIT_CHILD') && (
+                        <>
+                            <ProFormText
+                                name="name"
+                                label="列名称:"
+                                placeholder="请输入"
+                                rules={[{ required: true, message: '列名称不能为空!' }]}
+                            />
+                            <ProFormText
+                                name="headerText"
+                                label="列标题:"
+                                placeholder="请输入"
+                                rules={[{ required: true, message: '列标题不能为空!' }]}
+                            />
+                            <ProFormSelect
+                                name="columnType"
+                                label="列类型:"
                                 placeholder="请选择"
-                                fieldProps={{
-                                    labelInValue: true
-                                }}
                                 request={async () => {
-                                    const resp = await getManaIndic();
+                                    const resp = await getReportListType();
                                     if (resp) {
-                                        return resp.map((a: any) => ({ label: a.name, value: a.code }))
+                                        return resp.list.map((a: any) => ({ label: a.name, value: a.code }))
                                     }
                                 }}
-                                rules={[{ required: true, message: '数据来源不能为空!' }]}
+                                rules={[{ required: true, message: '列类型不能为空!' }]}
+                            />
+
+                            <ProFormCheckbox.Group
+                                name="checkbox"
+                                layout="vertical"
+                                label="取数格式:"
+                                options={['文本','金额','数值','百分比']}
                             />
-                        )
-                    }
-                </ProFormDependency>
-                <ProFormDependency name={['dataSource']}>
-                    {
-                        ({ dataSource }) => dataSource == 2 && (
-                            <ProFormTextArea name={'sql'} label='SQL:' rules={[{ required: true, message: 'SQL不能为空!' }]} />
-                        )
-                    }
-                </ProFormDependency>
+
+                            <ProFormSelect
+                                name="dataSource"
+                                label="取数类型:"
+                                placeholder="请选择"
+                                options={[
+                                    { label: '指标', value: 1 },
+                                    { label: '自定义SQL', value: 2 }
+                                ]}
+                                rules={[{ required: true, message: '取数类型不能为空!' }]}
+                            />
+                            <ProFormDependency name={['dataSource']}>
+                                {
+                                    ({ dataSource }) => dataSource == 1 && (
+                                        <ProFormSelect
+                                            name="indicatorCode"
+                                            label="取数来源:"
+                                            placeholder="请选择"
+                                            fieldProps={{
+                                                labelInValue: true
+                                            }}
+                                            request={async () => {
+                                                const resp = await getManaIndic();
+                                                if (resp) {
+                                                    return resp.map((a: any) => ({ label: a.name, value: a.code }))
+                                                }
+                                            }}
+                                            rules={[{ required: true, message: '数据来源不能为空!' }]}
+                                        />
+                                    )
+                                }
+                            </ProFormDependency>
+                            <ProFormDependency name={['dataSource']}>
+                                {
+                                    ({ dataSource }) => dataSource == 2 && (
+                                        <ProFormTextArea name={'sql'} label='SQL:' rules={[{ required: true, message: 'SQL不能为空!' }]} />
+                                    )
+                                }
+                            </ProFormDependency>
+                        </>
+                    )
+                } */}
+
+
 
             </ModalForm>
         )
@@ -317,12 +452,141 @@ export default function ReportListMana() {
     }
 
 
+    interface TableSelecterProps {
+        tableSelecterColumn: any[];
+        record: any
+    }
+
+    const TableSelecter = React.forwardRef(({ tableSelecterColumn, record }: TableSelecterProps, ref) => {
+
+
+        const [datasource, set_datasource] = useState<any[]>([]);
+        const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+        const [selectedRows, set_selectedRows] = useState<any[]>([])
+        const [showList, set_showList] = useState<any[]>([]);
+        const [tableParams, set_tableParams] = useState<any>({});
+        const [keywords, set_keywords] = useState('');
+
+        //获取表格数据
+        const getFuncList = async () => {
+            const resp = await getChildReportList(currentEditRow.code);
+            if (resp) {
+                set_datasource(resp);
+                set_showList(resp);
+               
+                if(currentEditRow&&currentEditRow.childColumnList){
+                     const defaultKeys = currentEditRow.childColumnList.map((a:any)=>a.code);
+                     setSelectedKeys(defaultKeys);
+                }
+            }
+           
+        }
+
+
+        const onSelectChange = (newSelectedRowKeys: React.Key[], selectedRows: any) => {
+            setSelectedKeys([...newSelectedRowKeys]);
+            set_selectedRows(selectedRows);
+
+        };
+
+        const save = async () => {
+              const result = selectedRows.map(a=>({
+                code:a.code,
+                columnType:a.columnType,
+                dataSource:a.dataSource,
+                dataType:a.dataType,
+                headerText:a.headerText,
+                indicatorCode:a.indicatorCode,
+                indicatorCodeName:a.indicatorCodeName,
+                name:a.name,
+                sql:a.sql
+              }))
+              const resp = await addChildReportList({
+                  parentCode:currentEditRow.code,
+                  childColumnList:result
+              });
+              if(resp){
+                set_ifShowModal(false);
+                tableRef.current?.reload();
+                message.success('操作成功!');
+              }
+        }
+
+        useEffect(() => {
+            getFuncList();
+
+        }, [])
+
+        return (
+            <div className='TableSelecter'>
+                <Input placeholder={'请输入'} allowClear
+                    suffix={
+                        <IconFont type="iconsousuo" />
+                    }
+                    style={{ marginBottom: 8 }}
+                    onChange={(e) => {
+                        if (e.target.value.length != 0) {
+                            const result = datasource.filter(item => item.name.indexOf(e.target.value) != -1);
+                            set_showList(result);
+                        } else {
+                            set_showList(datasource);
+                        }
+
+
+                    }}
+
+
+                />
+                <div className='wrapper' style={{maxHeight:489,overflowY:'scroll'}}>
+                <BMSTable columns={tableSelecterColumn}
+                    options={{
+                        density: true,
+                        setting: {
+                            listsHeight: 100,
+                        },
+                    }}
+                    rowKey='code'
+                    tableAlertRender={false}
+                    rowSelection={{
+                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+                        // 注释该行则默认不显示下拉选项
+                        selectedRowKeys:selectedKeys,
+                        onChange: onSelectChange,
+                        checkStrictly: false
+                    }}
+                    dataSource={showList}
+                    pagination={false}
+                    
+                />
+                </div>
+                
+                <div className='footer'>
+                    <span className='cancel' onClick={() => set_ifShowModal(false)}>取消</span>
+                    <span className='ok' onClick={() => save()}>{`确认(${selectedKeys.length > 0 && selectedKeys.length})`}</span>
+                </div>
+            </div>
+
+        )
+    });
+
+
     useEffect(() => {
 
     }, [])
 
     return (
         <BMSPagecontainer className='ReportListMana' title={false}>
+            <ModalForm title={`选择子报表列(${currentEditRow&&currentEditRow.headerText})`} width={400} submitter={{
+                render: (props, defaultDoms) => []
+            }} open={ifShowModal} modalProps={{
+                closable: false,
+            }}>
+                <TableSelecter
+                    ref={ref}
+                    record={undefined}
+                    tableSelecterColumn={tableSelecterColumn}
+                ></TableSelecter>
+            </ModalForm>
             <div className='toolBar'>
                 <div className='filter'>
                     <div className='filterItem'>

+ 68 - 33
src/pages/setting/reportSet/reportListMana/service.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 16:31:27
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-04-07 12:03:02
+ * @LastEditTime: 2023-06-30 17:27:16
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/service.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -14,46 +14,47 @@ import { request } from 'umi';
 //获取table列表数据
 
 export type ReportListTableDataType = {
-  id:number,
-  hospId:number,
-  code:number,
-  name:string,
-  headerText:string,
-  dataSource:number,
-  columnType:string,
-  columnTypeName:string,
-  sql:string,
-  indicatorCode:string,
-  indicatorCodeName:string
+  id: number,
+  hospId: number,
+  code: number,
+  name: string,
+  headerText: string,
+  dataSource: number,
+  columnType: string,
+  columnTypeName: string,
+  sql: string,
+  indicatorCode: string,
+  indicatorCodeName: string,
+  childColumnList: any[],
 }
 
 
-export const getReportListTableData = (params?:any) => {
+export const getReportListTableData = (params?: any) => {
   return request<{
-       current:number;
-       list:ReportListTableDataType[];
-       pageSize:number;
-       totalCount:number;
-       totalPage:number;
+    current: number;
+    list: ReportListTableDataType[];
+    pageSize: number;
+    totalCount: number;
+    totalPage: number;
   }>('/performance/report/getColumnList', {
     method: 'GET',
-    params:{...params}
+    params: { ...params }
   });
 };
 
 
 //新增报表
 export type AddTableDataType = {
-  name:string,
-  headerText:string,
-  dataSource:number,
-  columnType:string,
-  sql?:string,
-  indicatorCode?:string,
-  indicatorCodeName?:string
+  name: string,
+  headerText: string,
+  dataSource: number,
+  columnType: string,
+  sql?: string,
+  indicatorCode?: string,
+  indicatorCodeName?: string
 }
 
-export const addData = (data:any) => {
+export const addData = (data: any) => {
   return request('/performance/report/addColumn', {
     method: 'POST',
     data
@@ -82,10 +83,10 @@ export const getManaIndic = () => {
 //编辑表格数据
 
 export type ManaIndicItemTableRowEditType = {
-  id:number;
-}&AddTableDataType
+  id: number;
+} & AddTableDataType
 
-export const editData = (data:any) => {
+export const editData = (data: any) => {
   return request('/performance/report/editColumn', {
     method: 'POST',
     data
@@ -93,16 +94,16 @@ export const editData = (data:any) => {
 };
 
 //删除表格操作
-export const delData = (id:string) => {
+export const delData = (id: string) => {
   return request('/performance/report/deleteColumn', {
     method: 'POST',
-    params:{id}
+    params: { id }
   });
 };
 
 
 //添加报表列
-export const addReportTableList = (data:any) => {
+export const addReportTableList = (data: any) => {
   return request('/performance/report/addReportColumn', {
     method: 'POST',
     data
@@ -111,6 +112,40 @@ export const addReportTableList = (data:any) => {
 
 
 
+//获取子列报表列
+
+export const getChildReportList = (columnCode: string) => {
+  return request('/performance/report/getChildColumnList', {
+    method: 'GET',
+    params: { columnCode }
+  });
+};
+
+//添加子列报表列
+
+export type AddChildReportListDataType = {
+  parentCode: string,
+  childColumnList: {
+    "code": string, //流转功能code
+    "columnType":string, //报表列类型
+    "dataSource":number, //数据类型
+    "dataType": number, //数据格式 0 未知 1 文本 2金额 3 数值 4百分比
+    "headerText":string,
+    "indicatorCode": number, //指标代码
+    "indicatorCodeName":string,
+    "name":string, //功能名称
+    "sql": string //sql
+  }[]
+}
+
+export const addChildReportList = (data: AddChildReportListDataType) => {
+  return request('/performance/report/addChildColumn', {
+    method: 'POST',
+    data: { ...data }
+  });
+};
+
+
 
 
 

+ 31 - 0
src/pages/setting/reportSet/reportListMana/style.less

@@ -1,3 +1,34 @@
+.TableSelecter {
+  .footer {
+       display: flex;
+       flex-direction:row;
+       justify-content: flex-end;
+       margin-bottom:-10px;
+       margin-top: 15px;
+       span {
+           display: inline-block;
+           width: 56px;
+           height: 24px;  
+           font-size: 14px;
+           line-height: 23px;
+           text-align: center;
+           border-radius: 4px;
+           cursor: pointer;
+
+           &.ok {
+               color: #FFFFFF;
+               background:#3377FF;
+               margin-left: 8px;
+           }
+           &.cancel {
+               border: 1px solid #DAE2F2;
+           }
+       }
+
+  }
+}
+
+
 .ReportListMana {
   padding: 16px;
   background: #FFFFFF;

+ 73 - 2
src/utils/tooljs.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-02-20 14:31:06
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-27 10:18:39
+ * @LastEditTime: 2023-06-30 19:33:12
  * @FilePath: /BudgetManaSystem/src/utils/tooljs.js
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -29,7 +29,7 @@ export const getDeepestTreeData:any= (tree:any,childrenName:string)=>{
  * @param y {Object} 对象2
  * @return  {Boolean} true 为相等,false 为不等
  */
-export const deepEqual = (x: { [x: string]: any; } | null, y: { [x: string]: any; hasOwnProperty?: any; } | null) => {
+export  const deepEqual = (x: { [x: string]: any; } | null, y: { [x: string]: any; hasOwnProperty?: any; } | null) => {
       // 指向同一内存时
       if (x === y) {
         return true;
@@ -49,3 +49,74 @@ export const deepEqual = (x: { [x: string]: any; } | null, y: { [x: string]: any
         return false;
       }
 }
+
+
+// 查找父节点的函数
+
+interface Node {
+  code: string;
+  parentCode: number;
+  children?: Node[];
+}
+
+export const findAllParents = (data: Node[], parentCode:string): Node[] => {
+  let result: Node[] = [];
+
+  function findNodeRecursively(node: Node, path: Node[]): boolean {
+      if (node.code === `${parentCode}`) {
+          result = [...path, node];
+          return true;
+      }
+
+      if (node.children) {
+          for (const child of node.children) {
+              if (findNodeRecursively(child, [...path, node])) {
+                  return true;
+              }
+          }
+      }
+
+      return false;
+  }
+
+  for (const node of data) {
+      if (parentCode != '0' && findNodeRecursively(node, [])) {
+          break;
+      }
+  }
+
+  return result;
+}
+
+
+//获取所有children节点的code
+
+interface TreeNode {
+  code: string;
+  children?: TreeNode[];
+}
+
+
+export const getNodesWithChildren = (tree: TreeNode[]): TreeNode[] => {
+  let nodes: TreeNode[] = [];
+
+  function helper(node: TreeNode) {
+    if (node.children && node.children.length > 0) {
+      // 当前节点包含 children,添加整个节点
+      nodes.push(node);
+      // 递归处理子节点
+      for (const child of node.children) {
+        helper(child);
+      }
+    }
+  }
+
+  // 在这个版本中,我们对每个根节点进行操作
+  for (const node of tree) {
+    helper(node);
+  }
+
+  return nodes;
+}
+
+