فهرست منبع

添加报表列管理&报表设置

code4eat 2 سال پیش
والد
کامیت
90a5b9829c

+ 24 - 2
.umirc.ts

@@ -2,7 +2,7 @@
  * @Author: code4eat awesomedema@gmail.com
  * @Date: 2022-12-14 14:14:32
  * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-03-29 16:02:56
+ * @LastEditTime: 2023-04-06 15:25:59
  * @FilePath: /BudgetManaSystem/.umirc.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -49,7 +49,8 @@ export default defineConfig({
   proxy: {
 
     '/gateway': {
-      target: 'http://112.124.59.133:5000/gateway',
+      target: 'http://120.27.235.181:5000/gateway',
+      //target:'http://192.168.1.113:8901/gateway', //后端
       changeOrigin: true,
       // pathRewrite: { '^/gateway': '' },
 
@@ -108,6 +109,27 @@ export default defineConfig({
               name: '指标分组权重设定',
               path: '/setting/manaPerformanceSet/indicGroupWeightSet',
               component: './setting/manaPerformanceSet/indicGroupWeightSet',
+            },
+            {
+              name: '单元指标目标设定',
+              path: '/setting/manaPerformanceSet/unitIndicTargetSet',
+              component: './setting/manaPerformanceSet/unitIndicTargetSet',
+            }
+          ]
+        },
+        {
+          name: '报表设置',
+          path: '/setting/reportSet',
+          routes: [
+            {
+              name: '报表列管理',
+              path: '/setting/reportSet/reportListMana',
+              component: './setting/reportSet/reportListMana',
+            },
+            {
+              name: '报表设置',
+              path: '/setting/reportSet/reportSetting',
+              component: './setting/reportSet/reportSetting',
             }
           ]
         },

+ 2 - 1
package-lock.json

@@ -13,7 +13,8 @@
         "antd": "^5.0.7",
         "axios": "^1.3.3",
         "lodash": "^4.17.21",
-        "mathjs": "^11.6.0"
+        "mathjs": "^11.6.0",
+        "react-sortable-hoc": "^2.0.0"
       },
       "devDependencies": {
         "@types/lodash": "^4.14.192",

+ 2 - 1
package.json

@@ -19,7 +19,8 @@
     "antd": "^5.0.7",
     "axios": "^1.3.3",
     "lodash": "^4.17.21",
-    "mathjs": "^11.6.0"
+    "mathjs": "^11.6.0",
+    "react-sortable-hoc": "^2.0.0"
   },
   "devDependencies": {
     "@types/lodash": "^4.14.192",

+ 23 - 2
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-03-29 16:03:35
+ * @LastEditTime: 2023-04-04 17:19:18
  * @FilePath: /BudgetManaSystem/src/app.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -160,7 +160,6 @@ export const request: RequestConfig = {
 
             } else {
               notification.error({
-
                 message: '',
                 description: errorMessage,
                 placement: 'topRight',
@@ -363,8 +362,30 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
                     name: '指标分组权重设定',
                     icon: '',
                   },
+                  {
+                    name: '单元指标目标设定',
+                    path: '/setting/manaPerformanceSet/unitIndicTargetSet',
+                    icon:''
+                  }
                 ]
               },
+              {
+                path: '/setting/reportSet',
+                name: '报表设置',
+                icon:'',
+                children: [
+                  {
+                    path: '/setting/reportSet/reportListMana',
+                    name: '报表列管理',
+                    icon: '',
+                  },
+                  {
+                    name: '报表设置',
+                    path: '/setting/reportSet/reportSetting',
+                    icon:''
+                  }
+                ]
+              }
             ],
           }
         ];

+ 70 - 1
src/global.less

