Ver código fonte

添加静态展示菜单功能/非考核项目管理/职系二次分配设定界面

code4eat 2 anos atrás
pai
commit
68793dae99

+ 32 - 1
.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-05-05 14:06:58
+ * @LastEditTime: 2023-05-10 13:37:08
  * @FilePath: /BudgetManaSystem/.umirc.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -67,6 +67,11 @@ export default defineConfig({
       path: '/home',
       component: './Home',
     },
+    {
+      name: '静态测试',
+      path: '/static',
+      component: './static',
+    },
     {
       name: '系统设置',
       path: '/setting',
@@ -111,6 +116,11 @@ export default defineConfig({
               path: '/setting/projectSetting/bilingProjectMana',
               component: './setting/projectSetting/bilingProjectMana',
             },
+            {
+              name: '静态测试',
+              path: '/setting/projectSetting/static/:pageCode',
+              component: './setting/projectSetting/bilingProjectMana',
+            },
             {
               name: '指标项目管理',
               path: '/setting/projectSetting/indicProjectMana',
@@ -121,6 +131,16 @@ export default defineConfig({
               path: '/setting/projectSetting/secondaryProjectDistribute',
               component: './setting/projectSetting/secondaryProjectDistribute',
             },
+            {
+              name: '非考核项目管理',
+              path: '/setting/projectSetting/nonAssessmentProjectMana',
+              component: './setting/projectSetting/nonAssessmentProjectMana',
+            },
+            {
+              name: '职类二次分配设定',
+              path: '/setting/projectSetting/occupationsSecondaryDistriSet',
+              component: './setting/projectSetting/occupationsSecondaryDistriSet',
+            },
           ]
         },
         {
@@ -255,6 +275,17 @@ export default defineConfig({
         },
       ]
     },
+    {
+      name: '二次分配',
+      path: '/secondaryDistribute',
+      routes: [
+        {
+          name: '人员信息核对',
+          path: '/secondaryDistribute/employeeInfoCheck',
+          component: './secondaryDistribute/employeeInfoCheck',
+        },
+      ]
+    },
   ],
   npmClient: 'yarn',
 });

BIN
src/.DS_Store


+ 122 - 58
src/app.tsx

@@ -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:12:17
+ * @LastEditTime: 2023-05-10 15:56:43
  * @FilePath: /BudgetManaSystem/src/app.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -22,6 +22,7 @@ import type { RequestConfig } from 'umi';
 import iconEnum from './menuIcons.js';
 
 import Report from './pages/reports/index';
+import Static from './pages/static/index';
 
 
 import DevicePixelRatio from './utils/devicePixelRatio.js';
@@ -32,6 +33,7 @@ import { useState } from 'react';
 
 
 
+
 const IconFont = createFromIconfontCN({
   scriptUrl: '//at.alicdn.com/t/c/font_3878861_tw9yqguouab.js',
 });
@@ -56,24 +58,24 @@ interface ResponseStructure {
 }
 
 interface UserData {
-    name?:string,
-    ruleVersion?:string,
-    token?:string,
-    userId?:number,
-    youshuToken?:string
+  name?: string,
+  ruleVersion?: string,
+  token?: string,
+  userId?: number,
+  youshuToken?: string
 }
 
 
 
