shaogen1995 1 день назад
Родитель
Сommit
fbc3caed11

BIN
public/favicon.ico


+ 1 - 1
public/index.html

@@ -6,7 +6,7 @@
     <meta name="theme-color" content="#000000" />
     <meta name="theme-color" content="#000000" />
     <meta name="description" content="Web site created using create-react-app" />
     <meta name="description" content="Web site created using create-react-app" />
     <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
     <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
-    <!-- <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" /> -->
+    <link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
 
 
     <title>青岛啤酒博物馆-馆藏系统</title>
     <title>青岛啤酒博物馆-馆藏系统</title>
   </head>
   </head>

+ 1 - 1
src/assets/styles/base.css

@@ -16,7 +16,7 @@ html {
 body {
 body {
   font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB', 'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
   font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB', 'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
   height: 100%;
   height: 100%;
-  color: #002c15 !important;
+  color: var(--themeColor) !important;
 }
 }
 i {
 i {
   font-style: normal;
   font-style: normal;

+ 1 - 1
src/assets/styles/base.less

@@ -21,7 +21,7 @@ body {
   font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB',
   font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB',
     'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
     'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
   height: 100%;
   height: 100%;
-  color: #002c15 !important;
+  color: var(--themeColor) !important;
 }
 }
 
 
 i {
 i {

+ 1 - 1
src/pages/Isystem/I2dict/index.tsx

@@ -18,7 +18,7 @@ function I2dict() {
     dispatch(
     dispatch(
       I2_APIgetDict(data => {
       I2_APIgetDict(data => {
         setLoding(true)
         setLoding(true)
-        // if (data && data.length) setAcShu(data[0].id)
+        if (data && data.length) setAcShu(data[0].id)
       })
       })
     )
     )
   }, [dispatch])
   }, [dispatch])

+ 209 - 0
src/pages/Isystem/I5organization/I5add.tsx

@@ -0,0 +1,209 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Cascader, Form, FormInstance, Input, InputNumber, Modal } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import TextArea from 'antd/es/input/TextArea'
+import { I5AddInfoType, TypeI5Tree } from './data'
+import { I5_APIgetInfo, I5_APIsave } from '@/store/action/Isystem/I5organization'
+
+type Props = {
+  addInfo: I5AddInfoType
+  addFu: () => void
+  closeFu: () => void
+}
+
+function I5add({ addInfo, addFu, closeFu }: Props) {
+  const treeData = useSelector((state: RootState) => state.I5organization.treeData)
+
+  // 级联选择器改变的时候 筛选当前级联的 信息出来
+  const [acCardInfo, setAcCardInfo] = useState({} as TypeI5Tree)
+  const [parentIdArr, setParentIdArr] = useState<string[] | null>(null)
+
+  // useEffect(() => {
+  //   console.log(acCardInfo, parentIdArr)
+  // }, [acCardInfo, parentIdArr])
+
+  useEffect(() => {
+    setAcCardInfo(addInfo.acInfo)
+
+    let ids: string[] | null = addInfo.acInfo.id ? [addInfo.acInfo.id] : null
+
+    if (addInfo.acInfo.ancestor) ids = [...addInfo.acInfo.ancestor.split(','), addInfo.acInfo.id]
+
+    let idsRes = ids
+    if (ids && ids.length >= 1 && addInfo.txt === '编辑') {
+      ids.pop()
+    }
+
+    if (idsRes) idsRes = idsRes.filter((v, i) => v !== '0')
+
+    setParentIdArr(idsRes)
+  }, [addInfo.acInfo, addInfo.txt])
+
+  const cardChange = useCallback((aa: any, bb: any) => {
+    setParentIdArr(aa)
+
+    if (bb && bb.length) setAcCardInfo(bb[bb.length - 1])
+    else setAcCardInfo({} as TypeI5Tree)
+  }, [])
+
+  const getInfoFu = useCallback(async (id: string) => {
+    const res = await I5_APIgetInfo(id)
+    if (res.code === 0) {
+      FormBoxRef.current?.setFieldsValue({
+        ...res.data
+      })
+    }
+  }, [])
+  useEffect(() => {
+    if (addInfo.txt === '编辑') getInfoFu(addInfo.id)
+    else {
+      FormBoxRef.current?.setFieldsValue({
+        sort: 999
+      })
+    }
+  }, [addInfo.id, addInfo.txt, getInfoFu])
+
+  // 设置表单初始数据(区分编辑和新增)
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    // return MessageFu.warning("有表单不符号规则!");
+  }, [])
+
+  // 通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      let ancestor = ''
+      let parentId: string | null = null
+
+      if (parentIdArr && parentIdArr.length >= 5 && addInfo.txt === '新增')
+        return MessageFu.warning('最多支持五级!')
+
+      if (acCardInfo) parentId = addInfo.txt === '编辑' ? acCardInfo.parentId : acCardInfo.id
+      if (parentIdArr && parentId) ancestor = parentIdArr.filter(v => v !== addInfo.id).join(',')
+
+      let level = 1
+      if (parentIdArr) {
+        level = addInfo.txt === '新增' ? acCardInfo.level + 1 : acCardInfo.level
+      }
+
+      // 补0
+      if (addInfo.id === '-1') {
+        // 新增
+        if (!parentId && !ancestor) {
+          ancestor = '0'
+          parentId = '0'
+        } else ancestor = '0,' + ancestor
+      } else {
+        // 编辑
+        if (!ancestor) ancestor = '0'
+        else ancestor = '0,' + ancestor
+      }
+
+      const obj = {
+        ...values,
+        id: addInfo.id === '-1' ? null : addInfo.id,
+        ancestor,
+        level,
+        parentId
+      }
+      // console.log(123, obj)
+      // if (1 + 1 === 2) {
+      //   return
+      // }
+
+      const res = await I5_APIsave(obj)
+
+      if (res.code === 0) {
+        MessageFu.success(addInfo.txt + '成功!')
+        addFu()
+        closeFu()
+      }
+    },
+    [acCardInfo, addFu, addInfo.id, addInfo.txt, closeFu, parentIdArr]
+  )
+
+  return (
+    <Modal
+      wrapClassName={styles.I5add}
+      open={true}
+      title={addInfo.txt}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='I5aMain'>
+        <Form
+          scrollToFirstError={true}
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+        >
+          <div className='fromRow'>
+            <div className='fromRowll'>上级部门:</div>
+            <div className='fromRowrr'>
+              <Cascader
+                style={{ width: 658 }}
+                disabled={addInfo.txt === '编辑'}
+                changeOnSelect
+                fieldNames={{ label: 'name', value: 'id', children: 'children' }}
+                options={treeData}
+                placeholder={addInfo.txt === '编辑' ? '空' : '请选择'}
+                value={parentIdArr ? [...parentIdArr] : []}
+                onChange={cardChange}
+              />
+            </div>
+          </div>
+
+          <Form.Item
+            label='部门名称'
+            name='name'
+            rules={[{ required: true, message: '请输入部门名称!' }]}
+            getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
+          >
+            <Input maxLength={20} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <Form.Item label='部门说明' name='description'>
+            <TextArea maxLength={100} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <div className='fromRow2'>
+            <Form.Item
+              label='排序值'
+              name='sort'
+              rules={[{ required: true, message: '请输入排序值!' }]}
+            >
+              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
+            </Form.Item>
+            <div className='fromRowTit'>
+              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
+            </div>
+          </div>
+
+          {/* 确定和取消按钮 */}
+          <br />
+          <Form.Item wrapperCol={{ offset: 9, span: 16 }}>
+            <Button type='primary' htmlType='submit'>
+              提交
+            </Button>
+            &emsp;
+            <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+          </Form.Item>
+        </Form>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoI5add = React.memo(I5add)
+
+export default MemoI5add

+ 23 - 0
src/pages/Isystem/I5organization/data.ts

@@ -0,0 +1,23 @@
+export type TypeI5Tree = {
+  id: string
+  parentId: string
+  sort: number
+  name: string
+  ancestor: string
+  level: number
+  description: string
+  children?: TypeI5Tree[]
+}
+
+export type TypeI5UserList = {
+  deptId: number
+  isLeader: number
+  userId: number
+  userName: string
+}
+
+export type I5AddInfoType = {
+  id: string
+  txt: '新增' | '编辑'
+  acInfo: TypeI5Tree
+}

+ 134 - 0
src/pages/Isystem/I5organization/index.module.scss

@@ -1,4 +1,138 @@
 .I5organization {
 .I5organization {
+  background-color: var(--boxBcaColor);
+  border-radius: 10px;
+  padding: 24px;
   :global {
   :global {
+    .I5top {
+      text-align: right;
+    }
+
+    .I5main {
+      margin-top: 15px;
+      height: calc(100% - 50px);
+      & > div {
+        height: 100%;
+      }
+      .I5Null {
+        width: 100%;
+        height: 300px;
+        font-size: 24px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+      }
+      .I5m1 {
+        display: flex;
+        justify-content: space-between;
+        .I5m1ll {
+          width: 50%;
+          overflow-y: auto;
+          .site-tree-search-value {
+            color: red;
+            font-weight: 700;
+          }
+          .ant-tree {
+            background-color: var(--boxBcaColor);
+            min-height: 100%;
+          }
+          .ant-tree-node-selected {
+            background-color: var(--themeColor2) !important;
+          }
+        }
+        .I5m1rr {
+          width: calc(50% - 24px);
+
+          .I5mr2 {
+            .I5mr2Row {
+              display: flex;
+              // align-items: center;
+              margin-bottom: 10px;
+              font-size: 20px;
+              .I5mr2Row1 {
+                font-weight: 700;
+                font-size: 20px;
+              }
+
+              .ant-btn {
+                font-size: 20px;
+                height: 46px;
+              }
+
+              .I5mr2Row2 {
+                width: calc(100% - 105px);
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+              }
+              .I5mr2Row2_1 {
+                width: calc(100% - 105px);
+              }
+            }
+            .I5mr2Row0 {
+              margin-bottom: 0;
+              align-items: center;
+            }
+            .I5mr2RowLast {
+              align-items: self-start;
+              .I5mr2Row2 {
+                display: flex;
+                flex-wrap: wrap;
+              }
+            }
+          }
+
+          .I5mr3 {
+            margin-top: 15px;
+            height: calc(100% - 100px);
+            background-color: red;
+          }
+        }
+      }
+    }
+  }
+}
+
+// 新增弹窗页面
+.I5add {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal {
+      width: 800px !important;
+    }
+
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+    }
+
+    .I5aMain {
+      padding-top: 15px;
+      .fromRow2 {
+        position: relative;
+
+        .fromRowTit {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+      .fromRow {
+        display: flex;
+        align-items: center;
+        margin-bottom: 24px;
+        .fromRowll {
+          width: 94px;
+          text-align: right;
+          position: relative;
+        }
+        .fromRowrr {
+          width: calc(100% - 94px);
+        }
+      }
+    }
   }
   }
 }
 }

+ 217 - 1
src/pages/Isystem/I5organization/index.tsx

@@ -1,9 +1,225 @@
-import React from 'react'
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
 import styles from './index.module.scss'
 import styles from './index.module.scss'
+import { Button, Input, Tree, TreeDataNode } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { MessageFu } from '@/utils/message'
+import { I5_APIdel, I5_APIgetTree, I5_APIgetUserById } from '@/store/action/Isystem/I5organization'
+import { I5AddInfoType, TypeI5Tree, TypeI5UserList } from './data'
+import { treeResIdFu } from '../I2dict/data'
+import I5add from './I5add'
 function I5organization() {
 function I5organization() {
+  const dispatch = useDispatch()
+
+  const [loding, setLoding] = useState(false)
+
+  useEffect(() => {
+    dispatch(
+      I5_APIgetTree(data => {
+        setLoding(true)
+        if (data && data.length) setAcShu(data[0].id)
+      })
+    )
+  }, [dispatch])
+
+  const { treeData: treeDataTemp } = useSelector((state: RootState) => state.I5organization)
+
+  // 当前选中的树节点ID
+  const [acShu, setAcShu] = useState('')
+
+  // 获取相关成员列表
+  const [userList, setUserList] = useState<TypeI5UserList[]>([])
+
+  const getUserByIdFu = useCallback(async (id: string) => {
+    const res = await I5_APIgetUserById(id)
+    if (res.code === 0) {
+      setUserList(res.data)
+    }
+  }, [])
+
+  useEffect(() => {
+    if (acShu) getUserByIdFu(acShu)
+  }, [acShu, getUserByIdFu])
+
+  // 点击树节点
+  const onSelect = (id: any) => {
+    if (id[0]) setAcShu(id[0])
+  }
+
+  // 搜索高亮
+  const [value, setValue] = useState('')
+
+  const treeData = useMemo(() => {
+    const loop = (dataTemp: any[]): TreeDataNode[] => {
+      const data = dataTemp || []
+
+      return data.map(item => {
+        const strTitle = ((item.num ? item.num + ' ' : '') + item.name) as string
+
+        const index = strTitle.indexOf(value)
+
+        const beforeStr = strTitle.substring(0, index)
+        const afterStr = strTitle.slice(index + value.length)
+        const title =
+          index > -1 ? (
+            <span key={item.id}>
+              {beforeStr}
+              <span className='site-tree-search-value'>{value}</span>
+              {afterStr}
+            </span>
+          ) : (
+            <span key={item.id}>{strTitle}</span>
+          )
+        if (item.children) {
+          return { title, key: item.id, children: loop(item.children) }
+        }
+        return {
+          title,
+          key: item.id
+        }
+      })
+    }
+
+    return loop(treeDataTemp)
+  }, [treeDataTemp, value])
+
+  // 右侧信息
+  const rightData = useMemo(() => {
+    let obj = {} as TypeI5Tree
+
+    obj = treeResIdFu(treeDataTemp, acShu)
+
+    return obj || {}
+  }, [acShu, treeDataTemp])
+
+  // 点击删除
+  const delTree = useCallback(
+    async (id: string) => {
+      const res = await I5_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        dispatch(I5_APIgetTree())
+      }
+    },
+    [dispatch]
+  )
+
+  // 点击新增和编辑
+  const [addInfo, setAddInfo] = useState({} as I5AddInfoType)
+
+  const addSonFu = useCallback(
+    (id: string) => {
+      setAddInfo({
+        id,
+        txt: id === '-1' ? '新增' : '编辑',
+        acInfo: rightData
+      })
+    },
+    [rightData]
+  )
+
   return (
   return (
     <div className={styles.I5organization}>
     <div className={styles.I5organization}>
       <div className='pageTitle'>组织管理</div>
       <div className='pageTitle'>组织管理</div>
+      <div className='I5top'>
+        <Input value={value} onChange={e => setValue(e.target.value)} hidden />
+        <Button
+          type='primary'
+          onClick={() => setAddInfo({ id: '-1', txt: '新增', acInfo: rightData })}
+        >
+          新增
+        </Button>
+      </div>
+
+      {/* 主体 */}
+      <div className='I5main'>
+        <div className='I5m1'>
+          <div className='I5m1ll'>
+            {treeDataTemp && treeDataTemp.length ? (
+              <Tree
+                // 默认全部展开
+                defaultExpandAll={true}
+                // 数据
+                treeData={treeData}
+                // 自定义字段
+                // fieldNames={{ title: 'title', key: 'key', children: 'children' }}
+                // 选中
+                selectedKeys={[acShu]}
+                // 点击
+                onSelect={onSelect}
+              />
+            ) : loding ? (
+              <div className='I5Null'>暂无数据</div>
+            ) : null}
+          </div>
+          <div className='I5m1rr'>
+            {rightData.id ? (
+              <>
+                <div className='I5mr2'>
+                  <div className='I5mr2Row I5mr2Row0'>
+                    <div className='I5mr2Row1'>操作:</div>
+                    <div>
+                      <Button type='text' onClick={() => addSonFu(rightData.id)}>
+                        编辑
+                      </Button>
+                      &emsp;
+                      <MyPopconfirm txtK='删除' onConfirm={() => delTree(rightData.id)} />
+                    </div>
+                  </div>
+
+                  <div className='I5mr2Row'>
+                    <div className='I5mr2Row1'>部门名称:</div>
+                    <div>{rightData.name}</div>
+                  </div>
+
+                  <div className='I5mr2Row'>
+                    <div className='I5mr2Row1'>部门说明:</div>
+                    <div className='I5mr2Row2_1'>{rightData.description || '(空)'}</div>
+                  </div>
+
+                  <div className='I5mr2Row'>
+                    <div className='I5mr2Row1'>层级:</div>
+                    <div>{rightData.level}</div>
+                  </div>
+                  {/* <div className='I5mr2Row'>
+                    <div className='I5mr2Row1'>id:</div>
+                    <div>{rightData.id}</div>
+                  </div> */}
+
+                  <div className='I5mr2Row'>
+                    <div className='I5mr2Row1'>排序值:</div>
+                    <div>{rightData.sort}</div>
+                  </div>
+
+                  <div className='I5mr2Row I5mr2RowLast'>
+                    <div className='I5mr2Row1'>相关成员:</div>
+                    <div className='I5mr2Row2'>
+                      {userList.length
+                        ? userList.map((v, i) => (
+                            <div key={v.userId}>
+                              {v.userName}
+                              {v.isLeader === 1 ? '(部门主管)' : ''}
+                              {i < userList.length - 1 ? ',' : ''}
+                            </div>
+                          ))
+                        : '(空)'}
+                    </div>
+                  </div>
+                </div>
+              </>
+            ) : null}
+          </div>
+        </div>
+      </div>
+      {/* 新增/编辑页面 中图法分类 */}
+      {addInfo.id ? (
+        <I5add
+          addInfo={addInfo}
+          addFu={() => dispatch(I5_APIgetTree())}
+          closeFu={() => setAddInfo({} as I5AddInfoType)}
+        />
+      ) : null}
     </div>
     </div>
   )
   )
 }
 }

