code4eat 2 yıl önce
ebeveyn
işleme
095519b635

+ 27 - 2
.umirc.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-14 14:14:32
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-04-19 18:02:10
+ * @LastEditTime: 2023-04-26 09:58:54
  * @FilePath: /BudgetManaSystem/.umirc.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -124,7 +124,7 @@ export default defineConfig({
               name: '单元指标目标设定',
               path: '/setting/manaPerformanceSet/unitIndicTargetSet',
               component: './setting/manaPerformanceSet/unitIndicTargetSet',
-            }
+            },
           ]
         },
         {
@@ -162,6 +162,31 @@ export default defineConfig({
               path: '/setting/checkUnitSet/checkUnitClassMana',
               component: './setting/checkUnitSet/checkUnitClassMana',
             },
+            {
+              name: '核算单元管理',
+              path: '/setting/checkUnitSet/checkUnitMana',
+              component: './setting/checkUnitSet/checkUnitMana',
+            },
+            {
+              name: '核算单元科室对照',
+              path: '/setting/checkUnitSet/checkUnitDepMap',
+              component: './setting/checkUnitSet/checkUnitDepMap',
+            },
+            {
+              name: '核算单元人员设定',
+              path: '/setting/checkUnitSet/checkUnitEmpSet',
+              component: './setting/checkUnitSet/checkUnitEmpSet',
+            },
+            {
+              name: '医疗组设定',
+              path: '/setting/checkUnitSet/medicalGroupSet',
+              component: './setting/checkUnitSet/medicalGroupSet',
+            },
+            {
+              name: '检视单元权限设定',
+              path: '/setting/checkUnitSet/viewUnitPermSet',
+              component: './setting/checkUnitSet/viewUnitPermSet',
+            }
           ]
         },
 

+ 3 - 0
.vscode/settings.json

@@ -0,0 +1,3 @@
+{
+    "vue.features.codeActions.enable": false
+}

+ 3 - 3
src/components/BMSTable/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-20 15:24:11
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-27 16:37:22
+ * @LastEditTime: 2023-04-25 15:16:54
  * @FilePath: /BudgetManaSystem/src/components/BMSTable/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -22,7 +22,7 @@ export const BMSTablePageDefaultConfig = {
 
 export const BMSTable = (props: BMSTablePropsType<any, any, any>) => {
 
-    const { params,...rest } = props;
+    const { params,options = false,...rest } = props;
     // let prevParams:any = undefined;
     const [prevParams,set_prevParams] = useState<any>(undefined);
 
@@ -42,7 +42,7 @@ export const BMSTable = (props: BMSTablePropsType<any, any, any>) => {
         <ProTable
             tableClassName="BMSTable"
             toolBarRender={false}
-            options={false}
+            options={options}
             pagination={{
                    ...BMSTablePageDefaultConfig  
             }}

+ 6 - 0
src/components/BMSTable/style.less

@@ -43,6 +43,12 @@
             //border-top:1px solid #dae2f2 !important ;
             background: rgb(238 243 250 / 100%) !important;
 
+            .bms-ant-table-selection {
+                  .bms-ant-table-selection-extra {
+                      top:5px;
+                  }
+            }
+
             &::before {
                 display: none;
             }

+ 5 - 2
src/pages/reportCheck/report/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-01-04 14:12:31
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-04-20 18:52:43
+ * @LastEditTime: 2023-04-21 11:34:35
  * @FilePath: /BudgetManaSystem/src/pages/budgetMana/oneBatch/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -55,6 +55,8 @@ const ReportTemplate = () => {
 
   const reportJumphandle = (reportData: any) => {
 
+    console.log({reportData});
+
     let parameter: { [key: string]: any } = {};
     const { redirectParameter = undefined } = reportData;
     const _step = step + 1;
@@ -70,7 +72,7 @@ const ReportTemplate = () => {
       [...breadCrumbList,
       {
         index: _step,
-        name: reportData[`report_name`],
+        name: reportData[`report_name`]||reportData[`redirectReportName`],
         params: {
           reportCode: reportData.redirectReportCode,
           parameter:{
@@ -220,6 +222,7 @@ const ReportTemplate = () => {
     set_tableDataFilterParams({ reportCode: urlReportCode, parameter: { compute_date: currentComputeDate } });
     set_breadCrumbList([{
       name:'首页',
+      index:0,
       params: { reportCode: urlReportCode, parameter: { compute_date: currentComputeDate } }
     }])
   }, [urlReportCode]);

+ 4 - 0
src/pages/reportCheck/report/style.less

@@ -34,5 +34,9 @@
                 border-bottom: none !important;
             }
         }
+
+        .bms-ant-table-body {
+              max-height: 76.5vh !important;
+        }
     }
 }

+ 3 - 3
src/pages/setting/checkUnitSet/checkUnitClassMana/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-04-20 18:10:17
+ * @LastEditTime: 2023-04-26 15:23:17
  * @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
  */
@@ -12,7 +12,7 @@
 
 import BMSPagecontainer from '@/components/BMSPageContainer';
 import { BMSTable } from '@/components/BMSTable';
-import { getDataByKeyFromDic, getPubDicDataByKey } from '@/services/getDic';
+import { getDataByKeyFromDic, getPubDicData } from '@/services/getDic';
 import { createFromIconfontCN } from '@ant-design/icons';
 
 import { ActionType, ProFormInstance, ProFormText } from '@ant-design/pro-components';
@@ -135,7 +135,7 @@ export default function CheckUnitClassficationMana() {
 
     const getDirecData = async (key?: string) => {
 
-        const data = await getPubDicDataByKey();
+        const data = await getPubDicData();
         if (data) {
             set_dicData(data);
         }

+ 559 - 0
src/pages/setting/checkUnitSet/checkUnitDepMap/index.tsx

@@ -0,0 +1,559 @@
+
+
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-16 09:42:52
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-26 16:47:40
+ * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import BMSPagecontainer from '@/components/BMSPageContainer';
+
+import { useEffect, useImperativeHandle, useRef, useState } from 'react';
+import './style.less';
+
+import { TreeProps, Input, Modal, Transfer, Popconfirm, Table, message } from 'antd';
+import { DataNode } from 'antd/es/tree';
+
+import expandedIcon from '../../../../../static/treenode_open.png';
+import closeIcon from '../../../../../static/treenode_collapse.png';
+import { BMSTable } from '@/components/BMSTable';
+import { ActionType, ProColumns} from '@ant-design/pro-components';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { CheckUnitDepMapTableDataType, delTableData,addMapDep, getCheckUnitDepMapTableDataByUnitClass, getMapDepList, getTreeData, getTreeDataRespType } from './service';
+import { TransferItem, TransferProps } from 'antd/es/transfer';
+
+import difference from 'lodash/difference';
+
+
+
+import 'dayjs/locale/zh-cn';
+
+import React from 'react';
+import DirectoryTree from 'antd/es/tree/DirectoryTree';
+import { getDeepestTreeData } from '@/utils/tooljs';
+
+import { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
+
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+const SearchIcon = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
+});
+
+
+
+
+export type TableListItem = {
+    key: number;
+    name: string;
+};
+
+
+const CheckUnitDepMap: React.FC = () => {
+
+    const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
+    const [tableColumn, set_tableColumn] = useState<ProColumns[]>([]);
+    const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>(undefined);
+    const [tableDataSearchKeywords,set_tableDataSearchKeywords] = useState('');
+
+    const [tableData,set_tableData] = useState<CheckUnitDepMapTableDataType[]>([]);
+
+    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+    const [searchValue, setSearchValue] = useState('');
+    const [autoExpandParent, setAutoExpandParent] = useState(true);
+
+
+
+    const tableRef = useRef<ActionType>();
+
+
+    const column = [
+        {
+            title: '科室代码',
+            dataIndex: 'deptCode'
+        },
+        {
+            title: '科室名称',
+            dataIndex: 'deptName',
+        },
+        {
+            title: '类型',
+            dataIndex: 'deptTypeName',
+        },
+        {
+            title: '操作',
+            key: 'option',
+            valueType: 'option',
+            render: (_: any, record: any) => {
+                return [
+                    <Popconfirm
+                        title="是否确认删除?"
+                        key="del"
+                        onConfirm={() => delTableDataHandle(record)}
+                    >
+                        <a>删除</a>
+                    </Popconfirm>
+                ]
+            },
+        },
+    ];
+
+
+    const delTableDataHandle = async (record: any) => {
+        const resp: any = await delTableData(record.id);
+        if (resp) {
+            tableRef.current?.reload();
+            getTreeReqFunc();
+        }
+    }
+
+
+
+    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+        // console.log('selected', selectedKeys, info);
+        const { node } = info;
+        set_currentSelectedTreeNode(node);
+    };
+
+
+
+    const getTableData = async (type: 'PERSON' | 'DEP' | 'CHARGE', params: any, sort: any, filter: any) => {
+        // console.log({ currentSelectedTreeNode });
+        // console.log({ params, sort, filter });
+
+        if (currentSelectedTreeNode) {
+            const resp = await getCheckUnitDepMapTableDataByUnitClass({
+                ...params,
+                unitCode: currentSelectedTreeNode.code,
+
+            });
+            if (resp) {
+                set_tableData(resp.list);
+                return {
+                    data: resp.list,
+                    success: true,
+                    total: resp.totalCount,
+                    pageSize: resp.pageSize,
+                    totalPage: resp.totalPage,
+                }
+            }
+            return {
+                data: [],
+                success: true
+            }
+
+        }
+
+        return []
+    }
+
+
+
+    interface DataType {
+        key: string;
+        title: string;
+        description: string;
+        disabled: boolean;
+        tag: string;
+    }
+
+    interface TableTransferProps extends TransferProps<TransferItem> {
+        dataSource: DataType[];
+        leftColumns: ColumnsType<DataType>;
+        rightColumns: ColumnsType<DataType>;
+        record: any
+    }
+
+
+    const transferTableColumn: any[] = [
+        {
+            title: '科室名称',
+            dataIndex: 'deptName',
+            with: 100,
+            ellipsis: true,
+        },
+        {
+            title: '科室类型',
+            width: 120,
+            dataIndex: 'deptTypeName',
+            ellipsis: true
+        },
+    ];
+
+    const addHandle = () => {
+
+        const ref = React.createRef<{ save: any; }>();
+
+        Modal.confirm({
+            title: `添加单元对照科室(${currentSelectedTreeNode.name})`,
+            icon: <></>,
+            width: 750,
+            centered: true,
+            content: <TableTransfer
+                ref={ref}
+                record={currentSelectedTreeNode}
+                leftColumns={transferTableColumn}
+                rightColumns={transferTableColumn} dataSource={[]}
+            ></TableTransfer>,
+            onOk: () => {
+                return ref.current && ref.current.save();
+            }
+        })
+    }
+
+    const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, record }:any, ref) => {
+
+
+        const [targetKeys, setTargetKeys] = useState<string[]>([]);
+        const [datasource, set_datasource] = useState<any[]>([]);
+        const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
+
+        //获取对照科室
+        const getFuncList = async () => {
+            const resp = await getMapDepList();
+            if (resp) {
+                
+
+                const defaultSelctedkeys = tableData.map((item: any) => item.deptCode);
+                const hasSelectedData = tableData.map((a:any)=>({deptCode:a.deptCode,deptName:a.deptName,deptType:a.deptType,deptTypeName:a.deptTypeName}))
+
+                set_datasource([...resp,...hasSelectedData]);
+
+                setTargetKeys(defaultSelctedkeys);
+
+            }
+        }
+
+        const onChange = (nextTargetKeys: string[]) => {
+            setTargetKeys(nextTargetKeys);
+        };
+
+        const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
+            //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
+            setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+        };
+
+        useImperativeHandle(ref, () => ({
+            save: async () => {
+
+                const needData = datasource.filter(item => targetKeys.includes(item.deptCode));
+
+                const result = {
+                    unitCode:record.code,
+                    unitType:record.unitType,
+                    department:needData
+                };
+
+                const resp = await addMapDep(result);
+
+                if (resp) {
+                    message.success('添加成功!');
+                    tableRef.current?.reload();
+                    getTreeReqFunc();
+                   
+                }
+            }
+        }));
+
+        useEffect(() => {
+            getFuncList();
+        }, [])
+
+        return (
+            <Transfer className='TableTransfer' showSearch
+                titles={['待选项', '已选项']}
+                locale={{
+                    itemUnit: '项',
+                    itemsUnit: '项',
+                    searchPlaceholder: '请输入'
+                }}
+                onChange={onChange}
+                onSelectChange={onSelectChange}
+                dataSource={datasource}
+                rowKey={record => record.deptCode}
+                targetKeys={targetKeys}
+                selectedKeys={selectedKeys}
+                filterOption={(inputValue, item) => {
+                    return item.deptName!.indexOf(inputValue) !== -1
+
+                }}
+            >
+                {({
+                    direction,
+                    filteredItems,
+                    onItemSelectAll,
+                    onItemSelect,
+                    selectedKeys: listSelectedKeys,
+                    disabled: listDisabled,
+                }) => {
+
+                    // console.log({ filteredItems, listSelectedKeys,direction });
+                    const columns = direction === 'left' ? leftColumns : rightColumns;
+
+                    const rowSelection: TableRowSelection<TransferItem> = {
+                        getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
+                        onSelectAll(selected, selectedRows) {
+                            const treeSelectedKeys = selectedRows.map(({ deptCode }) => deptCode);
+                            const diffKeys = selected
+                                ? difference(treeSelectedKeys, listSelectedKeys)
+                                : difference(listSelectedKeys, treeSelectedKeys);
+                            onItemSelectAll(diffKeys as string[], selected);
+                        },
+                        onSelect({ deptCode }, selected) {
+                            onItemSelect(deptCode as string, selected);
+                        },
+                        selectedRowKeys: listSelectedKeys,
+                    };
+
+                    return (
+                        <Table
+                            rowSelection={rowSelection}
+                            columns={columns as TransferItem[]}
+                            dataSource={filteredItems}
+                            size="small"
+                            rowKey={'deptCode'}
+                            style={{ pointerEvents: listDisabled ? 'none' : undefined }}
+                            onRow={({ deptCode, disabled: itemDisabled }) => ({
+                                onClick: () => {
+                                    if (itemDisabled || listDisabled) return;
+                                    onItemSelect(deptCode as string, !listSelectedKeys.includes(deptCode as string));
+                                },
+                            })}
+                        />
+                    );
+                }}
+            </Transfer>
+        )
+    })
+
+
+    const dataList: any[] = [];
+
+    const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+        let parentKey: React.Key;
+        for (let i = 0; i < tree.length; i++) {
+            const node = tree[i];
+            if (node.child) {
+                if (node.child.some((item: { code: React.Key; }) => item.code === key)) {
+                    parentKey = node.code;
+                } else if (getParentKey(key, node.child)) {
+                    parentKey = getParentKey(key, node.child);
+                }
+            }
+        }
+        return parentKey!;
+    };
+
+
+    const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+
+        const { value } = e.target;
+        const newExpandedKeys = dataList
+            .map((item) => {
+                if (item.name.indexOf(value) > -1) {
+                    return getParentKey(item.code, treeData);
+                }
+                return null;
+            });
+
+        const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
+
+        setExpandedKeys(newExpandedKeys as React.Key[]);
+        setSearchValue(value);
+        setAutoExpandParent(true);
+    }
+
+
+    const onExpand = (newExpandedKeys: React.Key[]) => {
+        setExpandedKeys(newExpandedKeys);
+        setAutoExpandParent(false);
+    };
+
+    const generateList = (data: any[]) => {
+        for (let i = 0; i < data.length; i++) {
+            const node = data[i];
+            const { code, name } = node;
+            dataList.push({ code, name });
+            if (node.child) {
+                generateList(node.child);
+            }
+        }
+    };
+    generateList(treeData as any);
+
+
+    const getTreeReqFunc = async () => {
+        const resp = await getTreeData();
+        set_treeData(resp);
+    }
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+
+    }
+
+
+    useEffect(() => {
+        if(currentSelectedTreeNode&&currentSelectedTreeNode.unitType){
+            tableRef.current?.reload();
+        }
+    }, [currentSelectedTreeNode]);
+
+
+
+
+    useEffect(() => {
+        //初始化左侧树结构数据后
+
+        if(currentSelectedTreeNode)return;
+
+        if (treeData?.length > 0) {
+
+            if (treeData[0].child && treeData[0].child.length > 0) {
+                const [node, nodeParent] = getDeepestTreeData(treeData[0], 'child');
+
+                set_currentSelectedTreeNode(node);
+                setExpandedKeys([nodeParent.code]);
+            }
+        }
+    }, [treeData]);
+
+
+
+
+    useEffect(() => {
+        set_tableColumn(column as ProColumns[]);
+
+        getTreeReqFunc();
+
+
+    }, []);
+
+
+    return (
+        <div className='CheckUnitDepMap'>
+            <div className='leftTree'>
+                <div className='search'>
+                    <Input
+                        className='searchInput'
+                        placeholder="请输入类目名称"
+                        size='small'
+                        allowClear
+
+                        style={{ marginBottom: 16 }}
+                        onChange={onTreeSearchKeyChange}
+                        suffix={
+                            <SearchIcon type='iconsousuo' />
+                        }
+                    />
+                </div>
+                {
+                    treeData && treeData.length > 0 && currentSelectedTreeNode && (
+                        <DirectoryTree
+                            fieldNames={{ title: 'name', key: 'code',children:'child' }}
+                            rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
+                            onSelect={onSelect}
+                            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:'space-between', alignItems: 'center', height: 32,
+                                        borderRadius: '4px',
+                                        overflow: 'hidden',
+                                        color: '#17181A',
+                                        textOverflow: 'ellipsis',
+                                        whiteSpace: 'nowrap'
+
+                                    }}>
+                                        {title}
+                                        {!nodeData.map&&<span className='point'></span>}
+                                    </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 style={{width:16,height:'92vh',background:'#F5F7FA'}}></div> */}
+            <div className='rightContent'>
+                <BMSPagecontainer title={false} ghost>
+
+                    <div className='content'>
+                        <div className='tableToolbar'>
+                            <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,deptName:''});
+                                    }
+                                }} suffix={
+                                    <IconFont type="iconsousuo" onClick={() => tableDataSearchHandle('deptName')} />
+                                } 
+                                onPressEnter={(e) => {
+
+                                    set_tableDataFilterParams({
+                                        ...tableDataFilterParams,
+                                        deptName: (e.target as HTMLInputElement).value
+                                    });
+                                }}
+                                />
+                            </div>
+                            <div className='btnGroup'>
+                                <span className='add' onClick={()=>addHandle()}>添加</span>
+                            </div>
+                        </div>
+                        {currentSelectedTreeNode && <BMSTable actionRef={tableRef} params={tableDataFilterParams} rowKey='id' columns={tableColumn} request={(params, sort, filter) => getTableData('CHARGE', params, sort, filter)} />}
+                    </div>
+
+
+                </BMSPagecontainer>
+            </div>
+        </div>
+    );
+
+};
+
+export default CheckUnitDepMap;

