zhouna 3 лет назад
Родитель
Сommit
b4f931907b

+ 2 - 1
src/App.less

@@ -7,8 +7,9 @@
   line-height: @header-height;
 }
 .page-sider{
-  height: calc(100vh - @header-height);
+  height: calc(100vh - @header-height - 10px );
   background: #fff;
+  overflow-y: auto;
 }
 .page-content{
   height: calc(100vh - @header-height);

+ 2 - 2
src/api/index.js

@@ -1,7 +1,7 @@
 import api from './request';
 import {message} from 'antd'
 const axios=require('axios');
-axios.defaults.baseURL = 'http://192.168.2.237:8871/';//'http://192.168.2.232:8871';
+axios.defaults.baseURL = 'http://192.168.3.184:8871';//'http://192.168.2.237:8871/';
 const post=(url,data)=>{
     return axios({
         method:'post',
@@ -60,7 +60,7 @@ function interceptors(){
     //拦截响应
     axios.interceptors.response.use(function (res) {
         const code = res.data.code;
-        if (code===401) {   //401返回登录
+        if (code===401||code===403) {   //401/403返回登录
             localStorage.removeItem("token");
             localStorage.removeItem("systemId");
             localStorage.removeItem("hospitalId");

+ 92 - 0
src/common/MyDeptStruct.js

@@ -0,0 +1,92 @@
+import { Tree } from 'antd';
+import React, { useState, useEffect, useRef } from 'react';
+import goUp from "@images/goUp.png";
+import apiObj from '@api/index';
+/****
+ * 公用
+ * 当前登录用户权限下的组织结构树
+ * 自带获取数据源功能
+ *入参:checkEv选中事件,checkeds已选中项
+ * *****/
+const { post, api } = apiObj;
+function MyDeptStruct(props) {
+    useEffect(() => {
+        getHospitalTree();
+    }, []);
+    const { checkEv, checkeds } = props;
+    const [treeData, setTreeData] = useState(null);
+    const [hasScrolled, setHasScrolled] = useState(false);
+    const box = useRef();
+
+    //获取当前用户组织
+    function getHospitalTree() {
+        post(api.getHospitalTree).then((res) => {
+            if (res.data.code === 200) {
+                const data = res.data.data
+                let arr = structureTreeData(data)
+                setTreeData(arr)
+            }
+        })
+    }
+    //数据转换为树形结构所需字段
+    function structureTreeData(arr) {
+        arr.forEach(item => {
+            item.key = item.hospitalId + '-' + item.hospitalName
+            item.title = item.hospitalName
+            if (!item.children && item.depts) {
+                item.depts.forEach(it => {
+                    it.key = item.hospitalId + '-' + it.deptId + '-' + it.deptName
+                })
+                item.children = JSON.parse(JSON.stringify(item.depts).replace(/deptName/g, 'title').replace(/deptId/g, 'key'))
+                return
+            }
+            if (item.children) {
+                structureTreeData(item.children)
+            }
+        })
+        return arr
+    }
+    //菜单选中事件
+    function onCheck(checkedKeys,e) {
+        checkEv(checkedKeys,e)
+    }
+    function handleScroll(e) {
+        if (e.target.scrollTop > 500) {
+            setHasScrolled(true)
+        } else {
+            setHasScrolled(false)
+        }
+    }
+    function goTop() {
+        box.current.scrollTop = 0
+    }
+    function onSelect() { }
+    const defaultCheckedKeys = checkeds && checkeds.softwareMenuIds ? checkeds.softwareMenuIds.slice() : []
+    return (
+        <div className='treeContent' >
+            <p className='title'>组织结构</p>
+            <div className='tree' onScrollCapture={handleScroll} ref={box}>
+                <Tree
+                    checkable
+                    defaultCheckedKeys={defaultCheckedKeys}
+                    onCheck={onCheck}
+                    onSelect={onSelect}
+                    treeData={treeData}
+
+                />
+            </div>
+
+            {
+                hasScrolled ?
+                    <div className='goTop' onClick={goTop} >
+                        <img src={goUp} />
+                    </div>
+                    : null
+            }
+
+        </div>
+
+    )
+}
+
+export default MyDeptStruct;

+ 0 - 20
src/common/QuillEditor.js

@@ -1,20 +0,0 @@
-import Quill from 'quill/core';
-
-import Toolbar from 'quill/modules/toolbar';
-import Snow from 'quill/themes/snow';
-
-import Bold from 'quill/formats/bold';
-import Italic from 'quill/formats/italic';
-import Header from 'quill/formats/header';
-
-
-Quill.register({
-    'modules/toolbar': Toolbar,
-    'themes/snow': Snow,
-    'formats/bold': Bold,
-    'formats/italic': Italic,
-    'formats/header': Header
-});
-
-
-export default Quill;

+ 16 - 5
src/common/SelectedTag.js

@@ -1,15 +1,26 @@
+import { Tag } from 'antd';
 import delIcon from "@images/del.png";
 import './selectedTag.less';
-
-function SelectedTag(){
-
+/****
+ * 已选中的元素
+ * 入参:data:[{id,name}],delTag:移除事件
+ *
+ * ****/
+function SelectedTag(props){
+    const {data,delTag} = props;
     return (
         <div className="selected-box">
             <p className='clear-bar'>
                 <span>已选中</span>
-                <a href=""><img className='back-icon' src={delIcon} alt="清空所有" />清空所有</a>
+                <a onClick={()=>delTag()}><img className='back-icon' src={delIcon} alt="清空所有" /><i>清空所有</i></a>
             </p>
-            <div className="selected-items"></div>
+            <div className="selected-items">
+                {data.map((it)=>{
+                    return (<Tag closable key={it.id} onClose={()=>delTag(it.id)}>
+                        {it.name}
+                    </Tag>)
+                })}
+            </div>
         </div>
     )
 }

+ 0 - 6
src/common/common.less

@@ -108,15 +108,9 @@ body{
 .disable{
   color: #FB8537 ;
 }
-.disable:hover{
-  color: #FB8537 ;
-}
 .delete{
   color:#FF4D4D
 }
-.delete:hover{
-  color:#FF4D4D
-}
 .menuItem:hover{
   color: @primary-color;
   background: #DBEEFF;

+ 21 - 1
src/common/selectedTag.less

@@ -2,12 +2,28 @@
 
 .selected-box{
   border:1px @border-color-base solid;
-  min-height: 76px;
+  min-height: 78px;
+  .selected-items{
+    padding: 0 20px;
+    .ant-tag{
+      background: @active-bg;
+      color: @primary-color;
+      border:none;
+      height: 26px;
+      line-height: 26px;
+      margin-bottom: 10px;
+    }
+    .ant-tag-close-icon{
+      color: @primary-color;
+      vertical-align: baseline;
+    }
+  }
 }
 .clear-bar{
   line-height: 30px;
   background: @table-th-color;
   padding:0 20px;
+  margin-bottom: 10px;
   img{
     vertical-align: middle;
     margin-right: 2px;
@@ -15,5 +31,9 @@
   a{
     float: right;
     color: @text-color;
+    i{
+      vertical-align: middle;
+      font-style: normal;
+    }
   }
 }

+ 14 - 14
src/components/AMenu/index.js

@@ -16,7 +16,7 @@ import MyMessage from "../MyMessage";
 import MsgManage from "../MsgManage";
 import apiObj from '@api/index';
 
-const { xPost, api } = apiObj;
+const { post, api } = apiObj;
 const { SubMenu } = Menu;
 const propTypes = {};
 const defaultProps = {};
@@ -35,7 +35,7 @@ const pageMap = {
     '通知管理': <MsgManage />,
 }
 
-let firstMenuPage = null;         //第一个菜单,自动激活时用
+let firstMenuPage = {};         //第一个菜单,自动激活时用
 function AMenu() {
     const [menuList, setMenuList] = useState([]);        //菜单列表数据
     const dispatch = useDispatch();
@@ -60,7 +60,7 @@ function AMenu() {
     }
     //获取菜单数据
     function getUserMenus() {
-        xPost(api.getUserShowMemuTree).then((res) => {
+        post(api.getUserShowMemuTree).then((res) => {
             if (res.data.code === 200) {
                 const data = res.data.data;
                 const menuData = data.showMenuInfo;
@@ -102,17 +102,17 @@ function AMenu() {
 
     }, []);
     return (
-        <Menu
-            /*defaultSelectedKeys={[menuList[0].menuName]}
-            defaultOpenKeys={[menuList[0].menuId]}*/
-            selectedKeys={activeTab}
-            mode="inline"
-            onClick={changeMenu}
-        >
-            {
-                getSubMenu(menuList)
-            }
-        </Menu>
+            <Menu
+                /*defaultSelectedKeys={[menuList[0].menuName]}
+                defaultOpenKeys={[menuList[0].menuId]}*/
+                selectedKeys={activeTab}
+                mode="inline"
+                onClick={changeMenu}
+            >
+                {
+                    getSubMenu(menuList)
+                }
+            </Menu>
     )
 }
 AMenu.propTypes = propTypes;

+ 94 - 34
src/components/MsgManage/AddNewMsg.js

@@ -1,27 +1,34 @@
 import { useEffect, useState } from 'react';
-import { useSelector } from 'react-redux'
-import { Table, Modal, message, Menu, Breadcrumb, Dropdown, Space, Form, Radio, Input, Button, Tabs, Row, Col, Select } from 'antd';
+import {  Breadcrumb, Form, Radio, Input, Button, Tabs } from 'antd';
 import { DownOutlined, PlusOutlined } from '@ant-design/icons';
-import Quill from '@common/QuillEditor';
+import Quill from 'quill';
 import SelectedTag from '@common/SelectedTag.js';
+import MyDeptStruct from '@common/MyDeptStruct.js';
 import UserList from './UserList';
-import DeptTree from './DeptTree';
 import './index.less';
-import "quill/dist/quill.core.css";
 import "quill/dist/quill.snow.css";
 import backIcon from "@images/back.png";
-import apiObj from '@api/index';
-import utils from '@utils/index'
-const { post, api, xPost } = apiObj;
-const { Option } = Select;
+/*import apiObj from '@api/index';
+const { post, api, xPost } = apiObj;*/
 const { TabPane } = Tabs;
-function AddNewMsg() {
+function AddNewMsg(props) {
+    const {goBack} = props;
     const [form] = Form.useForm();
     const initialValues={receiveType:0,type:1};
-    const [showCustom,setShowCustom] = useState(false);
+    const [showCustom,setShowCustom] = useState(false);     //是否显示自定义内容
+    const [checkedUser, setCheckedUser] = useState([]);   //指定用户选中项
+    const [checkedIds, setCheckedIds] = useState([]);   //指定用户选中项id
+    const [checkedDepts, setCheckedDepts] = useState([]);   //指定科室选中项
+    const [checkedDeptIds, setCheckedDeptIds] = useState([]);   //指定科室选中项id
+
 
     useEffect(() => {
-        /*var toolbarOptions = [
+        initQuillEditor();
+
+    }, []);
+    //初始化quill富文本编辑器
+    function initQuillEditor(){
+        var toolbarOptions = [
             ['bold', 'italic', 'underline', 'strike'], // toggled buttons
             ['blockquote', 'code-block'],
 
@@ -46,29 +53,21 @@ function AddNewMsg() {
         let quill = new Quill(editor,{
             modules:{
                 toolbar: {
-                    container: [['bold', 'italic'], ['link', 'image']],
+                    container: toolbarOptions,
                 }
             },
             theme:'snow'
-        });*/
-        //刷新列表
-        getUserData();
-
-    }, []);
-    function getUserData(){
-        post(api.getHospitalUser, {}).then((res) => {
-            const { code } = res.data;
-            if (code === 200) {
-
-            } else {
-                message.warning(res.data.msg || '获取用户列表失败,请重试')
-            }
         });
+        //注册事件
+        quill.on('selection-change',(range)=>{
+            if(range===null){       //为空代表失焦
+                const content = quill.root.innerHTML;
+                form.setFieldsValue({content:content});
+                //console.log(quill.getContents(),quill.root.innerHTML);
+            }
+        })
     }
-    //返回通知管理页
-    function goBack(){
 
-    }
     //发送消息
     function sendMsg(){
         console.log(form.getFieldsValue())
@@ -85,6 +84,61 @@ function AddNewMsg() {
     //切换tab
     function handleTabChange(){
 
+    }
+    //选中用户
+    function handleTableCheck(userIdArr,userArr){
+        setCheckedUser(userArr);
+        setCheckedIds(userIdArr);
+        form.setFieldsValue({sendUsers:userIdArr})
+    }
+    //选中科室
+    function handleCheckDept(checks,e){
+        const checkedDepts = structureDeptTag(checks);
+        let deptIdsArr=[...checkedDepts.ids];
+        let deptArr=[...checkedDepts.obj];
+        setCheckedDepts(deptArr);
+        setCheckedDeptIds(deptIdsArr);
+        form.setFieldsValue({sendDepts:deptIdsArr});
+    }
+    //格式化选中科室数据
+    function structureDeptTag(arr){   //全选传医院id,非全选传科室id
+        let temp=[],hosIds=[],hosArr=[],len=0,deptIds=[],deptArr=[];
+        const arrSorted = arr.sort(()=>{return 1});
+        arrSorted.map((it)=>{
+            //it由 医院id-科室id(如果有)-医院/科室名称 组成
+            temp = it.split("-");
+            len=temp.length;
+            console.log(arrSorted,it,hosIds);
+            //if(len===2){
+                //医院id存入sendHospitals,科室id存入sendDepts
+                hosArr.push({id:temp[len-2],name:temp[len-1]});
+                hosIds.push(temp[len-2]);
+            /*}else{
+                if(!hosIds.includes(temp[0])){
+                    deptArr.push({id:temp[1],name:temp[2]});
+                    deptIds.push(temp[1]);
+                }
+            }*/
+
+        });
+        return {ids:hosIds,obj:hosArr};
+    }
+    //删除已选用户
+    function handleTagDel(id){
+        if(!id){    //无入参,清空所有
+            setCheckedUser([]);
+            setCheckedIds([]);
+            form.setFieldsValue({sendUsers:[]});
+            return;
+        }
+        const idx=checkedIds.findIndex((it)=>it===id);
+        let checkedIdsArr=[...checkedIds];
+        let checkedUserArr=[...checkedUser];
+        checkedIdsArr.splice(idx,1);
+        checkedUserArr.splice(idx,1);
+        setCheckedUser(checkedUserArr);
+        setCheckedIds(checkedIdsArr);
+        form.setFieldsValue({sendUsers:checkedIdsArr})
     }
     return (
         <>
@@ -106,7 +160,7 @@ function AddNewMsg() {
                     </Radio.Group>
                 </Form.Item>
                 <Form.Item name='title' label='标题' required>
-                    <Input />
+                    <Input autoComplete='off'/>
                 </Form.Item>
                 <Form.Item name='content' label='内容' required>
                     <div className="ql-snow">
@@ -120,16 +174,22 @@ function AddNewMsg() {
                         <Radio value={1}>自定义</Radio>
                     </Radio.Group>
                 </Form.Item>
+                <Form.Item name='sendUsers' hidden>
+                    <Input autoComplete='off'/>
+                </Form.Item>
+                <Form.Item name='sendDepts' hidden>
+                    <Input autoComplete='off'/>
+                </Form.Item>
             </Form>
-            {showCustom?<div className="choose-container">
-                <SelectedTag></SelectedTag>
+            {showCustom?<div className="receive-container">
+                <SelectedTag data={[...checkedUser,...checkedDepts]} delTag={handleTagDel}></SelectedTag>
                 <div className="user-type-box">
                     <Tabs defaultActiveKey="1" onChange={handleTabChange}>
                         <TabPane tab="指定用户" key="1">
-                            <UserList></UserList>
+                            <UserList setChecked={handleTableCheck} checkedIds={checkedIds}></UserList>
                         </TabPane>
                         <TabPane tab="指定科室" key="2">
-                            <DeptTree></DeptTree>
+                            <MyDeptStruct checkEv={handleCheckDept} checkeds={checkedDepts}></MyDeptStruct>
                         </TabPane>
                     </Tabs>
                 </div>

+ 13 - 6
src/components/MsgManage/UserList.js

@@ -7,13 +7,13 @@ import apiObj from '@api/index';
 import utils from '@utils/index'
 const { post, api, xPost } = apiObj;
 const { Option } = Select;
-function UserList() {
+function UserList(props) {
     useEffect(() => {
         //刷新列表
         getTableData();
 
     }, []);
-
+    const {checkedIds,setChecked} = props;
     const [size, setSize] = useState(15);       //每页显示条数
     const [total, setTotal] = useState(0);       //每页显示条数
     const [dataSource, setDataSource] = useState([]);   //列表数据
@@ -51,7 +51,14 @@ function UserList() {
             { title: '所属组织', dataIndex: 'hospitalName', key: 'hospitalName' },
         ];
         const rowSelection = {
-            onChange:()=>{}
+            /*getCheckboxProps:(record)=>{
+                console.log(23,record)
+            },*/
+            selectedRowKeys:checkedIds,
+            onChange:(selectedRowKeys,selectedRows)=>{
+                console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows)
+                setChecked(selectedRowKeys,selectedRows);
+            }
         };
         return (
             <Table
@@ -88,17 +95,17 @@ function UserList() {
                 <Form form={form} name="control-hooks" onFinish={onFinish}>
                     <Row gutter={24}>
                         <Col span={5} key={1}>
-                            <Form.Item name="type" label="姓名">
+                            <Form.Item name="name" label="姓名">
                                 <Input placeholder='姓名'/>
                             </Form.Item>
                         </Col>
                         <Col span={5} key={2}>
-                            <Form.Item name="type" label="手机号码">
+                            <Form.Item name="mobilePhone" label="手机号码">
                                 <Input placeholder='手机号码'/>
                             </Form.Item>
                         </Col>
                         <Col span={5} key={3}>
-                            <Form.Item name="status" label="所属组织">
+                            <Form.Item name="hospitalId" label="所属组织">
                                 <Select
                                     allowClear
                                 >

+ 4 - 4
src/components/MsgManage/index.js

@@ -88,8 +88,8 @@ function MsgManage() {
 
     }
     //新增通知
-    function showAddMsg(){
-        setIsAdd(true);
+    function showAddMsg(flag){
+        setIsAdd(flag);
     }
     //表格渲染
     function RenderTable() {
@@ -139,7 +139,7 @@ function MsgManage() {
         getTableData();
     };
     if(isAdd){
-        return (<AddNewMsg></AddNewMsg>);
+        return (<AddNewMsg  goBack={() => showAddMsg(false)}></AddNewMsg>);
     }
     return (
         <div className='wrapper'>
@@ -175,7 +175,7 @@ function MsgManage() {
             <div className="table">
                 <div className="table-header">
                     <h2 className="table-title">通知管理</h2>
-                    <Button type="primary" icon={<PlusOutlined />} onClick={() => showAddMsg()}>新增通知</Button>
+                    <Button type="primary" icon={<PlusOutlined />} onClick={() => showAddMsg(true)}>新增通知</Button>
                 </div>
                 <RenderTable />
             </div>

+ 5 - 1
src/components/MsgManage/index.less

@@ -93,11 +93,15 @@
 
 }
 /*********新增页面样式*******/
-.choose-container{
+.receive-container{
   margin-left: 8.3%;
 
 }
 .add-msg-container{
   height:calc(100vh - 162px);
   overflow-y: auto;
+  padding-bottom: 24px;
+  .button-box{
+    padding-right: 20px;
+  }
 }

+ 6 - 0
src/components/PageLayout/index.less

@@ -0,0 +1,6 @@
+@import "@common/common.less";
+
+.page-sider{
+  height: calc(100% - 70px);
+  overflow-y: auto;
+}