+ 382 - 0
src/pages/Isystem/I6role/I6edit.tsx

@@ -0,0 +1,382 @@
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Checkbox, Form, FormInstance, Input, InputNumber, Modal, Radio } from 'antd'
+import TextArea from 'antd/es/input/TextArea'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import classNmaes from 'classnames'
+import { MessageFu } from '@/utils/message'
+import { I6_APIgetAddTreeList, I6_APIgetInfo, I6_APIsave } from '@/store/action/Isystem/I6role'
+import { TypeI6Role } from './data'
+
+type Props = {
+  sId: number
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function I6edit({ sId, closeFu, addTableFu, editTableFu }: Props) {
+  const [goodsIdArr, setGoodsIdArr] = useState<string[]>([])
+
+  // 设置表单ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 侧边栏
+  const [roleArr, setRoleArr] = useState<TypeI6Role[]>([])
+
+  // 藏品详情
+  const [goodIds, setGoodIds] = useState<TypeI6Role[]>([])
+
+  // 藏品总账
+  const [zhangIds, setZhangIds] = useState<TypeI6Role[]>([])
+
+  // 流程可见权限
+  const [dataScope, setDataScope] = useState(0)
+
+  // 藏品可见权限
+  const [scopeStorage, setScopeStorage] = useState(0)
+  // 与库房相关的藏品id
+  // 待完善sg-从库房拿列表信息(等陈磊写完)
+  const [scopeStorageIds, setScopeStorageIds] = useState<number[]>([])
+
+  const otherIdsFu = useCallback((data: TypeI6Role[]) => {
+    let goodIdsTemp: TypeI6Role[] = []
+    let zhangIdsTemp: TypeI6Role[] = []
+
+    data.forEach(v1 => {
+      if (v1.children) {
+        v1.children.forEach(v2 => {
+          if (v2.children) {
+            v2.children.forEach(v3 => {
+              if (v2.id === 310 && v2.name === '藏品总账') zhangIdsTemp.push(v3)
+              else if (v2.id === 330 && v2.name === '藏品信息') goodIdsTemp.push(v3)
+            })
+          }
+        })
+      }
+    })
+
+    setGoodIds(goodIdsTemp)
+    setZhangIds(zhangIdsTemp)
+  }, [])
+
+  // 编辑进来获取详情
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      const res = await I6_APIgetInfo(id)
+      if (res.code === 0) {
+        const data: any = res.data
+        const roleInfo = data.role
+        FormBoxRef.current?.setFieldsValue(roleInfo)
+        // 设置多选框
+        setRoleArr(data.permission)
+        otherIdsFu(data.permission)
+
+        // 设置其他单选框
+        setDataScope(roleInfo.dataScope || 1)
+
+        setScopeStorage(roleInfo.scopeStorage || 1)
+        if (roleInfo.scopeStorageIds)
+          setScopeStorageIds(roleInfo.scopeStorageIds.split(',').map((v: string) => Number(v)))
+
+        // 后面加的藏品权限
+        if (roleInfo.scopeGoods) {
+          setGoodsIdArr(roleInfo.scopeGoods.split(','))
+        }
+      }
+    },
+    [otherIdsFu]
+  )
+
+  // 新增进来获取权限数据
+  const getAddInfoFu = useCallback(async () => {
+    const res = await I6_APIgetAddTreeList()
+    if (res.code === 0) {
+      const resArr: TypeI6Role[] = res.data || []
+      setRoleArr(resArr)
+      otherIdsFu(resArr)
+    }
+  }, [otherIdsFu])
+
+  useEffect(() => {
+    if (sId > 0) {
+      getInfoFu(sId)
+    } else {
+      FormBoxRef.current?.setFieldsValue({ sort: 999 })
+
+      setDataScope(1)
+
+      getAddInfoFu()
+      setScopeStorage(1)
+    }
+  }, [getAddInfoFu, getInfoFu, sId])
+
+  // 多选框变化
+  const onChange = useCallback(
+    (val: boolean, id1: number, id2: number) => {
+      setRoleArr(
+        roleArr.map(v => ({
+          ...v,
+          children:
+            v.id === id1
+              ? v.children.map(c => ({
+                  ...c,
+                  authority: c.id === id2 ? val : c.authority
+                }))
+              : v.children
+        }))
+      )
+    },
+    [roleArr]
+  )
+
+  // 侧边栏选中id集合
+  const checkIds = useMemo(() => {
+    const arr: number[] = []
+    roleArr.forEach(v => {
+      v.children.forEach(c => {
+        if (c.authority) arr.push(c.id)
+      })
+    })
+    // 过滤角色
+    return arr.filter(v => v !== 750)
+  }, [roleArr])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(async () => {
+    // return MessageFu.warning("有表单不符号规则!");
+  }, [])
+
+  // 通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      if (checkIds.length <= 0) MessageFu.warning('至少选中一个侧边栏')
+
+      if (scopeStorage === 2) {
+        if (!scopeStorageIds || scopeStorageIds.length === 0)
+          return MessageFu.warning('藏品可见权限-至少选中一个库房')
+      }
+
+      const goodIdsRes = goodIds.filter(v => v.authority).map(c => c.id)
+      const zhangIdsRes = zhangIds.filter(v => v.authority).map(c => c.id)
+
+      const obj = {
+        ...values,
+        id: sId > 0 ? sId : null,
+        resources: [...checkIds, ...goodIdsRes, ...zhangIdsRes],
+        scopeStorage,
+        scopeStorageIds: scopeStorageIds.join(','),
+        scopeGoods: goodsIdArr.join(','),
+        dataScope
+      }
+
+      const res = await I6_APIsave(obj)
+
+      if (res.code === 0) {
+        MessageFu.success(sId > 0 ? '编辑成功' : '新增成功')
+        sId > 0 ? editTableFu() : addTableFu()
+        closeFu()
+      }
+    },
+    [
+      addTableFu,
+      checkIds,
+      closeFu,
+      dataScope,
+      editTableFu,
+      goodIds,
+      goodsIdArr,
+      sId,
+      scopeStorage,
+      scopeStorageIds,
+      zhangIds
+    ]
+  )
+
+  return (
+    <Modal
+      wrapClassName={styles.I6edit}
+      open={true}
+      title={sId > 0 ? '编辑' : '新增'}
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='I6eMain'>
+        <Form
+          scrollToFirstError={true}
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+        >
+          <Form.Item
+            label='角色名称'
+            name='roleName'
+            rules={[{ required: true, message: '请输入角色名称' }]}
+          >
+            <Input maxLength={10} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <Form.Item label='角色说明' name='roleDesc'>
+            <TextArea maxLength={100} showCount placeholder='请输入内容' />
+          </Form.Item>
+
+          <div className='fromRow2'>
+            <Form.Item
+              label='排序值'
+              name='sort'
+              rules={[{ required: true, message: '请输入排序值!' }]}
+            >
+              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
+            </Form.Item>
+            <div className='fromRowTit'>
+              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
+            </div>
+          </div>
+
+          <div className='I6ebox'>
+            <div className='I6eboxll'>功能权限:</div>
+            <div className='I6eboxrr'>
+              <div className='I6eboxrrBox'>
+                <div className='I6eboxrrTit'>侧边栏</div>
+                {roleArr.map(v => (
+                  <div key={v.id} className='I6eRow'>
+                    <div className='I6eRow1'>
+                      <Checkbox
+                        checked={v.children.every(c => c.authority)}
+                        indeterminate={
+                          v.children.some(b => b.authority) && !v.children.every(c => c.authority)
+                        }
+                        onChange={e => {
+                          const flag = v.children.every(c => c.authority)
+
+                          setRoleArr(
+                            roleArr.map(p => ({
+                              ...p,
+                              children:
+                                v.id === p.id
+                                  ? v.children.map(a => ({ ...a, authority: !flag }))
+                                  : p.children
+                            }))
+                          )
+                        }}
+                      >
+                        {v.name}:
+                      </Checkbox>
+                    </div>
+                    <div className='I6eRow2'>
+                      {v.children.map(c => (
+                        <Checkbox
+                          style={{ display: c.name === '角色管理' ? 'none' : 'inline-flex' }}
+                          key={c.id}
+                          checked={c.authority}
+                          onChange={e => onChange(e.target.checked, v.id, c.id)}
+                        >
+                          {c.name}
+                        </Checkbox>
+                      ))}
+                    </div>
+                  </div>
+                ))}
+                <div className={classNmaes('I6eErr', checkIds.length <= 0 ? 'I6eErrAc' : '')}>
+                  至少选中一个
+                </div>
+              </div>
+
+              <div className='I6eboxrrBox I6eboxrrBox2'>
+                <div className='I6eboxrrTit'>藏品详情</div>
+
+                {goodIds.map(v => (
+                  <Checkbox
+                    key={v.id}
+                    checked={v.authority}
+                    onChange={e =>
+                      setGoodIds(
+                        goodIds.map(c => ({
+                          ...c,
+                          authority: c.id === v.id ? e.target.checked : c.authority
+                        }))
+                      )
+                    }
+                  >
+                    {v.name}
+                  </Checkbox>
+                ))}
+              </div>
+
+              <div className='I6eboxrrBox I6eboxrrBox2'>
+                <div className='I6eboxrrTit'>藏品总账</div>
+
+                {zhangIds.map(v => (
+                  <Checkbox
+                    key={v.id}
+                    checked={v.authority}
+                    onChange={e =>
+                      setZhangIds(
+                        zhangIds.map(c => ({
+                          ...c,
+                          authority: c.id === v.id ? e.target.checked : c.authority
+                        }))
+                      )
+                    }
+                  >
+                    {v.name}
+                  </Checkbox>
+                ))}
+              </div>
+            </div>
+          </div>
+
+          <br />
+
+          <div className='I6ebox'>
+            <div className='I6eboxll'>数据权限:</div>
+            <div className='I6eboxrr'>
+              <div className='I6eboxrrBox I6eboxrrBox2'>
+                <div className='I6eboxrrTit'>流程可见权限</div>
+                <Radio.Group value={dataScope} onChange={e => setDataScope(e.target.value)}>
+                  <Radio value={1}>所有流程</Radio>
+                  <Radio value={2}>与自己相关流程(发起人、审批人、抄送人)</Radio>
+                </Radio.Group>
+              </div>
+
+              <div className='I6eboxrrBox I6eboxrrBox2'>
+                <div className='I6eboxrrTit'>藏品可见权限</div>
+                <Radio.Group
+                  value={scopeStorage}
+                  onChange={e => {
+                    if (e.target.value === 2 && (!scopeStorageIds || scopeStorageIds.length === 0))
+                      return MessageFu.warning('暂无库房信息,请先去库房设置中添加')
+                    setScopeStorage(e.target.value)
+                  }}
+                  options={[
+                    { value: 1, label: '所有藏品' },
+                    { value: 2, label: '仅与库房相关的藏品' }
+                  ]}
+                />
+              </div>
+            </div>
+          </div>
+
+          {/* 确定和取消按钮 */}
+          <br />
+          <Form.Item wrapperCol={{ offset: 9, span: 16 }} className='I6eBtn'>
+            <Button type='primary' htmlType='submit'>
+              提交
+            </Button>
+            <br />
+            <br />
+            <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+          </Form.Item>
+        </Form>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoI6edit = React.memo(I6edit)
+
+export default MemoI6edit

+ 21 - 0
src/pages/Isystem/I6role/data.ts

@@ -0,0 +1,21 @@
+export type TypeI6table = {
+  count: number
+  createTime: string
+  creatorName: string
+  id: number
+  isEnabled: number
+  roleDesc: string
+  roleKey: string
+  roleName: string
+  sort: string
+  updateTime: string
+}
+
+// 功能权限列表
+export type TypeI6Role = {
+  authority: boolean
+  children: TypeI6Role[]
+  id: number
+  name: string
+  resourceType: string
+}

+ 169 - 0
src/pages/Isystem/I6role/index.module.scss

@@ -1,4 +1,173 @@
 .I6role {
 .I6role {
   :global {
   :global {
+    .I6top {
+      text-align: right;
+      border-radius: 10px;
+      padding: 15px 24px;
+      background-color: var(--boxBcaColor);
+    }
+    .tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: var(--boxBcaColor);
+    }
+  }
+}
+
+// 新增弹窗页面
+.I6edit {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+
+    .ant-modal {
+      top: 30px !important;
+      width: 1100px !important;
+    }
+
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+
+      .ant-form-item-label {
+        max-width: 100px;
+      }
+    }
+
+    .I6eMain {
+      width: 900px;
+      position: relative;
+      padding-top: 15px;
+      .fromRow2 {
+        position: relative;
+
+        .fromRowTit {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+      .fromRow {
+        display: flex;
+        align-items: center;
+        margin-bottom: 24px;
+        .fromRowll {
+          width: 94px;
+          text-align: right;
+          position: relative;
+        }
+        .fromRowrr {
+          width: calc(100% - 94px);
+        }
+      }
+      .I6eBtn {
+        position: absolute;
+        top: 50%;
+        transform: translateY(-50%);
+        right: -95px;
+        margin: 0;
+      }
+      .I6Rtit {
+        pointer-events: none;
+        width: 142px;
+        text-align: center;
+        .ant-radio {
+          display: none;
+        }
+      }
+
+      // 功能权限和数据权限
+      .I6ebox {
+        display: flex;
+        .I6eboxll {
+          width: 100px;
+          text-align: right;
+          & > span {
+            color: #ff4d4f;
+          }
+        }
+        .I6eboxrr {
+          width: calc(100% - 100px);
+
+          .I6eboxrrBox {
+            width: 100%;
+            padding-top: 10px;
+            border-radius: 10px;
+            background-color: var(--boxBcaColor);
+            margin-bottom: 10px;
+          }
+
+          .I6eboxrrTit {
+            padding-left: 14px;
+            font-weight: 700;
+            margin-bottom: 10px;
+            color: var(--themeColor);
+            font-size: 18px;
+          }
+
+          .I6eRow {
+            margin-bottom: 10px;
+            display: flex;
+
+            .I6eRow1 {
+              width: 110px;
+              font-weight: 700;
+              .ant-checkbox-wrapper {
+                width: 100%;
+                display: flex;
+                padding-left: 8px;
+              }
+            }
+
+            .I6eRow2 {
+              width: calc(100% - 110px);
+            }
+          }
+
+          .I6eErr {
+            text-align: center;
+            color: #ff4d4f;
+            opacity: 0;
+            pointer-events: none;
+            transition: all 0.3s;
+            position: relative;
+            top: -10px;
+          }
+
+          .I6eErrAc {
+            opacity: 1;
+            top: 0;
+          }
+          .I6eboxrr_1 {
+            margin-top: 5px;
+          }
+
+          .I6eboxrrBox2 {
+            padding-bottom: 20px;
+            padding-left: 14px;
+            .I6eboxrrTit {
+              padding-left: 0;
+            }
+          }
+        }
+        .I6eboxrr2 {
+          margin-bottom: 15px;
+        }
+      }
+      .I6ebox0 {
+        margin-top: -24px;
+      }
+      .I6ebox1 {
+        .I6eboxll {
+          width: 150px;
+          text-align: left;
+        }
+        padding-left: 110px;
+      }
+    }
   }
   }
 }
 }