-export async function getInitialState(): Promise<{ 
-  isCollapsed: boolean,spacicalPageParamsType?: any[],userData:UserData,
+export async function getInitialState(): Promise<{
+  isCollapsed: boolean, spacicalPageParamsType?: any[], userData: UserData,
 }> {
 
   new DevicePixelRatio().init();
 
 
 
-  return { isCollapsed: false,spacicalPageParamsType:[],userData:{} };
+  return { isCollapsed: false, spacicalPageParamsType: [], userData: {} };
 }
 
 export const request: RequestConfig = {
@@ -227,34 +229,75 @@ export const request: RequestConfig = {
 };
 
 
-export function patchClientRoutes({ routes }:{routes:any}) {
+export function patchClientRoutes({ routes }: { routes: any }) {
 
-  console.log({routes});
-  
-  const paths = [...new Array(10).keys()].map((a,index)=>({
-    path: `/setting/manaPerformanceSet/reports/${index}`,
-    exact: true,
-    element:<Report />,
-  }));
+  console.log({ routes });
+
+  // const paths = [...new Array(10).keys()].map((a, index) => ({
+  //   path: `/setting/manaPerformanceSet/reports/${index}`,
+  //   exact: true,
+  //   element: <Report />,
+  // }));
 
-  const treeLoop = (treeData:any)=>{
-    //console.log({treeData})
-    if(treeData.path == '/setting/manaPerformanceSet'){
-      paths.forEach((a:any)=>{
-        treeData.routes.push(a); 
+  // //蓝湖静态页面
+  // const lanhuPagePaths = [...new Array(10).keys()].map((a, index) => ({
+  //   path: `/setting/manaPerformanceSet/reports/${index}`,
+  //   exact: true,
+  //   element: <Report />,
+  // }));
+
+  const treeLoop = (treeData: any) => {
+    // console.log({treeData});
+    if(treeData.routes){
+      const paths = [...new Array(10).keys()].map((a, index) => ({
+        path: `${treeData.path == '/'?'':treeData.path}/reports/${index}`,
+        exact: true,
+        element: <Report />,
+      }));
+  
+      const lanhuPagePaths = [...new Array(10).keys()].map((a, index) => ({
+        path: `${treeData.path == '/'?'':treeData.path}/static/${index}`,
+        exact: true,
+        element: <Static />,
+      }));
+  
+      //console.log({paths});
+  
+      paths.forEach((a: any) => {
+        treeData.routes.push(a);
       });
+  
+      lanhuPagePaths.forEach((a: any) => {
+        treeData.routes.push(a);
+      });
+    }
+    
 
-      return;  
-    }else{
-        if(treeData.routes&&treeData.routes.length>0){
-          treeData.routes.forEach((a:any)=>{
-              treeLoop(a);
-          })
-        }
+    if (treeData.routes && treeData.routes.length > 0) {
+      treeData.routes.forEach((a: any) => {
+        treeLoop(a);
+      })
     }
-}
+  }
 
-treeLoop(routes[0]);
+  // const treeLoop = (treeData:any)=>{
+  //   console.log({treeData})
+  //   if(treeData.path == '/setting/manaPerformanceSet'){
+  //     paths.forEach((a:any)=>{
+  //       treeData.routes.push(a); 
+  //     });
+
+  //     return;  
+  //   }else{
+  //       if(treeData.routes&&treeData.routes.length>0){
+  //         treeData.routes.forEach((a:any)=>{
+  //             treeLoop(a);
+  //         })
+  //       }
+  //   }
+  // }
+
+  treeLoop(routes[0]);
 }
 
 
@@ -301,9 +344,13 @@ const setting = (params: any) => {
   return <IconFont type='icon-xitongshezhi' />
 };
 
+const secondaryDistribute = (params: any) => {
+  return <IconFont type='icon-ercifenpei' />
+};
+
 //布局配置
 
-export const layout = ({ initialState, setInitialState }: { initialState: any, setInitialState: any}) => {
+export const layout = ({ initialState, setInitialState }: { initialState: any, setInitialState: any }) => {
 
   const { isCollapsed } = initialState;
   const [openKeys, set_openKeys] = useState<string[]>([]);
@@ -334,6 +381,7 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
 
     },
     siderWidth: 200,
+
     menu: {
       locale: false,
       request: async () => {
@@ -350,12 +398,25 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
                 data.forEach((t) => {
                   if (t[key] && t[key] != 0) {
                     //非一般页面
-                    result.push({
-                      contentType: t[key],
-                      path: t['path'],
-                      reportId: t['reportId'],
-                      url: t['youshuUrl'],
-                    });
+                    if (t[key] == 1 || t[key] == 2 || t[key] == 3) {
+                      //网易有数页面
+                      result.push({
+                        contentType: t[key],
+                        path: t['path'],
+                        reportId: t['reportId'],
+                        url: t['youshuUrl'],
+                      });
+                    }
+                    if (t[key] == 5) {
+                      //网易有数页面
+                      result.push({
+                        contentType: t[key],
+                        path: t['path'],
+                        reportId: t['reportId'],
+                        url: t['softUrl'],
+                      });
+                    }
+
                   }
                   if (t.children && t.children.length > 0) {
                     looper(t.children, key);
@@ -367,35 +428,38 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
             };
 
             const _menu = getVFromTree(data, 'contentType');
-    
-            setInitialState((t: any) => ({ ...t, spacicalPageParamsType: _menu,userData:JSON.parse(userData as string) }));
+
+            setInitialState((t: any) => ({ ...t, spacicalPageParamsType: _menu, userData: JSON.parse(userData as string) }));
 
             //return mappingIcon(data);
 
-            
-            
-            function addIconToPath(node:any, paths:string[]) {
+
+
+            function addIconToPath(node: any, paths: string[]) {
               if (paths.includes(node.path)) {
-                  if(node.path == '/home'){
-                      node.icon =  <Icon component={imgNode} />;
-                  }
-                  if(node.path == '/budgetMana'){
-                    node.icon =  <Icon component={fileIcon} />;
-                  }
-                  if(node.path == '/setting'){
-                    node.icon =  <Icon component={setting} />;
-                  }
-                  if(node.path == '/reportCheck'){
-                    node.icon =  <Icon component={setting} />;
-                  }
+                if (node.path == '/home') {
+                  node.icon = <Icon component={imgNode} />;
+                }
+                if (node.path == '/budgetMana') {
+                  node.icon = <Icon component={fileIcon} />;
+                }
+                if (node.path == '/setting') {
+                  node.icon = <Icon component={setting} />;
+                }
+                if (node.path == '/reportCheck') {
+                  node.icon = <Icon component={setting} />;
+                }
+                if (node.path == '/secondaryDistribute') {
+                  node.icon = <Icon component={secondaryDistribute} />;
+                }
               }
               if (node.children) {
-                node.children.forEach((child:any) => addIconToPath(child, paths));
+                node.children.forEach((child: any) => addIconToPath(child, paths));
               }
             }
 
-            data.forEach((item:any)=>{
-              addIconToPath(item,['/home','/budgetMana','/setting','/reportCheck']);
+            data.forEach((item: any) => {
+              addIconToPath(item, ['/home', '/budgetMana', '/setting', '/reportCheck', '/secondaryDistribute']);
             });
 
             return data

+ 2 - 1
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-04-25 15:16:54
+ * @LastEditTime: 2023-05-09 15:25:48
  * @FilePath: /BudgetManaSystem/src/components/BMSTable/index.tsx
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -46,6 +46,7 @@ export const BMSTable = (props: BMSTablePropsType<any, any, any>) => {
             pagination={{
                    ...BMSTablePageDefaultConfig  
             }}
+            //locale={{emptyText:'暂无数据'}}
             params={{...params}}
             bordered={false}
             search={false}

+ 42 - 19
src/components/BMSTable/style.less

@@ -14,7 +14,7 @@
 }
 
 .bms-ant-table-wrapper .bms-ant-table-pagination.bms-ant-pagination {
-     margin: 10px 0 !important;
+  
      padding-right: 16px;
 }
 
@@ -64,30 +64,53 @@
             }  
         }
     }
-
-   
-    .bms-ant-table-cell {
-        height: 15px;
-        line-height: 15px;
-        font-size: 14px;
-        font-family: SourceHanSansCN-Medium, SourceHanSansCN;
-        // font-weight: 500;
+    .bms-ant-table-tbody {
+        &>tr {
+            .bms-ant-table-cell {
+                height: 15px;
+                line-height: 15px;
+                font-size: 14px;
+                font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+                // font-weight: 500;
+                
+                color: #17181A;
+                padding: 13px 16px !important; 
         
-        color: #17181A;
-        padding: 13px 16px !important; 
+                &:hover {
+                    border-radius: 0 !important;
+                    background: #FAFBFC !important;
+                   
+                }
+            }
+            &.bms-ant-table-row-selected {
+                  .bms-ant-table-cell {
+                    border-radius: 0 !important;
+                    &:hover {
+                        background:#bae0ff !important;   
+                    }
+                  }
+            }
 
-        &:hover {
-            background: #FAFBFC !important;
-           
+            &:last-child > td {
+                 border-bottom: none !important;
+            }
         }
     }
 
+   
+    
 
-    .bms-ant-pagination .bms-ant-pagination-item-active {
-        font-weight: 600;
-        background-color: #37F !important;
-        border-color: #37F !important;
-    }
+    
+    .bms-ant-pagination {
+        padding: 16px 0;
+        margin:0 !important;
+        border-top: 1px solid #dae2f2 !important;
+        .bms-ant-pagination-item-active {
+            font-weight: 600;
+            background-color: #37F !important;
+            border-color: #37F !important;
+        }
+    } 
 
     .bms-ant-pagination .bms-ant-pagination-item-active a {
         color: #fff !important;

+ 8 - 0
src/global.less

@@ -58,6 +58,7 @@ textarea {
                             }
 
                             .bms-ant-transfer-list {
+                                overflow: hidden;
                                 border: 1px solid #DAE2F2;
 
                                 .bms-ant-transfer-list-header {
@@ -82,6 +83,12 @@ textarea {
                                             }
                                         }
                                     }
+                                    .bms-ant-transfer-list-body-customize-wrapper {
+                                        .BMSTable {
+                                            border:none !important;
+                                            border-radius:0 !important;
+                                        }
+                                    }
                                 }
                             }
 
@@ -102,6 +109,7 @@ textarea {
                                                 padding: 4px 8px !important;
                                                 border-bottom: none;
                                             }
+                                            
                                         }
                                     }
                                 }

+ 1 - 0
src/pages/Table/components/UpdateForm.tsx

@@ -85,6 +85,7 @@ const UpdateForm: React.FC<UpdateFormProps> = (props) => (
           1: '表二',
         }}
       />
+      
       <ProFormSelect
         width="md"
         name="template"

+ 4 - 2
src/pages/reports/index.tsx

@@ -1,16 +1,18 @@
 /*
  * @Author: your name
  * @Date: 2022-03-03 18:04:40
- * @LastEditTime: 2023-04-17 14:11:54
+ * @LastEditTime: 2023-05-10 13:22:16
  * @LastEditors: code4eat awesomedema@gmail.com
  * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/reports/index.tsx
  */
 
 import { useEffect, useState } from 'react';
-import { useModel } from 'umi';
+
 import { Skeleton } from 'antd';
 import BMSPagecontainer from '@/components/BMSPageContainer';
+import { useModel } from '@umijs/max';
+
 
 export default () => {
   const { initialState, setInitialState } = useModel('@@initialState');

+ 620 - 0
src/pages/secondaryDistribute/employeeInfoCheck/index.tsx

@@ -0,0 +1,620 @@
+
+
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-16 09:42:52
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-05-10 14:33:11
+ * @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, useMemo, useRef, useState } from 'react';
+import './style.less';
+
+import { Tree, TreeProps, Tabs, Input, Modal, Transfer, Popconfirm, message, Popover } 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, ProColumnType } from '@ant-design/pro-components';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { checkRequest, delPersonRequest, generateDataRequest, getDepInfoTableData, getPersonInfoTableData, getProjectInfoTableData, getTotalEmps, getTreeData, getTreeDataRespType, PersonInfoTableDataType, saveEmpsRequest } from './service';
+import { TransferDirection } from 'antd/es/transfer';
+import { getComputeDate } from '@/pages/Home/service';
+
+
+import 'dayjs/locale/zh-cn';
+import locale from 'antd/es/date-picker/locale/zh_CN';
+import { getCurrentCheckStatus } from '@/services/auth';
+import React from 'react';
+import DirectoryTree from 'antd/es/tree/DirectoryTree';
+import { getDeepestTreeData } from '@/utils/tooljs';
+
+
+
+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 MonthlyInfoCheck: React.FC = () => {
+
+    const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
+    const [tableColumn, set_tableColumn] = useState<ProColumns[]>([]);
+    const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
+    const [currentSelectedTabKey, set_currentSelectedTabKey] = useState<string>('1');
+    const [currentComputeDate, set_currentComputeDate] = useState<string | undefined>();
+
+    const [ifShowTip, set_ifShowTip] = useState(false);
+
+    const [auditType, set_auditType] = useState('0');
+
+    const [empInfoSearchKeywords, set_empInfoSearchKeywords] = useState('');
+
+    const [empFilterParams, set_empFilterParams] = useState<any | undefined>(undefined);
+
+    const [depInfoSearchKeywords, set_depInfoSearchKeywords] = useState('');
+
+    const [depFilterParams, set_depFilterParams] = useState<any | undefined>(undefined);
+
+    const [itemInfoSearchKeywords, set_itemInfoSearchKeywords] = useState('');
+
+    const [itemFilterParams, set_itemFilterParams] = useState<any | undefined>(undefined);
+
+    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
+    const [searchValue, setSearchValue] = useState('');
+    const [autoExpandParent, setAutoExpandParent] = useState(true);
+
+
+
+    const tableRef = useRef<ActionType>();
+
+
+    const column = [
+        {
+            title: '工号',
+            dataIndex: 'empNo',
+            key: 'empNo',
+
+        },
+        {
+            title: '姓名',
+            dataIndex: 'empName',
+            key: 'empName',
+
+        },
+        {
+            title: '岗位层级',
+            dataIndex: 'positionLevelName',
+            key: 'positionLevelName',
+
+        },
+        {
+            title: '职务',
+            dataIndex: 'jobTitleName',
+            key: 'jobTitleName',
+
+        },
+        {
+            title: '岗位系数',
+            dataIndex: 'positionRate',
+            key: 'positionRate',
+
+        },
+        {
+            title: '年资',
+            dataIndex: 'seniority',
+            key: 'seniority',
+
+        },
+    ];
+
+
+    const delPersonHandle = async (record: any) => {
+
+        const { props: { record: { id } } } = record;
+
+        const currentComputeDateResp = await getComputeDate();
+        if (currentComputeDateResp) {
+            const resp = await delPersonRequest({
+                computeDate: currentComputeDateResp,
+                id: id
+            });
+            if (resp) {
+                tableRef.current?.reload();
+            }
+        }
+    }
+
+
+
+    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
+        // console.log('selected', selectedKeys, info);
+        const { node } = info;
+        set_currentSelectedTreeNode(node);
+    };
+
+
+    const getCurrentComputeDate = async () => {
+        const resp = await getComputeDate();
+        set_currentComputeDate(resp);
+    }
+
+
+    const onTabChange = (activeKey: string) => {
+        set_currentSelectedTabKey(activeKey);
+    }
+
+
+
+
+    const getTableData = async (type: 'PERSON' | 'DEP' | 'CHARGE', params: any, sort: any, filter: any) => {
+        // console.log({ currentSelectedTreeNode });
+        // console.log({ params, sort, filter });
+
+        if (currentSelectedTreeNode && currentComputeDate) {
+            if (type == 'PERSON') {
+                const resp = await getPersonInfoTableData({
+                    computeDate: currentComputeDate,
+                    unitCode: currentSelectedTreeNode.code,
+                    ...params,
+                });
+                if (resp) {
+                    return {
+                        data: resp.list,
+                        success: true,
+                        total: resp.totalCount,
+                        pageSize: resp.pageSize,
+                        totalPage: resp.totalPage,
+                    }
+                }
+                return {
+                    data: [],
+                    success: true
+                }
+            }
+            if (type == 'DEP') {
+                const resp = await getDepInfoTableData({
+                    computeDate: currentComputeDate,
+                    unitCode: currentSelectedTreeNode.code,
+                    ...params
+                });
+                if (resp) {
+                    return {
+                        data: resp.list,
+                        success: true,
+                        total: resp.totalCount,
+                        pageSize: resp.pageSize,
+                        totalPage: resp.totalPage,
+                    }
+                }
+                return {
+                    data: [],
+                    success: true
+                }
+            }
+            if (type == 'CHARGE') {
+                const resp = await getProjectInfoTableData({
+                    computeDate: currentComputeDate,
+                    unitCode: currentSelectedTreeNode.code,
+                    ...params
+                });
+                if (resp) {
+
+                    return {
+                        data: resp.list,
+                        success: true,
+                        total: resp.totalCount,
+                        pageSize: resp.pageSize,
+                        totalPage: resp.totalPage,
+                    }
+                }
+                return {
+                    data: [],
+                    success: true
+                }
+            }
+        }
+
+        return []
+    }
+
+
+
+    const TransferNode = React.forwardRef((props, ref) => {
+        const [_data, _set_data] = useState<any>();
+        const [targetKeys, setTargetKeys] = useState<string[]>(['admin']);
+        const [datasource, set_datasource] = useState<any[]>([]);
+        const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
+
+
+        useImperativeHandle(ref, () => ({
+            save: async () => {
+                const items = datasource.filter(a => targetKeys.includes(a.empNo));
+                const resp = await saveEmpsRequest(items);
+                if (resp) {
+                    tableRef.current?.reload();
+                }
+            }
+        }));
+
+        const onChange = (nextTargetKeys: string[], direction: TransferDirection, moveKeys: string[]) => {
+            // console.log('targetKeys:', nextTargetKeys);
+            // console.log('direction:', direction);
+            // console.log('moveKeys:', moveKeys);
+            setTargetKeys(nextTargetKeys);
+        };
+
+        const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
+            // console.log('sourceSelectedKeys:', sourceSelectedKeys);
+            // console.log('targetSelectedKeys:', targetSelectedKeys);
+            setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+        };
+
+        const getData = async () => {
+            const resp = await getTotalEmps({
+                computeDate: currentComputeDate as string,
+                unitCode: currentSelectedTreeNode.code
+            });
+            if (resp) {
+                //_set_data(resp);
+                const allData = resp.allEmployees.concat(resp.checkEmployees);
+                set_datasource(allData);
+                const defaultSelctedkeys = resp.checkEmployees.map((item: any) => item.empNo);
+                setTargetKeys(defaultSelctedkeys);
+            }
+        }
+
+
+
+        useEffect(() => {
+            getData();
+        }, [])
+
+        return (
+            <Transfer
+                dataSource={datasource}
+                titles={['未添加人员', '已添加人员']}
+                targetKeys={targetKeys}
+                selectedKeys={selectedKeys}
+                onChange={onChange}
+                listStyle={{
+                    width: '45%'
+                }}
+                locale={{
+                    itemUnit: '人',
+                    itemsUnit: '人',
+                    searchPlaceholder: '请输入姓名'
+                }}
+                rowKey={record => record.empNo}
+                showSearch
+                pagination
+                onSelectChange={onSelectChange}
+                render={(item) => item.name}
+            />
+        )
+    })
+
+    const addPersonFunc = () => {
+        const ref = React.createRef<{ save: any }>();
+        Modal.confirm({
+            title: '添加人员',
+            width: 800,
+            content: <TransferNode ref={ref}></TransferNode>,
+            onOk: () => {
+                return ref.current && ref.current.save();
+            }
+        })
+    }
+
+    const confirmGenerateHandle = async (type: number) => {
+        const resp = await generateDataRequest({
+            computeDate: currentComputeDate as string,
+            generateType: type
+        });
+        if (resp) {
+            message.success('生成数据成功');
+            tableRef.current?.reload();
+        } else {
+            message.success('生成数据错误!');
+        }
+    }
+
+    const generateFunc = (type: number) => {
+
+        let msg = '';
+
+        if (type == 1) msg = '生成操作会根据基础设定的单元人员对照信息重新生成数据,手动调整的人员信息将会丢失,确定继续生成操作?';
+        if (type == 2) msg = '生成操作会覆盖现有的科室数据,确定继续生成操作?';
+        if (type == 3) msg = '生成操作会覆盖现有的收费项目数据,确定继续生成操作?';
+
+
+        Modal.confirm({
+            title: '注意',
+            content: msg,
+            onOk: () => confirmGenerateHandle(type)
+
+        })
+    }
+
+    const searchEmpHandle = () => {
+        set_empFilterParams({
+            empInfo: empInfoSearchKeywords
+        })
+        // tableRef.current?.reload();
+    }
+
+    const searchDepHandle = () => {
+        set_depFilterParams({
+            deptName: depInfoSearchKeywords
+        })
+    }
+
+    const searchItemHandle = () => {
+        set_itemFilterParams({
+            itemName: itemInfoSearchKeywords
+        })
+    }
+
+    const checkHandle = async (type: string) => {
+
+        const resp = await checkRequest({
+            computeDate: currentComputeDate as string,
+            auditType: type == '0' ? '1' : '0',   //审核类型  1审核 0取消审核
+        });
+
+        if (resp) {
+            if (type == '0') {
+                message.success('审核提交成功!');
+                set_auditType('1');
+            }
+            if (type == '1') {
+                message.success('取消审核提交成功!');
+                set_auditType('0');
+            }
+        }
+    }
+
+    const getCheckStatus = async (computeDate: string) => {
+        const resp = await getCurrentCheckStatus(computeDate);
+        if (resp) {
+            set_auditType(`${resp}`);  //0 未审核 1 已审核
+        }
+    }
+
+    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: getTreeDataRespType[]) => {
+        for (let i = 0; i < data.length; i++) {
+            const node = data[i];
+            const { code, name } = node;
+            dataList.push({ code: code, name: name });
+            if (node.child) {
+                generateList(node.child);
+            }
+        }
+    };
+    generateList(treeData as any);
+
+
+    const getTreeReqFunc = async (computeDate: string) => {
+        const resp = await getTreeData(computeDate);
+        set_treeData(resp);
+    }
+
+    useEffect(() => {
+
+        if (currentComputeDate) {
+            getTreeReqFunc(currentComputeDate);
+            getCheckStatus(currentComputeDate);
+        }
+    }, [currentComputeDate]);
+
+    useEffect(() => {
+        tableRef.current?.reload();
+    }, [currentSelectedTreeNode]);
+
+  
+
+
+    useEffect(() => {
+        //初始化左侧树结构数据后
+
+        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[]);
+        getCurrentComputeDate();
+
+    }, []);
+
+
+    return (
+        <div className='MonthlyInfoCheck'>
+            <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: 'flex-start', alignItems: 'center', height: 32,
+                                        borderRadius: '4px',
+                                        overflow: 'hidden',
+                                        color: '#17181A',
+                                        textOverflow: 'ellipsis',
+                                        whiteSpace: 'nowrap'
+
+                                    }}>{title}</div>
+                                }
+                            }
+                            defaultSelectedKeys={[treeData[0].child[0].code]}
+                            treeData={treeData as unknown as DataNode[]}
+                            // treeData={treeDataNew}
+                            switcherIcon={(props: any) => {
+                                const { expanded } = props;
+                                return !expanded ? <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} /> : <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
+                            }}
+                        />
+                    )
+                }
+            </div>
+            {/* <div style={{width:16,height:'92vh',background:'#F5F7FA'}}></div> */}
+            <div className='rightContent'>
+                <BMSPagecontainer title={`核算年月:${currentComputeDate}`} ghost>
+                    <div className='tabContent'>
+                        <div className='tableToolbar'>
+                            <div className='search'>
+                                <span>人员:</span><Input className='searchInput' allowClear onChange={(e) => {
+
+                                    set_empInfoSearchKeywords(e.target.value)
+                                    if (e.target.value.length == 0) {
+                                        set_empFilterParams({
+                                            ...empFilterParams,
+                                            empInfo: ''
+                                        });
+                                    }
+                                }} placeholder="输入工号/姓名" suffix={
+                                    <IconFont type="iconsousuo" onClick={() => searchEmpHandle()} />
+                                } />
+                            </div>
+                            <Popover open={ifShowTip} content={'当前处于审核中,无法操作!'} >
+                                <div className={auditType != '0' ? 'btnGroup disabled' : 'btnGroup'}
+                                    onMouseEnter={() => auditType == '0' ? set_ifShowTip(false) : set_ifShowTip(true)}
+                                    onMouseLeave={() => set_ifShowTip(false)}
+                                >
+                                    {/* <span key="1">调整</span> */}
+                                    <span key="2" onClick={auditType == '0' ? () => generateFunc(1) : () => { }}>生成</span>
+                                    <span key="3" onClick={auditType == '0' ? () => addPersonFunc() : () => { }}>添加</span>
+                                </div>
+                            </Popover>
+
+                        </div>
+                        {currentSelectedTreeNode && <BMSTable params={empFilterParams} actionRef={tableRef} rowKey='empNo' columns={auditType == '0' ? [...tableColumn, {
+                            title: '操作',
+                            key: 'option',
+                            valueType: 'option',
+                            render: (record: any) => [
+
+                                <Popconfirm key="popconfirm" title={`确认删除吗?`} okText="是" cancelText="否" onConfirm={() => delPersonHandle(record)}>
+                                    <a key={'del'}>删除</a>
+                                </Popconfirm>
+                            ],
+                        },] : [...tableColumn]} request={(params, sort, filter) => getTableData('PERSON', params, sort, filter)} />}
+                    </div>
+                </BMSPagecontainer>
+            </div>
+        </div>
+    );
+
+};
+
+export default MonthlyInfoCheck;