+ 135 - 0
src/pages/setting/checkUnitSet/checkUnitDepMap/service.ts

@@ -0,0 +1,135 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-21 11:13:51
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-24 10:20:21
+ * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlyInfoCheck/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+import { request } from '@@/plugin-request';
+import { getCheckUnitClassTableData } from '../checkUnitClassMana/service';
+
+
+
+
+//获取树结构单元数据
+
+export type getTreeDataRespType = {
+    code: number;
+    name: string;
+    unitType?:string,
+    map?:boolean,
+    parentCode?:string,
+    child: getTreeDataRespType[]
+}
+
+export const getTreeData = () => {
+    return request('/performance/unit/getList', {
+        method: 'GET',
+    })
+}
+
+
+
+//获取人员信息表格数据
+
+export type pagesDataType = {
+
+    current: number,
+    pageSize: number,
+    totalCount: number,
+    totalPage: number,
+}
+
+
+export type CheckUnitDepMapTableDataType = {
+       
+    id:number,
+    hospId:number,
+    unitCode:string,
+    deptCode:string,
+    deptName:string,
+    unitType:string,
+    deptType:string,
+    deptTypeName:string
+
+}
+
+export const getCheckUnitDepMapTableDataByUnitClass = (params?:{
+    current:number,
+    pageSize:number,
+    unitCode:string,
+    deptName:string
+}) => {
+    return request<{list:CheckUnitDepMapTableDataType[]}&pagesDataType>('/performance/unit/getUnitDeptMap', {
+        method: 'GET',
+        params: { ...params }
+    })
+
+}
+
+
+//获取对照列表
+export const getMapDepList = () => {
+    return request('/performance/unit/getDepartment', {
+        method: 'GET',
+    })
+}
+
+
+
+export type AddCheckUnitDataType = {
+    unitName:string,
+    classCode:string,
+    unitType:string,
+    description:string,
+    specialUnit:number,
+    unitLevel:string
+}
+
+export const addCheckUnit = (data:AddCheckUnitDataType) => {
+    return request('/performance/unit/addUnitList', {
+        method: 'POST',
+        data
+    })
+
+}
+
+
+export type AddMapDepDataType = {
+    unitCode:string,
+    unitType:string,
+    department:{
+        deptCode:string,
+        deptName:string,
+        deptType:string,
+        deptTypeName:string
+    }[]
+}
+
+//添加对照科室
+export const addMapDep = (data:AddMapDepDataType) => {
+
+    return request('/performance/unit/addUnitDeptMap', {
+        method: 'POST',
+        data
+    })
+
+}
+
+
+
+//删除
+export const delTableData = ( id:number) => {
+
+    return request('/performance/unit/deleteUnitDeptMap', {
+        method: 'POST',
+        params: {id}
+    })
+
+}
+

+ 115 - 0
src/pages/setting/checkUnitSet/checkUnitDepMap/style.less