+ 106 - 1
src/pages/Isystem/I6role/index.tsx

@@ -1,9 +1,114 @@
-import React from 'react'
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
 import styles from './index.module.scss'
 import styles from './index.module.scss'
+import { Button } from 'antd'
+import { useDispatch, useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { I6_APIdel, I6_APIgetList } from '@/store/action/Isystem/I6role'
+import { TypeI6table } from './data'
+import { I6tableC } from '@/utils/tableData'
+import I6edit from './I6edit'
 function I6role() {
 function I6role() {
+  const dispatch = useDispatch()
+
+  // 顶部筛选
+  const [fromData, setFromData] = useState({
+    pageNum: 1,
+    pageSize: 10,
+    searchKey: ''
+  })
+
+  // 封装发送请求的函数
+  const getList = useCallback(async () => {
+    dispatch(I6_APIgetList(fromData))
+  }, [dispatch, fromData])
+
+  useEffect(() => {
+    getList()
+  }, [getList])
+
+  // 从仓库中获取表格数据
+  const tableInfo = useSelector((state: RootState) => state.I6role.tableInfo)
+
+  // 点击删除
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res: any = await I6_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getList()
+      }
+    },
+    [getList]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        width: 200,
+        render: (item: TypeI6table) => {
+          return item.id === 1 ? (
+            '-'
+          ) : (
+            <>
+              <Button size='small' type='text' onClick={() => setEditId(item.id)}>
+                编辑
+              </Button>
+              <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
+            </>
+          )
+        }
+      }
+    ]
+  }, [delTableFu])
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setFromData({
+      pageNum: 1,
+      pageSize: 10,
+      searchKey: ''
+    })
+  }, [])
+
+  // 点击新增和编辑
+  const [editId, setEditId] = useState(0)
+
   return (
   return (
     <div className={styles.I6role}>
     <div className={styles.I6role}>
       <div className='pageTitle'>角色管理</div>
       <div className='pageTitle'>角色管理</div>
+      <div className='I6top'>
+        <Button type='primary' onClick={() => setEditId(-1)}>
+          新增
+        </Button>
+      </div>
+      {/* 表格主体 */}
+      <div className='tableBox'>
+        <MyTable
+          yHeight={585}
+          list={tableInfo.list}
+          columnsTemp={I6tableC}
+          lastBtn={tableLastBtn}
+          pageNum={fromData.pageNum}
+          pageSize={fromData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
+          widthSet={{ roleDesc: 800, sort: 100 }}
+        />
+      </div>
+
+      {/* 新增和编辑 */}
+      {editId ? (
+        <I6edit
+          sId={editId}
+          closeFu={() => setEditId(0)}
+          addTableFu={resetSelectFu}
+          editTableFu={getList}
+        />
+      ) : null}
     </div>
     </div>
   )
   )
 }
 }