+ 241 - 0
src/pages/secondaryDistribute/employeeInfoCheck/service.ts

@@ -0,0 +1,241 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2022-12-21 11:13:51
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-05-10 13:50:34
+ * @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';
+
+
+
+
+//获取树结构单元数据
+
+export type getTreeDataRespType = {
+    code: number,
+    name: string,
+    map:boolean,
+    parentCode:string,
+    unitType?:string,
+    child: getTreeDataRespType[]
+}
+
+export const getTreeData = (computeDate: string) => {
+
+    return request<getTreeDataRespType[]>('/performance/secondSetting/getUnitList', {
+        method: 'GET',
+        params: { computeDate }
+    })
+}
+
+
+
+//获取人员信息表格数据
+
+export type getPersonInfoTableDataParamsType = {
+    computeDate: string; //核算年月
+    unitCode: string; //核算单元代码
+    empInfo?: string; //人员信息 (工号、姓名)
+    current: number;
+    pageSize: number;
+}
+
+export type PersonInfoType = {
+
+    unitCode: number;
+    empNo: string;
+    empName: string;
+    jobLevel: string;
+    jobTitle: string;
+    jobRate: string;
+    seniority: string;
+
+}
+
+export type PersonInfoTableDataType = {
+    current: number,
+    list: PersonInfoType[],
+    pageSize: number,
+    totalCount: number,
+    totalPage: number,
+}
+
+export const getPersonInfoTableData = (params: getPersonInfoTableDataParamsType) => {
+
+    return request<PersonInfoTableDataType>('/performance/check/empList', {
+        method: 'GET',
+        params: { ...params }
+    })
+
+}
+
+
+//获取科室信息表格数据
+
+export type getDepInfoTableDataParamsType = {
+    computeDate: string; //核算年月
+    unitCode: string; //核算单元代码
+    deptName?: string; //科室名称
+}
+
+export type DepInfoTableItemDataType = {
+    unitCode: number,
+    empNo: string,
+    empName: string,
+    jobLevel: string,
+    jobTitle: string,
+    jobRate: string,
+    seniority: string
+}
+
+export type DepInfoTableDataType = {
+
+    current: number,
+    list: DepInfoTableItemDataType[],
+    pageSize: number,
+    totalCount: number,
+    totalPage: number,
+}
+
+export const getDepInfoTableData = (params: getDepInfoTableDataParamsType) => {
+
+    return request<DepInfoTableDataType>('/performance/check/deptList', {
+        method: 'GET',
+        params: params
+    })
+
+}
+
+
+//获取收费项目信息
+
+export type getProjectInfoTableDataParamsType = {
+    computeDate: string; //核算年月
+    unitCode: string; //核算单元代码
+    itemName?: string; //项目名称
+}
+
+export type ProjectInfoTableItemDataType = {
+    itemCode: string,
+    itemName: string,
+    itemType: string,
+    itemPoint: number,
+    coreFlag: string,
+}
+
+export type ProjectInfoTableDataType = {
+
+    current: number,
+    list: ProjectInfoTableItemDataType[],
+    pageSize: number,
+    totalCount: number,
+    totalPage: number,
+}
+
+export const getProjectInfoTableData = (params: getProjectInfoTableDataParamsType) => {
+
+    return request<ProjectInfoTableDataType>('/performance/check/itemList', {
+        method: 'GET',
+        params: params
+    })
+
+}
+
+
+//获取收费项目信息表格数据
+
+export type getChargeItemTableDataParamsType = {
+    Date: string; //核算年月
+    unitCode: string; //核算单元代码
+    deptName?: string; //科室名称
+}
+
+export const getChargeItemfoTableData = (params: getDepInfoTableDataParamsType) => {
+
+    return request<getTreeDataRespType>('/performance/check/itemList', {
+        method: 'GET',
+        params: params
+    })
+
+}
+
+
+//获取可选人员列表
+
+///master/centerSys/user/list
+
+export const getTotalEmps = (params:{
+    computeDate:string,
+    unitCode:string
+}) => {
+
+    return request('/performance/check/getComputeEmployee', {
+        method: 'GET',
+        params: params
+    })
+
+}
+
+
+//删除人员
+export const delPersonRequest = (params:{
+    computeDate:string,
+    id:string
+}) => {
+
+    return request('/performance/check/deleteEmployee', {
+        method: 'POST',
+        params: params
+    })
+
+}
+
+
+//生成数据
+
+export type GenerateDataRequestParamsType = {
+    computeDate: string,
+    generateType: number,
+}
+
+export const generateDataRequest = (data: GenerateDataRequestParamsType) => {
+ 
+    return request('/performance/check/generate', {
+        method: 'POST',
+        params:data
+    })
+
+}
+
+
+//审核请求
+
+export type CheckRequestParamsType = {
+    computeDate:string,
+    auditType:string
+}
+export const checkRequest = (data:CheckRequestParamsType) => {
+ 
+    return request('/performance/check/audit', {
+        method: 'POST',
+        params:data
+    })
+
+}
+
+//保存添加的人员
+
+export const saveEmpsRequest = (data:any[]) => {
+ 
+    return request('/performance/check/addComputeEmployee', {
+        method: 'POST',
+        data:data
+    })
+
+}

