Przeglądaj źródła

字典/参数管理

zsw007 3 lat temu
rodzic
commit
afaa351ec2

+ 1 - 0
.gitignore

@@ -2,6 +2,7 @@
 
 # dependencies
 /node_modules
+.history/
 /.pnp
 .pnp.js
 

+ 1 - 1
craco.config.js

@@ -1,5 +1,4 @@
 /*******覆盖create-react-app默认配置******/
-
 const path = require('path');
 const resolve = dir => path.resolve(__dirname,dir);
 const CracoLessPlugin = require('craco-less');
@@ -18,6 +17,7 @@ module.exports = {
     devServer: (devServerConfig, { env, paths, proxy, allowedHost }) => {
         devServerConfig.proxy={
             '/security-center':'http://192.168.2.237:8871',
+            //'/security-center':'http://192.168.2.237:8871',
             pathRewrite: {'/security-center' : ''},
             changeOrigin: true
         };

+ 4 - 1
src/api/index.js

@@ -9,6 +9,8 @@ const post=(url,data)=>{
         data
     });
 };
+
+// 表单 form封装接口
 const xPost=(url,data)=>{
     let param = new URLSearchParams();
     for(let i in data){
@@ -21,6 +23,7 @@ const xPost=(url,data)=>{
         data:param
     });
 };