+ 4 - 0
src/pages/Isystem/I7user/index.module.scss

@@ -0,0 +1,4 @@
+.I7user {
+  :global {
+  }
+}

+ 13 - 0
src/pages/Isystem/I7user/index.tsx

@@ -0,0 +1,13 @@
+import React from 'react'
+import styles from './index.module.scss'
+function I7user() {
+  return (
+    <div className={styles.I7user}>
+      <div className='pageTitle'>流程设置</div>
+    </div>
+  )
+}
+
+const MemoI7user = React.memo(I7user)
+
+export default MemoI7user

+ 35 - 36
src/pages/Layout/data.ts

@@ -1,7 +1,6 @@
 import { RouterType, RouterTypeRow } from '@/types'
 import { RouterType, RouterTypeRow } from '@/types'
 import React from 'react'
 import React from 'react'
 
 
-// 待完善sg-id
 const tabLeftArr: RouterType = [
 const tabLeftArr: RouterType = [
   {
   {
     id: 1,
     id: 1,
@@ -9,25 +8,25 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 110,
         name: '数据统计',
         name: '数据统计',
         path: '/',
         path: '/',
         Com: React.lazy(() => import('../Abench/A1statistics'))
         Com: React.lazy(() => import('../Abench/A1statistics'))
       },
       },
       {
       {
-        id: 101,
+        id: 120,
         name: '工作台',
         name: '工作台',
         path: '/bench',
         path: '/bench',
         Com: React.lazy(() => import('../Abench/A2bench'))
         Com: React.lazy(() => import('../Abench/A2bench'))
       },
       },
       {
       {
-        id: 102,
+        id: 130,
         name: '流程中心',
         name: '流程中心',
         path: '/flow',
         path: '/flow',
         Com: React.lazy(() => import('../Abench/A3flow'))
         Com: React.lazy(() => import('../Abench/A3flow'))
       },
       },
       {
       {
-        id: 103,
+        id: 140,
         name: '凭证中心',
         name: '凭证中心',
         path: '/proof',
         path: '/proof',
         Com: React.lazy(() => import('../Abench/A4proof'))
         Com: React.lazy(() => import('../Abench/A4proof'))
@@ -41,25 +40,25 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 210,
         name: '藏品征集',
         name: '藏品征集',
         path: '/collect',
         path: '/collect',
         Com: React.lazy(() => import('../Benter/B1collect'))
         Com: React.lazy(() => import('../Benter/B1collect'))
       },
       },
       {
       {
-        id: 101,
+        id: 220,
         name: '藏品入馆',
         name: '藏品入馆',
         path: '/enterGuan',
         path: '/enterGuan',
         Com: React.lazy(() => import('../Benter/B2enterGuan'))
         Com: React.lazy(() => import('../Benter/B2enterGuan'))
       },
       },
       {
       {
-        id: 102,
+        id: 230,
         name: '藏品鉴定',
         name: '藏品鉴定',
         path: '/auth',
         path: '/auth',
         Com: React.lazy(() => import('../Benter/B3auth'))
         Com: React.lazy(() => import('../Benter/B3auth'))
       },
       },
       {
       {
-        id: 103,
+        id: 240,
         name: '藏品入藏',
         name: '藏品入藏',
         path: '/enterCang',
         path: '/enterCang',
         Com: React.lazy(() => import('../Benter/B4enterCang'))
         Com: React.lazy(() => import('../Benter/B4enterCang'))
@@ -73,25 +72,25 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 310,
         name: '藏品总账',
         name: '藏品总账',
         path: '/ledger',
         path: '/ledger',
         Com: React.lazy(() => import('../Cledger/C1ledger'))
         Com: React.lazy(() => import('../Cledger/C1ledger'))
       },
       },
       {
       {
-        id: 101,
+        id: 320,
         name: '藏品分账',
         name: '藏品分账',
         path: '/routing',
         path: '/routing',
         Com: React.lazy(() => import('../Cledger/C2routing'))
         Com: React.lazy(() => import('../Cledger/C2routing'))
       },
       },
       {
       {
-        id: 102,
+        id: 330,
         name: '藏品信息',
         name: '藏品信息',
         path: '/goodsInfo',
         path: '/goodsInfo',
         Com: React.lazy(() => import('../Cledger/C3goodsInfo'))
         Com: React.lazy(() => import('../Cledger/C3goodsInfo'))
       },
       },
       {
       {
-        id: 103,
+        id: 340,
         name: '藏品附件',
         name: '藏品附件',
         path: '/C4file',
         path: '/C4file',
         Com: React.lazy(() => import('../Cledger/C4file'))
         Com: React.lazy(() => import('../Cledger/C4file'))
@@ -104,25 +103,25 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 410,
         name: '藏品登记',
         name: '藏品登记',
         path: '/register',
         path: '/register',
         Com: React.lazy(() => import('../Dmanage/D1register'))
         Com: React.lazy(() => import('../Dmanage/D1register'))
       },
       },
       {
       {
-        id: 101,
+        id: 420,
         name: '藏品修改',
         name: '藏品修改',
         path: '/edit',
         path: '/edit',
         Com: React.lazy(() => import('../Dmanage/D2edit'))
         Com: React.lazy(() => import('../Dmanage/D2edit'))
       },
       },
       {
       {
-        id: 102,
+        id: 430,
         name: '藏品注销',
         name: '藏品注销',
         path: '/writeOff',
         path: '/writeOff',
         Com: React.lazy(() => import('../Dmanage/D3writeOff'))
         Com: React.lazy(() => import('../Dmanage/D3writeOff'))
       },
       },
       {
       {
-        id: 103,
+        id: 440,
         name: '资源使用',
         name: '资源使用',
         path: '/resource',
         path: '/resource',
         Com: React.lazy(() => import('../Dmanage/D4resource'))
         Com: React.lazy(() => import('../Dmanage/D4resource'))
@@ -135,13 +134,13 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 601,
         name: '标签管理',
         name: '标签管理',
         path: '/tag',
         path: '/tag',
         Com: React.lazy(() => import('../Eculture/E1tag'))
         Com: React.lazy(() => import('../Eculture/E1tag'))
       },
       },
       {
       {
-        id: 101,
+        id: 602,
         name: '故事管理',
         name: '故事管理',
         path: '/story',
         path: '/story',
         Com: React.lazy(() => import('../Eculture/E2story'))
         Com: React.lazy(() => import('../Eculture/E2story'))
@@ -154,31 +153,31 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 1010,
         name: '藏品入库',
         name: '藏品入库',
         path: '/inStorage',
         path: '/inStorage',
         Com: React.lazy(() => import('../Fstorehouse/F1inStorage'))
         Com: React.lazy(() => import('../Fstorehouse/F1inStorage'))
       },
       },
       {
       {
-        id: 101,
+        id: 1020,
         name: '藏品移库',
         name: '藏品移库',
         path: '/moveStorage',
         path: '/moveStorage',
         Com: React.lazy(() => import('../Fstorehouse/F2moveStorage'))
         Com: React.lazy(() => import('../Fstorehouse/F2moveStorage'))
       },
       },
       {
       {
-        id: 102,
+        id: 1030,
         name: '藏品出库',
         name: '藏品出库',
         path: '/outStorage',
         path: '/outStorage',
         Com: React.lazy(() => import('../Fstorehouse/F3outStorage'))
         Com: React.lazy(() => import('../Fstorehouse/F3outStorage'))
       },
       },
       {
       {
-        id: 103,
+        id: 1040,
         name: '藏品盘点',
         name: '藏品盘点',
         path: '/check',
         path: '/check',
         Com: React.lazy(() => import('../Fstorehouse/F4check'))
         Com: React.lazy(() => import('../Fstorehouse/F4check'))
       },
       },
       {
       {
-        id: 104,
+        id: 1050,
         name: '人员出入库',
         name: '人员出入库',
         path: '/staff',
         path: '/staff',
         Com: React.lazy(() => import('../Fstorehouse/F5staff'))
         Com: React.lazy(() => import('../Fstorehouse/F5staff'))
@@ -192,19 +191,19 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 510,
         name: '事故登记',
         name: '事故登记',
         path: '/accident',
         path: '/accident',
         Com: React.lazy(() => import('../Gmaintain/G1accident'))
         Com: React.lazy(() => import('../Gmaintain/G1accident'))
       },
       },
       {
       {
-        id: 101,
+        id: 540,
         name: '现状登记',
         name: '现状登记',
         path: '/actuality',
         path: '/actuality',
         Com: React.lazy(() => import('../Gmaintain/G2actuality'))
         Com: React.lazy(() => import('../Gmaintain/G2actuality'))
       },
       },
       {
       {
-        id: 102,
+        id: 550,
         name: '修复登记',
         name: '修复登记',
         path: '/repair',
         path: '/repair',
         Com: React.lazy(() => import('../Gmaintain/G3repair'))
         Com: React.lazy(() => import('../Gmaintain/G3repair'))
@@ -217,7 +216,7 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 910,
         name: '借展管理',
         name: '借展管理',
         path: '/loan',
         path: '/loan',
         Com: React.lazy(() => import('../Hexhibits/H1loan'))
         Com: React.lazy(() => import('../Hexhibits/H1loan'))
@@ -231,50 +230,50 @@ const tabLeftArr: RouterType = [
     show: true,
     show: true,
     son: [
     son: [
       {
       {
-        id: 100,
+        id: 709,
         name: '库房设置',
         name: '库房设置',
         path: '/storageSet',
         path: '/storageSet',
         Com: React.lazy(() => import('../Isystem/I1storageSet'))
         Com: React.lazy(() => import('../Isystem/I1storageSet'))
       },
       },
       {
       {
-        id: 101,
+        id: 710,
         name: '数据字典',
         name: '数据字典',
         path: '/dict',
         path: '/dict',
         Com: React.lazy(() => import('../Isystem/I2dict'))
         Com: React.lazy(() => import('../Isystem/I2dict'))
       },
       },
       {
       {
-        id: 102,
+        id: 720,
         name: '编号设置',
         name: '编号设置',
         path: '/numSet',
         path: '/numSet',
         Com: React.lazy(() => import('../Isystem/I3numSet'))
         Com: React.lazy(() => import('../Isystem/I3numSet'))
       },
       },
       {
       {
-        id: 103,
+        id: 730,
         name: '流程设置',
         name: '流程设置',
         path: '/processSet',
         path: '/processSet',
         Com: React.lazy(() => import('../Isystem/I4processSet'))
         Com: React.lazy(() => import('../Isystem/I4processSet'))
       },
       },
       {
       {
-        id: 104,
+        id: 740,
         name: '组织管理',
         name: '组织管理',
         path: '/organization',
         path: '/organization',
         Com: React.lazy(() => import('../Isystem/I5organization'))
         Com: React.lazy(() => import('../Isystem/I5organization'))
       },
       },
       {
       {
-        id: 105,
+        id: 750,
         name: '角色管理',
         name: '角色管理',
         path: '/role',
         path: '/role',
         Com: React.lazy(() => import('../Isystem/I6role'))
         Com: React.lazy(() => import('../Isystem/I6role'))
       },
       },
       {
       {
-        id: 2100,
+        id: 760,
         name: '用户管理',
         name: '用户管理',
         path: '/user',
         path: '/user',
         Com: React.lazy(() => import('../Z1user'))
         Com: React.lazy(() => import('../Z1user'))
       },
       },
 
 
       {
       {
-        id: 2200,
+        id: 770,
         name: '系统日志',
         name: '系统日志',
         path: '/log',
         path: '/log',
         Com: React.lazy(() => import('../Z2log'))
         Com: React.lazy(() => import('../Z2log'))

+ 77 - 73
src/pages/Layout/index.tsx

@@ -18,22 +18,24 @@ import MyPopconfirm from '@/components/MyPopconfirm'
 import store from '@/store'
 import store from '@/store'
 import SpinLodingSon from '@/components/SpinLodingSon'
 import SpinLodingSon from '@/components/SpinLodingSon'
 import { DownOutlined, RightOutlined } from '@ant-design/icons'
 import { DownOutlined, RightOutlined } from '@ant-design/icons'
+import { I6_APIgetInfo } from '@/store/action/Isystem/I6role'
+import { TypeI6Role } from '../Isystem/I6role/data'
+import { useDispatch } from 'react-redux'
+import { I2_APIgetDict } from '@/store/action/Isystem/I2dict'
 
 
 function Layout() {
 function Layout() {
   const [loding, setLoding] = useState(false)
   const [loding, setLoding] = useState(false)
 
 
   // 获取字典值
   // 获取字典值
-  // const dispatch = useDispatch()
+  const dispatch = useDispatch()
 
 
   const getListFu = useCallback(() => {
   const getListFu = useCallback(() => {
-    // 待完善sg
-    setLoding(true)
-    // dispatch(
-    //   D1_APIgetlist(() => {
-    //     setLoding(true)
-    //   })
-    // )
-  }, [])
+    dispatch(
+      I2_APIgetDict(() => {
+        setLoding(true)
+      })
+    )
+  }, [dispatch])
 
 
   useEffect(() => {
   useEffect(() => {
     getListFu()
     getListFu()
@@ -75,90 +77,92 @@ function Layout() {
   const getUserAuthFu = useCallback(async () => {
   const getUserAuthFu = useCallback(async () => {
     const userInfo = getTokenInfo().user
     const userInfo = getTokenInfo().user
 
 
-    // const res = await D3_APIgetInfo(userInfo.roleId)
-
-    // if (res.code === 0) {
+    const res = await I6_APIgetInfo(userInfo.roleId)
 
 
-    const isOkIdArr: number[] = [9901]
-    // 待完善sg
-    for (let index = 100; index < 110; index++) {
-      isOkIdArr.push(index)
-    }
+    if (res.code === 0) {
+      const isOkIdArr: number[] = [9901]
+
+      const roleArr: TypeI6Role[] = res.data.permission
+
+      roleArr.forEach(v1 => {
+        if (v1.children) {
+          v1.children.forEach(v2 => {
+            if (v2.authority) isOkIdArr.push(v2.id)
+            if (v2.children) {
+              v2.children.forEach(v3 => {
+                if (v3.authority) isOkIdArr.push(v3.id)
+              })
+            }
+          })
+        }
+      })
 
 
-    const roleArr: any[] = []
+      // 详情页,也需要看下有没有页面权限
+      setRouterSonRes(routerSon.filter(v => isOkIdArr.includes(v.id)))
 
 
-    roleArr.forEach(v => {
-      if (v.authority) {
-        isOkIdArr.push(v.id)
+      // 是管理员
+      if (userInfo.isAdmin === 1) {
+        ;[750].forEach(v => {
+          isOkIdArr.push(v)
+        })
       }
       }
-    })
 
 
-    // 详情页,也需要看下有没有页面权限
-    setRouterSonRes(routerSon.filter(v => isOkIdArr.includes(v.id)))
-
-    // 是管理员
-    // 待完善sg-这里管理员应该只添加 角色管理 的页面权限,最后在修改
-    if (userInfo.isAdmin === 1) {
-      ;[2100, 2200, 2300, 2400, 2500].forEach(v => {
-        isOkIdArr.push(v)
-      })
-    }
+      // 页面权限id,存到仓库
+      store.dispatch({ type: 'layout/authorityIds', payload: isOkIdArr })
 
 
-    // 页面权限id,存到仓库
-    store.dispatch({ type: 'layout/authorityIds', payload: isOkIdArr })
+      const tempArr: RouterTypeRow[] = []
 
 
-    const tempArr: RouterTypeRow[] = []
+      // 权限数据存到仓库
+      const roleArrStoreArr: RouterTypeRow[] = []
 
 
-    // 权限数据存到仓库
-    const roleArrStoreArr: RouterTypeRow[] = []
+      tabLeftArr.forEach(v1 => {
+        if (v1.son && v1.son[0]) {
+          v1.son.forEach(v2 => {
+            if (isOkIdArr.includes(v2.id)) {
+              tempArr.push(v2)
 
 
-    tabLeftArr.forEach(v1 => {
-      if (v1.son && v1.son[0]) {
-        v1.son.forEach(v2 => {
-          if (isOkIdArr.includes(v2.id)) {
-            tempArr.push(v2)
-
-            // 过滤掉 藏品详情 页
-            if (v2.id < 9901) {
-              roleArrStoreArr.push({ ...v2, authority: true })
+              // 过滤掉 藏品详情 页
+              if (v2.id < 9901) {
+                roleArrStoreArr.push({ ...v2, authority: true })
+              }
             }
             }
-          }
-        })
-      }
-    })
+          })
+        }
+      })
 
 
-    // 权限数据存到仓库
-    store.dispatch({ type: 'layout/userRolePermissions', payload: roleArrStoreArr })
+      // 权限数据存到仓库
+      store.dispatch({ type: 'layout/userRolePermissions', payload: roleArrStoreArr })
 
 
-    setRouterCom(tempArr)
+      setRouterCom(tempArr)
 
 
-    // 如果当前页面没有权限了,跳转有权限的第一个页面
-    const urlAll = window.location.hash
-    const isNowPath = urlAll.replace('#', '')
-    const pathArr = tempArr.map(v => v.pathLast || v.path)
+      // 如果当前页面没有权限了,跳转有权限的第一个页面
+      const urlAll = window.location.hash
+      const isNowPath = urlAll.replace('#', '')
+      const pathArr = tempArr.map(v => v.pathLast || v.path)
 
 
-    const routerSonArr = routerSon.map(v => v.path)
+      const routerSonArr = routerSon.map(v => v.path)
 
 
-    const lastArr = [...pathArr, ...routerSonArr]
+      const lastArr = [...pathArr, ...routerSonArr]
 
 
-    let flagPush = true
+      let flagPush = true
 
 
-    lastArr.forEach(v => {
-      if (v === '/') {
-        if (isNowPath === '/') flagPush = false
-      } else {
-        if (isNowPath.includes(v)) flagPush = false
-      }
-    })
+      lastArr.forEach(v => {
+        if (v === '/') {
+          if (isNowPath === '/') flagPush = false
+        } else {
+          if (isNowPath.includes(v)) flagPush = false
+        }
+      })
 
 
-    if (flagPush) history.push(pathArr[0])
+      if (flagPush) history.push(pathArr[0])
 
 
-    const resList = tabLeftArr.map(v => ({
-      ...v,
-      son: v.son.filter(c => isOkIdArr.includes(c.id))
-    }))
+      const resList = tabLeftArr.map(v => ({
+        ...v,
+        son: v.son.filter(c => isOkIdArr.includes(c.id))
+      }))
 
 
-    setList(resList)
+      setList(resList)
+    }
   }, [])
   }, [])
 
 
   useEffect(() => {
   useEffect(() => {

+ 44 - 0
src/store/action/Isystem/I5organization.ts

@@ -0,0 +1,44 @@
+import { TypeI5Tree } from '@/pages/Isystem/I5organization/data'
+import { AppDispatch } from '@/store'
+import http from '@/utils/http'
+
+/**
+ * 组织管理 - 获取树列表
+ */
+export const I5_APIgetTree = (callFu?: (data: TypeI5Tree[]) => void): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.get('sys/dept/getTree')
+    if (res.code === 0) {
+      callFu && callFu(res.data)
+      dispatch({ type: 'I5/getTree', payload: res.data })
+    }
+  }
+}
+
+/**
+ * 组织管理 - 删除
+ */
+export const I5_APIdel = (id: string) => {
+  return http.get(`sys/dept/remove/${id}`)
+}
+
+/**
+ * 组织管理 - 获取详情
+ */
+export const I5_APIgetInfo = (id: string) => {
+  return http.get(`sys/dept/detail/${id}`)
+}
+
+/**
+ * 组织管理 - 新增或修改
+ */
+export const I5_APIsave = (data: any) => {
+  return http.post('sys/dept/save', data)
+}
+
+/**
+ * 组织管理 - 获取相关成员
+ */
+export const I5_APIgetUserById = (id: string) => {
+  return http.get(`sys/dept/user/list/${id}`)
+}

+ 46 - 0
src/store/action/Isystem/I6role.ts

@@ -0,0 +1,46 @@
+import { AppDispatch } from '@/store'
+import http from '@/utils/http'
+/**
+ * 角色管理 -获取分页列表
+ */
+export const I6_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('sys/role/listCountPage', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'I6/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 角色管理 -删除
+ */
+export const I6_APIdel = (id: number) => {
+  return http.get(`sys/role/remove/${id}`)
+}
+
+/**
+ * 角色管理 -新增--获取权限列表
+ */
+export const I6_APIgetAddTreeList = () => {
+  return http.get('sys/resource/getTreeResource')
+}
+
+/**
+ * 角色管理 -新增/编辑
+ */
+export const I6_APIsave = (data: any) => {
+  return http.post('sys/role/save', data)
+}
+
+/**
+ * 角色管理 -获取详情
+ */
+export const I6_APIgetInfo = (id: number) => {
+  return http.get(`sys/role/detail/${id}`)
+}

+ 1 - 1
src/store/reducer/Isystem/I2dict.ts

@@ -13,7 +13,7 @@ type Props = {
 }
 }
 
 
 // reducer
 // reducer
-export default function userReducer(state = initState, action: Props) {
+export default function Reducer(state = initState, action: Props) {
   switch (action.type) {
   switch (action.type) {
     // 获取字典数据
     // 获取字典数据
     case 'I2/getDictAll':
     case 'I2/getDictAll':

+ 1 - 1
src/store/reducer/Isystem/I3numSet.ts

@@ -13,7 +13,7 @@ type Props = {
 }
 }
 
 
 // reducer
 // reducer
-export default function userReducer(state = initState, action: Props) {
+export default function Reducer(state = initState, action: Props) {
   switch (action.type) {
   switch (action.type) {
     // 获取列表数据
     // 获取列表数据
     case 'I3/getList':
     case 'I3/getList':

+ 25 - 0
src/store/reducer/Isystem/I5organization.ts

@@ -0,0 +1,25 @@
+import { TypeI5Tree } from '@/pages/Isystem/I5organization/data'
+
+// 初始化状态
+const initState = {
+  // 树数据
+  treeData: [] as TypeI5Tree[]
+}
+
+// 定义 action 类型
+type Props = {
+  type: 'I5/getTree'
+  payload: TypeI5Tree[]
+}
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取树数据
+    case 'I5/getTree':
+      return { ...state, treeData: action.payload }
+
+    default:
+      return state
+  }
+}

+ 28 - 0
src/store/reducer/Isystem/I6role.ts

@@ -0,0 +1,28 @@
+import { TypeI6table } from '@/pages/Isystem/I6role/data'
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as TypeI6table[],
+    total: 0
+  }
+}
+
+// 定义 action 类型
+type Props = {
+  type: 'I6/getList'
+  payload: { list: TypeI6table[]; total: number }
+}
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case 'I6/getList':
+      return { ...state, tableInfo: action.payload }
+
+    default:
+      return state
+  }
+}

+ 4 - 0
src/store/reducer/index.ts

@@ -6,6 +6,8 @@ import A0Layout from './layout'
 
 
 import I2dict from './Isystem/I2dict'
 import I2dict from './Isystem/I2dict'
 import I3numSet from './Isystem/I3numSet'
 import I3numSet from './Isystem/I3numSet'
+import I5organization from './Isystem/I5organization'
+import I6role from './Isystem/I6role'
 import Z1user from './Z1user'
 import Z1user from './Z1user'
 import Z2log from './Z2log'
 import Z2log from './Z2log'
 
 
@@ -14,6 +16,8 @@ const rootReducer = combineReducers({
   A0Layout,
   A0Layout,
   I2dict,
   I2dict,
   I3numSet,
   I3numSet,
+  I5organization,
+  I6role,
   Z1user,
   Z1user,
   Z2log
   Z2log
 })
 })

+ 1 - 1
src/utils/storage.ts

@@ -3,7 +3,7 @@
 import { RouterTypeRow } from '@/types'
 import { RouterTypeRow } from '@/types'
 
 
 // 用户 Token 的本地缓存键名,自己定义
 // 用户 Token 的本地缓存键名,自己定义
-const TOKEN_KEY = 'JILINGGOODS_HOUTAI_USETINFO'
+const TOKEN_KEY = 'QING_DAO_PI_JIU_GOODS_HOUTAI_USETINFO'
 
 
 /**
 /**
  * 从本地缓存中获取 用户 信息
  * 从本地缓存中获取 用户 信息

+ 5 - 0
src/utils/tableData.ts

@@ -20,6 +20,11 @@ export const I3tableC = [
   ['txt', '日期方式', 'dateType'],
   ['txt', '日期方式', 'dateType'],
   ['txt', '起始流水编号', 'length']
   ['txt', '起始流水编号', 'length']
 ]
 ]
+export const I6tableC = [
+  ['txt', '角色名称', 'roleName'],
+  ['text', '角色说明', 'roleDesc', 50],
+  ['txt', '排序值', 'sort']
+]
 
 
 export const Z1tableC = [
 export const Z1tableC = [
   ['txt', '用户名', 'userName'],
   ['txt', '用户名', 'userName'],