+ 154 - 0
src/pages/secondaryDistribute/employeeInfoCheck/style.less

@@ -0,0 +1,154 @@
+.MonthlyInfoCheck {
+    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;
+
+        .checkBtn {
+            position: absolute;
+            cursor: pointer;
+            top: 0;
+            right:0;
+            padding: 0 14px;
+            height: 24px;
+            line-height: 24px;
+            background: #3376FE;
+            border-radius: 4px;
+            text-align: center;
+            font-size: 14px;
+            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+            font-weight: 400;
+            color: #FFF;
+        }
+
+        .midLine {
+            display: flex;
+            flex-direction: row;
+            justify-content: center;
+            align-items: center;
+            height: 24px;
+            line-height: 24px;
+            background: #F0FCFC;
+            font-size: 12px;
+            color: #515866;
+            font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+            font-weight: 400;
+            margin-top: 12px;
+            margin-bottom: 15px;
+
+            &>span {
+                cursor: pointer;
+                font-size: 12px;
+                font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+                font-weight: 500;
+                color: #00B3B3;
+                padding-right: 4px;
+            }
+
+        }
+
+        .bms-ant-tabs-nav {
+            &::before {
+                border-bottom: none !important;
+            }
+        }
+
+        .tabContent {
+            display: flex;
+            flex-direction: column;
+
+            .tableToolbar {
+                display: flex;
+                flex-direction: row;
+                justify-content: space-between;
+                align-items: center;
+                margin-top:16px;
+                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 {
+                    &>span {
+                        display: inline-block;
+                        text-align: center;
+                        width: 56px;
+                        height: 24px;
+                        line-height: 21px;
+                        background: #FAFCFF;
+                        border-radius: 4px;
+                        cursor: pointer;
+                        border: 1px solid #DAE2F2;
+                        margin-right: 8px;
+
+                        &:last-child {
+                            margin-right: 0;
+                        }
+                    }
+
+                    &.disabled {
+                        &>span {
+                            cursor:not-allowed;
+                            color: rgb(0 0 0 / 50%);
+                            background-color:#f0f2f5;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 2 - 2
src/pages/setting/baseSetting/jobCateBaseSet/index.tsx

@@ -13,9 +13,9 @@
 import BMSPagecontainer from '@/components/BMSPageContainer';
 import { BMSTable } from '@/components/BMSTable';
 
-import { ActionType, EditableProTable } from '@ant-design/pro-components';
+import { ActionType, EditableProTable, ProColumns } from '@ant-design/pro-components';
 import {  ProFormDigit } from '@ant-design/pro-form'
-import { ProColumns } from '@ant-design/pro-table';
+
 import { Input, InputNumber, message } from 'antd';
 import { typeOf } from 'mathjs';
 import { useEffect, useRef, useState } from 'react';

+ 4 - 3
src/pages/setting/manaPerformanceSet/indicGroupWeightSet/index.tsx

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 11:30:33
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-04-21 11:16:00
+ * @LastEditTime: 2023-05-06 10:35:37
  * @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
  */
@@ -411,7 +411,8 @@ export default function IndicGroupWeightSet() {
 
         const addIndicator = () => {
            
-            const key = Math.random()
+            const key = Math.random();
+
             const temp = [...indicatorData, {tempId:key,id:key,[`indicatorCode${key}`]:'',[`weight${key}`]:''}];
 
             set_indicatorIniData({...indicatorIniData,[`indicatorCode${key}`]:'',[`weight${key}`]:''});
@@ -531,7 +532,7 @@ export default function IndicGroupWeightSet() {
                                                 if (resp) {
                                                     return resp.list.map((a: any) => ({
                                                         label: a.name,
-                                                        value: a.code
+                                                        value: Number(a.code)
                                                     }))
                                                 }
                                                 return []

+ 459 - 0
src/pages/setting/projectSetting/nonAssessmentProjectMana/index.tsx

@@ -0,0 +1,459 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-05-08 15:07:57
+ * @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 { getComputeDate } from '@/pages/Home/service';
+import { getDataByKeyFromDic, getPubDicData } from '@/services/getDic';
+import { createFromIconfontCN } from '@ant-design/icons';
+
+import { ActionType, ProFormDependency, ProFormRadio } from '@ant-design/pro-components';
+import { ModalForm, ProFormCascader, ProFormDigit, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
+import { ProColumns } from '@ant-design/pro-table';
+import { Form, Input, InputNumber, message, Popconfirm } from 'antd';
+import { useEffect, useRef, useState } from 'react'
+import { getSecondaryProjectDistriData } from '../secondaryProjectDistribute/service';
+
+
+import { addData, delData, editData, gainData, getData, saveScoreData } from './service';
+
+import './style.less';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+const AddIconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_3824256_kzhiq41zywa.js',
+});
+
+
+
+export default function MonAssessmentProjectMana() {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+    const tableRef = useRef<ActionType>();
+
+
+
+
+    const columns: ProColumns[] = [
+
+        {
+            title: '项目代码',
+            dataIndex: 'code',
+        },
+        {
+            title: '项目名称',
+            dataIndex: 'name',
+        },
+        {
+            title: '分配方式',
+            dataIndex: 'distributionTypeName',
+        },
+        {
+            title: '分配对象',
+            dataIndex: 'distributionTargetName',
+        },
+        {
+            title: '上限值',
+            dataIndex: 'ceiling',
+        },
+        {
+            title: '评分项',
+            dataIndex: 'secondItem',
+            width: 400,
+            ellipsis: true,
+            render: (_, record) => {
+                return record.secondItem ? (record.secondItem.map((a: any) => a.secondItemName)).join('|') : '-'
+            }
+
+        },
+        {
+            title: '操作',
+            key: 'option',
+            width: 200,
+            valueType: 'option',
+            render: (_: any, record: any) => {
+                return [
+                    <UpDataActBtn key={'SCORE'} record={record} type='SCORE' />,
+                    <UpDataActBtn key={'act'} record={record} type='EDIT' />,
+                    <Popconfirm
+                        title="是否确认删除?"
+                        key="del"
+                        onConfirm={() => delTableData(record)}
+                    >
+                        <a>删除</a>
+                    </Popconfirm>
+                ]
+            },
+        },
+
+    ]
+
+
+    const getTableData = async (params: any) => {
+        const resp = await getData(params);
+        if (resp) {
+            return {
+                data: resp.list,
+                success: true,
+                total: resp.totalCount,
+                pageSize: resp.pageSize,
+                totalPage: resp.totalPage,
+            }
+        }
+        return []
+    }
+
+    const delTableData = async (record: any) => {
+        const resp = await delData(record.id);
+        if (resp) {
+            message.success('操作成功!');
+            tableRef.current?.reload();
+            // message.success('操作成功!');
+        }
+    }
+
+    const updateTable = async (formVal: any, type: 'EDIT' | "ADD" | 'SCORE') => {
+
+        const result = {
+            name: formVal.name,
+            distributionType: formVal.distributionType,
+            distributionTarget: formVal.distributionTarget,
+            isCeiling: formVal.isCeiling,
+            ceiling: formVal.ceiling
+        }
+
+        if (type == 'ADD') {
+            const resp = await addData({ ...result });
+            if (resp) {
+                tableRef.current?.reload();
+                message.success('操作成功!');
+            }
+        }
+        if (type == 'EDIT') {
+            const resp = await editData({ id: formVal.id, ...result });
+            if (resp) {
+                tableRef.current?.reload();
+                message.success('操作成功!');
+            }
+        }
+
+        if (type == 'SCORE') {
+            console.log({formVal});
+            // const result = {
+            //     nonAssessmentCode:formVal.nonAssessmentCode,
+            //     secondItem:formVal.secondItem.map(())
+            // }
+            const resp = await saveScoreData({...formVal});
+            if (resp) {
+                tableRef.current?.reload();
+                message.success('操作成功!');
+            }
+        }
+
+        return true;
+    }
+
+    const [dicData, set_dicData] = useState<any[]>([]);
+
+    const getDirecData = async (key?: string) => {
+
+        const data = await getPubDicData();
+        if (data) {
+            set_dicData(data);
+        }
+    }
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' | 'SCORE' }) => {
+
+   
+        const [scoreList, set_scoreList] = useState<any[]>([]);
+        const [scoreInitList, set_scoreInitList] = useState({});
+
+        const addIndicator = () => {
+
+            const key = Math.random();
+
+            const temp = [...scoreList, { tempId: key, id: key, [`secondItemCode${key}`]: '', [`weight${key}`]: '' }];
+
+            set_scoreInitList({ ...scoreInitList, [`secondItemCode${key}`]: '', [`weight${key}`]: '' });
+
+            set_scoreList([...temp]);
+
+        }
+
+        const delGroupIndic = (data: any, index: number) => {
+            let temp = [...scoreList];
+            let defaultFormData: { [key: string]: any } = {};
+            const result = temp.filter((a: any) => a.id != data.id);
+            result.forEach((a: any) => {
+                defaultFormData[`indicatorCode${a.id}`] = a.indicatorCode;
+                defaultFormData[`weight${a.id}`] = a.weight;
+            });
+
+            set_scoreInitList({ ...defaultFormData });
+            set_scoreList([...result]);
+        }
+
+        
+        useEffect(() => {
+            if (type == 'SCORE') {
+                let defaultFormData: { [key: string]: any } = {};
+                if (record.secondItem && record.secondItem.length > 0) {
+                    const defaultVal = record.secondItem.map((a: any) => {
+                        defaultFormData[`secondItemCode${a.id}`] = a.secondItemCode;
+                        defaultFormData[`weight${a.id}`] = a.weight;
+                        return { ...a, tempId: Math.random() }
+                    });
+
+                    set_scoreInitList({ ...defaultFormData });
+
+                    set_scoreList([...defaultVal]);
+                } else {
+                    set_scoreList([{}]);
+                }
+            }
+        }, [type]);
+
+
+        return (
+            <ModalForm
+                title={`${type == 'EDIT' ? '编辑' : '新增'}非考核项目`}
+                className='MonAssessmentProjectMana-ModalForm'
+                width={352}
+                initialValues={type == 'EDIT' ? { ...record } :type == 'SCORE'?{...scoreInitList}:{}}
+                trigger={
+                    type == 'EDIT' ? <a key="edit" >编辑</a> :type != 'SCORE'?<span className='add'>新增</span>:<a className='score'>评分项</a>
+                }
+                onFinish={(val) => {
+                    return updateTable(type == 'EDIT' ? { ...record, ...val } : type == 'SCORE'?{secondItem:scoreList,nonAssessmentCode:record.code}:{ ...val }, type);
+                }}
+                modalProps={{ destroyOnClose: true }}
+            >
+                {
+                    type == 'SCORE' && (
+                        <div>
+                            {
+                                scoreList.map((item: any, index: number) => {
+
+                                    return (
+                                        <div className='item' key={index}>
+                                            <ProFormSelect label="评分项:" width={160} 
+                                                name={`secondItemCode${item.id}`}
+                                                 request={async () => {
+                                                    const resp = await getSecondaryProjectDistriData({pageSize:1000,current:1});
+                                                    if (resp) {
+                                                        return resp.list.map((a: any) => ({
+                                                            label: a.name,
+                                                            value: a.code
+                                                        }))
+                                                    }
+                                                    return []
+
+                                                }}
+                                                fieldProps={{
+                                                    //   labelInValue:true,
+                                                    onChange(value, option: any) {
+                                                        // console.log({value,option});
+                                                        const temp = [...scoreList];
+                                                        const newArr = temp.map((a: any) => {
+                                                            if (a.id == item.id) {
+                                                                return { ...a, secondItemCode: value, secondItemName: option.label }
+                                                            }
+                                                            return a
+                                                        });
+
+                                                        set_scoreList([...newArr]);
+                                                    },
+                                                }}
+                                            />
+                                            <Form.Item name={`weight${item.id}`} label='占比(请输入小数):'>
+                                                <InputNumber
+                                                    style={{ width: 120, height: 24, position: 'relative', top: 0 }}
+                                                    onChange={(value) => {
+                                                        //console.log({value,index,indicatorData});
+                                                        const temp = [...scoreList];
+                                                        const newArr = temp.map((a: any) => {
+                                                            if (a.id == item.id) {
+                                                                return { ...a, weight: value }
+                                                            }
+                                                            return a
+                                                        });
+
+                                                        console.log({ newArr });
+
+                                                        set_scoreList([...newArr]);
+                                                    }}
+                                                />
+                                            </Form.Item>
+                                            <span className='delIcon' onClick={() => delGroupIndic(item, index)}><IconFont type="iconshanchu" /></span>
+                                        </div>
+                                    )
+                                })
+                            }
+                            <div className='addBtn' onClick={() => addIndicator()}>
+                                <AddIconFont type="icon-zengjia" style={{ color: '#3376FE' }} /><span>增加一行</span>
+                            </div>
+                        </div>
+                    )
+                }
+
+                {
+                    type != 'SCORE' && (
+                        <>
+                            <ProFormText
+                                name="name"
+                                label="项目名称:"
+                                placeholder="请输入"
+                                rules={[{ required: true, message: '名称不能为空!' }]}
+                            />
+                            <ProFormSelect
+                                name="distributionType"
+                                label="分配方式:"
+                                placeholder="请输入"
+                                options={[
+                                    { label: '占比', value: 1 },
+                                    { label: '绝对数', value: 2 },
+                                    { label: '自动计算', value: 3 },
+                                ]}
+                                rules={[{ required: true, message: '分配方式不能为空!' }]}
+                            />
+                            <ProFormDependency name={['distributionType']}>
+                                {
+                                    ({ distributionType }) => {
+                                        return distributionType == 2 && (
+                                            <ProFormSelect
+                                                name="distributionTarget"
+                                                label="分配对象:"
+                                                placeholder="请输入"
+                                                options={[
+                                                    { label: '医师', value: 1 },
+                                                    { label: '核算单元', value: 2 },
+                                                    { label: '医疗组', value: 3 },
+                                                ]}
+                                                rules={[{ required: true, message: '分配对象不能为空!' }]}
+                                            />
+                                        )
+                                    }
+                                }
+                            </ProFormDependency>
+
+                            <ProFormRadio.Group
+                                name="isCeiling"
+                                label="是否有上限:"
+                                fieldProps={{
+                                    buttonStyle: 'solid'
+                                }}
+                                options={[
+                                    {
+                                        label: '有',
+                                        value: 1,
+                                    },
+                                    {
+                                        label: '无',
+                                        value: 0,
+                                    }
+                                ]}
+                                rules={[{ required: true, message: '评价方式不能为空!' }]}
+                            />
+                            <ProFormDependency name={['isCeiling']}>
+                                {
+                                    ({ isCeiling }) => {
+                                        return isCeiling == 1 && (
+                                            <ProFormDigit
+                                                name="ceiling"
+                                                label="上限值:"
+                                                placeholder="请输入"
+                                                rules={[{ required: true, message: '上限值不能为空!' }]}
+                                            />
+                                        )
+                                    }
+                                }
+                            </ProFormDependency>
+                        </>
+                    )
+                }
+
+            </ModalForm>
+        )
+    }
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+    }
+
+
+    //获取按钮点击后获取数据
+    const getDataBySQL = async () => {
+        const resp = await getComputeDate();
+        if (resp) {
+            const respStat = await gainData({ compute_date: resp });
+            if (respStat) {
+                tableRef.current?.reload();
+            }
+        }
+    }
+
+
+    useEffect(() => {
+        getDirecData();
+    }, [])
+
+    return (
+        <BMSPagecontainer className='BilingProjectMana' title={false}>
+            <div className='toolBar'>
+                <div className='filter'>
+                    <div className='filterItem'>
+                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
+                        <Input placeholder={'请输入项目名称'} allowClear
+                            suffix={
+                                <IconFont type="iconsousuo" onClick={() => tableDataSearchHandle('name')} />
+                            }
+                            onChange={(e) => {
+                                set_tableDataSearchKeywords(e.target.value);
+                                if (e.target.value.length == 0) {
+                                    set_tableDataFilterParams({
+                                        ...tableDataFilterParams,
+                                        name: ''
+                                    });
+                                }
+                            }}
+                            onPressEnter={(e) => {
+
+                                set_tableDataFilterParams({
+                                    ...tableDataFilterParams,
+                                    name: (e.target as HTMLInputElement).value
+                                });
+                            }}
+
+                        />
+                    </div>
+                </div>
+                <div className='btnGroup'>
+                    {/* <span className='getDataBtn' onClick={() => getDataBySQL()}>获取</span> */}
+                    <UpDataActBtn record type='ADD' />
+                </div>
+            </div>
+            <div style={{ marginTop: 16 }}>
+                <BMSTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id' params={tableDataFilterParams} request={(params) => getTableData(params)} />
+            </div>
+        </BMSPagecontainer>
+    )
+}

+ 105 - 0
src/pages/setting/projectSetting/nonAssessmentProjectMana/service.ts

@@ -0,0 +1,105 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-05-08 14:47:53
+ * @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 type NonAssessProjectTableItemDataType = {
+  id: number,
+  hospId: number,
+  code: string,
+  name: string,
+  distributionType: number,
+  distributionTypeName: string,
+  distributionTarget: number,
+  distributionTargetName: string,
+  isCeiling: number,
+  ceiling: number,
+  secondItem: any[]
+}
+
+
+export const getData = (params?: any) => {
+  return request<{
+    current: number;
+    list: NonAssessProjectTableItemDataType[];
+    pageSize: number;
+    totalCount: number;
+    totalPage: number;
+  }>('/performance/item/getNonAssessment', {
+    method: 'GET',
+    params: { ...params }
+  });
+};
+
+export const gainData = (params?: any) => {
+  return request('/performance/item/auto', {
+    method: 'GET',
+    params: { ...params }
+  });
+};
+
+
+
+
+//新增表格数据
+export type AddTableDataType = {
+  "name": string, //名称
+  "distributionType": number, //分配方式 1占比 2绝对数 3自动计算
+  "distributionTarget": number, //分配目标 1医师 2核算单元 3医疗组
+  "isCeiling": number, //是否有上限 1有 0无
+  "ceiling": number //上限值
+}
+export const addData = (data: AddTableDataType) => {
+  return request('/performance/item/addNonAssessment', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+//编辑表格数据
+
+export const editData = (data: AddTableDataType & { id: number }) => {
+  return request('/performance/item/editNonAssessment', {
+    method: 'POST',
+    data
+  });
+};
+
+//保存评分项
+export const saveScoreData = (data:{nonAssessmentCode:string,secondItem:any[]}) => {
+  return request('/performance/item/addNonAssessmentSecondItemMap', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//删除表格操作
+export const delData = (id: string) => {
+  return request('/performance/item/deleteNonAssessment', {
+    method: 'POST',
+    params: { id }
+  });
+};
+
+
+
+
+
+
+
+
+
+

+ 96 - 0
src/pages/setting/projectSetting/nonAssessmentProjectMana/style.less

@@ -0,0 +1,96 @@
+
+.MonAssessmentProjectMana-ModalForm {
+  .item {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .delIcon {
+      position: relative;
+      top:3px;
+      cursor: pointer;
+      display:flex;
+      justify-content: center;
+      align-items: center;
+      width: 24px;
+      height: 24px;
+      background: #FAFCFF;
+      border-radius: 4px;
+      border: 1px solid #DAE2F2;
+    }
+  }
+  .addBtn {
+    cursor: pointer;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+    width: 320px;
+    height: 40px;
+    background: #FFFFFF;
+    border-radius: 4px;
+    color: #3376FE;
+    border: 1px dashed #CFD6E6;
+
+    &>span {
+       margin-left: 8px;
+    }
+  }
+}
+
+.BilingProjectMana {
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+
+  .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 {
+      .getDataBtn {
+        display: inline-block;
+        text-align: center;
+        width: 56px;
+        height: 24px;
+        cursor: pointer;
+        line-height: 24px;
+        background: #FAFCFF;
+        border-radius: 4px;
+        margin-right: 8px;
+        border: 1px solid #DAE2F2;
+      }
+      .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;
+      }
+    }
+
+  }
+}

+ 541 - 0
src/pages/setting/projectSetting/occupationsSecondaryDistriSet/index.tsx

@@ -0,0 +1,541 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-05-09 16:20:40
+ * @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 { getPubDicData } from '@/services/getDic';
+import { createFromIconfontCN, MenuOutlined } from '@ant-design/icons';
+
+import { ActionType, arrayMoveImmutable, ProFormDependency, ProFormRadio, useRefFunction } from '@ant-design/pro-components';
+import { ModalForm, ProFormCascader, ProFormDigit, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
+import { ProColumns } from '@ant-design/pro-table';
+import { Form, Input, InputNumber, message, Modal, Popconfirm, Table, Tabs, Transfer } from 'antd';
+import { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
+import { TransferItem, TransferProps } from 'antd/es/transfer';
+import { difference } from 'lodash';
+import React, { useImperativeHandle } from 'react';
+import { useEffect, useRef, useState } from 'react'
+
+
+
+import { addData, delData, getData, getTransferTableData, saveScoreData, TableItemDataType } from './service';
+
+import './style.less';
+
+import {
+    SortableContainer,
+    SortableElement,
+    SortableHandle,
+} from 'react-sortable-hoc';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+const AddIconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_3824256_kzhiq41zywa.js',
+});
+
+
+
+const DragHandle = SortableHandle(() => (
+    <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />
+));
+
+
+
+
+export default function OccupationsSecondaryDistriSet() {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+    const tableRef = useRef<ActionType>();
+
+    const [ifAdjustment, set_ifAdjustment] = useState(false);
+
+    const [data, set_data] = useState<TableItemDataType[]>([]);
+
+    const [tabs, set_tabs] = useState<{ label: string, key: string }[]>([]);
+
+    const [currentTab, set_currentTab] = useState<{ key: string, label: string } | undefined>(undefined);
+
+    const [dataSource, set_dataSource] = useState<any[]>([]);
+
+    const [tableSelectedKeys, set_tableSelectedKeys] = useState<any[]>([]);
+
+    const [columns, set_columns] = useState<ProColumns[]>([]);
+
+
+    const static_columns: ProColumns[] = [
+
+        {
+            title: '项目名称',
+            width: 160,
+            dataIndex: 'secondItemName',
+        },
+        {
+            title: '评价方式',
+            width: 160,
+            dataIndex: 'evaluationName',
+        },
+        {
+            title: '来源',
+            width: 160,
+            dataIndex: 'sourceName',
+        },
+        {
+            title: '操作',
+            key: 'option',
+            width: 200,
+            valueType: 'option',
+            render: (_: any, record: any) => {
+                return [
+                    // <UpDataActBtn key={'SCORE'} record={record} type='SCORE' />,
+                    // <UpDataActBtn key={'act'} record={record} type='EDIT' />,
+                    <Popconfirm
+                        title="是否确认删除?"
+                        key="del"
+                        onConfirm={() => delTableData(record)}
+                    >
+                        <a>移除</a>
+                    </Popconfirm>
+                ]
+            },
+        },
+
+    ]
+
+
+    const getTableData = async () => {
+        const resp = await getData();
+        if (resp) {
+            set_data(resp);
+        }
+        return []
+    }
+
+    const delTableData = async (record: any) => {
+        const resp = await delData([record.id]);
+        if (resp) {
+            message.success('操作成功!');
+            getTableData();
+            // message.success('操作成功!');
+        }
+    }
+
+    const saveTableData = async () => {
+        let newDataSource = dataSource.map((a: any, index: number) => {
+            //更新排序
+            return { ...a, sort: index + 1 }
+        });
+
+        const resp = await addData({
+            unitTypeCode: currentTab?.key,
+            unitTypeName: currentTab?.label,
+            secondItemMap: newDataSource
+        });
+
+        if (resp) {
+            message.success('操作成功!');
+            getTableData();
+        }
+
+    }
+
+
+    interface TableTransferProps extends TransferProps<TransferItem> {
+        dataSource: any[];
+        leftColumns: ColumnsType<any>;
+        rightColumns: ColumnsType<any>;
+    }
+
+
+    const transferTableColumn = [
+        {
+            title: '项目名称',
+            dataIndex: 'name',
+        },
+        {
+            title: '评价方式',
+            dataIndex: 'evaluationName',
+
+        },
+    ]
+
+
+    const addFuncHandle = () => {
+
+        const ref = React.createRef<{ save: any; }>();
+
+        Modal.confirm({
+            title: `选择二次分配`,
+            icon: <></>,
+            width: 672,
+            okText: '确定',
+            cancelText: '取消',
+            content: <TableTransfer
+                ref={ref}
+                leftColumns={transferTableColumn}
+                rightColumns={transferTableColumn} dataSource={[]}
+            ></TableTransfer>,
+            onOk: () => {
+                return ref.current && ref.current.save();
+            }
+        })
+    }
+
+    const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, ...restProps }: TableTransferProps, ref) => {
+
+        const [_data, _set_data] = useState<any>();
+        const [targetKeys, setTargetKeys] = useState<string[]>([]);
+        const [datasource, set_datasource] = useState<any[]>([]);
+        const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
+
+        //获取单元
+        const getFuncList = async () => {
+            const resp = await getTransferTableData(currentTab ? currentTab.key : '');
+            if (resp) {
+
+                if (dataSource) {
+
+                    const defaultSelctedkeys = dataSource.map((item: any) => item.secondItemCode);
+
+                    set_datasource([...resp, ...(dataSource.map((a: any) => ({ ...a, name: a.secondItemName, code: a.secondItemCode })))]);
+
+
+                    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));
+                needData.reverse();
+                const result = needData.map((a, index) => ({
+                    secondItemCode: a.code,
+                    secondItemName: a.name,
+                    evaluation: a.evaluation,
+                    source: a.source,
+                    sort: a.sort ? a.sort : index
+                }))
+
+                const resp = await addData({
+                    unitTypeCode: currentTab?.key,
+                    unitTypeName: currentTab?.label,
+                    secondItemMap: result
+                });
+                if (resp) {
+                    message.success('操作成功!');
+                    getTableData();
+                }
+            }
+        }));
+
+        useEffect(() => {
+            getFuncList();
+        }, [])
+
+        return (
+            <Transfer className='TableTransfer' showSearch
+                titles={['待选项', '已选项']}
+                locale={{
+                    itemUnit: '项',
+                    itemsUnit: '项',
+                    searchPlaceholder: '请输入',
+                }}
+                oneWay={true}
+                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 (
+                        <BMSTable
+                            rowSelection={rowSelection}
+                            columns={columns as TransferItem[]}
+                            dataSource={filteredItems}
+                            size="small"
+                            bordered={false}
+                            rowKey={'code'}
+                            tableAlertRender={false}
+                            style={{ pointerEvents: listDisabled ? 'none' : undefined }}
+                            onRow={({ code, disabled: itemDisabled }) => ({
+                                onClick: () => {
+                                    if (itemDisabled || listDisabled) return;
+                                    onItemSelect(code as string, !listSelectedKeys.includes(code as string));
+                                },
+                            })}
+                        />
+                    );
+                }}
+            </Transfer>
+        )
+    })
+
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+    }
+
+
+    const onTabChange = (activeKey: string) => {
+        const need = tabs.filter(a => a.key == activeKey);
+
+        need.length > 0 && set_currentTab(need[0]);
+    }
+
+    const onTableSelectChange = (newSelectedRowKeys: React.Key[]) => {
+        set_tableSelectedKeys([...newSelectedRowKeys]);
+    };
+
+    const delTableDataHanfle = async (record?: { id: number; }) => {
+        const resp = await delData(tableSelectedKeys);
+        if (resp) {
+            message.success('操作成功!');
+            getTableData();
+        }
+    }
+
+    const SortableItem = SortableElement((props: any) => <tr {...props} />);
+    const SortContainer = SortableContainer((props: any) => <tbody {...props} />);
+
+    const onSortEnd = useRefFunction(
+        ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {
+            if (oldIndex !== newIndex) {
+                const newData = arrayMoveImmutable({
+                    array: [...dataSource],
+                    fromIndex: oldIndex,
+                    toIndex: newIndex,
+                }).filter((el) => !!el);
+                const updatedSortArr = newData.map((item: any, index: number) => ({ ...item, sort: index }))
+                set_dataSource([...updatedSortArr])
+            }
+        },
+    );
+
+    const DraggableContainer = (props: any) => (
+        <SortContainer
+            useDragHandle
+            disableAutoscroll
+            helperClass="row-dragging"
+            onSortEnd={onSortEnd}
+            {...props}
+        />
+    );
+
+    const DraggableBodyRow = (props: any) => {
+        const { className, style, ...restProps } = props;
+        // function findIndex base on Table rowKey props and should always be a right array index
+        const index = dataSource.findIndex(
+            (x) => x.id === restProps['data-row-key'],
+        );
+
+        return <SortableItem index={index} {...restProps} />;
+    };
+
+
+    useEffect(()=>{
+        //搜索
+       
+        if(tableDataFilterParams){
+              const {name} = tableDataFilterParams;
+              if(name.length>0){
+                const results = dataSource.filter(a=>a.secondItemName.indexOf(name) != -1 );
+                set_dataSource([...results]);
+              }else{
+                getTableData();
+              }
+        }
+    },[tableDataFilterParams]);
+
+
+    useEffect(() => {
+        if (currentTab) {
+            const result = data.filter((a: any) => a.unitTypeCode == currentTab.key);
+            if (result.length > 0) {
+                set_dataSource(result[0].secondItemMap)
+            }
+        }
+    }, [currentTab])
+
+    useEffect(() => {
+        if (data) {
+            const tabs = data.map((a: any) => ({ key: a.unitTypeCode, label: a.unitTypeName }));
+            set_tabs(tabs);
+            if (tabs.length > 0 && !currentTab) {
+                //已选择了,保留当前选择的tab
+                set_currentTab({ label: tabs[0].label, key: tabs[0].key });
+            } else {
+                const result = data.filter((a: any) => a.unitTypeCode == currentTab?.key);
+                if (result.length > 0) {
+                    set_dataSource(result[0].secondItemMap)
+                }
+            }
+
+        }
+    }, [data]);
+
+    useEffect(() => {
+        if (ifAdjustment) {
+            set_columns([{
+                title: '排序',
+                dataIndex: 'sort',
+                width: 60,
+                className: 'drag-visible',
+                render: () => <DragHandle />,
+            }, ...columns])
+        }
+    }, [ifAdjustment]);
+
+    useEffect(() => {
+        set_columns(static_columns);
+        getTableData();
+    }, [])
+
+    return (
+        <BMSPagecontainer className='OccupationsSecondaryDistriSet' title={false}>
+            <Tabs
+                defaultActiveKey="1"
+                onChange={onTabChange}
+                items={tabs}
+            />
+            <div className='toolBar'>
+                <div className='filter'>
+                    <div className='filterItem'>
+                        <span className='label' style={{ whiteSpace: 'nowrap' }}> 检索:</span>
+                        <Input placeholder={'请输入项目名称'} allowClear
+                            suffix={
+                                <IconFont type="iconsousuo" onClick={() => tableDataSearchHandle('name')} />
+                            }
+                            onChange={(e) => {
+                                set_tableDataSearchKeywords(e.target.value);
+                                if (e.target.value.length == 0) {
+                                    set_tableDataFilterParams({
+                                        ...tableDataFilterParams,
+                                        name: ''
+                                    });
+                                }
+                            }}
+                            onPressEnter={(e) => {
+
+                                set_tableDataFilterParams({
+                                    ...tableDataFilterParams,
+                                    name: (e.target as HTMLInputElement).value
+                                });
+                            }}
+
+                        />
+                    </div>
+                </div>
+                <div className='btnGroup'>
+                    {!ifAdjustment && <span className='set' onClick={() => set_ifAdjustment(true)}>调整</span>}
+                    {ifAdjustment && <>
+                        <span className='set' onClick={() => set_ifAdjustment(false)}>取消</span>
+                        <span className='save' onClick={() => saveTableData()}>保存</span>
+                    </>
+                    }
+                </div>
+            </div>
+            <div style={{ marginTop: 16 }}>
+                <BMSTable columns={columns as ProColumns[]} actionRef={tableRef} rowKey='id'
+                    params={tableDataFilterParams} dataSource={dataSource}
+                    tableAlertRender={false}
+                    pagination={false}
+                    rowSelection={ifAdjustment ? false : {
+                        // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
+                        // 注释该行则默认不显示下拉选项
+                        selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
+                        onChange: onTableSelectChange,
+                    }}
+
+                    components={ifAdjustment ? {
+                        body: {
+                            wrapper: DraggableContainer,
+                            row: DraggableBodyRow,
+                        },
+                    } : undefined}
+                />
+                {!ifAdjustment && <div className='bottomAddBtn' onClick={() => addFuncHandle()}>新增</div>}
+
+            </div>
+            {
+                tableSelectedKeys.length > 0 && (
+                    <div className='bottomToolbar'>
+                        <span className='leftAccount'>已选择<a>{tableSelectedKeys.length}</a>项</span>
+                        <div className='btnGroup'>
+                            <span className='cancel' onClick={() => tableRef.current?.clearSelected && tableRef.current?.clearSelected()}>取消选择</span>
+                            <Popconfirm
+                                title="是否确认删除?"
+                                key="del"
+                                onConfirm={() => delTableDataHanfle()}
+                            >
+                                <span className='batchDel'>批量删除</span>
+                            </Popconfirm>
+
+                        </div>
+                    </div>
+                )
+            }
+        </BMSPagecontainer>
+    )
+}