@@ -0,0 +1,115 @@
+.CheckUnitDepMap {
+    display: flex;
+    flex-direction: row;
+    // height: 100%;
+    background: #F5F7FA;
+
+    .leftTree {
+        position: fixed;
+        top: 64px;
+        width: 220px;
+        height: calc(100vh - 80px);
+        background: #FFF;
+        border-radius: 4px;
+        overflow: hidden;
+        padding-top: 16px;
+        padding-bottom: 16px;
+        margin-right: 16px;
+        // border-right:16px solid #F5F7FA;
+        .search {
+            margin: 0 16px;
+        }
+        .searchInput {
+            border: 1px solid #CFD7E6;
+        }
+
+        .bms-ant-tree {
+            padding-left: 16px;
+            padding-right: 16px;
+        }
+
+        .site-tree-search-value {
+            display: inline-block;
+            position: relative;
+        }
+
+        .point {
+            display: block;
+            content: '';
+            width: 6px;
+            height: 6px;
+            border-radius: 50%;
+            z-index:99;
+            background: #FF9832;
+        }
+
+        .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%);
+        }
+
+        .bms-ant-tree.bms-ant-tree-directory .bms-ant-tree-treenode .bms-ant-tree-node-content-wrapper.bms-ant-tree-node-selected {
+            font-weight: bold;
+        }
+    }
+
+    .rightContent {
+        position: relative;
+        border-radius: 4px;
+        width: calc(100% - 220px);
+        padding: 16px;
+        margin-left: 236px;
+        background: #FFF;
+
+        .content {
+            display: flex;
+            flex-direction: column;
+
+            .tableToolbar {
+                display: flex;
+                flex-direction: row;
+                justify-content: space-between;
+                align-items: center;
+                margin-bottom: 16px;
+
+                .search {
+                    display: flex;
+                    flex-direction: row;
+                    justify-content: flex-start;
+                    align-items: center;
+
+                    .searchInput {
+                        width: 167px;
+                        height: 24px;
+                        background: #FFF;
+                        border-radius: 4px;
+                        border: 1px solid #CFD7E6;
+                    }
+
+                    &>span {
+                        font-size: 14px;
+                        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                        font-weight: 400;
+                        color: #17181A;
+                    }
+                }
+
+                .btnGroup {
+                    .add {
+                        cursor: pointer;
+                        display: inline-block;
+                        font-size: 14px;
+                        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                        font-weight: 400;
+                        color: #FFFFFF;
+                        line-height: 24px;
+                        padding: 0 14px;
+                        background: #3377FF;
+                        border-radius: 4px;
+                    }
+                }
+            }
+        }
+    }
+}

+ 560 - 0
src/pages/setting/checkUnitSet/checkUnitEmpSet/index.tsx

@@ -0,0 +1,560 @@
+
+
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-16 09:42:52
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-26 16:48:34
+ * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import BMSPagecontainer from '@/components/BMSPageContainer';
+
+import { useEffect, useImperativeHandle, useRef, useState } from 'react';
+import './style.less';
+
+import { TreeProps, Input, Modal, Transfer, Popconfirm, Table, message } from 'antd';
+import { DataNode } from 'antd/es/tree';
+
+import expandedIcon from '../../../../../static/treenode_open.png';
+import closeIcon from '../../../../../static/treenode_collapse.png';
+import { BMSTable } from '@/components/BMSTable';
+import { ActionType, ProColumns} from '@ant-design/pro-components';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { CheckUnitEmpMapTableDataType, delTableData,addMapEmp,getCheckUnitEmpMapTableDataByUnitClass,getMapEmpList, getTreeData, getTreeDataRespType } from './service';
+import { TransferItem, TransferProps } from 'antd/es/transfer';
+
+import difference from 'lodash/difference';
+
+
+
+import 'dayjs/locale/zh-cn';
+
+import React from 'react';
+import DirectoryTree from 'antd/es/tree/DirectoryTree';
+import { getDeepestTreeData } from '@/utils/tooljs';
+
+import { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
+
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+const SearchIcon = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
+});
+
+
+
+
+export type TableListItem = {
+    key: number;
+    name: string;
+};
+
+
+const CheckUnitDepMap: React.FC = () => {
+
+    const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
+    const [tableColumn, set_tableColumn] = useState<ProColumns[]>([]);
+    const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>(undefined);
+    const [tableDataSearchKeywords,set_tableDataSearchKeywords] = useState('');
+
+    const [tableData,set_tableData] = useState<CheckUnitEmpMapTableDataType[]>([]);
+
+    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+    const [searchValue, setSearchValue] = useState('');
+    const [autoExpandParent, setAutoExpandParent] = useState(true);
+
+    const tableRef = useRef<ActionType>();
+
+    const column = [
+        {
+            title: '工号',
+            dataIndex: 'account'
+        },
+        {
+            title: '姓名',
+            dataIndex: 'name',
+        },
+        {
+            title: '人员类别',
+            dataIndex: 'userCateName',
+        },
+        {
+            title: '职务',
+            dataIndex: 'jobTitleName',
+        },
+        {
+            title: '职称',
+            dataIndex: 'titleName',
+        },
+        {
+            title: '岗位',
+            dataIndex: 'positionName',
+        },
+        {
+            title: '学历',
+            dataIndex: 'degreeName',
+        },
+        {
+            title: '入职时间',
+            dataIndex: 'entryTime',
+        },
+        {
+            title: '在职',
+            dataIndex: 'isOnServiceName',
+        },
+        {
+            title: '操作',
+            key: 'option',
+            valueType: 'option',
+            render: (_: any, record: any) => {
+                return [
+                    <Popconfirm
+                        title="是否确认删除?"
+                        key="del"
+                        onConfirm={() => delTableDataHandle(record)}
+                    >
+                        <a>删除</a>
+                    </Popconfirm>
+                ]
+            },
+        },
+    ];
+
+
+    const delTableDataHandle = async (record: any) => {
+        const resp: any = await delTableData(record.id);
+        if (resp) {
+            tableRef.current?.reload();
+            getTreeReqFunc();
+        }
+    }
+
+
+
+    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+        // console.log('selected', selectedKeys, info);
+        const { node } = info;
+        set_currentSelectedTreeNode(node);
+    };
+
+
+
+    const getTableData = async (type: 'PERSON' | 'DEP' | 'CHARGE', params: any, sort: any, filter: any) => {
+        // console.log({ currentSelectedTreeNode });
+        // console.log({ params, sort, filter });
+
+        if (currentSelectedTreeNode) {
+            const resp = await getCheckUnitEmpMapTableDataByUnitClass({
+                ...params,
+                unitCode: currentSelectedTreeNode.code,
+
+            });
+            if (resp) {
+                set_tableData(resp.list);
+                return {
+                    data: resp.list,
+                    success: true,
+                    total: resp.totalCount,
+                    pageSize: resp.pageSize,
+                    totalPage: resp.totalPage,
+                }
+            }
+            return {
+                data: [],
+                success: true
+            }
+
+        }
+
+        return []
+    }
+
+
+    const transferTableColumn: any[] = [
+        {
+            title: '工号',
+            dataIndex: 'account',
+            with: 100,
+            ellipsis: true,
+        },
+        {
+            title: '姓名',
+            width: 120,
+            dataIndex: 'name',
+            ellipsis: true
+        },
+    ];
+
+    const addHandle = () => {
+
+        const ref = React.createRef<{ save: any; }>();
+
+        Modal.confirm({
+            title: `添加单元对照科室(${currentSelectedTreeNode.name})`,
+            icon: <></>,
+            width: 750,
+            centered: true,
+            content: <TableTransfer
+                ref={ref}
+                record={currentSelectedTreeNode}
+                leftColumns={transferTableColumn}
+                rightColumns={transferTableColumn} dataSource={[]}
+            ></TableTransfer>,
+            onOk: () => {
+                return ref.current && ref.current.save();
+            }
+        })
+    }
+
+    const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, record }:any, ref) => {
+
+
+        const [targetKeys, setTargetKeys] = useState<string[]>([]);
+        const [datasource, set_datasource] = useState<any[]>([]);
+        const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
+
+        //获取对照科室
+        const getFuncList = async () => {
+            const resp = await getMapEmpList();
+            if (resp) {
+                
+                const defaultSelctedkeys = tableData.map((item: any) => item.userId);
+        
+                set_datasource([...resp,...tableData]);
+
+                setTargetKeys(defaultSelctedkeys);
+
+            }
+        }
+
+        const onChange = (nextTargetKeys: string[]) => {
+            setTargetKeys(nextTargetKeys);
+        };
+
+        const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
+            //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
+            setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+        };
+
+        useImperativeHandle(ref, () => ({
+            save: async () => {
+
+                const needData = datasource.filter(item => targetKeys.includes(item.userId));
+
+                const result = {
+                    unitCode:record.code,
+                    unitType:record.unitType,
+                    employee:needData
+                };
+
+                const resp = await addMapEmp(result);
+
+                if (resp) {
+                    message.success('添加成功!');
+                    tableRef.current?.reload();
+                    getTreeReqFunc();
+                   
+                }
+            }
+        }));
+
+        useEffect(() => {
+            getFuncList();
+        }, [])
+
+        return (
+            <Transfer className='TableTransfer' showSearch
+                titles={['待选项', '已选项']}
+                locale={{
+                    itemUnit: '项',
+                    itemsUnit: '项',
+                    searchPlaceholder: '请输入'
+                }}
+                onChange={onChange}
+                onSelectChange={onSelectChange}
+                dataSource={datasource}
+                rowKey={record => record.userId}
+                targetKeys={targetKeys}
+                selectedKeys={selectedKeys}
+                filterOption={(inputValue, item) => {
+                    return item.deptName!.indexOf(inputValue) !== -1
+
+                }}
+            >
+                {({
+                    direction,
+                    filteredItems,
+                    onItemSelectAll,
+                    onItemSelect,
+                    selectedKeys: listSelectedKeys,
+                    disabled: listDisabled,
+                }) => {
+
+                    // console.log({ filteredItems, listSelectedKeys,direction });
+                    const columns = direction === 'left' ? leftColumns : rightColumns;
+
+                    const rowSelection: TableRowSelection<TransferItem> = {
+                        getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
+                        onSelectAll(selected, selectedRows) {
+                            const treeSelectedKeys = selectedRows.map(({ userId }) => userId);
+                            const diffKeys = selected
+                                ? difference(treeSelectedKeys, listSelectedKeys)
+                                : difference(listSelectedKeys, treeSelectedKeys);
+                            onItemSelectAll(diffKeys as string[], selected);
+                        },
+                        onSelect({ userId }, selected) {
+                            onItemSelect(userId as string, selected);
+                        },
+                        selectedRowKeys: listSelectedKeys,
+                    };
+
+                    return (
+                        <Table
+                            rowSelection={rowSelection}
+                            columns={columns as TransferItem[]}
+                            dataSource={filteredItems}
+                            size="small"
+                            rowKey={'userId'}
+                            style={{ pointerEvents: listDisabled ? 'none' : undefined }}
+                            onRow={({ userId, disabled: itemDisabled }) => ({
+                                onClick: () => {
+                                    if (itemDisabled || listDisabled) return;
+                                    onItemSelect(userId as string, !listSelectedKeys.includes(userId as string));
+                                },
+                            })}
+                        />
+                    );
+                }}
+            </Transfer>
+        )
+    })
+
+
+    const dataList: any[] = [];
+
+    const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+        let parentKey: React.Key;
+        for (let i = 0; i < tree.length; i++) {
+            const node = tree[i];
+            if (node.child) {
+                if (node.child.some((item: { code: React.Key; }) => item.code === key)) {
+                    parentKey = node.code;
+                } else if (getParentKey(key, node.child)) {
+                    parentKey = getParentKey(key, node.child);
+                }
+            }
+        }
+        return parentKey!;
+    };
+
+
+    const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+
+        const { value } = e.target;
+        const newExpandedKeys = dataList
+            .map((item) => {
+                if (item.name.indexOf(value) > -1) {
+                    return getParentKey(item.code, treeData);
+                }
+                return null;
+            });
+
+        const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
+
+        setExpandedKeys(newExpandedKeys as React.Key[]);
+        setSearchValue(value);
+        setAutoExpandParent(true);
+    }
+
+
+    const onExpand = (newExpandedKeys: React.Key[]) => {
+        setExpandedKeys(newExpandedKeys);
+        setAutoExpandParent(false);
+    };
+
+    const generateList = (data: any[]) => {
+        for (let i = 0; i < data.length; i++) {
+            const node = data[i];
+            const { code, name } = node;
+            dataList.push({ code, name });
+            if (node.child) {
+                generateList(node.child);
+            }
+        }
+    };
+    generateList(treeData as any);
+
+
+    const getTreeReqFunc = async () => {
+        const resp = await getTreeData();
+        set_treeData(resp);
+    }
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+
+    }
+
+
+    useEffect(() => {
+        if(currentSelectedTreeNode&&currentSelectedTreeNode.unitType){
+            tableRef.current?.reload();
+        }
+    }, [currentSelectedTreeNode]);
+
+
+
+
+    useEffect(() => {
+        //初始化左侧树结构数据后
+        if(currentSelectedTreeNode) return;
+        if (treeData?.length > 0) {
+
+            if (treeData[0].child && treeData[0].child.length > 0) {
+                const [node, nodeParent] = getDeepestTreeData(treeData[0], 'child');
+
+                set_currentSelectedTreeNode(node);
+                setExpandedKeys([nodeParent.code]);
+            }
+        }
+    }, [treeData]);
+
+
+
+
+    useEffect(() => {
+        set_tableColumn(column as ProColumns[]);
+
+        getTreeReqFunc();
+
+
+    }, []);
+
+
+    return (
+        <div className='CheckUnitDepMap'>
+            <div className='leftTree'>
+                <div className='search'>
+                    <Input
+                        className='searchInput'
+                        placeholder="请输入类目名称"
+                        size='small'
+                        allowClear
+
+                        style={{ marginBottom: 16 }}
+                        onChange={onTreeSearchKeyChange}
+                        suffix={
+                            <SearchIcon type='iconsousuo' />
+                        }
+                    />
+                </div>
+                {
+                    treeData && treeData.length > 0 && currentSelectedTreeNode && (
+                        <DirectoryTree
+                            fieldNames={{ title: 'name', key: 'code',children:'child' }}
+                            rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
+                            onSelect={onSelect}
+                            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 style={{display:'flex',flexDirection:'row',justifyContent:'center',alignItems:'center'}}>
+                                                {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:'space-between', alignItems: 'center', height: 32,
+                                        borderRadius: '4px',
+                                        overflow: 'hidden',
+                                        color: '#17181A',
+                                        textOverflow: 'ellipsis',
+                                        whiteSpace: 'nowrap'
+
+                                    }}>
+                                        {title}
+                                        {!nodeData.map&&<span className='point'></span>}
+                                    </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 style={{width:16,height:'92vh',background:'#F5F7FA'}}></div> */}
+            <div className='rightContent'>
+                <BMSPagecontainer title={false} ghost>
+
+                    <div className='content'>
+                        <div className='tableToolbar'>
+                            <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,empName:''});
+                                    }
+                                }} suffix={
+                                    <IconFont type="iconsousuo" onClick={() => tableDataSearchHandle('empName')} />
+                                } 
+
+                                onPressEnter={(e) => {
+
+                                    set_tableDataFilterParams({
+                                        ...tableDataFilterParams,
+                                        empName: (e.target as HTMLInputElement).value
+                                    });
+                                }}
+                                />
+                            </div>
+                            <div className='btnGroup'>
+                                <span className='add' onClick={()=>addHandle()}>添加</span>
+                            </div>
+                        </div>
+                        {currentSelectedTreeNode && <BMSTable actionRef={tableRef} params={tableDataFilterParams} rowKey='id' columns={tableColumn} request={(params, sort, filter) => getTableData('CHARGE', params, sort, filter)} />}
+                    </div>
+
+
+                </BMSPagecontainer>
+            </div>
+        </div>
+    );
+
+};
+
+export default CheckUnitDepMap;