+
 // 导出
 const expJson = (url,data) =>{
     return axios({
@@ -60,7 +63,7 @@ function interceptors(){
     //拦截响应
     axios.interceptors.response.use(function (res) {
         const code = res.data.code;
-        if (code===401||code===403) {   //401/403返回登录
+        if (code===401) {   //401/403返回登录
             localStorage.removeItem("token");
             localStorage.removeItem("systemId");
             localStorage.removeItem("hospitalId");

+ 14 - 0
src/api/request.js

@@ -32,8 +32,22 @@ const request = {
     disableUser: '/security-center/userManage/disableUser',//禁用用户
     deleteUser: '/security-center/userManage/deleteUser',//删除用户
     resetPasswordUser: '/security-center/userManage/resetPassword',//重置密码
+
+    // 字典管理相关接口
+    getDictionary: '/security-center/dictionaryManage/getDictionary',//字典管理列表
+    getCodeCategory: '/security-center/dictionaryManage/getCodeCategory',//字典管理代码类别
+    deleteDictionary: '/security-center/dictionaryManage/deleteDictionary',//删除字典管理
+    updateDictionary: '/security-center/dictionaryManage/updateDictionary',//修改字典
+    addDictionary: '/security-center/dictionaryManage/addDictionary',//添加用户
     
 
+    // 参数管理相关接口
+    getHospitalSet: '/security-center/hospitalSetManage/getHospitalSet',//参数管理列表
+    getHospitalNames: '/security-center/hospitalSetManage/getHospitalNames',//所属组织
+    deleteHospitalSet: '/security-center/hospitalSetManage/deleteHospitalSet',//删除参数
+    updateHospitalSet: '/security-center/hospitalSetManage/updateHospitalSet',//修改参数
+    addHospitalSet: '/security-center/hospitalSetManage/addHospitalSet',//添加参数
+
 
     //数据权限相关接口
     getDataAuthPage: '/security-center/dataAuthManage/getDataAuthPage',//数据权限列表

+ 1 - 1
src/components/AFilterBar/index.js

@@ -8,7 +8,7 @@ const { Option } = Select;
 function AdminFilter(){
     return (
         <div className="filter-box">
-
+                11111
         </div>
     )
 }

+ 7 - 2
src/components/AMenu/index.js

@@ -14,6 +14,8 @@ import LoginLog from "../LoginLog";
 import ExceptionLog from "../ExceptionLog";
 import MyMessage from "../MyMessage";
 import MsgManage from "../MsgManage";
+import ParaManager from "../ParaManager";
+import DictManager from "../DictManager";
 import apiObj from '@api/index';
 
 const { post, api } = apiObj;
@@ -28,6 +30,8 @@ const pageMap = {
     'QXGL-SJQX': <DataManager />,
     'QXGL-BQQX': <InpaManager />,
     'XTSZ-GNGL': <FuncManager />,
+    'XTSZ-SCGL': <ParaManager />, // 参数管理
+    'XTSZ-ZDGL': <DictManager />, // 字典管理
     'RZGL-CZRZ': <OperationLog />,
     'RZGL-DLRZ': <LoginLog />,
     'RZGL-YCRZ': <ExceptionLog />,
@@ -35,9 +39,9 @@ const pageMap = {
     'ZNTZ-TZGL': <MsgManage />,
 }
 
-let firstMenuPage = {};         //第一个菜单,自动激活时用
+let firstMenuPage = {}; //第一个菜单,自动激活时用
 function AMenu() {
-    const [menuList, setMenuList] = useState([]);        //菜单列表数据
+    const [menuList, setMenuList] = useState([]); //菜单列表数据
     const dispatch = useDispatch();
     //当前选中的菜单
     const { activeTab, panes } = useSelector(state => {
@@ -64,6 +68,7 @@ function AMenu() {
             if (res.data.code === 200) {
                 const data = res.data.data;
                 const menuData = data.showMenuInfo;
+                console.log('菜单导航:', menuData);
                 setMenuList(menuData);
                 firstMenuPage = menuData[0].children ? menuData[0].children[0] : menuData[0]
                 

+ 263 - 0
src/components/DictManager/AddDict.js

@@ -0,0 +1,263 @@
+import React, {
+    useState, useEffect, useContext
+  } from 'react';
+  import { Modal, Form, Input, Select, Button, Switch, TreeSelect, message, Space } from 'antd';
+  import apiObj from '@api/index';
+  import utils from '@utils/index'
+  import UserContext from './dict-context';
+  import { useSelector } from 'react-redux'
+  import Item from 'antd/lib/list/Item';
+  const { post, api, xPost } = apiObj;
+  const { Option, OptGroup } = Select;
+  const { organizationData } = utils;
+  const { SHOW_PARENT } = TreeSelect;
+  const { TextArea } = Input;
+  function AddUser(props) {
+    useEffect(() => {
+      getHospitalTree();
+      getCreateRoles();
+    }, []);
+    const [form] = Form.useForm();
+    const { id, type, formData, roleList } = useContext(UserContext);
+    const [treeData, setTreeData] = useState([]);
+    const [treeRloe, setTreeRloe] = useState([]);
+    const [addHospitalTreeVO, setAddHospitalTreeVO] = useState({
+      depts: [],
+      hospitals: []
+    });
+    const staticInfo = useSelector(state => {
+      return state.staticInfo;
+    });
+    const { titleList } = staticInfo;
+    const initialValues = formData;
+    console.log('需修改的数据:',formData);
+    console.log(form.getFieldsValue())
+    let addHospitalTreeVOs = {
+      depts: [],
+      hospitals: [],
+    }
+    //获取当前用户组织
+    function getHospitalTree() {
+      post(api.getHospitalTree).then((res) => {
+        if (res.data.code === 200) {
+          const data = res.data.data;
+          const treeData = organizationData(data)
+          setTreeData(treeData)
+        }
+      })
+    }
+    //获取当前用于所属角色
+    function getCreateRoles() {
+      const params = {
+        softwareId: ''
+      }
+      xPost(api.getCreateRoles, params).then((res) => {
+        if (res.data.code === 200) {
+          const data = res.data.data;
+          console.log(data);
+          
+          let arr = JSON.parse(JSON.stringify(data).replace(/name/g, 'title').replace(/id/g, 'value'))
+          setTreeRloe(arr)
+        }
+      })
+    }
+    // 去重
+    function unique(arr) {
+      return arr.filter(function (item, index, arr) {
+        return arr.indexOf(item, 0) === index;
+      });
+    }
+    function swichChange(val) {
+      form.setFieldsValue({ status: val ? 1 : 0 })
+    }
+    // 判断元素存在格式
+    function getSameNum(val, arr) {
+      let processArr = arr.filter(function (value) {
+        return value == val;
+      })
+      return processArr.length;
+    }
+    //递归获取科室
+    function gethospitals(arr, val) {
+      arr.forEach(item => {
+        if (item.value == val) {
+          if (item.children) {
+            getdepts(item.children)
+          }
+          if (item.children && item.depts) {
+            item.children.forEach(item => {
+              addHospitalTreeVOs.depts.push(item.value.split('-')[1])
+            })
+          }
+        } else {
+          if (item.children) {
+            gethospitals(item.children, val)
+          }
+        }
+      })
+    }
+    //递归获取医院
+    function getdepts(arr) {
+      arr.forEach(item => {
+        if (JSON.stringify(item.value).indexOf('-') < 0) {
+          addHospitalTreeVOs.hospitals.push(item.value)
+        }
+        if (item.children && item.depts) {
+          item.children.forEach(it => {
+            addHospitalTreeVOs.depts.push(it.value.split('-')[1])
+          })
+          return
+        }
+        if (item.children) {
+  
+          getdepts(item.children)
+        }
+      })
+    }
+    const onChange = value => {
+      value.forEach(it => {
+        if (JSON.stringify(it).indexOf('-') > 0) {
+          addHospitalTreeVOs.depts.push(it.split('-')[1])
+        } else {
+          addHospitalTreeVOs.hospitals.push(it)
+          gethospitals(treeData, it)
+        }
+      })
+      setAddHospitalTreeVO(addHospitalTreeVOs)
+      console.log(form.getFieldsValue())
+    };
+    const onChangeRloe = value => {
+      form.setFieldsValue({ roles: value })
+    };
+    
+    const onFinish = values => {
+      let params = values
+      addHospitalTreeVO.hospitals = unique(addHospitalTreeVO.hospitals)
+      params.addHospitalTreeVO = addHospitalTreeVO
+      if (type == 2) {
+        params.id = id
+        editUser(params)
+      } else {
+        addUser(params)
+      }
+  
+    };
+    function addUser(param) {
+      post(api.addHospitalSet, param).then((res) => {
+        if (res.data.code === 200) {
+          props.userChange()
+          message.success(res.data.message);
+          form.resetFields();
+        } else {
+          message.error(res.data.message);
+        }
+      })
+    }
+    function editUser(param) {
+      post(api.updateDictionary, param).then((res) => {
+        console.log('修改字典管理:', res);
+        if (res.data.code === 200) {
+          props.userChange()
+          message.success(res.data.message);
+          form.resetFields();
+        } else {
+          message.error(res.data.message);
+        }
+      })
+    }
+    function cancel() {
+      props.userChange()
+    }
+  
+    return (
+      <>
+        <Form
+          labelCol={{ span: 6 }}
+          wrapperCol={{ span: 16 }}
+          form={form}
+          name="register"
+          onFinish={onFinish}
+          initialValues={initialValues}
+        >
+          <Form.Item
+            name="groupType"
+            label="代码类别"
+            rules={[
+              {
+                required: true,
+                message: '请输入代码类别',
+              },
+            ]}
+          >
+            <Input placeholder="请输入字典编码" autoComplete='off'/>
+  
+          </Form.Item>
+          <Form.Item
+            name="val"
+            label="字典编码"
+            rules={[
+              {
+                required: true,
+                message: '请输入字典编码',
+              },
+            ]}
+          >
+            <Input placeholder="请输入字典编码" autoComplete='off'/>
+  
+          </Form.Item>
+          <Form.Item
+            name="name"
+            label="代码名称"
+            rules={[{ required: true, message: '请输入代码名称', whitespace: true }]}
+          >
+            <Input placeholder="请输入代码名称" autoComplete='off'/>
+  
+          </Form.Item>
+
+          <Form.Item
+            name="remark"
+            label="字典说明"
+            rules={
+              [
+                { required: true, message: '请选择字典说明' },
+                {max:50, message: '字典说明不能大于50个字符'}
+              ]
+            }
+          >
+            <TextArea placeholder='字典说明不能超过50个字符' rows={4} />
+          </Form.Item>
+
+          <Form.Item
+            name="status"
+            valuePropName="checked"
+            label="当前状态"
+          >
+            <Switch onChange={swichChange} />
+  
+          </Form.Item>
+          {type == 3 ?
+            <Form.Item wrapperCol={{ offset: 10, span: 16 }}>
+              <Space size="middle">
+                <Button type="primary" onClick={e => cancel()}>
+                  返回
+              </Button>
+              </Space>
+            </Form.Item>
+            :
+            <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
+              <Space size="middle">
+                <Button htmlType="button" onClick={e => cancel()}>
+                  取消
+              </Button>
+                <Button type="primary" htmlType="submit">
+                  保存
+              </Button>
+              </Space>
+            </Form.Item>}
+  
+        </Form>
+      </>
+    );
+  }
+  
+  export default AddUser;

+ 4 - 0
src/components/DictManager/dict-context.js

@@ -0,0 +1,4 @@
+import {createContext} from 'react';
+const DictContext = createContext(null);
+
+export default DictContext;

+ 380 - 0
src/components/DictManager/index.js

@@ -0,0 +1,380 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { Form, Input, Button, Table, Select, Pagination, Space, Menu, Dropdown, Modal, Breadcrumb, message, Row, Col } from 'antd';
+import { DownOutlined, PlusOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
+import AddUser from './AddDict'
+import '@common/common.less';
+import { useSelector } from 'react-redux'
+import apiObj from '@api/index';
+import UserContext from './dict-context';
+import utils from '@utils/index'
+const { getValueFromEvent } = utils;
+const { post, api, xPost } = apiObj;
+const { Option } = Select;
+function DictManager() {
+  useEffect(() => {
+    getDictionary();
+    getCodeCategory();
+  }, []);
+  const [dictList, setDictList] = useState([]);
+  const [title, setTitle] = useState("");
+  const [visible, setVisible] = useState(false);
+  const [id, setDictId] = useState("");
+  const [val, setDictVal] = useState("");
+  const [groupType, setDictGroupType] = useState([]);
+  const [status, setDictStatus] = useState("");
+  const [remark, setDictRemark] = useState("");
+  const [msvisible, setMsvisible] = useState(false);
+  const [modalType, setModalType] = useState("");
+  const [type, setType] = useState("");
+  const [formData, setFormData] = useState(null);
+  const [username, setUsername] = useState(null);
+  const [roleList, setRoleList] = useState([]);
+  const [size, setSize] = useState(15);
+  const [groupTypeList, setGroupTypeList] = useState([]);
+  const [total, setTotal] = useState(0);
+  const [current, setCurrent] = useState(1);
+  const [params, setParams] = useState({
+    pages: 1,
+    current: 1,
+    size: 15,
+    name: '',
+    groupType: ''
+  });
+  const [query, setQuery] = useState({
+    groupType: ''
+  });
+  const [form] = Form.useForm();
+  const tipText = {
+    1: '确定要删除该字典?',
+    2: '禁用后该用户将无法登录,确定要禁用该字典',
+    3: '确定要重置该用户密码?',
+  };
+  const staticInfo = useSelector(state => {
+    return state.staticInfo;
+  });
+  let list = []
+  let data = {
+    pages: 1,
+    current: 1,
+    size: size
+  }
+  const {statusList } = staticInfo;
+
+  //新增弹窗
+  const showModal = (title, type, flag, id, groupType, val,name,remark, status) => {
+    setVisible(type);
+    setType(flag)
+    setDictId(id)
+    setDictGroupType(groupType)
+    setDictVal(val)
+    setTitle(title);
+    setDictRemark(remark)
+    console.log('groupType', status)
+    setDictStatus(status)
+    if (flag == 1) {
+      setFormData({
+        status: '1'
+      })
+    }
+    if ( flag == 2) {
+      setFormData({
+        id: id,
+        groupType: groupType,
+        val: val,
+        name: name,
+        remark: remark,
+        status: '1',
+      })
+    }
+  }
+
+  //表格数据
+  function getDictionary(param) {
+    post(api.getDictionary, param || params).then((res) => {
+      if (res.data.code === 200) {
+        const data = res.data.data;
+        setDictList(data.records);
+        setTotal(data.total)
+      }
+    })
+  }
+
+  // 代码类别 
+  function getCodeCategory() {
+    xPost(api.getCodeCategory, query).then((res) => {
+      console.log('字典管理代码类别:', res);
+      if (res.data.code === 200) {
+        const groupTypeList = res.data.data;
+        setGroupTypeList(groupTypeList)
+      }
+    })
+  }
+
+  // 处理组织结构数据回显
+  function getHospitals(arr) {
+    arr.forEach((item, i, array) => {
+      item.value = item.hospitalId
+      item.title = item.hospitalName
+      if (!item.children && item.depts) {
+        item.depts.forEach(it => {
+          it.value = item.parentId + '-' + it.deptId
+          if (it.relation == 1) {
+            list.push(it.value)
+          }
+        })
+      }
+      if (item.type != 0 && item.relation == 1) {
+        list.push(item.value)
+        console.log(list)
+      }
+      if (item.children) {
+        getHospitals(item.children)
+      }
+    })
+    return list
+  }
+
+  // 禁用/启用接口
+  function disableUser(id, status) {
+    const param = { id: id, status: status };
+    xPost(api.disableUser, param).then((res) => {
+      if (res.data.code === 200) {
+        getDictionary();
+        setMsvisible(false);
+        message.success((status ? '启用' : '禁用') + "成功");
+      } else {
+        message.warning(res.data.msg || '操作失败');
+      }
+    }).catch(() => {
+      message.error("接口出错");
+    });
+  }
+
+  //重置密码
+  function onResetPsd(id) {
+    const param = { id: id };
+    xPost(api.resetPasswordUser, param).then((res) => {
+      if (res.data.code === 200) {
+        getDictionary();
+        message.success("重置成功");
+      } else {
+        message.warning(res.data.msg || '操作失败');
+      }
+    }).catch(() => {
+      message.error("接口出错");
+    });
+  }
+
+  //删除
+  function deleteDictionary() {
+    const param = { id: id };
+    xPost(api.deleteDictionary, param).then((res) => {
+      if (res.data.code === 200) {
+        getDictionary();
+        setMsvisible(false);
+        message.success("删除成功");
+      } else {
+        message.warning(res.data.msg || '操作失败');
+      }
+    }).catch(() => {
+      message.error("接口出错");
+    });
+  }
+
+  function onSizeChange(current, pageSize) {
+    params.current = current
+    params.size = pageSize
+    setSize(pageSize)
+    setCurrent(current)
+    setParams(params)
+    setQuery(query)
+    getDictionary()
+  }
+  function changePage(page, pageSize) {
+    params.current = page
+    params.size = pageSize
+    setCurrent(page)
+    setParams(params)
+    setQuery(query)
+    getDictionary()
+  }
+  const onFinish = (value) => {
+    const param = {
+      ...data,
+      ...value
+    }
+
+    console.log(123);
+    setCurrent(1)
+    setParams(param)
+    setQuery(param)
+    getDictionary(param);
+  };
+  const onReset = () => {
+    // setCurrent(1)
+    // setParams(data)
+    // setQuery(query)
+    form.resetFields();
+    getDictionary(data);
+  };
+  const messageBox = (type, id) => {
+    setMsvisible(true)
+    setDictId(id)
+    setModalType(type)
+  }
+
+  //提示框确认事件
+  function handleOk() {
+    if (modalType == 1) {
+      deleteDictionary(id)
+    } else if (modalType == 2) {
+      disableUser(id, 0)
+    } else if (modalType == 3) {
+      onResetPsd(id);
+    }
+  }
+  //提示框取消
+  function handleCancel() {
+    setMsvisible(false);
+  }
+  function cancel() {
+    setVisible(false)
+    setFormData(null)
+  }
+  function userChange() {
+    let val = form.getFieldsValue()  // 页面刷新
+    const param = {
+      ...data,
+      //...value
+      ...val
+    }
+    getDictionary(param)
+    setVisible(false)
+  }
+
+  // 表格渲染
+  const columns = [
+    { title: '代码类别', dataIndex: 'groupType', key: 'index' },
+    { title: '字典编码', dataIndex: 'val', key: 'index' },
+    { title: '代码名称', dataIndex: 'name', key: 'index' },
+    { title: '字典说明', dataIndex: 'remark', key: 'index' },
+    {title: '状态', dataIndex: 'status', key: 'status'},
+    {
+      title: '操作', dataIndex: 'key', render: (text, record) => (
+        <Space size="middle">
+          <a onClick={e => showModal(
+            '修改字典', 
+            true, 2, 
+            record.id,
+            record.groupType,
+            record.val,
+            record.name,
+            record.remark,
+            record.status,
+            )} >修改</a>
+          <a className='delete' onClick={() => messageBox(1, record.id)}>删除</a>
+        </Space>
+      )
+    }
+  ]
+
+  return (
+    // 搜索框
+    <div className="wrapper">
+      <div className="filter-box">
+        <Form
+          form={form}
+          name="normal_login"
+          onFinish={onFinish}
+          initialValues={{ status: '' }}
+        >
+          <Row gutter={24}>
+          <Col span={5} key={0}>
+              <Form.Item name="groupType" label="代码类别">
+                <Select
+                  allowClear
+                >
+                  {groupTypeList.map((item) => {
+                    return (
+                      <Option value={item} key={item}>{item}</Option>
+                    )
+                  })}
+                </Select>
+              </Form.Item>
+            </Col>
+            <Col span={5} key={1}>
+              <Form.Item label="代码名称" name="name" getValueFromEvent={getValueFromEvent}>
+                <Input placeholder="代码名称" autoComplete='off'/>
+              </Form.Item>
+            </Col>
+            
+            <Col span={6} key={3}>
+              <Form.Item>
+                <Button type="primary" htmlType="submit">
+                  查询
+                </Button>
+                <Button onClick={onReset}>
+                  重置
+                </Button>
+              </Form.Item>
+            </Col>
+          </Row>
+        </Form>
+      </div>
+
+      <div className="table">
+        <div className="table-header">
+          <h2 className="table-title">字典管理</h2>
+          <Button type="primary" icon={<PlusOutlined />} onClick={e => showModal('新增字典', true, 1)}>新增字典</Button>
+        </div>
+
+        <Table
+          columns={columns}
+          scroll={{ y: 'calc(100vh - 320px)' }}
+          dataSource={dictList}
+          rowKey={record => record.id + record.name}
+          pagination={{
+            current: current,
+            pageSize: size,
+            size: 'small',
+            showSizeChanger: true,
+            pageSizeOptions: ['15', '30', '60', '120'],
+            showTotal: (total, range) => `第${range[0]}-${range[1]} 条/共 ${total} 条数据`,
+            onShowSizeChange: (current, pageSize) => onSizeChange(current, pageSize), // 改变每页数量时更新显示
+            onChange: (page, pageSize) => changePage(page, pageSize),//点击页码事件
+            total: total
+          }} />
+      </div>
+      {visible && formData ?
+        <Modal
+          title={title}
+          okText='确定'
+          cancelText='取消'
+          width={'45%'}
+          visible={visible}
+          onCancel={cancel}
+          footer={null}
+          forceRender={true}
+        >
+          <UserContext.Provider value={{ id, type, formData, dictList }}>
+            <AddUser userChange={userChange} />
+          </UserContext.Provider>
+
+        </Modal>
+        : ''}
+      <Modal
+        title="提示"
+        okText='确定'
+        cancelText='取消'
+        width={400}
+        visible={msvisible}
+        onOk={handleOk}
+        onCancel={handleCancel}
+      >
+        <p>{tipText[modalType]}</p>
+      </Modal>
+    </div >
+  )
+}
+
+export default DictManager;

+ 1 - 0
src/components/OrgManager/index.js

@@ -61,6 +61,7 @@ function OrgManager() {
         post(api.getHospitalListInfo, param).then((res) => {
             if (res.data.code === 200) {
                 let data = res.data.data
+                console.log('组织列表数据:', data);
                 let obj = {};
                 if (orgType == 4) {
                     data.map((it, i) => {

+ 1 - 1
src/components/PageLayout/index.js

@@ -27,7 +27,7 @@ function PageLayout(){
         post(api.getManagerBoxInfo).then((res) => {
             if (res.data.code === 200) {
                 const data = res.data.data;
-                dispatch(setHisTypeList(data[43]||data[45]));       //非单家医院为医院类型43,单家医院为病区45
+                dispatch(setHisTypeList(data[43]||data[45])); //非单家医院为医院类型43,单家医院为病区45
                 dispatch(setStatusList(data[47]));
                 dispatch(setTitleList(data[40]));
                 dispatch(setDataList(data[48]));

+ 278 - 0
src/components/ParaManager/AddPara.js

@@ -0,0 +1,278 @@
+import React, {
+  useState, useEffect, useContext
+} from 'react';
+import { Modal, Form, Input, Select, Button, Switch, TreeSelect, message, Space } from 'antd';
+import apiObj from '@api/index';
+import utils from '@utils/index'
+import UserContext from './para-context';
+import { useSelector } from 'react-redux'
+import Item from 'antd/lib/list/Item';
+const { post, api, xPost } = apiObj;
+const { Option, OptGroup } = Select;
+const { organizationData } = utils;
+const { SHOW_PARENT } = TreeSelect;
+const { TextArea } = Input;
+function AddUser(props) {
+  useEffect(() => {
+    getHospitalTree();
+    getCreateRoles();
+  }, []);
+  const [form] = Form.useForm();
+  const { id, type, formData, roleList } = useContext(UserContext);
+  const [treeData, setTreeData] = useState([]);
+  const [treeRloe, setTreeRloe] = useState([]);
+  const [hospitalNamesList, setHospitalNamesList] = useState([]);
+  const [addHospitalTreeVO, setAddHospitalTreeVO] = useState({
+    depts: [],
+    hospitals: []
+  });
+  const staticInfo = useSelector(state => {
+    return state.staticInfo;
+  });
+  const { titleList } = staticInfo;
+  const initialValues = formData;
+  console.log(formData);
+  console.log(form.getFieldsValue())
+  let addHospitalTreeVOs = {
+    depts: [],
+    hospitals: [],
+  }
+  //获取当前用户组织
+  function getHospitalTree() {
+    post(api.getHospitalTree).then((res) => {
+      if (res.data.code === 200) {
+        const data = res.data.data;
+        const treeData = organizationData(data)
+        setTreeData(treeData)
+      }
+    })
+  }
+  function addAttr(data) {
+    for (var j = 0; j < data.length; j++) {
+      data[j].title = data[j].name //添加title属性
+      data[j].key = data[j].code //添加key属性
+      if (data[j].children.length > 0) {
+        addAttr(data[j].children)
+      }
+    }
+    return data
+  }
+  //获取当前用于所属角色
+  function getCreateRoles() {
+    const params = {
+      softwareId: ''
+    }
+    xPost(api.getCreateRoles, params).then((res) => {
+      if (res.data.code === 200) {
+        const data = res.data.data;
+        console.log(data);
+        
+        let arr = JSON.parse(JSON.stringify(data).replace(/name/g, 'title').replace(/id/g, 'value'))
+        setTreeRloe(arr)
+      }
+    })
+  }
+  // 去重
+  function unique(arr) {
+    return arr.filter(function (item, index, arr) {
+      return arr.indexOf(item, 0) === index;
+    });
+  }
+  function swichChange(val) {
+    form.setFieldsValue({ status: val ? 1 : 0 })
+  }
+  // 判断元素存在格式
+  function getSameNum(val, arr) {
+    let processArr = arr.filter(function (value) {
+      return value == val;
+    })
+    return processArr.length;
+  }
+  //递归获取科室
+  function gethospitals(arr, val) {
+    arr.forEach(item => {
+      if (item.value == val) {
+        if (item.children) {
+          getdepts(item.children)
+        }
+        if (item.children && item.depts) {
+          item.children.forEach(item => {
+            addHospitalTreeVOs.depts.push(item.value.split('-')[1])
+          })
+        }
+      } else {
+        if (item.children) {
+          gethospitals(item.children, val)
+        }
+      }
+    })
+  }
+  //递归获取医院
+  function getdepts(arr) {
+    arr.forEach(item => {
+      if (JSON.stringify(item.value).indexOf('-') < 0) {
+        addHospitalTreeVOs.hospitals.push(item.value)
+      }
+      if (item.children && item.depts) {
+        item.children.forEach(it => {
+          addHospitalTreeVOs.depts.push(it.value.split('-')[1])
+        })
+        return
+      }
+      if (item.children) {
+        getdepts(item.children)
+      }
+    })
+  }
+  const onChange = value => {
+    value.forEach(it => {
+      if (JSON.stringify(it).indexOf('-') > 0) {
+        addHospitalTreeVOs.depts.push(it.split('-')[1])
+      } else {
+        addHospitalTreeVOs.hospitals.push(it)
+        gethospitals(treeData, it)
+      }
+    })
+    setAddHospitalTreeVO(addHospitalTreeVOs)
+    console.log(form.getFieldsValue())
+  };
+  const onChangeRloe = value => {
+    form.setFieldsValue({ roles: value })
+  };
+  
+  const onFinish = values => {
+    let params = values
+    addHospitalTreeVO.hospitals = unique(addHospitalTreeVO.hospitals)
+    params.addHospitalTreeVO = addHospitalTreeVO
+    if (type == 2) {
+      params.id = id
+      editUser(params)
+    } else {
+      addUser(params)
+    }
+
+  };
+  function addUser(param) {
+    post(api.addDictionary, param).then((res) => {
+      if (res.data.code === 200) {
+        props.userChange()
+        message.success(res.data.message);
+        form.resetFields();
+      } else {
+        message.error(res.data.message);
+      }
+    })
+  }
+  function editUser(param) {
+    post(api.updateHospitalSet, param).then((res) => {
+      console.log('修改字典管理:', res);
+      if (res.data.code === 200) {
+        props.userChange()
+        message.success(res.data.message);
+        form.resetFields();
+      } else {
+        message.error(res.data.message);
+      }
+    })
+  }
+  function cancel() {
+    props.userChange()
+  }
+
+  return (
+    <>
+      <Form
+        labelCol={{ span: 6 }}
+        wrapperCol={{ span: 16 }}
+        form={form}
+        name="register"
+        onFinish={onFinish}
+        initialValues={initialValues}
+      >
+        <Form.Item
+          name="addHospitalTreeVO"
+          label="所属组织"
+          rules={[{ required: true, message: '请选择所属组织' }]}
+        >
+          <TreeSelect
+            showSearch={false}
+            treeData={treeData}
+            onChange={onChange}
+            maxTagCount={1}
+            treeCheckable
+            showCheckedStrategy={SHOW_PARENT}
+            placeholder="请选择组织"
+            style={{ width: '100%' }}
+          />
+        </Form.Item>
+        <Form.Item
+          name="name"
+          label="参数名"
+          rules={[
+            {
+              required: true,
+              message: '请输入参数名',
+            },
+          ]}
+        >
+          <Input placeholder="请输入参数名" autoComplete='off'/>
+
+        </Form.Item>
+        <Form.Item
+          name="val"
+          label="参数值"
+          rules={[{ required: true, message: '请输入参数值', whitespace: true }]}
+        >
+          <Input placeholder="请输入参数值" autoComplete='off'/>
+
+        </Form.Item>
+
+        <Form.Item
+          name="code"
+          label="参数说明"
+          rules={
+            [
+              { required: true, message: '请输入参数说明' }
+            ]
+          }
+        >
+          <TextArea placeholder='请输入参数说明' rows={4} />
+        </Form.Item>
+
+        <Form.Item
+          name="remark"
+          label="参数描述"
+          rules={
+            [
+              { required: true, message: '请输入参数描述' }
+            ]
+          }
+        >
+            <TextArea placeholder='请输入参数说明' rows={4} />
+        </Form.Item>
+        {type == 3 ?
+          <Form.Item wrapperCol={{ offset: 10, span: 16 }}>
+            <Space size="middle">
+              <Button type="primary" onClick={e => cancel()}>
+                返回
+            </Button>
+            </Space>
+          </Form.Item>
+          :
+          <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
+            <Space size="middle">
+              <Button htmlType="button" onClick={e => cancel()}>
+                取消
+            </Button>
+              <Button type="primary" htmlType="submit">
+                保存
+            </Button>
+            </Space>
+          </Form.Item>}
+
+      </Form>
+    </>
+  );
+}
+
+export default AddUser;

+ 460 - 0
src/components/ParaManager/index.js

@@ -0,0 +1,460 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { Form, Input, Button, Table, Select, TreeSelect, Pagination, Space, Menu, Dropdown, Modal, Breadcrumb, message, Row, Col } from 'antd';
+import { DownOutlined, PlusOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
+import AddUser from './AddPara'
+import '@common/common.less';
+import { useSelector } from 'react-redux'
+import apiObj from '@api/index';
+import UserContext from './para-context';
+import utils from '@utils/index'
+const { getValueFromEvent } = utils;
+const { post, api, xPost } = apiObj;
+const { Option } = Select;
+function DictManager() {
+  useEffect(() => {
+    getHospitalSet();
+    getHospitalTree();
+  }, []);
+  const [dictList, setDictList] = useState([]);
+  const [title, setTitle] = useState("");
+  const [visible, setVisible] = useState(false);
+  const [id, setParaId] = useState("");
+  const [val, setParaVal] = useState("");
+  const [hospitalName, setHospitalName] = useState([]);
+  const [code, setParaCode] = useState("");
+  const [remark, setParaRemark] = useState("");
+  const [msvisible, setMsvisible] = useState(false);
+  const [modalType, setModalType] = useState("");
+  const [type, setType] = useState("");
+  const [formData, setFormData] = useState(null);
+  const [username, setUsername] = useState(null);
+  const [roleList, setRoleList] = useState([]);
+  const [size, setSize] = useState(15);
+  const [treeData, setTreeData] = useState([]);
+  const [total, setTotal] = useState(0);
+  const [current, setCurrent] = useState(1);
+  const { organizationData } = utils;
+  const { SHOW_PARENT } = TreeSelect;
+  const [addHospitalTreeVO, setAddHospitalTreeVO] = useState({
+    depts: [],
+    hospitals: []
+  });
+  const [params, setParams] = useState({
+    pages: 1,
+    current: 1,
+    size: 15,
+    name: '',
+    groupType: '',
+    code: ''
+  });
+  const [query, setQuery] = useState({
+    hospitalName: '',
+    code: ''
+  });
+  const [form] = Form.useForm();
+  const tipText = {
+    1: '确定要删除该参数?',
+    2: '禁用后该用户将无法登录,确定要禁用该参数?',
+    3: '确定要重置该用户密码?',
+  };
+  const staticInfo = useSelector(state => {
+    return state.staticInfo;
+  });
+  let list = []
+  let data = {
+    pages: 1,
+    current: 1,
+    size: size
+  }
+  const {statusList } = staticInfo;
+
+  let addHospitalTreeVOs = {
+    depts: [],
+    hospitals: [],
+  }
+
+  //新增弹窗
+  const showModal = (name, type, flag, id, hospitalName, val, code, remark) => {
+    setVisible(type);
+    setTitle(name);
+    setType(flag)
+    setParaId(id)
+    setParaVal(val)
+    setHospitalName(hospitalName)
+    setParaCode(code)
+    setParaRemark(remark)
+    if (flag == 1) {
+      setFormData({
+        status: '1'
+      })
+    }
+    if ( flag == 2) {
+      setFormData({
+        status: '1',
+        id: id,
+        hospitalName: hospitalName,
+        name: name,
+        val: val,
+        code: code,
+        remark: remark
+      })
+    }
+  }
+
+  //表格数据
+  function getHospitalSet(param) {
+    post(api.getHospitalSet, param || params).then((res) => {
+      if (res.data.code === 200) {
+        const data = res.data.data;
+        console.log('参数列表数据:', data);
+        setDictList(data.records);
+        setTotal(data.total)
+      }
+    })
+  }
+
+  //获取当前所属组织
+  function getHospitalTree() {
+    post(api.getHospitalTree).then((res) => {
+      if (res.data.code === 200) {
+        const data = res.data.data;
+        const treeData = organizationData(data)
+        setTreeData(treeData)
+      }
+    })
+  }
+
+  const onChange = value => {
+    value.forEach(it => {
+      if (JSON.stringify(it).indexOf('-') > 0) {
+        addHospitalTreeVOs.depts.push(it.split('-')[1])
+      } else {
+        addHospitalTreeVOs.hospitals.push(it)
+        gethospitals(treeData, it)
+      }
+    })
+    setAddHospitalTreeVO(addHospitalTreeVOs)
+    console.log(form.getFieldsValue())
+  };
+
+  //递归获取科室
+  function gethospitals(arr, val) {
+    arr.forEach(item => {
+      if (item.value == val) {
+        if (item.children) {
+          getdepts(item.children)
+        }
+        if (item.children && item.depts) {
+          item.children.forEach(item => {
+            addHospitalTreeVOs.depts.push(item.value.split('-')[1])
+          })
+        }
+      } else {
+        if (item.children) {
+          gethospitals(item.children, val)
+        }
+      }
+    })
+  }
+
+  //递归获取医院
+  function getdepts(arr) {
+    arr.forEach(item => {
+      if (JSON.stringify(item.value).indexOf('-') < 0) {
+        addHospitalTreeVOs.hospitals.push(item.value)
+      }
+      if (item.children && item.depts) {
+        item.children.forEach(it => {
+          addHospitalTreeVOs.depts.push(it.value.split('-')[1])
+        })
+        return
+      }
+      if (item.children) {
+
+        getdepts(item.children)
+      }
+    })
+  }
+
+  // 处理组织结构数据回显
+  function getHospitals(arr) {
+    arr.forEach((item, i, array) => {
+      item.value = item.hospitalId
+      item.title = item.hospitalName
+      if (!item.children && item.depts) {
+        item.depts.forEach(it => {
+          it.value = item.parentId + '-' + it.deptId
+          if (it.relation == 1) {
+            list.push(it.value)
+          }
+        })
+      }
+      if (item.type != 0 && item.relation == 1) {
+        list.push(item.value)
+        console.log(list)
+      }
+      if (item.children) {
+        getHospitals(item.children)
+      }
+    })
+    return list
+  }
+
+  // 禁用/启用接口
+  function disableUser(id, status) {
+    const param = { id: id, status: status };
+    xPost(api.disableUser, param).then((res) => {
+      if (res.data.code === 200) {
+        getHospitalSet();
+        setMsvisible(false);
+        message.success((status ? '启用' : '禁用') + "成功");
+      } else {
+        message.warning(res.data.msg || '操作失败');
+      }
+    }).catch(() => {
+      message.error("接口出错");
+    });
+  }
+
+  //重置密码
+  function onResetPsd(id) {
+    const param = { id: id };
+    xPost(api.resetPasswordUser, param).then((res) => {
+      if (res.data.code === 200) {
+        getHospitalSet();
+        message.success("重置成功");
+      } else {
+        message.warning(res.data.msg || '操作失败');
+      }
+    }).catch(() => {
+      message.error("接口出错");
+    });
+  }
+
+  //删除
+  function deleteHospitalSet() {
+    const param = { id: id };
+    xPost(api.deleteHospitalSet, param).then((res) => {
+      if (res.data.code === 200) {
+        getHospitalSet();
+        setMsvisible(false);
+        message.success("删除成功");
+      } else {
+        message.warning(res.data.msg || '操作失败');
+      }
+    }).catch(() => {
+      message.error("接口出错");
+    });
+  }
+
+  function onSizeChange(current, pageSize) {
+    params.current = current
+    params.size = pageSize
+    setSize(pageSize)
+    setCurrent(current)
+    setParams(params)
+    setQuery(query)
+    getHospitalSet()
+  }
+  function changePage(page, pageSize) {
+    params.current = page
+    params.size = pageSize
+    setCurrent(page)
+    setParams(params)
+    setQuery(query)
+    getHospitalSet()
+  }
+  const onFinish = (value) => {
+    const param = {
+      ...data,
+      ...value
+    }
+    setCurrent(1)
+    setParams(param)
+    setQuery(param)
+    getHospitalSet(param);
+  };
+  const onReset = () => {
+    // setCurrent(1)
+    // setParams(data)
+    // setQuery(query)
+    form.resetFields();
+    getHospitalSet(data);
+  };
+  const messageBox = (type, id) => {
+    setMsvisible(true)
+    setParaId(id)
+    setModalType(type)
+  }
+
+  //提示框确认事件
+  function handleOk() {
+    if (modalType == 1) {
+      deleteHospitalSet(id)
+    } else if (modalType == 2) {
+      disableUser(id, 0)
+    } else if (modalType == 3) {
+      onResetPsd(id);
+    }
+  }
+  //提示框取消
+  function handleCancel() {
+    setMsvisible(false);
+  }
+  function cancel() {
+    setVisible(false)
+    setFormData(null)
+  }
+  function userChange() {
+    let val = form.getFieldsValue()  // 页面刷新
+    const param = {
+      ...data,
+      //...value
+      ...val
+    }
+    getHospitalSet(param)
+    setVisible(false)
+  }
+
+  // 表格渲染
+  const columns = [
+    { title: '所属组织', render: (row) => {
+      if(row.hospitalName === null){
+        return '-'
+      }else {
+        return hospitalName
+      }
+    }, key: 'index' },
+    { title: '参数名', dataIndex: 'name', key: 'index' },
+    { title: '参数值', dataIndex: 'val', key: 'index' },
+    { title: '参数说明', dataIndex: 'code', key: 'index' },
+    {title: '参数描述', dataIndex: 'remark', key: 'status'},
+    {
+      title: '操作', dataIndex: 'key', render: (text, record) => (
+        <Space size="middle">
+          <a onClick={e => showModal(
+            '修改参数', 
+            true, 2, 
+            record.id,
+            record.hospitalName,
+            record.name,
+            record.val,
+            record.code,
+            record.remark
+            )} >修改</a>
+          <a className='delete' onClick={() => messageBox(1, record.id)}>删除</a>
+        </Space>
+      )
+    }
+  ]
+
+  return (
+    // 搜索框
+    <div className="wrapper">
+      <div className="filter-box">
+        <Form
+          form={form}
+          name="normal_login"
+          onFinish={onFinish}
+          initialValues={{ status: '' }}
+        >
+          <Row gutter={24}>
+          <Col span={5} key={0}>
+          <Form.Item
+          name="addHospitalTreeVO"
+          label="所属组织"
+        >
+          <TreeSelect
+            showSearch={false}
+            treeData={treeData}
+            onChange={onChange}
+            maxTagCount={1}
+            treeCheckable
+            showCheckedStrategy={SHOW_PARENT}
+            placeholder="请选择组织"
+            style={{ width: '100%' }}
+          />
+        </Form.Item>
+            </Col>
+            <Col span={5} key={1}>
+              <Form.Item label="参数名" name="name" getValueFromEvent={getValueFromEvent}>
+                <Input placeholder="参数名" autoComplete='off'/>
+              </Form.Item>
+            </Col>
+
+            <Col span={5} key={2}>
+              <Form.Item label="参数说明" name="code" getValueFromEvent={getValueFromEvent}>
+                <Input placeholder="参数说明" autoComplete='off'/>
+              </Form.Item>
+            </Col>
+            
+            <Col span={6} key={3}>
+              <Form.Item>
+                <Button type="primary" htmlType="submit">
+                  查询
+                </Button>
+                <Button onClick={onReset}>
+                  重置
+                </Button>
+              </Form.Item>
+            </Col>
+          </Row>
+        </Form>
+      </div>
+
+      <div className="table">
+        <div className="table-header">
+          <h2 className="table-title">参数管理</h2>
+          <Button type="primary" icon={<PlusOutlined />} onClick={e => showModal('新增参数', true, 1)}>新增参数</Button>
+        </div>
+
+        <Table
+          columns={columns}
+          scroll={{ y: 'calc(100vh - 320px)' }}
+          dataSource={dictList}
+          rowKey={record => record.id + record.hospitalName}
+          pagination={{
+            current: current,
+            pageSize: size,
+            size: 'small',
+            showSizeChanger: true,
+            pageSizeOptions: ['15', '30', '60', '120'],
+            showTotal: (total, range) => `第${range[0]}-${range[1]} 条/共 ${total} 条数据`,
+            onShowSizeChange: (current, pageSize) => onSizeChange(current, pageSize), // 改变每页数量时更新显示
+            onChange: (page, pageSize) => changePage(page, pageSize),//点击页码事件
+            total: total
+          }} />
+      </div>
+      {visible && formData ?
+        <Modal
+          title={title}
+          okText='确定'
+          cancelText='取消'
+          width={'45%'}
+          visible={visible}
+          onCancel={cancel}
+          footer={null}
+          forceRender={true}
+        >
+          <UserContext.Provider value={{ id, type, formData, dictList }}>
+            <AddUser userChange={userChange} />
+          </UserContext.Provider>
+
+        </Modal>
+        : ''}
+      <Modal
+        title="提示"
+        okText='确定'
+        cancelText='取消'
+        width={400}
+        visible={msvisible}
+        onOk={handleOk}
+        onCancel={handleCancel}
+      >
+        <p>{tipText[modalType]}</p>
+      </Modal>
+    </div >
+  )
+}
+
+export default DictManager;

+ 4 - 0
src/components/ParaManager/para-context.js

@@ -0,0 +1,4 @@
+import {createContext} from 'react';
+const ParaContext = createContext(null);
+
+export default ParaContext;

+ 1 - 0
src/components/UserManager/addUser.js

@@ -20,6 +20,7 @@ function AddUser(props) {
   const { userId, type, formData, roleList } = useContext(UserContext);
   const [treeData, setTreeData] = useState([]);
   const [treeRloe, setTreeRloe] = useState([]);
+  
   const [addHospitalTreeVO, setAddHospitalTreeVO] = useState({
     depts: [],
     hospitals: []

+ 1 - 0
src/components/UserManager/index.js

@@ -68,6 +68,7 @@ function UserManager() {
     post(api.getUserPage, param || params).then((res) => {
       if (res.data.code === 200) {
         const data = res.data.data;
+        console.log('用户列表数据:', data);
         setUserList(data.records);
         setTotal(data.total)
       }

+ 1 - 1
src/store/reducers/staticInfo.js

@@ -32,6 +32,6 @@ export const slice = createSlice({
     },
 });
 
-export const { setStatusList, setHisTypeList, setTitleList, setDataList,setMsgStatusList,setMsgTypeList} = slice.actions;
+export const { setStatusList, setHisTypeList, setGroupTypeList, setTitleList, setDataList,setMsgStatusList,setMsgTypeList} = slice.actions;
 
 export default slice.reducer;

+ 1 - 1
src/store/reducers/tabPanes.js

@@ -8,7 +8,7 @@ export const slice = createSlice({
         toUnRead:false
     },
     reducers: {
-        close: (state,action) => {        //关闭tab
+        close: (state,action) => {  //关闭tab
             const {delIndex,active} = action.payload;
             if(active===state.activeTab){       //如果关闭的是当前激活的tab则激活前一个或后一个tab
                 state.activeTab = state.panes[delIndex-1]?state.panes[delIndex-1].key:state.panes[delIndex+1].key;