+ 89 - 0
src/pages/setting/projectSetting/occupationsSecondaryDistriSet/service.ts

@@ -0,0 +1,89 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-05-09 14:16:19
+ * @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 { Key } from 'react';
+import { request } from 'umi';
+
+//获取table列表数据
+
+export type TableItemDataType = {
+  unitTypeCode:string,
+  unitTypeName:string,
+  secondItemMap:any[]
+}
+
+
+export const getData = (params?: any) => {
+  return request<TableItemDataType[]>('/performance/item/getUnitTypeSecondItem', {
+    method: 'GET',
+    params: { ...params }
+  });
+};
+
+export const gainData = (params?: any) => {
+  return request('/performance/item/auto', {
+    method: 'GET',
+    params: { ...params }
+  });
+};
+
+
+
+
+//新增表格数据
+
+export const addData = (data:any) => {
+  return request('/performance/item/addUnitTypeSecondItem', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+
+//保存评分项
+export const saveScoreData = (data:{nonAssessmentCode:string,secondItem:any[]}) => {
+  return request('/performance/item/addNonAssessmentSecondItemMap', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//删除表格操作
+export const delData = (ids:Key[]) => {
+  return request('/performance/item/deleteUnitTypeSecondItem', {
+    method: 'POST',
+    data:ids
+  });
+};
+
+
+
+//获取穿梭框列表数据
+export const getTransferTableData = (unitTypeCode:string) => {
+  return request('/performance/item/getSecondItem', {
+    method: 'GET',
+    params:{unitTypeCode}
+  });
+};
+
+
+
+
+
+
+
+
+
+
+

+ 186 - 0
src/pages/setting/projectSetting/occupationsSecondaryDistriSet/style.less

@@ -0,0 +1,186 @@
+.row-dragging {
+
+  .bms-ant-table-cell {
+    width: 130px;
+  }
+}
+
+.OccupationsSecondaryDistriSet-ModalForm {
+  .item {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+
+    .delIcon {
+      position: relative;
+      top: 3px;
+      cursor: pointer;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      width: 24px;
+      height: 24px;
+      background: #FAFCFF;
+      border-radius: 4px;
+      border: 1px solid #DAE2F2;
+    }
+  }
+
+  .addBtn {
+    cursor: pointer;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+    width: 320px;
+    height: 40px;
+    background: #FFFFFF;
+    border-radius: 4px;
+    color: #3376FE;
+    border: 1px dashed #CFD6E6;
+
+    &>span {
+      margin-left: 8px;
+    }
+  }
+}
+
+.OccupationsSecondaryDistriSet {
+  padding: 16px;
+  background: #FFFFFF;
+  border-radius: 4px;
+
+  .bms-ant-tabs-nav {
+    .bms-ant-tabs-tab {
+      padding-top: 0 !important;
+    }
+
+    &::before {
+      border-bottom: none !important;
+    }
+  }
+
+
+  .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 {
+      .set {
+        display: inline-block;
+        text-align: center;
+        width: 56px;
+        height: 24px;
+        cursor: pointer;
+        line-height: 23px;
+        background: #FAFCFF;
+        border-radius: 4px;
+        margin-right: 8px;
+        border: 1px solid #DAE2F2;
+      }
+
+      .save {
+        display: inline-block;
+        text-align: center;
+        width: 56px;
+        height: 24px;
+        cursor: pointer;
+        line-height: 23px;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #FFFFFF;
+        background: #3377FF;
+        border-radius: 4px;
+        margin-right: 8px;
+      }
+
+    }
+
+  }
+
+  .bottomAddBtn {
+    text-align: center;
+    line-height: 40px;
+    height: 40px;
+    cursor: pointer;
+    font-size: 14px;
+    font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+    font-weight: 400;
+    color: #17181A;
+    background: #FFFFFF;
+    border-radius: 4px;
+    margin-top: 16px;
+    border: 1px dashed #CFD6E6;
+  }
+
+  .bottomToolbar {
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    align-items: center;
+    position: fixed;
+    left: 200px;
+    bottom: 0;
+    padding: 0 16px;
+    width: calc(100% - 200px);
+    height: 48px;
+    background: #FFFFFF;
+    box-shadow: 0px -8px 16px 0px rgba(64, 85, 128, 0.1);
+
+    .leftAccount {
+      font-size: 14px;
+      font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+      font-weight: 400;
+      color: #17181A;
+      line-height: 21px;
+
+    }
+
+    .btnGroup {
+      .cancel {
+        display: inline-block;
+        width: 80px;
+        height: 24px;
+        border-radius: 4px;
+        font-size: 14px;
+        text-align: center;
+        line-height: 23px;
+        margin-right: 8px;
+        cursor: pointer;
+        border: 1px solid #DAE2F2;
+      }
+
+      .batchDel {
+        display: inline-block;
+        width: 80px;
+        height: 24px;
+        border-radius: 4px;
+        font-size: 14px;
+        text-align: center;
+        line-height: 23px;
+        color: #FFFFFF;
+        cursor: pointer;
+        background: #3377FF;
+      }
+    }
+  }
+
+}

+ 3 - 4
src/pages/setting/projectSetting/secondaryProjectDistribute/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-05-05 14:30:26
+ * @LastEditTime: 2023-05-08 14:18:26
  * @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
  */
@@ -22,7 +22,7 @@ import { ProColumns } from '@ant-design/pro-table';
 import { Input, message, Popconfirm } from 'antd';
 import { useEffect, useRef, useState } from 'react'
 
-import { addData, delData, editData, gainData, getData } from './service';
+import { addData, delData, editData, gainData, getSecondaryProjectDistriData } from './service';
 
 import './style.less';
 
@@ -94,7 +94,7 @@ export default function BilingProjectMana() {
 
 
     const getTableData = async (params: any) => {
-        const resp = await getData(params);
+        const resp = await getSecondaryProjectDistriData(params);
         if (resp) {
             return {
                 data: resp.list,
@@ -249,7 +249,6 @@ export default function BilingProjectMana() {
 
     const tableDataSearchHandle = (paramName: string) => {
 
-
         set_tableDataFilterParams({
             ...tableDataFilterParams,
             [`${paramName}`]: tableDataSearchKeywords

+ 4 - 2
src/pages/setting/projectSetting/secondaryProjectDistribute/service.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2023-03-03 16:31:27
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-05-05 14:21:34
+ * @LastEditTime: 2023-05-08 14:18:12
  * @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
  */
@@ -28,7 +28,7 @@ export type SecondaryDistriProjectTableItemDataType = {
 }
 
 
-export const getData = (params?: any) => {
+export const getSecondaryProjectDistriData = (params?: any) => {
   return request<{
     current: number;
     list: SecondaryDistriProjectTableItemDataType[];
@@ -92,3 +92,5 @@ export const delData = (id: string) => {
 
 
 
+
+

+ 65 - 0
src/pages/static/index.tsx

@@ -0,0 +1,65 @@
+/*
+ * @Author: your name
+ * @Date: 2022-03-03 18:04:40
+ * @LastEditTime: 2023-05-10 15:18:21
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/reports/index.tsx
+ */
+
+import { useEffect, useState } from 'react';
+
+import { Skeleton } from 'antd';
+import BMSPagecontainer from '@/components/BMSPageContainer';
+import { useModel } from '@umijs/max';
+
+
+export default () => {
+  const { initialState, setInitialState } = useModel('@@initialState');
+  const [specialPageUrl, setspecialPageUrl] = useState<string | undefined>(undefined);
+  const [loading, setloading] = useState(false);
+
+  
+  
+
+  const onLoadhandle = () => {
+    setloading(false);
+  };
+
+  useEffect(() => {
+    setloading(true);
+    if (initialState && initialState.spacicalPageParamsType && initialState.userData) {
+      const {
+        spacicalPageParamsType,
+        userData: { youshuToken },
+      } = initialState;
+
+      console.log({spacicalPageParamsType});
+      
+      const { pathname } = location;
+      const spacialPage = spacicalPageParamsType.filter((t) => `/budgetManaSystem${t.path}` == pathname);
+
+      //console.log({pathname,spacialPage,spacicalPageParamsType,initialState});
+
+      if (spacialPage.length > 0) {
+        //当前页面属于有数数据展示页面
+        console.log(`${spacialPage[0].url}`);
+
+        const url = `${spacialPage[0].url}`;
+        setspecialPageUrl(url);
+      }
+    }
+    
+  }, [initialState]);
+
+  return (
+    <BMSPagecontainer title={false}>
+      <Skeleton loading={loading} paragraph={{ rows: 50 }} active />
+      <iframe
+        onLoad={() => onLoadhandle()}
+        style={{ width: '100%', height: '90vh', border: 'none' }}
+        src={specialPageUrl}
+      ></iframe>
+    </BMSPagecontainer>
+  );
+};