+ 102 - 0
src/pages/setting/checkUnitSet/checkUnitEmpSet/service.ts

@@ -0,0 +1,102 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-21 11:13:51
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-26 15:59:31
+ * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlyInfoCheck/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+import { request } from '@@/plugin-request';
+import { getCheckUnitClassTableData } from '../checkUnitClassMana/service';
+
+
+
+
+//获取树结构单元数据
+
+export type getTreeDataRespType = {
+    code: number;
+    name: string;
+    unitType?:string,
+    map?:boolean,
+    parentCode?:string,
+    child: getTreeDataRespType[]
+}
+
+export const getTreeData = () => {
+    return request('/performance/unit/getEmpUnitList', {
+        method: 'GET',
+    })
+}
+
+
+
+//获取人员信息表格数据
+
+export type pagesDataType = {
+
+    current: number,
+    pageSize: number,
+    totalCount: number,
+    totalPage: number,
+}
+
+
+export type CheckUnitEmpMapTableDataType = {[key:string]:any}
+
+export const getCheckUnitEmpMapTableDataByUnitClass = (params?:{
+    current:number,
+    pageSize:number,
+    unitCode:string,
+    empName:string
+}) => {
+    return request<{list:CheckUnitEmpMapTableDataType[]}&pagesDataType>('/performance/unit/getUnitEmpMap', {
+        method: 'GET',
+        params: { ...params }
+    })
+
+}
+
+
+//获取对照列表
+export const getMapEmpList = () => {
+    return request('/performance/unit/getEmployee', {
+        method: 'GET',
+    })
+}
+
+
+
+
+export type AddMapEmpDataType = {
+    unitCode:string,
+    unitType:string,
+    employee:any[]
+}
+
+//添加对照人员
+export const addMapEmp = (data:AddMapEmpDataType) => {
+
+    return request('/performance/unit/addUnitEmpMap', {
+        method: 'POST',
+        data
+    })
+
+}
+
+
+
+//删除
+export const delTableData = ( id:number) => {
+
+    return request('/performance/unit/deleteUnitEmpMap', {
+        method: 'POST',
+        params: {id}
+    })
+
+}
+

+ 115 - 0
src/pages/setting/checkUnitSet/checkUnitEmpSet/style.less

@@ -0,0 +1,115 @@
+.CheckUnitDepMap {
+    display: flex;
+    flex-direction: row;
+    // height: 100%;
+    background: #F5F7FA;
+
+    .leftTree {
+        position: fixed;
+        top: 64px;
+        width: 220px;
+        height: calc(100vh - 80px);
+        background: #FFF;
+        border-radius: 4px;
+        overflow: hidden;
+        padding-top: 16px;
+        padding-bottom: 16px;
+        margin-right: 16px;
+        // border-right:16px solid #F5F7FA;
+        .search {
+            margin: 0 16px;
+        }
+        .searchInput {
+            border: 1px solid #CFD7E6;
+        }
+
+        .bms-ant-tree {
+            padding-left: 16px;
+            padding-right: 16px;
+        }
+
+        .site-tree-search-value {
+            display: inline-block;
+            position: relative;
+        }
+
+        .point {
+            display: block;
+            content: '';
+            width: 6px;
+            height: 6px;
+            border-radius: 50%;
+            z-index:99;
+            background: #FF9832;
+        }
+
+        .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%);
+        }
+
+        .bms-ant-tree.bms-ant-tree-directory .bms-ant-tree-treenode .bms-ant-tree-node-content-wrapper.bms-ant-tree-node-selected {
+            font-weight: bold;
+        }
+    }
+
+    .rightContent {
+        position: relative;
+        border-radius: 4px;
+        width: calc(100% - 220px);
+        padding: 16px;
+        margin-left: 236px;
+        background: #FFF;
+
+        .content {
+            display: flex;
+            flex-direction: column;
+
+            .tableToolbar {
+                display: flex;
+                flex-direction: row;
+                justify-content: space-between;
+                align-items: center;
+                margin-bottom: 16px;
+
+                .search {
+                    display: flex;
+                    flex-direction: row;
+                    justify-content: flex-start;
+                    align-items: center;
+
+                    .searchInput {
+                        width: 167px;
+                        height: 24px;
+                        background: #FFF;
+                        border-radius: 4px;
+                        border: 1px solid #CFD7E6;
+                    }
+
+                    &>span {
+                        font-size: 14px;
+                        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                        font-weight: 400;
+                        color: #17181A;
+                    }
+                }
+
+                .btnGroup {
+                    .add {
+                        cursor: pointer;
+                        display: inline-block;
+                        font-size: 14px;
+                        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                        font-weight: 400;
+                        color: #FFFFFF;
+                        line-height: 24px;
+                        padding: 0 14px;
+                        background: #3377FF;
+                        border-radius: 4px;
+                    }
+                }
+            }
+        }
+    }
+}

+ 486 - 0
src/pages/setting/checkUnitSet/checkUnitMana/index.tsx