@@ -39,6 +39,72 @@ textarea {
                    .bms-ant-modal-confirm-body {
                        .bms-ant-modal-confirm-content {
                           max-width: 100% !important;
+                          max-height: 70vh !important;
+                          overflow-y: scroll;
+
+                          .TableTransfer {
+                            .bms-ant-transfer-operation {
+                            //   align-self: self-end;
+                            //   margin-bottom: 30px;
+                        
+                              button {
+                                //color: #17181A;
+                                width: 24px;
+                                height: 40px !important;
+                                // background: #FAFCFF;
+                                border-radius: 4px;
+                                border: 1px solid #DAE2F2;
+                              }
+                            }
+
+                            .bms-ant-transfer-list {
+                                border: 1px solid #DAE2F2;
+                                .bms-ant-transfer-list-header {
+                                    border-bottom: 1px solid #DAE2F2;
+                                    .anticon {
+                                      color: #99A6BF;
+                                    }
+                              
+                                    .bms-ant-transfer-list-header-selected {
+                                      color: #515866;
+                                    }
+                                  }
+                              
+                                  .bms-ant-transfer-list-body {
+                                    .bms-ant-transfer-list-body-search-wrapper {
+                                      padding: 8px;
+                              
+                                      .bms-ant-input-prefix {
+                                        .anticon-search {
+                                          color: #99A6BF;
+                                        }
+                                      }
+                                    }
+                                  }
+                            } 
+                        
+                            
+                        
+                            .bms-ant-table {
+                              .bms-ant-table-container {
+                                .bms-ant-table-content {
+                                  .bms-ant-table-thead {
+                        
+                                    &>tr>th {
+                                      font-size: 14px;
+                                      font-family: SourceHanSansCN-Medium, SourceHanSansCN;
+                                      font-weight: 500;
+                                      color: #17181A;
+                                      background: #EEF3FA;
+                                      border-radius: 0 !important;
+                                      padding: 4px 8px !important;
+                                      border-bottom: none;
+                                    }
+                                  }
+                                }
+                              }
+                            }
+                          }
                        }
                    }
                    .bms-ant-modal-confirm-btns {
@@ -196,12 +262,15 @@ textarea {
 }
 
 .bms-ant-table-wrapper {
+    .bms-ant-table:not(.bms-ant-table-bordered) .bms-ant-table-tbody>tr.bms-ant-table-row.bms-ant-table-row-selected>td:first-child  {
+           border-radius: 0 !important;
+    }
     .bms-ant-table-content {
         .bms-ant-table-thead {
             tr {
                 &:last-child {
                       .bms-ant-table-cell {
-                          border-top: 1px solid #dae2f2;
+                         // border-top: 1px solid #dae2f2;
                       }
                 }
             }

+ 2 - 2
src/pages/setting/baseSetting/businessDicMana/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-03-30 16:10:13
+ * @LastEditTime: 2023-04-06 18:32:45
  * @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
  */
@@ -158,7 +158,7 @@ const BusinessDicMana = () => {
 
         return (
             <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}公用字典(职称)`}
+                title={`${type == 'EDIT' ? '编辑' : '新增'}公用字典(${record.name})`}
                 width={352}
                 initialValues={type == 'EDIT' ? { ...record } : {defaultFlag:0}}
                 trigger={

+ 2 - 2
src/pages/setting/manaPerformanceSet/classAssessAndGradeSet/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-03-31 13:23:29
+ * @LastEditTime: 2023-03-31 14:38:43
  * @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
  */
@@ -165,7 +165,7 @@ export default function ClassAssessAndGradeSet() {
     
         return (
             <ModalForm
-                title={`考核分级设定(${record.unitTypeName})`}
+                title={record.unitTypeName?`考核分级设定(${record.unitTypeName})`:'新增考核分级设定'}
                 className='ClassAssessAndGradeSet-ModalForm'
                 width={400}
                 initialValues={type == 'EDIT' ? { ...record } : {}}

+ 30 - 15
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-03-31 13:37:11
+ * @LastEditTime: 2023-04-06 18:25:55
  * @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
  */
@@ -32,6 +32,14 @@ import { addData, addIndicGroup, addUnitForGroup, delData, editData, getAllUnit,
 import './style.less';
 import { omit } from 'lodash';
 
+import { create, all } from 'mathjs'
+
+const config = {
+  number: 'bignumber',
+  precision:2
+}
+const math = create(all, config as any);
+
 
 const IconFont = createFromIconfontCN({
     scriptUrl: '//at.alicdn.com/t/c/font_1927152_gfxzp431jpt.js',
@@ -158,6 +166,8 @@ export default function IndicGroupWeightSet() {
             if (resp) {
                 tableRef.current?.reload();
                 message.success('操作成功!');
+            }else{
+                return false
             }
         }
 
@@ -383,7 +393,7 @@ export default function IndicGroupWeightSet() {
 
         const title = () => {
             if (type == 'ADD') {
-                return `新增指标分组(${record.groupName})`
+                return `新增指标分组`
             }
             if (type == 'EDIT') {
                 return `编辑指标分组(${record.groupName})`
@@ -416,7 +426,7 @@ export default function IndicGroupWeightSet() {
                 defaultFormData[`indicatorCode${a.id}`] = a.indicatorCode;
                 defaultFormData[`weight${a.id}`] = a.weight;
               });
-              console.log({defaultFormData});
+             
               set_indicatorIniData({...defaultFormData});
               set_indicatorData([...result]);
         }
@@ -467,17 +477,21 @@ export default function IndicGroupWeightSet() {
                         return updateTable({ ...record, ...val }, type)
                     }
                     if (type == 'INDICATOR') {
-                      
-                        const total = indicatorData.reduce((prev:any,cur:any)=>prev + cur.weight,0);
-
-                        if(total != 1){
-                              Modal.confirm({
-                                 title:'占比加总必须是1!'
-                              });
-                              return Promise.resolve(false);
-                        }else{
-                            return updateTable({ id: record.id, indicatorWeights: indicatorData }, type)
-                        }
+            
+                        // const total = indicatorData.reduce((prev:any,cur:any)=>{
+                        //         return math.add(Number(prev).toFixed(2),cur['weight'])
+                        // },0);
+                        
+                        // if(total != 1){
+                        //       Modal.confirm({
+                        //          title:'占比加总必须是1!'
+                        //       });
+                        //       return Promise.resolve(false);
+                        // }else{
+                            
+                        // }
+
+                        return updateTable({ id: record.id, indicatorWeights: indicatorData }, type);
                     }
 
                     return Promise.resolve(true);
@@ -504,6 +518,7 @@ export default function IndicGroupWeightSet() {
                         <div>
                             {
                                 indicatorData.map((item: any, index: number) => {
+        
                                     return (
                                         <div className='item' key={index}>
                                             <ProFormSelect label="管理指标:" width={160} 
@@ -513,7 +528,7 @@ export default function IndicGroupWeightSet() {
                                                 if (resp) {
                                                     return resp.list.map((a: any) => ({
                                                         label: a.name,
-                                                        value: `${a.code}`
+                                                        value: a.code
                                                     }))
                                                 }
                                                 return []

+ 2 - 2
src/pages/setting/manaPerformanceSet/manaIndicItemSet/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-03-31 13:35:09
+ * @LastEditTime: 2023-03-31 14:40:32
  * @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
  */
@@ -135,7 +135,7 @@ export default function manaIndicItemSet() {
 
         return (
             <ModalForm
-                title={`${type == 'EDIT' ? '编辑' : '新增'}管理指标项目(${record.name})`}
+                title={`${type == 'EDIT' ? '编辑' : '新增'}管理指标项目${record.name?`(${record.name})`:''}`}
                 width={352}
                 initialValues={type == 'EDIT' ? { ...record } : {}}
                 trigger={

+ 484 - 0
src/pages/setting/manaPerformanceSet/unitIndicTargetSet/index.tsx

@@ -0,0 +1,484 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-06 18:30:05
+ * @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, BMSTablePageDefaultConfig } from '@/components/BMSTable';
+import { deepEqual } from '@/utils/tooljs';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { ActionType } from '@ant-design/pro-components';
+import { ModalForm, ProFormDigit, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
+import { ProColumns } from '@ant-design/pro-table';
+import { Input, message, Modal, Popconfirm, Table } from 'antd';
+import { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
+import Transfer, { TransferItem, TransferProps } from 'antd/es/transfer';
+import React from 'react';
+import { useEffect, useImperativeHandle, useRef, useState } from 'react';
+import { getAllUnit } from '../indicGroupWeightSet/service';
+
+import difference from 'lodash/difference';
+
+import {  copyGroupUnit, delData, editUnitIndicTargetTbaleData, getUnitGroupList, getUnitIndicTargetTableData, getUnitUnderGroupById } from './service';
+
+
+import './style.less';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+
+
+const UnitIndicTargetSet = () => {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+    const [tableColumn, set_tableColumn] = useState<ProColumns[] | any[]>([]);
+    const [typeList, set_typeList] = useState<any[]>([]);
+    const [showTypeListArr, set_showTypeListArr] = useState<any[]>([]);
+    const [currentSelectedType, set_currentSelectedType] = useState<any | undefined>(undefined);
+
+    const tableRef = useRef<ActionType>();
+
+
+
+    const getTableData = async (params: any) => {
+        const { groupId } = params;
+        console.log({ params });
+        if (groupId) {
+            const resp = await getUnitIndicTargetTableData(params);
+            if (resp) {
+
+                const { title, unitWeightData } = resp;
+                const columns = title.map((item: any) => {
+
+                    return {
+                        title: item.name,
+                        dataIndex: `${item.code}`,
+                        key: `${item.code}`,
+                        // render:(_:number,record:any)=>{
+                        //      return `${Number(_ * 100).toFixed(2)}%`
+                        // }
+                        // width: 140,
+
+                    }
+                });
+                set_tableColumn([{
+                    title: '核算单元',
+                    dataIndex: 'unitName',
+
+                }, ...columns, {
+                    title: '操作',
+                    key: 'option',
+                    width: 120,
+                    valueType: 'option',
+                    render: (_: any, record: any) => {
+                        return [
+                            <UpDataActBtn key={'act'} record={record} type='EDIT' />,
+                            <a key={'copy'} onClick={()=>copyHandle(record)}>复制</a>
+                        ]
+                    },
+                }]);
+
+                const data = unitWeightData.map((item: any) => {
+
+                    let rowData: { [key: string]: any } = {};
+
+                    for (let index = 0; index < item.value.length; index++) {
+
+                        for (const key in item.value[index]) {
+                            if (key == 'code') {
+                                rowData[`${item.value[index][`code`]}`] = item.value[index][`target`];
+                                rowData[`targetValue${item.value[index][`code`]}`] = item.value[index][`targetValue`]    
+                            }
+                        }
+                    }
+
+                    return { ...item, ...rowData, columns }
+                });
+                console.log({data});
+                return {
+                    data,
+                    success: true
+                }
+
+            }
+            return []
+        }
+        return []
+    }
+
+    //获取左侧单元
+    const getTypeList = async () => {
+        const resp = await getUnitGroupList();
+        if (resp) {
+            set_typeList(resp);
+            set_showTypeListArr(resp);
+        }
+    }
+
+
+    const updateTable = async (formVal: any, type: 'EDIT' | "ADD") => {
+        
+        const temp = formVal.columns.map((a:any)=>{
+              return {
+                code:a.key,
+                targetValue:formVal[`targetValue${a.key}`],
+                
+              }
+        })
+        
+        if (type == 'EDIT') {
+            const result = {
+                unitCode:formVal.unitCode,
+                unitName:formVal.unitName,
+                value:temp
+            }
+            const resp = await editUnitIndicTargetTbaleData(result);
+            if (resp) {
+                tableRef.current?.reload();
+            }
+        }
+
+        return true;
+
+    }
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
+
+        return (
+            <ModalForm
+                title={`设定指标目标值(${record.unitName})`}
+                width={352}
+                initialValues={type == 'EDIT' ? { ...record } : { }}
+                trigger={
+                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
+                }
+                onFinish={(val) => {
+                    return updateTable(type == 'EDIT' ? { ...record, ...val } : val, type);
+                }}
+            >
+                {
+                    record.value.map((item:any, index:number) => {
+                        const label = record.columns.filter((a:ProColumns)=>a.key == item.code);
+                      
+                        if(label.length>0){
+                            return (
+                                <ProFormDigit
+                                    key={index}
+                                    name={`targetValue${item.code}`}
+                                    label={`${label[0].title}`}
+                                    placeholder="请输入"
+                                    rules={[{ required: true, message:`请填写${label[0].title}` }]}
+    
+                                />
+                            )
+                        }
+                        
+                    })
+                }
+            </ModalForm>
+        )
+    }
+     
+
+
+    interface DataType {
+        key: string;
+        title: string;
+        description: string;
+        disabled: boolean;
+        tag: string;
+    }
+
+    interface TableTransferProps extends TransferProps<TransferItem> {
+        dataSource: DataType[];
+        leftColumns: ColumnsType<DataType>;
+        rightColumns: ColumnsType<DataType>;
+        record: any
+    }
+    
+
+    const transferTableColumn:any[] = [
+        {
+            title: '核算单元',
+            dataIndex: 'unitName',
+            key: 'unitName',
+
+        },
+        {
+            title: '职类',
+            dataIndex: 'unitType',
+            key: 'unitType',
+            render: (_: any, record: any) => {
+                switch (parseInt(record.unitType)) {
+                    case 1:
+                        return '临床'
+                        break;
+                    case 2:
+                        return '医技'
+                        break;
+                    case 3:
+                        return '护理'
+                        break;
+                    case 6:
+                        return '行政后勤'
+                        break;
+                    default:
+                        break;
+                }
+            }
+        },
+    ];
+
+    const copyHandle = (record: any) => {
+      
+        const ref = React.createRef<{ save: any; }>();
+
+        Modal.confirm({
+            title: `复制单元考核目标设定信息(${record.unitName})`,
+            icon: <></>,
+            width: 672,
+            content: <TableTransfer
+                ref={ref}
+                record={record}
+                leftColumns={transferTableColumn}
+                rightColumns={transferTableColumn} dataSource={[]}
+            ></TableTransfer>,
+            onOk: () => {
+                return ref.current && ref.current.save();
+            }
+        })
+    }
+
+    const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, record, ...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 getAllUnit();
+            if (resp) {
+
+                set_datasource(resp);
+
+                if (record && record.unitInfoVos) {
+
+                    const defaultSelctedkeys = record.unitInfoVos.map((item: any) => item.unitCode);
+
+                    setTargetKeys(defaultSelctedkeys);
+                }
+
+            }
+        }
+
+        const onChange = (nextTargetKeys: string[]) => {
+            setTargetKeys(nextTargetKeys);
+        };
+
+        const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
+            //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
+            setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+        };
+
+        useImperativeHandle(ref, () => ({
+            save: async () => {
+
+                const needData = datasource.filter(item => targetKeys.includes(item.code));
+
+                const result = needData.map(a=>({unitCode:a.code,unitName:a.unitName}));
+
+                // console.log({result,record});
+        
+                const resp = await copyGroupUnit({
+                    unitInfos:result,
+                    value:record.value
+                });
+                if (resp) {
+                    message.success('操作成功!');
+                    tableRef.current?.reload();
+                }
+            }
+        }));
+
+        useEffect(() => {
+            getFuncList();
+        }, [])
+
+        return (
+            <Transfer className='TableTransfer' showSearch
+                titles={['待选项', '已选项']}
+                locale={{
+                    itemUnit: '项',
+                    itemsUnit: '项',
+                    searchPlaceholder: '请输入'
+                }}
+                onChange={onChange}
+                onSelectChange={onSelectChange}
+                dataSource={datasource}
+                rowKey={record => record.code}
+                targetKeys={targetKeys}
+                selectedKeys={selectedKeys}
+                filterOption={(inputValue, item) => {
+                    return item.unitName!.indexOf(inputValue) !== -1
+
+                }}
+            >
+                {({
+                    direction,
+                    filteredItems,
+                    onItemSelectAll,
+                    onItemSelect,
+                    selectedKeys: listSelectedKeys,
+                    disabled: listDisabled,
+                }) => {
+
+                    // console.log({ filteredItems, listSelectedKeys,direction });
+                    const columns = direction === 'left' ? leftColumns : rightColumns;
+
+                    const rowSelection: TableRowSelection<TransferItem> = {
+                        getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
+                        onSelectAll(selected, selectedRows) {
+                            const treeSelectedKeys = selectedRows.map(({ code }) => code);
+                            const diffKeys = selected
+                                ? difference(treeSelectedKeys, listSelectedKeys)
+                                : difference(listSelectedKeys, treeSelectedKeys);
+                            onItemSelectAll(diffKeys as string[], selected);
+                        },
+                        onSelect({ code }, selected) {
+                            onItemSelect(code as string, selected);
+                        },
+                        selectedRowKeys: listSelectedKeys,
+                    };
+
+                    return (
+                        <Table
+                            rowSelection={rowSelection}
+                            columns={columns as TransferItem[]}
+                            dataSource={filteredItems}
+                            size="small"
+                            rowKey={'code'}
+                            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
+        })
+    }
+   
+
+    useEffect(() => {
+        if (currentSelectedType) {
+            set_tableDataFilterParams({ ...tableDataFilterParams, groupId: currentSelectedType.id })
+        }
+    }, [currentSelectedType])
+
+    useEffect(() => {
+        if (showTypeListArr.length > 0) {
+            set_currentSelectedType(showTypeListArr[0]);
+            set_tableDataFilterParams({ ...tableDataFilterParams, groupId: showTypeListArr[0].id });
+        }
+    }, [showTypeListArr])
+
+    useEffect(() => {
+        getTypeList();
+    }, [])
+
+
+
+    return (
+        <BMSPagecontainer title={false} className='UnitIndicTargetSet'>
+            <div className='left'>
+                <Input placeholder={'请输入'} allowClear
+                    suffix={
+                        <IconFont type="iconsousuo" />
+                    }
+                    onChange={(e) => {
+                        const result = typeList.filter(item => item.groupName.indexOf(e.target.value) != -1);
+                        set_showTypeListArr(result);
+                    }}
+
+                />
+                <div className='wrap'>
+                    {
+                        showTypeListArr.map((item, index) => {
+                            return (
+                                <div className={currentSelectedType ? currentSelectedType.id == item.id ? 'type on' : 'type' : 'type'}
+                                    key={index}
+                                    onClick={() => set_currentSelectedType(item)}
+                                >{item.groupName}</div>
+                            )
+                        })
+                    }
+                </div>
+            </div>
+            <div className='right'>
+                <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('unitCode')} />
+                                }
+                                onChange={(e) => {
+                                    set_tableDataSearchKeywords(e.target.value);
+                                    if (e.target.value.length == 0) {
+                                        set_tableDataFilterParams({
+                                            ...tableDataFilterParams,
+                                            unitCode: ''
+                                        });
+                                    }
+                                }}
+                                onPressEnter={(e) => {
+
+                                    set_tableDataFilterParams({
+                                        ...tableDataFilterParams,
+                                        unitCode: (e.target as HTMLInputElement).value
+                                    });
+                                }}
+
+                            />
+                        </div>
+                    </div>
+                    <div className='btnGroup'>
+                        {/* <UpDataActBtn record type='ADD' /> */}
+                    </div>
+                </div>
+                <div style={{ marginTop: 16 }}>
+                    {currentSelectedType && <BMSTable actionRef={tableRef} columns={tableColumn} rowKey='unitCode' params={tableDataFilterParams} request={(params) => getTableData(params)} />}
+                </div>
+            </div>
+        </BMSPagecontainer>
+    )
+}
+
+
+export default UnitIndicTargetSet;

+ 82 - 0
src/pages/setting/manaPerformanceSet/unitIndicTargetSet/service.ts

@@ -0,0 +1,82 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-07 11:12:10
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-04 10:13:22
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicMana/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+import { getManaIndexGroup } from '@/pages/budgetMana/monthlyDataCheck/service';
+import { request } from 'umi';
+
+
+
+//获取表格数据
+
+export type UnitIndicTargetTableDataType = {
+  id:number;
+  
+}
+
+export const getUnitIndicTargetTableData = (params:{groupId:string,unitCode:string}) => {
+    return request('/performance/managerIndicator/getGroupUnitList', {
+      method: 'GET',
+      params:{...params}
+    });
+};
+
+
+
+
+//编辑表格数据
+
+export const editUnitIndicTargetTbaleData = (data:any) => {
+    return request('/performance/managerIndicator/editGroupUnit', {
+      method: 'POST',
+      data
+    });
+};
+
+
+//删除表格操作
+export const delData = (id:number) => {
+    return request('/performance/dict/deleteData', {
+      method: 'POST',
+      params:{id}
+    });
+};
+
+
+//获取单元分组
+export const  getUnitGroupList= () => {
+    return getManaIndexGroup()
+};
+
+//获取分组下的单元
+export const getUnitUnderGroupById = (groupId:number) => {
+  return request('/performance/managerIndicator/getGroupUnit', {
+    method: 'GET',
+    params:{groupId}
+  });
+};
+
+
+//复制
+
+export type CopyGroupUnitDataType = {
+  unitInfos:{unitCode:string,unitName:string}[],
+  value:{code:string,targetValue:string}[]
+}
+
+export const copyGroupUnit = (data:CopyGroupUnitDataType) => {
+  return request('/performance/managerIndicator/copyGroupUnit', {
+    method: 'POST',
+    data
+  });
+};
+
+

+ 88 - 0
src/pages/setting/manaPerformanceSet/unitIndicTargetSet/style.less

@@ -0,0 +1,88 @@
+.UnitIndicTargetSet {
+  width: 100%;
+  overflow: hidden;
+
+  .left {
+    float: left;
+    border-radius: 4px;
+    width: 220px;
+    height:calc(100vh - 80px);
+    overflow: scroll;
+    margin-right: 16px;
+    padding: 16px;
+    background: #FFFFFF;
+    
+    .wrap {
+      margin-top: 16px;
+
+      .type {
+        cursor: pointer;
+        height: 32px;
+        line-height: 32px;
+        padding-left: 8px;
+        background: #FFFFFF;
+        border-radius: 4px;
+        font-size: 14px;
+        font-family: SourceHanSansCN-Normal, SourceHanSansCN;
+        font-weight: 400;
+        color: #17181A;
+        margin-bottom: 4px;
+
+        &.on {
+          font-weight: 500;
+          color: #17181A;
+          background: #F0F2F5;
+        }
+
+        &:last-child {
+            margin-bottom: 0;
+        }
+      }
+    }
+  }
+
+  .right {
+    float: left;
+    width: calc(100% - 236px);
+    padding: 16px;
+    border-radius: 4px;
+    background: #FFFFFF;
+
+    .toolBar {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+
+      .filter {
+        display: flex;
+        flex-direction: row;
+        justify-content: flex-start;
+        align-items: center;
+
+        .filterItem {
+          display: flex;
+          flex-direction: row;
+          justify-content: center;
+          align-items: center;
+        }
+      }
+
+      .btnGroup {
+        .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;
+        }
+      }
+
+    }
+  }
+}

+ 350 - 0
src/pages/setting/reportSet/reportListMana/index.tsx

@@ -0,0 +1,350 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-07 10:12: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
+ */
+
+
+
+
+import BMSPagecontainer from '@/components/BMSPageContainer';
+import { BMSTable } from '@/components/BMSTable';
+import { createFromIconfontCN } from '@ant-design/icons';
+
+import { ActionType, ProFormRadio } from '@ant-design/pro-components';
+import { ModalForm, ProFormDependency, ProFormDigit, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form'
+import { ProColumns } from '@ant-design/pro-table';
+import { Input, message, Popconfirm } from 'antd';
+import { useEffect, useRef, useState } from 'react';
+
+import { addData, delData, editData, getManaIndic, getReportListTableData, getReportListType } from './service';
+
+import './style.less';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+
+
+export default function ReportListMana() {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+    const tableRef = useRef<ActionType>();
+
+    const columns: ProColumns[] = [
+
+        {
+            title: '列名称',
+            dataIndex: 'name',
+        },
+        {
+            title: '列标题',
+            dataIndex: 'headerText',
+        },
+        {
+            title: '列类型',
+            dataIndex: 'columnTypeName',
+            // render:(_:any)=>_ == 1?'指标':'自定义SQL'
+        },
+        {
+            title: '取数类型',
+            dataIndex: 'dataSource',
+            render: (_: any) => _ == 1 ? '指标' : '自定义SQL'
+        },
+        {
+            title: '取数来源',
+            width: 300,
+            ellipsis: true,
+            dataIndex: 'sql',
+            render: (_: any, record: any) => {
+
+                if (record.sql) return record.sql;
+                if (record.indicatorCodeName) return record.indicatorCodeName
+            }
+        },
+        {
+            title: '操作',
+            key: 'option',
+            width: 120,
+            valueType: 'option',
+            render: (_: any, record: any) => {
+                return [
+                    <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 getReportListTableData(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") => {
+
+        if (type == 'ADD') {
+            if (formVal.dataSource == 1) {
+                //
+                let result = {
+                    name: formVal.name,
+                    headerText: formVal.headerText,
+                    dataSource: formVal.dataSource,
+                    columnType: formVal.columnType,
+                    sql:'',
+                    indicatorCode: formVal.indicatorCode.key,
+                    indicatorCodeName: formVal.indicatorCode.label,
+                }
+
+                const resp = await addData({ ...result });
+                if (resp) {
+                    tableRef.current?.reload();
+                    message.success('操作成功!');
+                }
+
+            }
+            if(formVal.dataSource == 2){
+                //sql
+                let result = {
+                    name: formVal.name,
+                    headerText: formVal.headerText,
+                    dataSource: formVal.dataSource,
+                    columnType: formVal.columnType,
+                    sql: formVal.sql,
+                    indicatorCode:'',
+                    indicatorCodeName:''
+                }
+
+                const resp = await addData({ ...result });
+                if (resp) {
+                    tableRef.current?.reload();
+                    message.success('操作成功!');
+                }
+            }
+
+
+
+        }
+        if (type == 'EDIT') {
+
+            if (formVal.dataSource == 1){
+                //指标
+                const result = {
+                    id: formVal.id,
+                    name: formVal.name,
+                    headerText: formVal.headerText,
+                    dataSource: formVal.dataSource,
+                    columnType: formVal.columnType,
+                    sql:'',
+                    indicatorCode: formVal.indicatorCode.key,
+                    indicatorCodeName: formVal.indicatorCode.label,
+                }
+                const resp = await editData({ ...result });
+                if (resp) {
+                    tableRef.current?.reload();
+                    message.success('操作成功!');
+                }
+
+            }
+
+            if(formVal.dataSource == 2){
+                //sql
+                const result = {
+                    id: formVal.id,
+                    name: formVal.name,
+                    headerText: formVal.headerText,
+                    dataSource: formVal.dataSource,
+                    columnType: formVal.columnType,
+                    sql: formVal.sql,
+                    indicatorCode:'',
+                    indicatorCodeName:''
+                }
+                const resp = await editData({ ...result });
+                if (resp) {
+                    tableRef.current?.reload();
+                    message.success('操作成功!');
+                }
+            }
+
+            
+        }
+        return true;
+
+    }
+
+    const formRef = useRef();
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
+
+        return (
+            <ModalForm
+                title={`${type == 'EDIT' ? '编辑' : '新增'}报表列`}
+                width={352}
+                formRef={formRef}
+                initialValues={type == 'EDIT' ? { ...record, indicatorCode: { label: record.indicatorCodeName, value: record.indicatorCode } } : {}}
+                trigger={
+                    type == 'EDIT' ? <a key="edit" >编辑</a> : <span className='add'>新增</span>
+                }
+                onFinish={(val) => {
+                    console.log({ val });
+                    return updateTable(type == 'EDIT' ? { ...record, ...val, sql: val.sql ? val.sql : '', } : { ...val }, type);
+                }}
+                colProps={{ span: 24 }}
+                grid
+            >
+
+                <ProFormText
+                    name="name"
+                    label="列名称:"
+                    placeholder="请输入"
+                    rules={[{ required: true, message: '列名称不能为空!' }]}
+                />
+                <ProFormText
+                    name="headerText"
+                    label="列标题:"
+                    placeholder="请输入"
+                    rules={[{ required: true, message: '列标题不能为空!' }]}
+                />
+                <ProFormSelect
+                    name="columnType"
+                    label="列类型:"
+                    placeholder="请选择"
+                    request={async () => {
+                        const resp = await getReportListType();
+                        if (resp) {
+                            return resp.list.map((a: any) => ({ label: a.name, value: a.code }))
+                        }
+                    }}
+                    rules={[{ required: true, message: '列类型不能为空!' }]}
+                />
+
+                <ProFormSelect
+                    name="dataSource"
+                    label="取数类型:"
+                    placeholder="请选择"
+                    options={[
+                        { label: '指标', value: 1 },
+                        { label: '自定义SQL', value: 2 }
+                    ]}
+                    rules={[{ required: true, message: '取数类型不能为空!' }]}
+                />
+                <ProFormDependency name={['dataSource']}>
+                    {
+                        ({ dataSource }) => dataSource == 1 && (
+                            <ProFormSelect
+                                name="indicatorCode"
+                                label="取数来源:"
+                                placeholder="请选择"
+                                fieldProps={{
+                                    labelInValue: true
+                                }}
+                                request={async () => {
+                                    const resp = await getManaIndic();
+                                    if (resp) {
+                                        return resp.map((a: any) => ({ label: a.name, value: a.code }))
+                                    }
+                                }}
+                                rules={[{ required: true, message: '数据来源不能为空!' }]}
+                            />
+                        )
+                    }
+                </ProFormDependency>
+                <ProFormDependency name={['dataSource']}>
+                    {
+                        ({ dataSource }) => dataSource == 2 && (
+                            <ProFormTextArea name={'sql'} label='SQL:' rules={[{ required: true, message: 'SQL不能为空!' }]} />
+                        )
+                    }
+                </ProFormDependency>
+
+            </ModalForm>
+        )
+    }
+
+    const tableDataSearchHandle = (paramName: string) => {
+
+        set_tableDataFilterParams({
+            ...tableDataFilterParams,
+            [`${paramName}`]: tableDataSearchKeywords
+        })
+
+    }
+
+
+    useEffect(() => {
+
+    }, [])
+
+    return (
+        <BMSPagecontainer className='ReportListMana' 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('columnName')} />
+                            }
+                            onChange={(e) => {
+                                set_tableDataSearchKeywords(e.target.value);
+                                if (e.target.value.length == 0) {
+                                    set_tableDataFilterParams({
+                                        ...tableDataFilterParams,
+                                        columnName: ''
+                                    });
+                                }
+                            }}
+                            onPressEnter={(e) => {
+
+                                set_tableDataFilterParams({
+                                    ...tableDataFilterParams,
+                                    columnName: (e.target as HTMLInputElement).value
+                                });
+                            }}
+
+                        />
+                    </div>
+                </div>
+                <div className='btnGroup'>
+                    <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>
+    )
+}

+ 119 - 0
src/pages/setting/reportSet/reportListMana/service.ts

@@ -0,0 +1,119 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 16:31:27
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-07 12:03:02
+ * @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 ReportListTableDataType = {
+  id:number,
+  hospId:number,
+  code:number,
+  name:string,
+  headerText:string,
+  dataSource:number,
+  columnType:string,
+  columnTypeName:string,
+  sql:string,
+  indicatorCode:string,
+  indicatorCodeName:string
+}
+
+
+export const getReportListTableData = (params?:any) => {
+  return request<{
+       current:number;
+       list:ReportListTableDataType[];
+       pageSize:number;
+       totalCount:number;
+       totalPage:number;
+  }>('/performance/report/getColumnList', {
+    method: 'GET',
+    params:{...params}
+  });
+};
+
+
+//新增报表
+export type AddTableDataType = {
+  name:string,
+  headerText:string,
+  dataSource:number,
+  columnType:string,
+  sql?:string,
+  indicatorCode?:string,
+  indicatorCodeName?:string
+}
+
+export const addData = (data:any) => {
+  return request('/performance/report/addColumn', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+//获取报表列类型
+
+export const getReportListType = () => {
+  return request('/performance/dict/getDictDataList?current=1&pageSize=10&typeCode=9', {
+    method: 'GET',
+  });
+};
+
+//获取管理指标
+
+export const getManaIndic = () => {
+  return request('/performance/report/getIndicatorList', {
+    method: 'GET',
+  });
+};
+
+
+//编辑表格数据
+
+export type ManaIndicItemTableRowEditType = {
+  id:number;
+}&AddTableDataType
+
+export const editData = (data:any) => {
+  return request('/performance/report/editColumn', {
+    method: 'POST',
+    data
+  });
+};
+
+//删除表格操作
+export const delData = (id:string) => {
+  return request('/performance/report/deleteColumn', {
+    method: 'POST',
+    params:{id}
+  });
+};
+
+
+//添加报表列
+export const addReportTableList = (data:any) => {
+  return request('/performance/report/addReportColumn', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+
+
+
+
+
+

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

@@ -0,0 +1,43 @@
+.ReportListMana {
+  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 {
+      .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;
+      }
+    }
+
+  }
+}

+ 649 - 0
src/pages/setting/reportSet/reportSetting/index.tsx

@@ -0,0 +1,649 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-03 11:30:33
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-07 12:14:31
+ * @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 { deepEqual } from '@/utils/tooljs';
+import { createFromIconfontCN } from '@ant-design/icons';
+import { ActionType, arrayMoveImmutable, useRefFunction } from '@ant-design/pro-components';
+import { ModalForm, ProFormSelect, ProFormText } from '@ant-design/pro-form';
+import { ProColumns } from '@ant-design/pro-table';
+import { Dropdown, Input, MenuProps, message, Modal,Popconfirm,Switch, Table } from 'antd';
+import { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
+import Transfer, { TransferItem, TransferProps } from 'antd/es/transfer';
+import React from 'react';
+import { useEffect, useImperativeHandle, useRef, useState } from 'react';
+
+
+import difference from 'lodash/difference';
+
+import { copyGroupUnit, getReportColumn, getClolumnTableData, addReport, editReport, delData, editReportTbaleData, delLeftReportData } from './service';
+
+
+import './style.less';
+
+import { addReportTableList, getReportListTableData, getReportListType } from '../reportListMana/service';
+import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
+
+
+const IconFont = createFromIconfontCN({
+    scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
+});
+
+var temp_dataSource: any[] = [];
+
+const ReportSetting = () => {
+
+    const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
+    const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
+
+    const [typeList, set_typeList] = useState<any[]>([]);
+    const [showTypeListArr, set_showTypeListArr] = useState<any[]>([]);
+    const [currentSelectedType, set_currentSelectedType] = useState<any | undefined>(undefined);
+
+
+
+    const [dataSource, setDataSource] = useState<any[]>([]);
+    const SortableItem = SortableElement((props: any) => <tr {...props} />);
+    const SortContainer = SortableContainer((props: any) => <tbody {...props} />);
+
+    const [currentEditLeftData, set_currentEditLeftData] = useState<any | undefined>(undefined);
+
+    const [ifEditTable, set_ifEditTable] = useState(false);
+
+    const tableRef = useRef<ActionType>();
+
+    const DragHandle = SortableHandle(() => <img width={16} style={{ cursor: 'pointer' }} src={require('../../../../../static/tuozhuai_icon.png')} alt="" />);
+
+    const column = [
+
+        {
+            title: '列名称',
+            width: 120,
+            dataIndex: 'columnName',
+
+        },
+        {
+            title: '列标题',
+            width: 160,
+            dataIndex: 'columnHeaderText',
+
+        },
+        {
+            title: '主键',
+            width: 120,
+            dataIndex: 'primaryKey',
+            render: (_: any, record: any) => {
+                return <Switch disabled={!ifEditTable} size='small' checked={_} onChange={(bool) => switchChangeHandle(bool, record, 'primaryKey')} />
+            }
+        },
+        {
+            title: '隐藏',
+            width: 120,
+            dataIndex: 'hide',
+            render: (_: any, record: any) => {
+                return <Switch disabled={!ifEditTable} size='small' checked={_} onChange={(bool) => switchChangeHandle(bool, record, 'hide')} />
+            }
+        },
+    ]
+
+    const [tableColumn, set_tableColumn] = useState<ProColumns[] | any[]>(column);
+
+
+
+
+    const getTableData = async (params: any) => {
+        const { reportCode } = params;
+
+        if (reportCode) {
+            const resp = await getClolumnTableData(params);
+            if (resp) {
+
+                setDataSource(resp);
+                temp_dataSource = [...resp];
+
+            }
+
+        }
+
+    }
+
+    const switchChangeHandle = (checked: boolean, record: any, key: string) => {
+
+        const newData = temp_dataSource.map((a: any) => {
+            if (a.id == record.id) {
+                return { ...a, [`${key}`]: checked ? 1 : 0 }
+            }
+            return a
+        });
+
+        setDataSource([...newData]);
+    }
+
+    //获取左侧单元
+    const getPageLeftReports = async () => {
+        const resp = await getReportColumn();
+
+        if (resp) {
+
+            set_typeList(resp);
+            set_showTypeListArr(resp);
+        }
+    }
+
+
+    const updateTable = async (formVal: any, type: 'EDIT' | "ADD" | 'ADD_LEFTDATA'|'EDIT_LEFTDATA') => {
+
+
+        if (type == 'ADD_LEFTDATA') {
+            const resp = await addReport({
+                reportName: formVal.reportName,
+                reportShortName: formVal.reportShortName,
+                reportType: formVal.reportType
+            });
+            if (resp) {
+                getPageLeftReports();
+            }
+        }
+
+    
+
+        if (type == 'EDIT_LEFTDATA') {
+            const resp = await editReport({
+                id: formVal.id,
+                reportName: formVal.reportName,
+                reportShortName: formVal.reportShortName,
+                reportType: formVal.reportType
+            });
+            if (resp) {
+                getPageLeftReports();
+            }
+        }
+
+        if(type == 'EDIT'){
+            // console.log({dataSource,temp_dataSource});
+            // return;
+            let newDataSource = dataSource.map((a:any,index:number)=>{
+                  //更新排序
+                  return {...a,sort:index+1}
+            })
+            const resp = await editReportTbaleData(newDataSource);
+            set_ifEditTable(false);
+            if (resp) {
+                getTableData({ reportCode: currentSelectedType.code });
+            }
+        }
+
+        return true;
+
+    }
+
+    const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' | 'ADD_LEFTDATA'|'EDIT_LEFTDATA' }) => {
+
+
+        const getTrriger = () => {
+            if (type == 'ADD') {
+                return <span className='add'>新增</span>
+            }
+            if (type == 'EDIT') {
+                return <a key="edit" >编辑</a>
+            }
+            if (type == 'ADD_LEFTDATA') {
+                return (
+                    <div className='add'>
+                        <img src={require('../../../../../static/addIcon_black.png')} alt="" />
+                    </div>
+                )
+            }
+            if (type == 'EDIT_LEFTDATA') {
+                return <a key="edit" >编辑</a>
+            }
+        }
+
+        return (
+            <ModalForm
+                title={type == 'ADD_LEFTDATA' ? `新增医疗组` : `编辑医疗组`}
+                width={352}
+                initialValues={type == 'EDIT' ? { ...record } : {}}
+                trigger={
+                    getTrriger()
+                }
+                onFinish={(val) => {
+                    return updateTable(type == 'EDIT' ? { ...record, ...val } : val, type);
+                }}
+            >
+
+                <ProFormText
+                    label='报表名称:'
+                    name='reportName'
+                    rules={[{ required: true, message: '报表名称不能为空!' }]}
+                />
+                <ProFormText
+                    label='报表简称:'
+                    name='reportShortName'
+                    rules={[{ required: true, message: '报表简称不能为空!' }]}
+                />
+                <ProFormSelect
+                    name="reportType"
+                    label="列类型:"
+                    placeholder="请选择"
+                    request={async () => {
+                        const resp = await getReportListType();
+                        if (resp) {
+                            return resp.list.map((a: any) => ({ label: a.name, value: a.code }))
+                        }
+                    }}
+                    rules={[{ required: true, message: '列类型不能为空!' }]}
+                />
+            </ModalForm>
+        )
+    }
+
+
+
+    interface DataType {
+        key: string;
+        title: string;
+        description: string;
+        disabled: boolean;
+        tag: string;
+    }
+
+    interface TableTransferProps extends TransferProps<TransferItem> {
+        dataSource: DataType[];
+        leftColumns: ColumnsType<DataType>;
+        rightColumns: ColumnsType<DataType>;
+        record: any
+    }
+
+
+    const transferTableColumn: any[] = [
+        {
+            title: '列名称',
+            dataIndex: 'name',
+            key: 'name',
+
+        },
+        {
+            title: '列标题',
+            width:120,
+            dataIndex: 'headerText',
+            key: 'headerText',
+            ellipsis:true
+        },
+    ];
+
+    const addReportColumnHandle = () => {
+
+        const ref = React.createRef<{ save: any; }>();
+
+        Modal.confirm({
+            title: `选择报表列`,
+            icon: <></>,
+            width: 750,
+            content: <TableTransfer
+                ref={ref}
+                record={undefined}
+                leftColumns={transferTableColumn}
+                rightColumns={transferTableColumn} dataSource={[]}
+            ></TableTransfer>,
+            onOk: () => {
+                return ref.current && ref.current.save();
+            }
+        })
+    }
+
+    const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, record, ...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 getReportListTableData({pageSize:1000,current:1});
+            if (resp) {
+
+                set_datasource(resp.list);
+
+                // if (record && record.unitInfoVos) {
+
+                //     const defaultSelctedkeys = record.unitInfoVos.map((item: any) => item.unitCode);
+
+                //     setTargetKeys(defaultSelctedkeys);
+                // }
+
+            }
+        }
+
+        const onChange = (nextTargetKeys: string[]) => {
+            setTargetKeys(nextTargetKeys);
+        };
+
+        const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
+            //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
+            setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
+        };
+
+        useImperativeHandle(ref, () => ({
+            save: async () => {
+
+                const needData = datasource.filter(item => targetKeys.includes(item.code));
+
+                const result = needData.map(a => ({
+                    reportCode:currentSelectedType.code,
+                    columnCode:a.code,
+                    columnHeaderText:a.headerText,
+                    columnName:a.name,
+                    sort:dataSource.length+1,
+                    primaryKey:0,
+                    hide:0
+                }));
+
+                // console.log({result,record});
+
+                const resp = await addReportTableList(result);
+                if (resp) {
+                    message.success('添加成功!');
+                    getTableData({ reportCode: currentSelectedType.code });
+                }
+            }
+        }));
+
+        useEffect(() => {
+            getFuncList();
+        }, [])
+
+        return (
+            <Transfer className='TableTransfer' showSearch
+                titles={['待选项', '已选项']}
+                locale={{
+                    itemUnit: '项',
+                    itemsUnit: '项',
+                    searchPlaceholder: '请输入'
+                }}
+                onChange={onChange}
+                onSelectChange={onSelectChange}
+                dataSource={datasource}
+                rowKey={record => record.code}
+                targetKeys={targetKeys}
+                selectedKeys={selectedKeys}
+                filterOption={(inputValue, item) => {
+                    return item.unitName!.indexOf(inputValue) !== -1
+
+                }}
+            >
+                {({
+                    direction,
+                    filteredItems,
+                    onItemSelectAll,
+                    onItemSelect,
+                    selectedKeys: listSelectedKeys,
+                    disabled: listDisabled,
+                }) => {
+
+                    // console.log({ filteredItems, listSelectedKeys,direction });
+                    const columns = direction === 'left' ? leftColumns : rightColumns;
+
+                    const rowSelection: TableRowSelection<TransferItem> = {
+                        getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
+                        onSelectAll(selected, selectedRows) {
+                            const treeSelectedKeys = selectedRows.map(({ code }) => code);
+                            const diffKeys = selected
+                                ? difference(treeSelectedKeys, listSelectedKeys)
+                                : difference(listSelectedKeys, treeSelectedKeys);
+                            onItemSelectAll(diffKeys as string[], selected);
+                        },
+                        onSelect({ code }, selected) {
+                            onItemSelect(code as string, selected);
+                        },
+                        selectedRowKeys: listSelectedKeys,
+                    };
+
+                    return (
+                        <Table
+                            rowSelection={rowSelection}
+                            columns={columns as TransferItem[]}
+                            dataSource={filteredItems}
+                            size="small"
+                            rowKey={'code'}
+                            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 moreItems: MenuProps['items'] = [
+        {
+            key: '1',
+            label: <UpDataActBtn key={'act'} record={currentEditLeftData} type='EDIT_LEFTDATA' />,
+        },
+        {
+            key: '2',
+            label: (
+                <a onClick={async (e)=>{
+                     e.preventDefault();
+                     const resp = await delLeftReportData(currentEditLeftData.id);
+                     if(resp){
+                        getPageLeftReports();
+                     }
+                }}>
+                    删除
+                </a>
+            ),
+        },
+    ];
+
+
+
+    const onSortEnd = useRefFunction(
+        ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => {
+            if (oldIndex !== newIndex) {
+                const newData = arrayMoveImmutable({
+                    array: [...dataSource],
+                    fromIndex: oldIndex,
+                    toIndex: newIndex,
+                }).filter((el) => !!el);
+                setDataSource([...newData]);
+            }
+        },
+    );
+
+    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 (currentSelectedType) {
+            set_tableDataFilterParams({ ...tableDataFilterParams, reportCode: currentSelectedType.code });
+            getTableData({ reportCode: currentSelectedType.code });
+        }
+    }, [currentSelectedType])
+
+    useEffect(() => {
+        if (showTypeListArr.length > 0) {
+            set_currentSelectedType(showTypeListArr[0]);
+            set_tableDataFilterParams({ ...tableDataFilterParams, reportCode: showTypeListArr[0].code });
+        }
+    }, [showTypeListArr]);
+
+    useEffect(() => {
+        if (ifEditTable) {
+            set_tableColumn([{
+                title: '排序',
+                dataIndex: 'sort',
+                width: 60,
+                className: 'drag-visible',
+                render: () => <DragHandle />
+            }, ...column, {
+                title: '操作',
+                key: 'option',
+                width: 120,
+                valueType: 'option',
+                render: (_: any, record: any) => {
+                    return [
+                        <Popconfirm
+                            title="是否确认移除?"
+                            key="del"
+                            onConfirm={() => {delData(record.id);getTableData({ reportCode: currentSelectedType.code });}}
+                        >
+                            <a>删除</a>
+                        </Popconfirm>
+                    ]
+                },
+            }])
+        }else{
+            set_tableColumn(column);
+        }
+    }, [ifEditTable]);
+
+    useEffect(() => {
+        temp_dataSource = [...dataSource];
+    }, [dataSource])
+
+    useEffect(() => {
+        getPageLeftReports();
+    }, [])
+
+
+
+    return (
+        <BMSPagecontainer title={false} className='ReportSetting'>
+            <div className='left'>
+                <div className='toolbar'>
+                    <Input placeholder={'报表名称'} allowClear
+                        suffix={
+                            <IconFont type="iconsousuo" />
+                        }
+                        style={{ width: 156 }}
+                        onChange={(e) => {
+                            const result = typeList.filter(item => item.reportName.indexOf(e.target.value) != -1);
+                            set_showTypeListArr(result);
+                        }}
+
+                    />
+                    <UpDataActBtn key={'act'} record={undefined} type='ADD_LEFTDATA' />
+
+                </div>
+
+                <div className='wrap'>
+                    {
+                        showTypeListArr.map((item, index) => {
+                            return (
+                                <div className={currentSelectedType ? currentSelectedType.id == item.id ? 'type on' : 'type' : 'type'}
+                                    key={index}
+                                    onClick={() => set_currentSelectedType(item)}
+                                >
+                                    <img className='icon' src={require('../../../../../static/reportIcon.png')} alt="" />
+                                    <div className='content'>
+                                        <div className='name'>{item.reportName}</div>
+                                        <div className='sub'>{item.reportTypeName}</div>
+                                    </div>
+
+                                    <Dropdown menu={{ items: moreItems }} placement="bottom" onOpenChange={(bool) => { bool && set_currentEditLeftData(item) }}>
+                                        <div className='more'>
+                                            <img src={require('../../../../../static/more_point_gray.png')} alt="" />
+                                        </div>
+                                    </Dropdown>
+                                </div>
+                            )
+                        })
+                    }
+                </div>
+            </div>
+            <div className='right'>
+                <div className='toolBar'>
+                    <div className='filter'>
+                        {/* <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'>
+                        {!ifEditTable && <span className='manaBtn' onClick={() => set_ifEditTable(true)}>管理列</span>}
+                        {
+                            ifEditTable && (
+                                <div className='inner'>
+                                    <span className='save' onClick={()=>updateTable(undefined,'EDIT')}>保存</span>
+                                    <span className='add' onClick={() => addReportColumnHandle()}>添加列</span>
+                                </div>
+                            )
+                        }
+                    </div>
+                </div>
+                <div style={{ marginTop: 16 }}>
+                    {currentSelectedType && <BMSTable actionRef={tableRef} columns={tableColumn}
+                        rowKey='id' dataSource={dataSource}
+                        pagination={false}
+                        components={{
+                            body: {
+                                wrapper: DraggableContainer,
+                                row: DraggableBodyRow,
+                            },
+                        }}
+                    />}
+                </div>
+            </div>
+        </BMSPagecontainer>
+    )
+}
+
+
+export default ReportSetting;

+ 119 - 0
src/pages/setting/reportSet/reportSetting/service.ts

@@ -0,0 +1,119 @@
+/*
+ * @Author: code4eat awesomedema@gmail.com
+ * @Date: 2023-03-07 11:12:10
+ * @LastEditors: code4eat awesomedema@gmail.com
+ * @LastEditTime: 2023-04-07 12:06:23
+ * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicMana/service.ts
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+ */
+
+
+
+
+import { getManaIndexGroup } from '@/pages/budgetMana/monthlyDataCheck/service';
+import { request } from 'umi';
+
+
+//获取左侧报表数据
+
+export const getReportColumn = () => {
+  return request('/performance/report/getReport', {
+    method: 'GET',
+  });
+};
+
+//获取表格数据
+
+export type  ClolumnTableDataType = {
+  id:number;
+  
+}
+
+export const getClolumnTableData = (params:{reportCode:string}) => {
+    return request('/performance/report/getReportColumn', {
+      method: 'GET',
+      params:{...params}
+    });
+};
+
+
+//新增报表
+
+
+export const addReport = (data:any) => {
+  return request('/performance/report/addReport', {
+    method: 'POST',
+    data
+  });
+};
+
+
+//编辑报表
+export const editReport = (data:any) => {
+  return request('/performance/report/editReport', {
+    method: 'POST',
+    data
+  });
+};
+
+
+
+
+
+
+//编辑表格数据
+
+export const editReportTbaleData = (data:any) => {
+    return request('/performance/report/editReportColumn', {
+      method: 'POST',
+      data
+    });
+};
+
+
+//删除表格操作
+export const delData = (id:number) => {
+    return request('/performance/report/deleteReportColumn', {
+      method: 'POST',
+      params:{id}
+    });
+};
+
+//删除左侧报表
+export const delLeftReportData = (id:number) => {
+  return request('/performance/report/deleteReport', {
+    method: 'POST',
+    params:{id}
+  });
+};
+
+
+//获取单元分组
+export const  getUnitGroupList= () => {
+    return getManaIndexGroup()
+};
+
+//获取分组下的单元
+export const getUnitUnderGroupById = (groupId:number) => {
+  return request('/performance/managerIndicator/getGroupUnit', {
+    method: 'GET',
+    params:{groupId}
+  });
+};
+
+
+//复制
+
+export type CopyGroupUnitDataType = {
+  unitInfos:{unitCode:string,unitName:string}[],
+  value:{code:string,targetValue:string}[]
+}
+
+export const copyGroupUnit = (data:CopyGroupUnitDataType) => {
+  return request('/performance/managerIndicator/copyGroupUnit', {
+    method: 'POST',
+    data
+  });
+};
+
+

+ 181 - 0
src/pages/setting/reportSet/reportSetting/style.less

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

BIN
static/addIcon_black.png


BIN
static/more_point_gray.png


BIN
static/reportIcon.png


BIN
static/tuozhuai_icon.png