@@ -0,0 +1,486 @@
+
+
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-16 09:42:52
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-26 15:36:03
+ * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+import BMSPagecontainer from '@/components/BMSPageContainer';
+
+import { useEffect,useRef, useState } from 'react';
+import './style.less';
+
+import { TreeProps, Input,Popconfirm, message } from 'antd';
+import { DataNode } from 'antd/es/tree';
+
+import expandedIcon from '../../../../../static/treenode_open.png';
+import closeIcon from '../../../../../static/treenode_collapse.png';
+import { BMSTable } from '@/components/BMSTable';
+import { ActionType, ModalForm, ProColumns, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { addCheckUnit, delTableData, editCheckUnit, getCheckUnitTableDataByUnitClass, getTreeData } from './service';
+
+
+
+
+import 'dayjs/locale/zh-cn';
+
+import React from 'react';
+import DirectoryTree from 'antd/es/tree/DirectoryTree';
+import { getDeepestTreeData } from '@/utils/tooljs';
+import { CheckUnitClassTableDataType } from '../checkUnitClassMana/service';
+import { getDataByKeyFromDic, getPubDicData } from '@/services/getDic';
+
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+const SearchIcon = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
+});
+
+
+
+
+export type TableListItem = {
+    key: number;
+    name: string;
+};
+
+
+const CheckUnitMana: React.FC = () => {
+
+    const [treeData, set_treeData] = useState<CheckUnitClassTableDataType[]>([]);
+    const [tableColumn, set_tableColumn] = useState<ProColumns[]>([]);
+    const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>(undefined);
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState('');
+
+    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+    const [searchValue, setSearchValue] = useState('');
+    const [autoExpandParent, setAutoExpandParent] = useState(true);
+
+
+
+    const tableRef = useRef<ActionType>();
+
+
+    const column = [
+        {
+            title: '核算单元名称',
+            dataIndex: 'unitName'
+        },
+        {
+            title: '核算单元代码',
+            dataIndex: 'code',
+        },
+        {
+            title: '职类',
+            dataIndex: 'unitTypeName',
+        },
+        {
+            title: '特殊单元',
+            dataIndex: 'specialUnit',
+            render: (_: any, record: any) => {
+                return record.specialUnit == 1 ? '是' : '否'
+            }
+        },
+        {
+            title: '特殊分级',
+            dataIndex: 'unitLevelName',
+            // render: (_: any, record: any) => {
+            //     return record.specialUnit == 1 ? '是' : '否'
+            // }
+        },
+        {
+            title: '系数',
+            dataIndex: 'rate',
+        },
+        {
+            title: '说明',
+            dataIndex: 'description',
+        },
+        {
+            title: '操作',
+            key: 'option',
+            valueType: 'option',
+            render: (_: any, record: any) => {
+                return [
+                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
+                    <Popconfirm
+                        title="是否确认删除?"
+                        key="del"
+                        onConfirm={() => delTableDataHanfle(record)}
+                    >
+                        <a>删除</a>
+                    </Popconfirm>
+                ]
+            },
+        },
+    ];
+
+
+    const delTableDataHanfle = async (record: any) => {
+        const resp: any = await delTableData(record.id);
+        if (resp) {
+            tableRef.current?.reload();
+        }
+    }
+
+
+
+    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+        // console.log('selected', selectedKeys, info);
+        const { node } = info;
+        set_currentSelectedTreeNode(node);
+    };
+
+
+    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
+
+
+        if (type == 'ADD') {
+            const resp = await addCheckUnit({
+                ...formVal,
+                classCode: currentSelectedTreeNode.code,
+                unitType: currentSelectedTreeNode.unitType
+            });
+            if (resp) {
+                tableRef.current?.reload();
+                message.success('操作成功!');
+            }
+
+        }
+        if (type == 'EDIT') {
+
+            const resp = await editCheckUnit({
+                ...formVal
+            });
+            if (resp) {
+                tableRef.current?.reload();
+                message.success('操作成功!');
+            }
+        }
+        return true;
+
+    }
+
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
+
+        const [dicData, set_dicData] = useState<any[]>([]);
+
+        const getDirecData = async (key?: string) => {
+
+            const data = await getPubDicData();
+            if (data) {
+                set_dicData(data);
+            }
+        }
+
+        useEffect(()=>{
+            getDirecData();
+        },[]);
+
+        return (
+            <ModalForm
+                title={`${type == 'EDIT' ? '编辑' : '新增'}核算单元`}
+                width={400}
+                initialValues={type == 'EDIT' ? {
+                    ...record,
+
+                } : {}}
+                trigger={
+                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
+                }
+                onFinish={(val) => {
+                    return updateTable(type == 'EDIT' ? { ...record, ...val } : { ...val }, type);
+                }}
+                modalProps={{ destroyOnClose: true }}
+                colProps={{ span: 24 }}
+                grid
+            >
+                <ProFormText
+                    name="unitName"
+                    label="核算单元名称:"
+                    placeholder="请输入"
+                    rules={[{ required: true, message: '名称不能为空!' }]}
+                />
+                <ProFormRadio.Group
+                    label="特殊单元"
+                    name="specialUnit"
+                    options={[{ label: '是', value: 1 }, { label: '否', value: 0 }]}
+                    rules={[{ required: true, message: '特殊单元不能为空!' }]}
+                />
+
+                <ProFormSelect label="核算单元分级:"
+                    name='unitLevel'
+                    options={(getDataByKeyFromDic(dicData, '4')).list}
+                    rules={[{ required: true, message: '职类不能为空!' }]}
+                />
+
+                <ProFormTextArea
+                    name="description"
+                    label="说明:"
+                    placeholder="请输入"
+
+                />
+            </ModalForm>
+        )
+    }
+
+
+
+
+    const getTableData = async (params: any, sort: any, filter: any) => {
+        // console.log({ currentSelectedTreeNode });
+        // console.log({ params, sort, filter });
+
+        if (currentSelectedTreeNode) {
+            const resp = await getCheckUnitTableDataByUnitClass({
+                ...params,
+                classCode: currentSelectedTreeNode.code,
+
+            });
+            if (resp) {
+
+                return {
+                    data: resp.list,
+                    success: true,
+                    total: resp.totalCount,
+                    pageSize: resp.pageSize,
+                    totalPage: resp.totalPage,
+                }
+            }
+            return {
+                data: [],
+                success: true
+            }
+
+        }
+
+        return []
+    }
+
+
+
+    const dataList: any[] = [];
+
+    const getParentKey = (key: React.Key, tree: any[]): React.Key => {
+        let parentKey: React.Key;
+        for (let i = 0; i < tree.length; i++) {
+            const node = tree[i];
+            if (node.children) {
+                if (node.children.some((item: { code: React.Key; }) => item.code === key)) {
+                    parentKey = node.code;
+                } else if (getParentKey(key, node.children)) {
+                    parentKey = getParentKey(key, node.children);
+                }
+            }
+        }
+        return parentKey!;
+    };
+
+
+    const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+
+        const { value } = e.target;
+        const newExpandedKeys = dataList
+            .map((item) => {
+                if (item.className.indexOf(value) > -1) {
+                    return getParentKey(item.code, treeData);
+                }
+                return null;
+            });
+
+        const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
+
+        setExpandedKeys(newExpandedKeys as React.Key[]);
+        setSearchValue(value);
+        setAutoExpandParent(true);
+    }
+
+
+    const onExpand = (newExpandedKeys: React.Key[]) => {
+        setExpandedKeys(newExpandedKeys);
+        setAutoExpandParent(false);
+    };
+
+    const generateList = (data: any[]) => {
+        for (let i = 0; i < data.length; i++) {
+            const node = data[i];
+            const { code, className } = node;
+            dataList.push({ code, className });
+            if (node.children) {
+                generateList(node.children);
+            }
+        }
+    };
+    generateList(treeData as any);
+
+
+    const getTreeReqFunc = async () => {
+        const resp = await getTreeData();
+        set_treeData(resp);
+    }
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+
+    }
+
+
+    useEffect(() => {
+        tableRef.current?.reload();
+    }, [currentSelectedTreeNode]);
+
+
+
+
+    useEffect(() => {
+        //初始化左侧树结构数据后
+
+        if (treeData?.length > 0) {
+
+            if (treeData[0].children && treeData[0].children.length > 0) {
+                const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
+
+                set_currentSelectedTreeNode(node);
+                setExpandedKeys([nodeParent.code]);
+            }
+        }
+    }, [treeData]);
+
+
+
+
+    useEffect(() => {
+        set_tableColumn(column as ProColumns[]);
+
+        getTreeReqFunc();
+
+    }, []);
+
+
+    return (
+        <div className='CheckUnitMana'>
+            <div className='leftTree'>
+                <div className='search'>
+                    <Input
+                        className='searchInput'
+                        placeholder="请输入类目名称"
+                        size='small'
+                        allowClear
+
+                        style={{ marginBottom: 16 }}
+                        onChange={onTreeSearchKeyChange}
+                        suffix={
+                            <SearchIcon type='iconsousuo' />
+                        }
+                    />
+                </div>
+                {
+                    treeData && treeData.length > 0 && currentSelectedTreeNode && (
+                        <DirectoryTree
+                            fieldNames={{ title: 'className', key: 'code' }}
+                            rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
+                            onSelect={onSelect}
+                            onExpand={onExpand}
+                            expandedKeys={expandedKeys}
+                            autoExpandParent={autoExpandParent}
+                            selectedKeys={[currentSelectedTreeNode.code]}
+                            blockNode={true}
+                            icon={() => null}
+                            titleRender={
+                                (nodeData: any) => {
+                                    const strTitle = nodeData.className 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].children[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 style={{width:16,height:'92vh',background:'#F5F7FA'}}></div> */}
+            <div className='rightContent'>
+                <BMSPagecontainer title={false} ghost>
+
+                    <div className='content'>
+                        <div className='tableToolbar'>
+                            <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, unitName: '' });
+                                    }
+                                }} suffix={
+                                    <IconFont type="iconsousuo" onClick={() => tableDataSearchHandle('unitName')} />
+                                }
+                                    onPressEnter={(e) => {
+
+                                        set_tableDataFilterParams({
+                                            ...tableDataFilterParams,
+                                            unitName: (e.target as HTMLInputElement).value
+                                        });
+                                    }}
+                                />
+                            </div>
+                            <div className='btnGroup'>
+                                <UpDataActBtn record type='ADD' />
+                            </div>
+                        </div>
+                        {currentSelectedTreeNode && <BMSTable actionRef={tableRef} params={tableDataFilterParams} rowKey='id' columns={tableColumn} request={(params, sort, filter) => getTableData(params, sort, filter)} />}
+                    </div>
+
+
+                </BMSPagecontainer>
+            </div>
+        </div>
+    );
+
+};
+
+export default CheckUnitMana;

+ 110 - 0
src/pages/setting/checkUnitSet/checkUnitMana/service.ts

@@ -0,0 +1,110 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-21 11:13:51
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-23 14:28:57
+ * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlyInfoCheck/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+import { request } from '@@/plugin-request';
+import { getCheckUnitClassTableData } from '../checkUnitClassMana/service';
+
+
+
+
+//获取树结构单元数据
+
+export type getTreeDataRespType = {
+    code: number;
+    name: string;
+    child: getTreeDataRespType[]
+}
+
+export const getTreeData = () => {
+     return getCheckUnitClassTableData()
+}
+
+
+
+//获取人员信息表格数据
+
+export type pagesDataType = {
+
+    current: number,
+    pageSize: number,
+    totalCount: number,
+    totalPage: number,
+}
+
+
+export type CheckUnitTableDataType = {
+       
+    id:number,
+    hospId:number,
+    code:string,
+    unitName:string,
+    classCode:string,
+    unitType:string,
+    unitTypeName:string,
+    rate:string,
+    description:string,
+    specialUnit:number,
+    unitLevel:string,
+    unitLevelName:string
+
+}
+
+export const getCheckUnitTableDataByUnitClass = (params?:{
+    current:number,
+    pageSize:number,
+    classCode:string,
+    unitName:string
+}) => {
+    return request<{list:CheckUnitTableDataType[]}&pagesDataType>('/performance/unit/getUnitList', {
+        method: 'GET',
+        params: { ...params }
+    })
+
+}
+
+
+export type AddCheckUnitDataType = {
+    unitName:string,
+    classCode:string,
+    unitType:string,
+    description:string,
+    specialUnit:number,
+    unitLevel:string
+}
+
+export const addCheckUnit = (data:AddCheckUnitDataType) => {
+    return request('/performance/unit/addUnitList', {
+        method: 'POST',
+        data
+    })
+
+}
+
+export const editCheckUnit = (data:{id:number}&AddCheckUnitDataType) => {
+    return request('/performance/unit/editUnitList', {
+        method: 'POST',
+        data
+    })
+
+}
+
+
+//删除
+export const delTableData = ( id:number) => {
+
+    return request('/performance/unit/deleteUnitList', {
+        method: 'POST',
+        params: {id}
+    })
+
+}
+

+ 92 - 0
src/pages/setting/checkUnitSet/checkUnitMana/style.less

@@ -0,0 +1,92 @@
+.CheckUnitMana {
+    display: flex;
+    flex-direction: row;
+    // height: 100%;
+    background: #F5F7FA;
+
+    .leftTree {
+        position:fixed;
+        top:64px;
+        width: 220px;
+        height: calc(100vh - 80px);
+        background: #FFF;
+        border-radius: 4px;
+        padding: 16px;
+        overflow: hidden;
+        margin-right: 16px;
+        // border-right:16px solid #F5F7FA;
+
+        .searchInput {
+              border: 1px solid #CFD7E6;
+        }
+
+
+        .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%);
+        }
+
+        .bms-ant-tree.bms-ant-tree-directory .bms-ant-tree-treenode .bms-ant-tree-node-content-wrapper.bms-ant-tree-node-selected {
+            font-weight: bold;
+        }
+    }
+
+    .rightContent {
+        position: relative;
+        border-radius: 4px;
+        width: calc(100% - 220px);
+        padding: 16px;
+        margin-left: 236px;
+        background: #FFF;
+
+        .content {
+            display: flex;
+            flex-direction: column;
+
+            .tableToolbar {
+                display: flex;
+                flex-direction: row;
+                justify-content: space-between;
+                align-items: center;
+                margin-bottom: 16px;
+
+                .search {
+                    display: flex;
+                    flex-direction: row;
+                    justify-content: flex-start;
+                    align-items: center;
+
+                    .searchInput {
+                        width: 167px;
+                        height: 24px;
+                        background: #FFF;
+                        border-radius: 4px;
+                        border: 1px solid #CFD7E6;
+                    }
+
+                    &>span {
+                        font-size: 14px;
+                        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                        font-weight: 400;
+                        color: #17181A;
+                    }
+                }
+
+                .btnGroup {
+                    .add {
+                      cursor: pointer;
+                      display: inline-block;
+                      font-size: 14px;
+                      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+                      font-weight: 400;
+                      color: #FFFFFF;
+                      line-height: 24px;
+                      padding: 0 14px;
+                      background: #3377FF;
+                      border-radius: 4px;
+                    }
+                  }
+            }
+        }
+    }
+}

+ 491 - 0
src/pages/setting/checkUnitSet/medicalGroupSet/index.tsx

@@ -0,0 +1,491 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-26 16:09:12
+ * @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 BMSPagecontainer from '@/components/BMSPageContainer';
+import { BMSTable } from '@/components/BMSTable';
+
+import { createFromIconfontCN } from '@ant-design/icons';
+import { ActionType } from '@ant-design/pro-components';
+import { ModalForm, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
+import { ProColumns } from '@ant-design/pro-table';
+import { Dropdown, Input, MenuProps, message, Modal, Popconfirm, Space, Switch, Table } from 'antd';
+
+import { TransferItem, TransferProps } from 'antd/es/transfer';
+import React from 'react';
+import { useEffect, useImperativeHandle, useRef, useState } from 'react';
+
+import { getMedicalGroup, getEmpTableDataFromMedicalGroup, addMedicalGroup, editMedicalGroup, delLeftReportData, getMedicalAllEmp, addMedicalGroupEmp, MedicalEmpInfoType, updateMedicalGroupEmpInfo, delTableData } from './service';
+
+import './style.less';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+
+
+const MedicalGroupSet = () => {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+
+    const [typeList, set_typeList] = useState<any[]>([]);
+    const [showTypeListArr, set_showTypeListArr] = useState<any[]>([]);
+    const [currentSelectedType, set_currentSelectedType] = useState<any | undefined>(undefined);
+
+
+
+    const [tableSelectedKeys, set_tableSelectedKeys] = useState<any[]>([]);
+
+    const [currentEditLeftData, set_currentEditLeftData] = useState<any | undefined>(undefined);
+
+    const [ifEditTable, set_ifEditTable] = useState(false);
+
+    const tableRef = useRef<ActionType>();
+
+    const column = [
+
+        {
+            title: '工号',
+            ellipsis: true,
+            dataIndex: 'account',
+
+        },
+        {
+            title: '姓名',
+            dataIndex: 'name',
+
+        },
+        {
+            title: '组长',
+            dataIndex: 'medicalGroupManager',
+            render: (_: any, record: any) => {
+                return <Switch size='small' checked={_} onChange={(bool) => switchChangeHandle(bool, record, 'medicalGroupManager')} />
+            }
+        },
+        {
+            title: '操作',
+            key: 'option',
+            valueType: 'option',
+            render: (_: any, record: any) => {
+                return [
+                    <Popconfirm
+                        title="是否确认删除?"
+                        key="del"
+                        onConfirm={() => delTableDataHanfle(record)}
+                    >
+                        <a>删除</a>
+                    </Popconfirm>
+                ]
+            },
+        },
+    ]
+
+    const delTableDataHanfle = async (record?: { id: number; }) => {
+        const resp = await delTableData(record?[record.id]:[...tableSelectedKeys]);
+
+        if (resp) {
+            tableRef.current?.reload();
+        }
+    }
+
+    const [tableColumn, set_tableColumn] = useState<ProColumns[] | any[]>(column);
+
+
+    const getTableData = async (params: any, sort: any, filter: any) => {
+        const { medicalGroupCode } = params;
+
+        if (medicalGroupCode) {
+            const resp = await getEmpTableDataFromMedicalGroup(params);
+            if (resp) {
+
+                return {
+                    data: resp.list,
+                    success: true,
+                    total: resp.totalCount,
+                    pageSize: resp.pageSize,
+                    totalPage: resp.totalPage,
+                }
+
+            }
+        }
+        return {
+            data: [],
+            success: true
+        }
+    }
+
+    const switchChangeHandle = async (checked: boolean, record: any, key: string) => {
+        const result = { ...record, medicalGroupManager: checked ? 1 : 0 }
+        const resp = await updateMedicalGroupEmpInfo(result);
+        if (resp) {
+            tableRef.current?.reload();
+        }
+    }
+
+    //获取左侧数据
+    const getPageLeftData = async () => {
+        const resp = await getMedicalGroup();
+
+        if (resp) {
+
+            set_typeList(resp);
+            set_showTypeListArr(resp);
+        }
+    }
+
+
+    const updateTable = async (formVal: any, type: 'EDIT' | "ADD" | 'ADD_LEFTDATA' | 'EDIT_LEFTDATA') => {
+
+        // console.log({formVal,type});
+
+        if (type == 'ADD_LEFTDATA') {
+            const resp = await addMedicalGroup({
+                name: formVal.name,
+                remark: formVal.remark,
+            });
+            if (resp) {
+                getPageLeftData();
+            }
+        }
+
+
+
+        if (type == 'EDIT_LEFTDATA') {
+            const resp = await editMedicalGroup({
+                id: formVal.id,
+                name: formVal.name,
+                remark: formVal.remark
+            });
+            if (resp) {
+                getPageLeftData();
+            }
+        }
+
+        return true;
+
+    }
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' | 'ADD_LEFTDATA' | 'EDIT_LEFTDATA' }) => {
+
+        const getTrriger = () => {
+            if (type == 'ADD') {
+                return <span className='add'>添加</span>
+            }
+            if (type == 'EDIT') {
+                return <a key="edit" >编辑</a>
+            }
+            if (type == 'ADD_LEFTDATA') {
+                return (
+                    <div className='add'>
+                        <img src={require('../../../../../static/addIcon_black.png')} alt="" />
+                    </div>
+                )
+            }
+            if (type == 'EDIT_LEFTDATA') {
+                return <a key="edit" >编辑</a>
+            }
+        }
+
+        return (
+            <ModalForm
+                title={type == 'ADD_LEFTDATA' ? `新增医疗组` : `编辑医疗组`}
+                width={352}
+                initialValues={type == 'EDIT_LEFTDATA' ? { ...record } : {}}
+                trigger={
+                    getTrriger()
+                }
+                onFinish={(val) => {
+                    return updateTable(type == 'EDIT_LEFTDATA' ? { ...record, ...val } : val, type);
+                }}
+            >
+
+                <ProFormText
+                    label='医疗组名称:'
+                    name='name'
+                    rules={[{ required: true, message: '名称不能为空!' }]}
+                />
+                <ProFormTextArea
+                    label='说明:'
+                    name='remark'
+                />
+            </ModalForm>
+        )
+    }
+
+
+    interface TableSelecterProps extends TransferProps<TransferItem> {
+        tableSelecterColumn: any[];
+        record: any
+    }
+
+
+    const tableSelecterColumn: any[] = [
+        {
+            title: '工号',
+            dataIndex: 'account',
+        },
+        {
+            title: '姓名',
+            dataIndex: 'name',
+        },
+    ];
+
+    const addGroupEmpHandle = () => {
+
+        const ref = React.createRef<{ save: any; }>();
+
+        Modal.confirm({
+            title: `添加医疗组人员信息`,
+            icon: <></>,
+            width:400,
+            centered: true,
+            content: <TableSelecter
+                ref={ref}
+                record={undefined}
+                tableSelecterColumn={tableSelecterColumn}
+            ></TableSelecter>,
+            okText:'确定',
+            cancelText:'取消',
+            onOk: () => {
+                return ref.current && ref.current.save();
+            }
+        })
+    }
+
+    const TableSelecter = React.forwardRef(({ tableSelecterColumn, record }: TableSelecterProps, ref) => {
+
+        const [datasource, set_datasource] = useState<any[]>([]);
+        const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
+
+        //获取表格数据
+        const getFuncList = async () => {
+            const resp = await getMedicalAllEmp({medicalGroupCode:currentSelectedType.code});
+            if (resp) {
+                set_datasource(resp);
+            }
+        }
+
+
+        const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
+            setSelectedKeys([...newSelectedRowKeys]);
+        };
+
+        useImperativeHandle(ref, () => ({
+            save: async () => {
+
+                const needData = datasource.filter(item => selectedKeys.includes(item.userId));
+
+                const result = {
+                    medicalGroupCode: currentSelectedType.code as string,
+                    employee: needData as MedicalEmpInfoType[]
+                };
+
+                const resp = await addMedicalGroupEmp(result);
+
+                if (resp) {
+                    message.success('添加成功!');
+                    tableRef.current?.reload();
+                }
+            }
+        }));
+
+        useEffect(() => {
+            getFuncList();
+        }, [])
+
+        return (
+            <div>
+                <Input placeholder={'请输入'} allowClear
+                    suffix={
+                        <IconFont type="iconsousuo" />
+                    }
+                    style={{ marginBottom: 8 }}
+                    onChange={(e) => {
+                        const result = typeList.filter(item => item.reportName.indexOf(e.target.value) != -1);
+                        set_showTypeListArr(result);
+                    }}
+
+                />
+                <BMSTable columns={tableSelecterColumn}
+                    options={{
+                        density: true,
+                        setting: {
+                            listsHeight: 100,
+                        },
+                    }}
+                    rowKey='userId'
+                    rowSelection={{
+                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+                        // 注释该行则默认不显示下拉选项
+                        selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+                        onChange: onSelectChange,
+                    }}
+                    pagination={{ showSizeChanger: false, pageSize: 10, simple: true, showTitle: false }}
+                    dataSource={datasource}
+                />
+            </div>
+
+        )
+    });
+
+    const moreItems: MenuProps['items'] = [
+        {
+            key: '1',
+            label: <UpDataActBtn key={'act'} record={currentEditLeftData} type='EDIT_LEFTDATA' />,
+        },
+        {
+            key: '2',
+            label: (
+                <a onClick={async (e) => {
+                    e.preventDefault();
+                    const resp = await delLeftReportData(currentEditLeftData.id);
+                    if (resp) {
+                        getPageLeftData();
+                    }
+                }}>
+                    删除
+                </a>
+            ),
+        }
+    ];
+
+
+    const onTableSelectChange = (newSelectedRowKeys: React.Key[]) => {
+        set_tableSelectedKeys([...newSelectedRowKeys]);
+    };
+
+
+    useEffect(() => {
+
+        if (currentSelectedType) {
+            set_tableDataFilterParams({ ...tableDataFilterParams, medicalGroupCode: currentSelectedType.code });
+
+        }
+    }, [currentSelectedType])
+
+    useEffect(() => {
+        if (showTypeListArr.length > 0) {
+            set_currentSelectedType(showTypeListArr[0]);
+            //set_tableDataFilterParams({ ...tableDataFilterParams, medicalGroupCode: showTypeListArr[0].code });
+        }
+    }, [showTypeListArr]);
+
+
+    useEffect(() => {
+        getPageLeftData();
+    }, [])
+
+
+
+    return (
+        <BMSPagecontainer title={false} className='MedicalGroupSet'>
+            <div className='left'>
+                <div className='toolbar'>
+                    <Input placeholder={'医疗组名称'} allowClear
+                        suffix={
+                            <IconFont type="iconsousuo" />
+                        }
+                        style={{ width: 156 }}
+                        onChange={(e) => {
+                            const result = typeList.filter(item => item.name.indexOf(e.target.value) != -1);
+                            set_showTypeListArr(result);
+                        }}
+                    />
+                    
+                    <UpDataActBtn key={'act'} record={undefined} type='ADD_LEFTDATA' />
+
+                </div>
+
+                <div className='wrap'>
+                    {
+                        showTypeListArr.map((item, index) => {
+                            return (
+                                <div className={currentSelectedType ? currentSelectedType.id == item.id ? 'type on' : 'type' : 'type'}
+                                    key={index}
+                                    onClick={() => {
+                                        if (ifEditTable) {
+                                            //编辑状态还未保存
+                                            Modal.confirm({
+                                                title: '当前存在编辑未保存,请保存后再操作!',
+                                                okText: '放弃编辑',
+                                                cancelText: '继续编辑',
+                                                onOk(...args) {
+                                                    set_ifEditTable(false);
+                                                    set_currentSelectedType(item);
+
+                                                },
+                                            })
+                                        } else {
+                                            set_currentSelectedType(item)
+                                        }
+                                    }}
+                                >
+                                    <div className='content'>
+                                        <div className='name'>{item.name}</div>
+                                    </div>
+
+                                    <Dropdown menu={{ items: moreItems }} placement="bottom" onOpenChange={(bool) => { bool && set_currentEditLeftData(item) }}>
+                                        <div className='more'>
+                                            <img src={require('../../../../../static/more_point_gray.png')} alt="" />
+                                        </div>
+                                    </Dropdown>
+                                </div>
+                            )
+                        })
+                    }
+                </div>
+            </div>
+            <div className='right'>
+                <div className='toolBar'>
+                    <div className='filter'>
+                        <span style={{fontSize:16,color:'#17181A',fontWeight:500}}>{currentSelectedType?currentSelectedType.name:''}</span>
+                    </div>
+                    <div className='btnGroup'>
+                        {<span className='manaBtn' onClick={() => addGroupEmpHandle()}>添加</span>}
+                    </div>
+                </div>
+                <div style={{ marginTop: 16 }}>
+                    {currentSelectedType && <BMSTable actionRef={tableRef} columns={tableColumn}
+                        rowKey='id'
+                        pagination={false}
+                        rowSelection={{
+                            // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+                            // 注释该行则默认不显示下拉选项
+                            selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+                            onChange: onTableSelectChange,
+                        }}
+                        tableAlertOptionRender={() => {
+                            return (
+
+                                <Space size={16}>
+                                    <Popconfirm
+                                        title="是否确认删除?"
+                                        key="del"
+                                        onConfirm={() => delTableDataHanfle()}
+                                    >
+                                        <a>批量删除</a>
+                                    </Popconfirm>
+                                </Space>
+                            );
+                        }}
+                        params={tableDataFilterParams}
+                        request={(params, sort, filter) => getTableData(params, sort, filter)}
+                    />}
+                </div>
+            </div>
+        </BMSPagecontainer >
+    )
+}
+
+
+export default MedicalGroupSet;

+ 109 - 0
src/pages/setting/checkUnitSet/medicalGroupSet/service.ts

@@ -0,0 +1,109 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-07 11:12:10
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-26 16:05:25
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicMana/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+import { getManaIndexGroup } from '@/pages/budgetMana/monthlyDataCheck/service';
+import { request } from 'umi';
+
+
+//获取左侧医疗组
+export const getMedicalGroup = () => {
+  return request('/performance/unit/getMedicalGroup', {
+    method: 'GET',
+  });
+};
+
+//获取表格数据
+export const getEmpTableDataFromMedicalGroup = (params:{medicalGroupCode:string}) => {
+    return request('/performance/unit/getMedicalGroupMap', {
+      method: 'GET',
+      params:{...params}
+    });
+};
+
+
+//新增医疗组
+export const addMedicalGroup = (data:any) => {
+  return request('/performance/unit/addMedicalGroup', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//编辑医疗组
+export const editMedicalGroup = (data:any) => {
+  return request('/performance/unit/editMedicalGroup', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//删除左侧数据
+export const delLeftReportData = (id:number) => {
+  return request('/performance/unit/deleteMedicalGroup', {
+    method: 'POST',
+    params:{id}
+  });
+};
+
+
+
+//添加医疗组人员信息
+
+type AddMedicalGroupEmpDataType = {medicalGroupCode:string,employee:MedicalEmpInfoType[]}
+export const addMedicalGroupEmp = (data:AddMedicalGroupEmpDataType) => {
+  return request('/performance/unit/addMedicalGroupMap', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+//编辑表格数据
+
+export const updateMedicalGroupEmpInfo = (data:any) => {
+    return request('/performance/unit/editMedicalGroupMap', {
+      method: 'POST',
+      data
+    });
+};
+
+
+
+
+//删除表格操作
+export const delTableData = (ids:number[]) => {
+    return request('/performance/unit/deleteMedicalGroupMap', {
+      method: 'POST',
+      data:[...ids]
+    });
+};
+
+
+//获取医疗组人员
+
+export type MedicalEmpInfoType = {
+  account:string,
+  userId:number,
+  name:string
+}
+export const getMedicalAllEmp = (params:{medicalGroupCode:string}) => {
+  return request<MedicalEmpInfoType[]>('/performance/unit/getMedicalGroupEmployee', {
+    method: 'GET',
+    params
+  });
+};
+
+
+

+ 178 - 0
src/pages/setting/checkUnitSet/medicalGroupSet/style.less

@@ -0,0 +1,178 @@
+.row-dragging {
+ 
+    .bms-ant-table-cell {
+        width: 130px;
+    }
+}
+
+.MedicalGroupSet {
+  width: 100%;
+  overflow: hidden;
+
+  .left {
+    float: left;
+    border-radius: 4px;
+    width: 220px;
+    height: calc(100vh - 80px);
+    overflow: scroll;
+    margin-right: 16px;
+    padding:16px 8px;
+    background: #FFFFFF;
+
+    .toolbar {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+      padding: 0 8px;
+
+      .add {
+        cursor: pointer;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: 24px;
+        height: 24px;
+        background: #FAFCFF;
+        border-radius: 4px;
+        border: 1px solid #DAE2F2;
+        &>img {
+            width: 16px;
+            height: 16px;
+        }
+      }
+    }
+
+    .wrap {
+      margin-top: 16px;
+
+      .type {
+        cursor: pointer;
+        height: 32px;
+        border-radius: 4px;
+        background: #FFFFFF;
+        display: flex;
+        padding-left: 8px;
+        padding-right: 8px;
+        flex-direction: row;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 4px;
+
+        .icon {
+          width: 25px;
+          height: 25px;
+        }
+
+        .content {
+          width: 80%;
+          padding-left: 7px;
+
+          .name {
+            height: 15px;
+            font-size: 14px;
+            font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+            font-weight: 400;
+            color: #17181A;
+            line-height: 15px;
+            overflow: hidden;
+            white-space: nowrap;
+            text-overflow: ellipsis;
+          }
+        }
+
+        .more {
+          display: flex;
+          justify-content: center;
+          align-items:center;
+          cursor: pointer;
+          width: 16px;
+          height: 16px;
+          border-radius: 4px;
+          background: #FFFFFF;
+
+          &>img {
+            width: 100%;
+            height: 100%;
+          }
+        }
+
+        &.on {
+          background: #F0F2F5;
+          .content {
+            .name {
+              font-weight: 500;
+              color: #17181A;
+            }
+          }
+        }
+
+        &:last-child {
+          margin-bottom: 0;
+        }
+      }
+    }
+  }
+
+  .right {
+    float: left;
+    width: calc(100% - 236px);
+    padding: 16px;
+    border-radius: 4px;
+    background: #FFFFFF;
+
+    .toolBar {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+
+      .filter {
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        align-items: center;
+
+        .filterItem {
+          display: flex;
+          flex-direction: row;
+          justify-content: center;
+          align-items: center;
+        }
+      }
+
+      .btnGroup {
+        .manaBtn {
+          cursor: pointer;
+          display: inline-block;
+          font-size: 14px;
+          font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+          font-weight: 400;
+          color: #FFFFFF;
+          line-height: 24px;
+          padding: 0 14px;
+          background: #3377FF;
+          border-radius: 4px;
+        }
+        .inner {
+            &>span {
+              cursor: pointer;
+              display: inline-block;
+              font-size: 14px;
+              font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+              font-weight: 400;
+              color: #FFFFFF;
+              line-height: 24px;
+              padding: 0 14px;
+              background: #3377FF;
+              border-radius: 4px;
+              margin-left: 8px;
+            }
+            
+        }
+      }
+
+
+    }
+  }
+}

+ 340 - 0
src/pages/setting/checkUnitSet/viewUnitPermSet/index.tsx

@@ -0,0 +1,340 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-26 14:11:24
+ * @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 BMSPagecontainer from '@/components/BMSPageContainer';
+import { BMSTable } from '@/components/BMSTable';
+import { createFromIconfontCN } from '@ant-design/icons';
+
+import { ActionType } from '@ant-design/pro-components';
+
+import { ProColumns } from '@ant-design/pro-table';
+import { Input, message, Modal, Popconfirm, Switch } from 'antd';
+import Table, { ColumnsType } from 'antd/es/table';
+import { TableRowSelection } from 'antd/es/table/interface';
+import Transfer, { TransferItem, TransferProps } from 'antd/es/transfer';
+import { difference } from 'lodash';
+import React, { Key, useImperativeHandle } from 'react';
+import { useEffect, useRef, useState } from 'react'
+
+import { getViewUnitTableData, getAllCheckUnit, saveCheckViewUnit, postCheckViewAll } from './service';
+
+import './style.less';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+
+export default function ViewUnitPermSet() {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+    const tableRef = useRef<ActionType>();
+
+    const columns = [
+
+        {
+            title: '工号',
+            dataIndex: 'account',
+        },
+        {
+            title: '姓名',
+            dataIndex: 'name',
+        },
+        {
+            title: '职务',
+            dataIndex: 'jobTitleName',
+        },
+        {
+            title: '职称',
+            dataIndex: 'titleName',
+        },
+        {
+            title: '岗位',
+            dataIndex: 'positionName',
+        },
+        {
+            title: '检视单元',
+            width: 300,
+            ellipsis: true,
+            dataIndex: 'unitList',
+            render: (_: any, record: any) => {
+                if (record.unitList) {
+                    return record.unitList.reduce((prev: any, cur: any) => {
+                        if (cur.unitCode != '0') {
+                            return `${prev ? prev + '|' : ''}${cur.unitName}`
+                        } else {
+                            return <span style={{ color: '#FF8C19' }}>{cur.unitName}</span>
+                        }
+
+                    }, undefined)
+                }
+                return ''
+            }
+        },
+        {
+            title: '操作',
+            key: 'option',
+            width: 200,
+            valueType: 'option',
+            render: (_: any, record: any) => {
+                return [
+                    <a key={'option'} onClick={() => selectpositionHandle(record)}>选择单元</a>,
+                    <a key={'viewAll'} onClick={() => checkViewAllHandle(record)}>检视全部</a>
+                ]
+            },
+        },
+
+    ];
+
+
+    interface DataType {
+        key: string;
+        title: string;
+        description: string;
+        disabled: boolean;
+        tag: string;
+    }
+
+    interface TableTransferProps extends TransferProps<TransferItem> {
+
+        leftColumns: ColumnsType<DataType>;
+        rightColumns: ColumnsType<DataType>;
+        record: any
+    }
+
+
+    const transferTableColumn: any[] = [
+        {
+            title: '核算单元名称',
+            dataIndex: 'unitName',
+        },
+        {
+            title: '职类',
+            width: 120,
+            dataIndex: 'unitTypeName',
+            ellipsis: true
+        },
+    ];
+
+
+    const selectpositionHandle = (record: any) => {
+
+        const ref = React.createRef<{ save: any; }>();
+
+        Modal.confirm({
+            title: `添加检视单元(${record.name})`,
+            icon: <></>,
+            width: 750,
+            content: <TableTransfer
+                ref={ref}
+                record={record}
+                leftColumns={transferTableColumn}
+                rightColumns={transferTableColumn}
+
+            ></TableTransfer>,
+            onOk: () => {
+                return ref.current && ref.current.save();
+            }
+        })
+
+    }
+
+    const checkViewAllHandle = async (record: any) => {
+        const resp = await postCheckViewAll(record.id);
+        if (resp) {
+            tableRef.current?.reload();
+        }
+    }
+
+    const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, record, ...restProps }: TableTransferProps, ref) => {
+
+
+        const [targetKeys, setTargetKeys] = useState<string[]>([]);
+        const [datasource, set_datasource] = useState<any[]>([]);
+        const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
+
+        //获取岗位字典数据
+        const getFuncList = async () => {
+            const resp = await getAllCheckUnit();
+            if (resp) {
+
+                const defaultSelctedkeys = record.unitList ? record.unitList.map((item: any) => item.unitCode) : [];
+                const defalt = record.unitList ? record.unitList : [];
+                set_datasource([...resp, ...defalt]);
+                setTargetKeys(defaultSelctedkeys);
+
+            }
+        }
+
+        const onChange = (nextTargetKeys: string[]) => {
+            setTargetKeys(nextTargetKeys);
+        };
+
+        const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
+            //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
+            setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+        };
+
+        useImperativeHandle(ref, () => ({
+            save: async () => {
+
+                const needData = datasource.filter(item => targetKeys.includes(item.code));
+
+                const resp = await saveCheckViewUnit({
+                    userId: record.id,
+                    unitList: needData.map((a: any) => ({
+                        unitCode: a.code as string,
+                        unitName: a.unitName as string,
+                        unitType: a.unitType as string
+                    }))
+                });
+
+                if (resp) {
+                    message.success('添加成功!');
+                    tableRef.current?.reload();
+                }
+            }
+        }));
+
+        useEffect(() => {
+            getFuncList();
+        }, [])
+
+        return (
+            <Transfer className='TableTransfer' showSearch
+                titles={['待选项', '已选项']}
+                locale={{
+                    itemUnit: '项',
+                    itemsUnit: '项',
+                    searchPlaceholder: '请输入'
+                }}
+                onChange={onChange}
+                onSelectChange={onSelectChange}
+                dataSource={datasource}
+                rowKey={record => record.code}
+                targetKeys={targetKeys}
+                selectedKeys={selectedKeys}
+                filterOption={(inputValue, item) => {
+                    return item.unitName!.indexOf(inputValue) !== -1
+
+                }}
+            >
+                {({
+                    direction,
+                    filteredItems,
+                    onItemSelectAll,
+                    onItemSelect,
+                    selectedKeys: listSelectedKeys,
+                    disabled: listDisabled,
+                }) => {
+
+                    // console.log({ filteredItems, listSelectedKeys,direction });
+                    const columns = direction === 'left' ? leftColumns : rightColumns;
+
+                    const rowSelection: TableRowSelection<TransferItem> = {
+                        getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
+                        onSelectAll(selected, selectedRows) {
+                            const treeSelectedKeys = selectedRows.map(({ code }) => code);
+                            const diffKeys = selected
+                                ? difference(treeSelectedKeys, listSelectedKeys)
+                                : difference(listSelectedKeys, treeSelectedKeys);
+                            onItemSelectAll(diffKeys as string[], selected);
+                        },
+                        onSelect({ code }, selected) {
+                            onItemSelect(code as string, selected);
+                        },
+                        selectedRowKeys: listSelectedKeys,
+                    };
+
+                    return (
+                        <Table
+                            rowSelection={rowSelection}
+                            columns={columns as TransferItem[]}
+                            dataSource={filteredItems}
+                            size="small"
+                            pagination={{ showSizeChanger: false }}
+                            rowKey={'code'}
+                            style={{ pointerEvents: listDisabled ? 'none' : undefined }}
+                            onRow={({ code, disabled: itemDisabled }) => ({
+                                onClick: () => {
+                                    if (itemDisabled || listDisabled) return;
+                                    onItemSelect(code, !listSelectedKeys.includes(code));
+                                },
+                            })}
+                        />
+                    );
+                }}
+            </Transfer>
+        )
+    });
+
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+
+    }
+
+
+    const getTableData = async (params: any, sort: any, filter: any) => {
+        const resp = await getViewUnitTableData({ ...params });
+        if (resp) {
+            return {
+                data: resp.list,
+                success: true,
+                total: resp.totalCount,
+                pageSize: resp.pageSize,
+                totalPage: resp.totalPage,
+            }
+        }
+        return []
+    }
+
+
+    return (
+        <BMSPagecontainer className='ViewUnitPermSet' title={false}>
+            <div className='tableToolbar'>
+                <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, name: '' });
+                        }
+                    }} suffix={
+                        <IconFont type="iconsousuo" onClick={() => tableDataSearchHandle('name')} />
+                    }
+
+                        onPressEnter={(e) => {
+
+                            set_tableDataFilterParams({
+                                ...tableDataFilterParams,
+                                name: (e.target as HTMLInputElement).value
+                            });
+                        }}
+                    />
+                </div>
+                <div className='btnGroup'>
+                    <Switch size="small" onChange={(bool:boolean)=>set_tableDataFilterParams({...tableDataFilterParams,hide:bool?1:0})} />
+                    <span style={{marginLeft:8}}>隐藏未设定人员</span>
+                </div>
+            </div>
+            <div style={{ marginTop: 16 }}>
+                <BMSTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params, sort, filter) => getTableData(params, sort, filter)} />
+            </div>
+        </BMSPagecontainer>
+    )
+}

+ 64 - 0
src/pages/setting/checkUnitSet/viewUnitPermSet/service.ts

@@ -0,0 +1,64 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-26 13:56:05
+ * @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
+ */
+
+
+
+import { request } from 'umi';
+
+//获取table列表数据
+
+export const getViewUnitTableData = (params?:{name:string,hide?:string}) => {
+  return request('/performance/unit/getViewUnitMap', {
+    method: 'GET',
+    params
+  });
+};
+
+
+//获取所有核算单元
+
+export const getAllCheckUnit = () => {
+  return request('/performance/kpi/getUnitList', {
+    method: 'GET',
+  });
+};
+
+//检视所有提交
+export const postCheckViewAll = (userId:number) => {
+  return request(`/performance/unit/addAllViewUnit?userId=${userId}`, {
+    method: 'POST',
+  });
+};
+
+
+//保存
+
+export type SaveCheckViewUnitDataType= {
+  userId:number,
+  unitList:{unitCode:string,unitName:string,unitType:string}[]
+}
+
+export const saveCheckViewUnit = (data:SaveCheckViewUnitDataType) => {
+  return request('/performance/unit/addViewUnit', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+
+
+
+
+
+
+
+
+

+ 51 - 0
src/pages/setting/checkUnitSet/viewUnitPermSet/style.less

@@ -0,0 +1,51 @@
+.ViewUnitPermSet {
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+  .tableToolbar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 16px;
+
+    .search {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .searchInput {
+        width: 167px;
+        height: 24px;
+        background: #FFF;
+        border-radius: 4px;
+        border: 1px solid #CFD7E6;
+      }
+
+      &>span {
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #17181A;
+      }
+    }
+
+    .btnGroup {
+      .add {
+        cursor: pointer;
+        display: inline-block;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 24px;
+        padding: 0 14px;
+        background: #3377FF;
+        border-radius: 4px;
+      }
+    }
+  }
+
+}

+ 4 - 2
src/services/getDic.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-04-20 14:06:17
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-04-20 14:45:29
+ * @LastEditTime: 2023-04-26 15:25:58
  * @FilePath: /BudgetManaSystem/src/services/getDic.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -17,7 +17,7 @@ import { request } from "@umijs/max"
 
 
 //从公共字典获取数据
-export const getPubDicDataByKey =  () => {
+export const getPubDicData =  () => {
     
     return request('/performance/dict', {
         method: 'GET',
@@ -28,6 +28,8 @@ export const getPubDicDataByKey =  () => {
 
 export const getDataByKeyFromDic = (dicData:any[],key: string) => {
 
+    console.log({dicData});
+
     let result = dicData.filter((t: any) => (t.code == key));
 
     if (result.length > 0) {