Przeglądaj źródła

Merge branch 'master' of http://192.168.0.115:3000/shaogen1995/qingDao_goods

lanxin 11 godzin temu
rodzic
commit
3c00294ab6
64 zmienionych plików z 3478 dodań i 176 usunięć
  1. 1 0
      src/components/Z3upFiles/index.module.scss
  2. 1 0
      src/components/Z3upFilesRef/index.module.scss
  3. 101 0
      src/components/ZupOne/index.module.scss
  4. 295 0
      src/components/ZupOne/index.tsx
  5. 35 0
      src/pages/Abench/A2bench/A2editUser/index.module.scss
  6. 120 0
      src/pages/Abench/A2bench/A2editUser/index.tsx
  7. 59 0
      src/pages/Abench/A2bench/A2setStock/index.module.scss
  8. 117 0
      src/pages/Abench/A2bench/A2setStock/index.tsx
  9. 50 0
      src/pages/Abench/A2bench/A2table/index.module.scss
  10. 222 0
      src/pages/Abench/A2bench/A2table/index.tsx
  11. 119 0
      src/pages/Abench/A2bench/index.module.scss
  12. 158 1
      src/pages/Abench/A2bench/index.tsx
  13. 16 0
      src/pages/Dmanage/D4resource/D4edit/index.module.scss
  14. 130 0
      src/pages/Dmanage/D4resource/D4edit/index.tsx
  15. 95 1
      src/pages/Dmanage/D4resource/index.tsx
  16. 16 0
      src/pages/Fstorehouse/F2moveStorage/F2edit/index.module.scss
  17. 253 0
      src/pages/Fstorehouse/F2moveStorage/F2edit/index.tsx
  18. 122 1
      src/pages/Fstorehouse/F2moveStorage/index.tsx
  19. 15 8
      src/pages/Fstorehouse/F4check/F4edit/index.tsx
  20. 77 0
      src/pages/Fstorehouse/F5staff/F5edit/components/StaffModal.tsx
  21. 2 0
      src/pages/Fstorehouse/F5staff/F5edit/components/index.ts
  22. 22 0
      src/pages/Fstorehouse/F5staff/F5edit/index.module.scss
  23. 266 0
      src/pages/Fstorehouse/F5staff/F5edit/index.tsx
  24. 122 1
      src/pages/Fstorehouse/F5staff/index.tsx
  25. 7 4
      src/pages/Gmaintain/G1accident/G1edit/index.tsx
  26. 2 2
      src/pages/Gmaintain/G1accident/data.ts
  27. 4 0
      src/pages/Gmaintain/G2actuality/G2edit/index.module.scss
  28. 74 0
      src/pages/Gmaintain/G2actuality/G2edit/index.tsx
  29. 28 0
      src/pages/Gmaintain/G2actuality/data.ts
  30. 4 4
      src/pages/Gmaintain/G2actuality/index.module.scss
  31. 24 0
      src/pages/Gmaintain/G2actuality/index.tsx
  32. 5 0
      src/pages/Gmaintain/G3repair/G3edit/index.module.scss
  33. 74 0
      src/pages/Gmaintain/G3repair/G3edit/index.tsx
  34. 46 0
      src/pages/Gmaintain/G3repair/data.ts
  35. 4 4
      src/pages/Gmaintain/G3repair/index.module.scss
  36. 24 0
      src/pages/Gmaintain/G3repair/index.tsx
  37. 1 1
      src/pages/Isystem/I7user/I7add/index.tsx
  38. 1 1
      src/pages/Isystem/I7user/index.tsx
  39. 31 1
      src/pages/Layout/data.ts
  40. 9 3
      src/pages/Layout/index.module.scss
  41. 36 17
      src/pages/Layout/index.tsx
  42. 2 2
      src/pages/ZgoodsInfo/GItab5/index.tsx
  43. 6 3
      src/pages/Zother/EditBtn/index.tsx
  44. 59 1
      src/pages/Zother/EditInput/index.tsx
  45. 2 0
      src/pages/Zother/EditTop/index.module.scss
  46. 1 1
      src/pages/Zother/EditTop/index.tsx
  47. 26 0
      src/store/action/Abench/A2bench.ts
  48. 38 0
      src/store/action/Dmanage/D4resource.ts
  49. 45 0
      src/store/action/Fstorehouse/F2moveStorage.ts
  50. 31 0
      src/store/action/Fstorehouse/F5staff.ts
  51. 38 0
      src/store/action/Gmaintain/G2actuality.ts
  52. 38 0
      src/store/action/Gmaintain/G3repair.ts
  53. 28 0
      src/store/reducer/Dmanage/D4resource.ts
  54. 28 0
      src/store/reducer/Fstorehouse/F2moveStorage.ts
  55. 28 0
      src/store/reducer/Fstorehouse/F5staff.ts
  56. 28 0
      src/store/reducer/Gmaintain/G2actuality.ts
  57. 28 0
      src/store/reducer/Gmaintain/G3repair.ts
  58. 41 0
      src/store/reducer/ZformData.ts
  59. 16 1
      src/store/reducer/index.ts
  60. 16 3
      src/store/reducer/layout.ts
  61. 5 0
      src/utils/http.ts
  62. 122 85
      src/utils/pass.ts
  63. 19 22
      src/utils/storage.ts
  64. 45 9
      src/utils/tableData.ts

+ 1 - 0
src/components/Z3upFiles/index.module.scss

@@ -71,6 +71,7 @@
 
       .Z3filesRow {
         width: 100%;
+        max-width: 786px;
         display: flex;
         align-items: center;
         padding: 0px 12px;

+ 1 - 0
src/components/Z3upFilesRef/index.module.scss

@@ -77,6 +77,7 @@
 
       .Z3filesRow {
         width: 100%;
+        max-width: 786px;
         display: flex;
         align-items: center;
         padding: 0px 12px;

+ 101 - 0
src/components/ZupOne/index.module.scss

@@ -0,0 +1,101 @@
+.ZupOne {
+  width: 100%;
+  height: 100%;
+  position: relative;
+
+  :global {
+    .file_upIcon {
+      color: #a6a6a6;
+      border-radius: 3px;
+      cursor: pointer;
+      font-size: 30px;
+      width: 100px;
+      height: 100px;
+      border: 1px dashed #797979;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+
+    .file_img {
+      width: 100px;
+      height: 126px;
+      position: relative;
+      margin-top: 10px;
+
+      .file_closeBox {
+        position: absolute;
+        right: -10px;
+        top: -10px;
+        z-index: 99;
+        background-color: rgba(0, 0, 0, 0.8);
+        width: 20px;
+        height: 20px;
+        border-radius: 50%;
+        font-size: 16px;
+        color: #fff;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+      }
+
+      .file_lookBox {
+        width: 100%;
+        background-color: rgba(0, 0, 0, 0.6);
+        color: #fff;
+        display: flex;
+        justify-content: space-around;
+
+        & > a {
+          color: #fff !important;
+        }
+
+        font-size: 16px;
+      }
+    }
+
+    .file_imgYuan {
+      #ImageLazy {
+        border-radius: 50%;
+        overflow: hidden;
+      }
+    }
+
+    .fileInfo {
+      display: flex;
+      align-items: center;
+      font-size: 16px;
+
+      .clearCover {
+        margin-left: 20px;
+        cursor: pointer;
+        font-size: 16px;
+      }
+
+      & > a {
+        color: black;
+      }
+    }
+
+    .fileBoxRow_r_tit {
+      height: 46px;
+      margin-top: 5px;
+      font-size: 14px;
+      color: rgb(126, 124, 124);
+    }
+
+    .noUpThumb {
+      position: relative;
+      overflow: hidden;
+      opacity: 0;
+      transition: top 0.2s;
+      color: #ff4d4f;
+      top: -10px;
+    }
+
+    .noUpThumbAc {
+      top: 0;
+      opacity: 1;
+    }
+  }
+}

+ 295 - 0
src/components/ZupOne/index.tsx

@@ -0,0 +1,295 @@
+import React, { useCallback, useMemo, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import ImageLazy from '@/components/ImageLazy'
+import {
+  PlusOutlined,
+  EyeOutlined,
+  CloseOutlined,
+  DownloadOutlined,
+  UploadOutlined
+} from '@ant-design/icons'
+import store from '@/store'
+import { baseURL } from '@/utils/http'
+import classNames from 'classnames'
+import { Button } from 'antd'
+import { MessageFu } from '@/utils/message'
+import { fileDomInitialFu } from '@/utils/domShow'
+import { API_upFile } from '@/store/action/layout'
+import { forwardRef, useImperativeHandle } from 'react'
+import MyPopconfirm from '../MyPopconfirm'
+
+type MyTypeType = 'thumb' | 'video' | 'audio' | 'model' | 'pdf' | 'epub'
+
+// 这个组件 只处理 上传 一张图片或者 视频 音频 模型 pdf 的情况
+
+type Props = {
+  fileCheck: boolean //有没有点击过确定
+  dirCode: string //文件的code码
+  myUrl: string //请求地址
+  format: string[] //上传格式 ["image/jpeg", "image/png"] ["video/mp4"] ,application/pdf
+  formatTxt: string //上传图片提示
+  checkTxt: string
+  upTxt: string
+  myType: MyTypeType
+  isLook?: boolean //是不是查看
+  fromData?: any
+  ref: any //当前自己的ref,给父组件调用
+  isTouXiang?: boolean //圆形头像展示
+}
+
+function ZupOne(
+  {
+    fileCheck,
+    dirCode,
+    myUrl,
+    format,
+    formatTxt,
+    checkTxt,
+    upTxt,
+    myType,
+    isLook = false,
+    fromData,
+    isTouXiang
+  }: Props,
+  ref: any
+) {
+  const [fileUrl, setFileUrl] = useState({
+    fileName: '',
+    filePath: '',
+    thumb: '' //压缩图
+  })
+
+  const myInput = useRef<HTMLInputElement>(null)
+
+  // 上传封面图
+  const handeUpPhoto = useCallback(
+    async (e: React.ChangeEvent<HTMLInputElement>) => {
+      if (e.target.files) {
+        // 拿到files信息
+        const filesInfo = e.target.files[0]
+        // console.log("-----", filesInfo.type);
+
+        // 校验格式
+        const type = format
+
+        if (myType === 'pdf') {
+          if (!filesInfo.type.includes('pdf')) {
+            e.target.value = ''
+            return MessageFu.warning(`只支持${formatTxt}格式!`)
+          }
+        } else if (myType === 'epub') {
+          if (!filesInfo.name.endsWith('.epub')) {
+            e.target.value = ''
+            return MessageFu.warning(`只支持${formatTxt}格式!`)
+          }
+        } else {
+          if (!type.includes(filesInfo.type)) {
+            e.target.value = ''
+            return MessageFu.warning(`只支持${formatTxt}格式!`)
+          }
+        }
+
+        // 校验大小
+        // if (filesInfo.size > size * 1024 * 1024) {
+        //   e.target.value = ''
+        //   return MessageFu.warning(`最大支持${size}M!`)
+        // }
+        // 创建FormData对象
+        const fd = new FormData()
+        // 把files添加进FormData对象(‘photo’为后端需要的字段)
+        let myTypeRes: string = myType
+        if (['pdf', 'epub'].includes(myTypeRes)) myTypeRes = 'doc'
+        fd.append('type', myTypeRes === 'thumb' ? 'img' : myTypeRes)
+        fd.append('dirCode', dirCode)
+        fd.append('file', filesInfo)
+
+        if (fromData) {
+          for (const k in fromData) {
+            if (fromData[k]) fd.append(k, fromData[k])
+          }
+        }
+
+        // 开启压缩图片
+        fd.append('isCompress', 'true')
+
+        e.target.value = ''
+
+        try {
+          const res = await API_upFile(fd, myUrl)
+          if (res.code === 0) {
+            MessageFu.success('上传成功!')
+            setFileUrl(res.data)
+          }
+          fileDomInitialFu()
+        } catch (error) {
+          fileDomInitialFu()
+        }
+      }
+    },
+    [dirCode, format, formatTxt, fromData, myType, myUrl]
+  )
+
+  // 让父组件调用的 回显 附件 地址
+  const setFileComFileFu = useCallback(
+    (valObj: { fileName: string; filePath: string; thumb: string }) => {
+      setFileUrl(valObj)
+    },
+    []
+  )
+
+  // 让父组件调用的返回 附件 名字和路径
+  const fileComFileResFu = useCallback(() => {
+    return fileUrl
+  }, [fileUrl])
+
+  // 可以让父组件调用子组件的方法
+  useImperativeHandle(ref, () => ({
+    setFileComFileFu,
+    fileComFileResFu
+  }))
+
+  const acceptRes = useMemo(() => {
+    let accept = '.png,.jpg,.jpeg'
+    if (myType === 'video') accept = '.mp4'
+    else if (myType === 'audio') accept = '.mp3'
+    else if (myType === 'model') accept = '.4dage'
+    else if (myType === 'pdf') accept = '.pdf'
+    else if (myType === 'epub') accept = '.epub'
+    return accept
+  }, [myType])
+
+  // 点击 预览(除了图片)
+  const lookFileNoImgFu = useCallback(
+    (type: MyTypeType) => {
+      if (type === 'pdf' || type === 'thumb') {
+        // 新窗口打开
+        window.open(baseURL + fileUrl.filePath)
+      } else if (type !== 'epub') {
+        store.dispatch({
+          type: 'layout/lookDom',
+          payload: { src: fileUrl.filePath, type }
+        })
+      }
+
+      // if (type === "pdf") {
+      // } else {
+      // }
+    },
+    [fileUrl.filePath]
+  )
+
+  return (
+    <div className={styles.ZupOne}>
+      <input
+        id='upInput'
+        type='file'
+        accept={acceptRes}
+        ref={myInput}
+        onChange={e => handeUpPhoto(e)}
+      />
+      {myType === 'thumb' ? (
+        <div
+          hidden={fileUrl.filePath !== ''}
+          className='file_upIcon'
+          onClick={() => myInput.current?.click()}
+        >
+          <PlusOutlined rev={undefined} />
+        </div>
+      ) : (
+        <Button
+          hidden={fileUrl.filePath !== ''}
+          onClick={() => myInput.current?.click()}
+          icon={<UploadOutlined rev={undefined} />}
+        >
+          上传
+        </Button>
+      )}
+
+      {/* 为图片的情况-------------- */}
+      {myType === 'thumb' ? (
+        <div
+          className={classNames('file_img', isTouXiang ? 'file_imgYuan' : '')}
+          hidden={fileUrl.filePath === ''}
+        >
+          {fileUrl ? (
+            <ImageLazy
+              width={100}
+              height={100}
+              srcBig={fileUrl.filePath}
+              src={fileUrl.thumb}
+              noLook
+            />
+          ) : null}
+
+          {/* 删除 */}
+          <div className='file_closeBox' hidden={isLook}>
+            <MyPopconfirm
+              txtK='删除'
+              onConfirm={() => setFileUrl({ fileName: '', filePath: '', thumb: '' })}
+              Dom={<CloseOutlined rev={undefined} />}
+            />
+          </div>
+
+          {/* 预览 下载 */}
+          <div className='file_lookBox' hidden={isTouXiang}>
+            <EyeOutlined
+              onClick={() =>
+                store.dispatch({
+                  type: 'layout/lookBigImg',
+                  payload: { url: baseURL + fileUrl.filePath, show: true }
+                })
+              }
+              rev={undefined}
+            />
+            <a href={baseURL + fileUrl.filePath} download target='_blank' rel='noreferrer'>
+              <DownloadOutlined rev={undefined} />
+            </a>
+          </div>
+        </div>
+      ) : fileUrl.filePath ? (
+        <div className='fileInfo'>
+          <div className='upSuccTxt'>{fileUrl.fileName}</div>
+          {/* 视频预览 */}
+          <div
+            className='clearCover'
+            hidden={!fileUrl.filePath || myType === 'epub'}
+            onClick={() => lookFileNoImgFu(myType)}
+          >
+            <EyeOutlined rev={undefined} />
+          </div>
+          {/* 视频下载 */}
+          <a
+            href={baseURL + fileUrl.filePath}
+            download
+            target='_blank'
+            className='clearCover'
+            rel='noreferrer'
+          >
+            <DownloadOutlined rev={undefined} />
+          </a>
+          {/* 视频删除 */}
+
+          {isLook ? null : (
+            <MyPopconfirm
+              txtK='删除'
+              onConfirm={() => setFileUrl({ fileName: '', filePath: '', thumb: '' })}
+              Dom={<CloseOutlined className='clearCover' rev={undefined} />}
+            />
+          )}
+        </div>
+      ) : null}
+
+      <div className='fileBoxRow_r_tit' hidden={isLook}>
+        格式要求:支持{formatTxt}格式。{upTxt}
+        <br />
+        <div
+          className={classNames('noUpThumb', !fileUrl.filePath && fileCheck ? 'noUpThumbAc' : '')}
+        >
+          {checkTxt}
+        </div>
+      </div>
+    </div>
+  )
+}
+
+export default forwardRef(ZupOne)

+ 35 - 0
src/pages/Abench/A2bench/A2editUser/index.module.scss

@@ -0,0 +1,35 @@
+.A2editUser {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal {
+      width: 800px !important;
+    }
+    .A2Emain {
+      border-top: 1px solid #999999;
+      padding-top: 15px;
+      width: 100%;
+
+      // 封面
+      .formRow {
+        display: flex;
+        margin-bottom: 24px;
+        .formLeft {
+          width: 100px;
+          text-align: right;
+          position: relative;
+          top: 4px;
+          & > span {
+            color: #ff4d4f;
+          }
+        }
+      }
+
+      .A2Ebtn {
+        margin-top: 20px;
+        text-align: center;
+      }
+    }
+  }
+}

+ 120 - 0
src/pages/Abench/A2bench/A2editUser/index.tsx

@@ -0,0 +1,120 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Input, Modal } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { MessageFu } from '@/utils/message'
+import { UserTableListType } from '@/pages/Isystem/I7user/data'
+import { A2_APIeditUser } from '@/store/action/Abench/A2bench'
+import ZupOne from '@/components/ZupOne'
+
+type Props = {
+  closeFu: () => void
+  userInfo: UserTableListType
+  succFu: (obj: any) => void
+}
+
+function A2editUser({ closeFu, userInfo, succFu }: Props) {
+  const [realName, setRealName] = useState('')
+
+  // 头像的ref
+  const ZupThumbRef = useRef<any>(null)
+
+  useEffect(() => {
+    setRealName(userInfo.realName)
+    // 设置头像
+    ZupThumbRef.current?.setFileComFileFu({
+      fileName: '',
+      filePath: userInfo.thumb,
+      thumb: userInfo.thumb
+    })
+  }, [userInfo])
+
+  const [fileCheck, setFileCheck] = useState(false)
+
+  const btnOk = useCallback(async () => {
+    setFileCheck(true)
+
+    // 头像
+    const coverUrl1 = ZupThumbRef.current?.fileComFileResFu()
+
+    if (!coverUrl1.thumb) return
+
+    const obj = {
+      id: userInfo.id,
+      realName,
+      thumb: coverUrl1.thumb
+    }
+
+    const res = await A2_APIeditUser(obj)
+
+    if (res.code === 0) {
+      MessageFu.success('编辑成功')
+      succFu(obj)
+      closeFu()
+    }
+  }, [closeFu, realName, succFu, userInfo.id])
+
+  return (
+    <Modal
+      wrapClassName={styles.A2editUser}
+      destroyOnClose
+      open={true}
+      title='个人资料'
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='A2Emain'>
+        <div className='formRow'>
+          <div className='formLeft'>
+            <span> * </span>真实姓名:
+          </div>
+          <div className='formRight'>
+            <Input
+              style={{ width: 300 }}
+              maxLength={10}
+              showCount
+              placeholder='请输入内容'
+              value={realName}
+              onChange={e => setRealName(e.target.value.replace(/\s+/g, ''))}
+            />
+          </div>
+        </div>
+
+        {/* 封面 */}
+        <div className='formRow'>
+          <div className='formLeft'>
+            <span> * </span> 头像:
+          </div>
+          <div className='formRight'>
+            <ZupOne
+              ref={ZupThumbRef}
+              isLook={false}
+              fileCheck={fileCheck}
+              dirCode='businessEditUser'
+              myUrl='sys/user/upload'
+              format={['image/jpeg', 'image/png']}
+              formatTxt='png、jpg和jpeg'
+              checkTxt='请上传头像!'
+              upTxt='最多1张'
+              myType='thumb'
+              isTouXiang={true}
+            />
+          </div>
+        </div>
+
+        <div className='A2Ebtn'>
+          <Button type='primary' onClick={btnOk}>
+            提交
+          </Button>
+          &emsp;
+          <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+        </div>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoA2editUser = React.memo(A2editUser)
+
+export default MemoA2editUser

+ 59 - 0
src/pages/Abench/A2bench/A2setStock/index.module.scss

@@ -0,0 +1,59 @@
+.A2setStock {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal {
+      width: 800px !important;
+    }
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+      .A2Smain {
+        margin-top: 20px;
+
+        .Z5eboxrr {
+          width: 100%;
+          .Z5eRow {
+            margin-bottom: 10px;
+            display: flex;
+
+            .Z5eRow1 {
+              width: 70px;
+              font-weight: 700;
+              text-align: right;
+              margin-right: 10px;
+            }
+
+            .Z5eRow2 {
+              width: calc(100% - 80px);
+            }
+          }
+
+          .Z5eErr {
+            margin-bottom: 20px;
+            text-align: center;
+            color: #ff4d4f;
+            opacity: 0;
+            pointer-events: none;
+            transition: all 0.3s;
+            position: relative;
+            top: -10px;
+          }
+
+          .Z5eErrAc {
+            opacity: 1;
+            top: 0;
+          }
+          .Z5eboxrr_1 {
+            margin-top: 5px;
+          }
+        }
+
+        .A2Sbtn {
+          margin-top: 20px;
+          text-align: center;
+        }
+      }
+    }
+  }
+}

+ 117 - 0
src/pages/Abench/A2bench/A2setStock/index.tsx

@@ -0,0 +1,117 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, Checkbox, Modal } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import classNmaes from 'classnames'
+import { MessageFu } from '@/utils/message'
+import { A2_APIsetStock } from '@/store/action/Abench/A2bench'
+import { RouterType } from '@/pages/Layout/data'
+
+type Props = {
+  sId: number
+  arr: RouterType
+  closeFu: () => void
+  succFu: () => void
+}
+
+function A2setStock({ arr, closeFu, succFu, sId }: Props) {
+  const [roleArr, setRoleArr] = useState<RouterType>([])
+
+  useEffect(() => {
+    setRoleArr(arr)
+  }, [arr])
+
+  // 多选框变化
+  const onChange = useCallback(
+    (val: boolean, id1: number, id2: number) => {
+      setRoleArr(
+        roleArr.map(v => ({
+          ...v,
+          son:
+            v.id === id1
+              ? v.son.map(c => ({
+                  ...c,
+                  authority: c.id === id2 ? val : c.authority
+                }))
+              : v.son
+        }))
+      )
+    },
+    [roleArr]
+  )
+
+  // 二级选中的数组id集合
+  const checkIds = useMemo(() => {
+    const arr: number[] = []
+    roleArr.forEach(v => {
+      v.son.forEach(c => {
+        if (c.authority) arr.push(c.id)
+      })
+    })
+    return arr
+  }, [roleArr])
+
+  // 点击提交
+  const btnOk = useCallback(async () => {
+    const res = await A2_APIsetStock(sId, JSON.stringify(roleArr))
+    if (res.code === 0) {
+      MessageFu.success('设置成功')
+      succFu()
+      closeFu()
+    }
+  }, [closeFu, roleArr, sId, succFu])
+
+  return (
+    <Modal
+      wrapClassName={styles.A2setStock}
+      open={true}
+      title='常用功能'
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <div className='A2Smain'>
+        <div className='Z5eboxrr'>
+          {roleArr.map(v => (
+            <div
+              key={v.id}
+              className='Z5eRow'
+              hidden={v.son.length === 0 || (v.son.length === 1 && v.son[0].name === '工作台')}
+            >
+              <div className='Z5eRow1'>{v.name}</div>
+              <div className='Z5eRow2'>
+                {v.son.map(c =>
+                  c.name === '工作台' ? null : (
+                    <Checkbox
+                      key={c.id}
+                      checked={c.authority}
+                      onChange={e => onChange(e.target.checked, v.id, c.id)}
+                    >
+                      {c.name}
+                    </Checkbox>
+                  )
+                )}
+              </div>
+            </div>
+          ))}
+
+          <div className={classNmaes('Z5eErr', checkIds.length <= 0 ? 'Z5eErrAc' : '')}>
+            至少选中一个
+          </div>
+        </div>
+
+        <div className='A2Sbtn'>
+          <Button type='primary' disabled={checkIds.length <= 0} onClick={btnOk}>
+            提交
+          </Button>
+          &emsp;
+          <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+        </div>
+      </div>
+    </Modal>
+  )
+}
+
+const MemoA2setStock = React.memo(A2setStock)
+
+export default MemoA2setStock

+ 50 - 0
src/pages/Abench/A2bench/A2table/index.module.scss

@@ -0,0 +1,50 @@
+.A2table {
+  width: 100%;
+  padding: 20px;
+  background-color: #fff;
+  border-radius: 10px;
+  margin-top: 20px;
+
+  :global {
+    .A2Ttop {
+      display: flex;
+      justify-content: space-between;
+      margin-bottom: 15px;
+
+      .A2TtopLL {
+        display: flex;
+        align-items: center;
+        .ant-btn {
+          margin-right: 15px;
+        }
+        & > div {
+          font-weight: 700;
+          font-size: 18px;
+          position: relative;
+          padding-left: 16px;
+          margin-right: 20px;
+          &::before {
+            content: '';
+            position: absolute;
+            top: 48%;
+            left: 0;
+            transform: translateY(-50%);
+            width: 5px;
+            height: 20px;
+            background-color: var(--themeColor);
+          }
+        }
+      }
+
+      .A2TtopRR {
+        display: flex;
+        & > div {
+          margin-left: 15px;
+        }
+      }
+    }
+    .ant-table-cell {
+      padding: 8px !important;
+    }
+  }
+}

+ 222 - 0
src/pages/Abench/A2bench/A2table/index.tsx

@@ -0,0 +1,222 @@
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { Button, DatePicker, Input, Select } from 'antd'
+import tabLeftArr, { RouterTypeRow } from '@/pages/Layout/data'
+import MyTable from '@/components/MyTable'
+import { MessageFu } from '@/utils/message'
+import { A2_APIgetList } from '@/store/action/Abench/A2bench'
+import { GI5tableType } from '@/pages/ZgoodsInfo/data'
+import { authorityFu, tableListAuditBtnFu } from '@/utils/authority'
+import history from '@/utils/history'
+import { selectObj } from '@/utils/dataChange'
+import { GI5tableC } from '@/utils/tableData'
+import { useSelector } from 'react-redux'
+import store, { RootState } from '@/store'
+
+const { RangePicker } = DatePicker
+
+const btnArr = [
+  { name: '我发起的', key: '1' },
+  { name: '待我审批', key: '2' }
+]
+
+function A2table() {
+  // 路由信息过滤过来
+  const typePageArr = useMemo(() => {
+    const arr: RouterTypeRow[] = []
+    tabLeftArr.forEach(v1 => {
+      v1.son.forEach(v2 => {
+        if (v2.pageType) arr.push(v2)
+      })
+    })
+    return arr
+  }, [])
+
+  const [formData, setFormData] = useState({} as any)
+
+  // 回调页面的时候 回显参数
+  const A2formData = useSelector((state: RootState) => state.ZformData.A2formData)
+
+  useEffect(() => {
+    setFormData({ ...A2formData })
+  }, [A2formData])
+
+  const getListFu = useCallback(async () => {
+    if (formData.pageNum) {
+      const res = await A2_APIgetList(formData)
+      if (res.code === 0) {
+        setTableObj({ list: res.data.records || [], total: res.data.total })
+      }
+    }
+  }, [formData])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 时间选择器改变
+  const timeChange = useCallback(
+    (date: any, dateString: any) => {
+      let startTime = ''
+      let endTime = ''
+      if (dateString[0] && dateString[1]) {
+        startTime = dateString[0] + ' 00:00:00'
+        endTime = dateString[1] + ' 23:59:59'
+      }
+      setFormData({ ...formData, startTime, endTime, pageNum: 1 })
+    },
+    [formData]
+  )
+
+  // 页码变化
+  const paginationChange = useCallback(
+    (pageNum: number, pageSize: number) => {
+      setFormData({ ...formData, pageNum, pageSize })
+    },
+    [formData]
+  )
+
+  // 输入框的输入
+  const timeRef = useRef(-1)
+  const txtChangeFu = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>, key: 'num') => {
+      clearTimeout(timeRef.current)
+      timeRef.current = window.setTimeout(() => {
+        setFormData({
+          ...formData,
+          [key]: e.target.value.replaceAll("'", ''),
+          pageNum: 1
+        })
+      }, 500)
+    },
+    [formData]
+  )
+
+  const [tableObj, setTableObj] = useState<{ list: GI5tableType[]; total: number }>({
+    list: [],
+    total: 0
+  })
+
+  const btnFu = useCallback(
+    (pageKey: '3' | '4', obj: any, id: number) => {
+      if (obj) {
+        store.dispatch({ type: 'ZF/A2formData', payload: formData })
+        authorityFu(obj.id, obj.name, () => history.push(`${obj.path}_edit/${pageKey}/${id}`))
+      } else MessageFu.warning('业务类型错误')
+    },
+    [formData]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: any) => {
+          const obj = typePageArr.find(v => v.pageType === item.type)
+          return (
+            <>
+              <Button size='small' type='text' onClick={() => btnFu('4', obj, item.id)}>
+                查看
+              </Button>
+
+              {tableListAuditBtnFu(item) ? (
+                <Button size='small' type='text' onClick={() => btnFu('3', obj, item.id)}>
+                  审批
+                </Button>
+              ) : null}
+            </>
+          )
+        }
+      }
+    ]
+  }, [btnFu, typePageArr])
+
+  const staBtn = useMemo(() => {
+    return [
+      {
+        title: '业务类型',
+        render: (item: GI5tableType) => {
+          let txt = '(空)'
+          const obj = typePageArr.find(v => v.pageType === item.type)
+          if (obj) txt = obj.name
+          return txt
+        }
+      }
+    ]
+  }, [typePageArr])
+
+  return (
+    <div className={styles.A2table}>
+      <div className='A2Ttop'>
+        <div className='A2TtopLL'>
+          <div>申请管理</div>
+          {btnArr.map(v => (
+            <Button
+              onClick={() => setFormData({ ...formData, auditType: v.key, pageNum: 1 })}
+              key={v.key}
+              type={formData.auditType === v.key ? 'primary' : 'default'}
+            >
+              {v.name}
+            </Button>
+          ))}
+        </div>
+        <div className='A2TtopRR'>
+          <div>
+            <Select
+              allowClear={true}
+              placeholder='业务类型'
+              style={{ width: 150 }}
+              value={formData.type ? formData.type : null}
+              onChange={e => setFormData({ ...formData, type: e, pageNum: 1 })}
+              options={typePageArr.map(v => ({ value: v.pageType, label: v.name }))}
+            />
+          </div>
+
+          <div>
+            <Input
+              style={{ width: 150 }}
+              placeholder='请输入业务编号'
+              maxLength={30}
+              onChange={e => txtChangeFu(e, 'num')}
+            />
+          </div>
+
+          <div>
+            <RangePicker
+              style={{ width: 260 }}
+              onChange={timeChange}
+              placeholder={['发起日期开始', '发起日期结束']}
+            />
+          </div>
+
+          <div>
+            <Select
+              allowClear={true}
+              placeholder='申请状态'
+              style={{ width: 150 }}
+              value={formData.status ? formData.status : null}
+              onChange={e => setFormData({ ...formData, status: e, pageNum: 1 })}
+              options={selectObj['订单审批状态']}
+            />
+          </div>
+        </div>
+      </div>
+
+      {/* 表格 */}
+      <MyTable
+        list={tableObj.list}
+        columnsTemp={GI5tableC(true)}
+        lastBtn={tableLastBtn}
+        staBtn={staBtn}
+        pageNum={formData.pageNum}
+        pageSize={formData.pageSize}
+        total={tableObj.total}
+        onChange={(pageNum, pageSize) => paginationChange(pageNum, pageSize)}
+      />
+    </div>
+  )
+}
+
+const MemoA2table = React.memo(A2table)
+
+export default MemoA2table

+ 119 - 0
src/pages/Abench/A2bench/index.module.scss

@@ -1,4 +1,123 @@
 .A2bench {
+  display: flex;
+  justify-content: space-between;
+  font-size: 16px;
   :global {
+    .A2tit {
+      height: 52px;
+      font-weight: 700;
+      font-size: 18px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-bottom: 10px;
+      position: relative;
+      padding-left: 16px;
+      &::before {
+        content: '';
+        position: absolute;
+        top: 48%;
+        left: 0;
+        transform: translateY(-50%);
+        width: 5px;
+        height: 20px;
+        background-color: var(--themeColor);
+      }
+    }
+    .A2none {
+      width: 100%;
+      height: 70px;
+      font-weight: 700;
+      font-size: 18px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+
+    .A2ll {
+      width: 100%;
+      height: 100%;
+      overflow-y: auto;
+
+      .A2ll1 {
+        height: 100px;
+        background-color: #fff;
+        border-radius: 10px;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 0 24px;
+        .A2ll1_1 {
+          display: flex;
+          img {
+            width: 70px;
+            height: 70px;
+            border-radius: 50%;
+          }
+          .A2ll1_1Txt {
+            margin-left: 30px;
+            & > h1 {
+              font-size: 18px;
+            }
+            & > p {
+              margin-top: 20px;
+            }
+          }
+        }
+      }
+
+      .A2ll2 {
+        margin-top: 15px;
+        display: flex;
+        justify-content: space-between;
+
+        .A2ll2_1 {
+          width: 100%;
+          padding: 10px 20px 0px;
+          background-color: #fff;
+          border-radius: 10px;
+        }
+        // .A2ll2_2 {
+        //   width: 500px;
+        //   margin-left: 20px;
+        //   padding: 10px 20px 0px;
+        //   background-color: #fff;
+        //   border-radius: 10px;
+        // }
+
+        .A2ll2RowBox {
+          display: flex;
+          flex-wrap: wrap;
+          align-items: center;
+          .A2ll2Row {
+            cursor: pointer;
+            transition: all 0.3s;
+            margin-right: 20px;
+            margin-bottom: 20px;
+            height: 90px;
+            width: 100px;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+            & > img {
+              width: 40px;
+              height: auto;
+              transition: all 0.3s;
+            }
+            & > p {
+              font-size: 14px;
+              margin-top: 10px;
+            }
+            &:hover {
+              color: var(--themeColor);
+              & > img {
+                transform: scale(1.1);
+              }
+            }
+          }
+        }
+      }
+    }
   }
 }

+ 158 - 1
src/pages/Abench/A2bench/index.tsx

@@ -1,9 +1,166 @@
-import React from 'react'
+import React, { useCallback, useEffect, useState } from 'react'
 import styles from './index.module.scss'
+import { useSelector } from 'react-redux'
+import store, { RootState } from '@/store'
+import { Button } from 'antd'
+import { baseURL, iconUrl } from '@/utils/http'
+import baseTouXiangImg from '@/assets/img/user.png'
+import { getTokenInfo, removeTokenInfo, setTokenInfo } from '@/utils/storage'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import history from '@/utils/history'
+import { getUserInfoByIdAPI } from '@/store/action/Isystem/I7user'
+import { RouterType } from '@/pages/Layout/data'
+import A2table from './A2table'
+import A2setStock from './A2setStock'
+import A2editUser from './A2editUser'
+
+const userInfoJting = getTokenInfo().user || {}
+
 function A2bench() {
+  // 设置常用功能
+  const userRolePermissions = useSelector((state: RootState) => state.A0Layout.userRolePermissions)
+  const [stockShow, setStockShow] = useState(false)
+  const [stockList, setStockList] = useState<RouterType>([])
+
+  const getUserInfo = useCallback(async () => {
+    const res = await getUserInfoByIdAPI(userInfoJting.id)
+    if (res.code === 0) {
+      store.dispatch({ type: 'layout/userInfo', payload: res.data })
+      // 设置常用功能
+      if (res.data.permRtf) {
+        setStockList(JSON.parse(res.data.permRtf || '[]'))
+      } else setStockList(userRolePermissions)
+    }
+  }, [userRolePermissions])
+
+  useEffect(() => {
+    getUserInfo()
+  }, [getUserInfo])
+
+  // 获取组织管理列表
+  // const dispatch = useDispatch()
+  // useEffect(() => {
+  //   dispatch(I5_APIgetTree())
+  // }, [dispatch])
+
+  // const { treeData } = useSelector((state: RootState) => state.I5organization)
+
+  const { userInfo } = useSelector((state: RootState) => state.A0Layout)
+
+  // 点击退出登录
+  const loginExit = () => {
+    removeTokenInfo()
+    history.push('/login')
+  }
+
+  // 点击编辑个人资料
+  const [editUser, setEditUser] = useState(false)
+
+  // 更新用户信息
+  const upUserInfoFu = useCallback(
+    (obj: any) => {
+      const userInfoOld = getTokenInfo()
+      setTokenInfo({
+        ...userInfoOld,
+        user: {
+          ...userInfoOld.user,
+          thumb: obj.thumb,
+          realName: obj.realName
+        }
+      })
+      getUserInfo()
+    },
+    [getUserInfo]
+  )
+
   return (
     <div className={styles.A2bench}>
       <div className='pageTitle'>工作台</div>
+      <div className='A2ll'>
+        {/* 顶部盒子 */}
+        <div className='A2ll1'>
+          <div className='A2ll1_1'>
+            <img src={userInfo.thumb ? baseURL + userInfo.thumb : baseTouXiangImg} alt='' />
+            <div className='A2ll1_1Txt'>
+              <h1>{userInfo.realName || userInfo.userName || '匿名'}</h1>
+              <p>
+                {userInfo.userName}
+                {userInfo.deptName ? <>&emsp;{userInfo.deptName}</> : null}
+                &emsp;|&emsp;{userInfo.roleName}
+              </p>
+            </div>
+          </div>
+          <div className='A2ll1_2'>
+            <Button onClick={() => setEditUser(true)}>编辑个人资料</Button>&emsp;
+            <Button onClick={() => store.dispatch({ type: 'layout/passEditShow', payload: true })}>
+              修改密码
+            </Button>
+            &emsp;
+            <MyPopconfirm
+              txtK='退出登录'
+              onConfirm={loginExit}
+              Dom={<Button>退出登录</Button>}
+              loc='bottom'
+            />
+          </div>
+        </div>
+        <div className='A2ll2'>
+          {/* 常用功能*/}
+          <div className='A2ll2_1'>
+            <div className='A2tit'>
+              <div>常用功能</div>
+              <div>
+                <Button onClick={() => setStockShow(true)}>设置</Button>
+              </div>
+            </div>
+            <div className='A2ll2RowBox'>
+              {stockList.map(v1 =>
+                v1.son.map(v2 =>
+                  v2.authority && v2.name !== '工作台' ? (
+                    <div key={v2.id} className='A2ll2Row' onClick={() => history.push(v2.path)}>
+                      <img src={`${iconUrl}/${v2.name}.png`} alt='' />
+                      <p>{v2.name}</p>
+                    </div>
+                  ) : null
+                )
+              )}
+            </div>
+          </div>
+          {/* 最近使用 */}
+          {/* <div className='A2ll2_2'>
+            <div className='A2tit'>最近使用</div>
+            <div className='A2ll2RowBox'>
+              {changGetFu().length ? (
+                changGetFu().map((v, i) => (
+                  <div key={i} className='A2ll2Row' onClick={() => history.push(v.path)}>
+                    <img src={`${baseURL}/baseData/tabImg/${v.name}.png`} alt='' />
+                    <p>{v.name}</p>
+                  </div>
+                ))
+              ) : (
+                <div className='A2none'>暂无信息</div>
+              )}
+            </div>
+          </div> */}
+        </div>
+        {/* 表格 */}
+        <A2table />
+      </div>
+
+      {/* 编辑个人资料 */}
+      {editUser ? (
+        <A2editUser closeFu={() => setEditUser(false)} userInfo={userInfo} succFu={upUserInfoFu} />
+      ) : null}
+
+      {/* 设置常用功能 */}
+      {stockShow ? (
+        <A2setStock
+          sId={userInfoJting.id}
+          arr={stockList}
+          closeFu={() => setStockShow(false)}
+          succFu={getUserInfo}
+        />
+      ) : null}
     </div>
   )
 }

+ 16 - 0
src/pages/Dmanage/D4resource/D4edit/index.module.scss

@@ -0,0 +1,16 @@
+.D4edit {
+  :global {
+    .D4editResource {
+      width: 100%;
+      border-top: 1px solid #ccc;
+      padding: 15px;
+      display: flex;
+      align-items: center;
+      gap: 15px;
+    }
+    .D4editResourceTitle {
+      font-weight: 700;
+      font-size: 18px;
+    }
+  }
+}

+ 130 - 0
src/pages/Dmanage/D4resource/D4edit/index.tsx

@@ -0,0 +1,130 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import EditTop from '@/pages/Zother/EditTop'
+import EditBtn from '@/pages/Zother/EditBtn'
+import { InfoProvider, useInfo } from '@/pages/Zother/InfoContext'
+import SonGoodsList from '@/pages/Zother/SonGoodsList'
+import FileArchive from '@/pages/Zother/FileArchive'
+import { getDictFu, selectObj } from '@/utils/dataChange'
+import { D4_APIgetClueList, D4API_obj } from '@/store/action/Dmanage/D4resource'
+import { Checkbox } from 'antd'
+import { useParams } from 'react-router-dom'
+
+const rowArr = [
+  {
+    name: `资源使用`,
+    type: 'txt'
+  },
+  {
+    name: `使用日期`,
+    must: true,
+    key: ['dateStart', 'dateEnd'],
+    modeKey: 'dateMode',
+    type: 'DatePicker2'
+  },
+  {
+    name: '申请编号',
+    must: true,
+    key: 'num',
+    type: 'Input',
+    noNull: true //不允许输入空格
+  },
+  {
+    name: '申请类型',
+    key: 'dictIdApply',
+    type: 'Cascader',
+    options: getDictFu('资源使用')
+  },
+  {
+    name: '事由说明',
+    full: true,
+    key: 'reason',
+    type: 'TextArea'
+  },
+  {
+    name: '备注',
+    full: true,
+    key: 'remark',
+    type: 'TextArea'
+  }
+]
+
+function D4editContent() {
+  const { info } = useInfo() as { info: any }
+  const { key } = useParams<any>()
+  const [resourceType, setResourceType] = useState<string[]>(
+    key === '1' ? selectObj['附件类型'].map((v: any) => v.value) : []
+  )
+  const canEdit = useMemo(() => ['1', '2'].includes(key), [key])
+
+  const handleResourceTypeChange = useCallback((val: string[]) => {
+    setResourceType(val)
+  }, [])
+
+  const getExtraData = () => {
+    return {
+      snapType: resourceType.join(',')
+    }
+  }
+
+  useEffect(() => {
+    if (!info.snapType) return
+    setResourceType(info.snapType.split(','))
+  }, [info.snapType])
+
+  return (
+    <div className={styles.D4edit} id='editBox'>
+      <div className='editMain'>
+        {/* 顶部 */}
+        <EditTop
+          pageTxt='申请信息'
+          rowArr={rowArr}
+          APIobj={D4API_obj}
+          fileUpInfo={{ myUrl: 'cms/order/resource/upload', dirCode: 'resource' }}
+        />
+
+        <div className='D4editResource'>
+          <p className='D4editResourceTitle'>资源类型</p>
+          <Checkbox.Group
+            disabled={!canEdit}
+            options={selectObj['附件类型']}
+            value={resourceType}
+            onChange={handleResourceTypeChange}
+          />
+        </div>
+
+        {/* 藏品清单 */}
+        <SonGoodsList
+          fileUpInfo={{ myUrl: 'cms/order/resource/son/upload', dirCode: 'resourceGoods' }}
+          selectApi={D4_APIgetClueList}
+          addShow={false}
+          isClueSelect={false}
+          btnTxt='选择藏品'
+        />
+
+        {/* 附件归档 */}
+        <FileArchive />
+
+        {/* 底部按钮 */}
+        <EditBtn
+          path='/resource'
+          APIobj={D4API_obj}
+          checkListTxt='请添加藏品'
+          getExtraData={getExtraData}
+        />
+      </div>
+    </div>
+  )
+}
+
+function D4edit() {
+  return (
+    <InfoProvider>
+      <D4editContent />
+    </InfoProvider>
+  )
+}
+
+const MemoD4edit = React.memo(D4edit)
+
+export default MemoD4edit

+ 95 - 1
src/pages/Dmanage/D4resource/index.tsx

@@ -1,9 +1,103 @@
-import React from 'react'
+import React, { useCallback, useRef } from 'react'
 import styles from './index.module.scss'
+import TableList from '@/pages/Zother/TableList'
+import { tableListAuditBtnFu } from '@/utils/authority'
+import { selectObj } from '@/utils/dataChange'
+import { resourceTableC } from '@/utils/tableData'
+import { Button } from 'antd'
+import { baseFormData } from '@/pages/Zother/data'
+import { RootState } from '@/store'
+import { useSelector } from 'react-redux'
+import { useHistory } from 'react-router-dom'
+import { D4_APIgetList } from '@/store/action/Dmanage/D4resource'
+
+const D4baseFormData = baseFormData()
+
 function D4resource() {
+  const tableListRef = useRef<any>(null)
+  const history = useHistory()
+  // 从仓库拿数据
+  const tableInfo = useSelector((state: RootState) => state.D4resource.tableInfo)
+
+  const dataExport = () => {
+    console.log('数据导出了')
+  }
+
+  const tableBtnFu = useCallback(
+    (id: number | null, key: string) => {
+      history.push(`/resource_edit/${key}/${id}`)
+    },
+    [history]
+  )
+
   return (
     <div className={styles.D4resource}>
       <div className='pageTitle'>资源使用</div>
+
+      <TableList
+        ref={tableListRef}
+        baseFormData={D4baseFormData}
+        getListAPI={D4_APIgetList}
+        pageKey='resource'
+        tableInfo={tableInfo}
+        columnsTemp={resourceTableC}
+        rightBtnWidth={340}
+        yHeight={585}
+        searchDom={[
+          {
+            type: 'time',
+            key: ['startTime', 'endTime'],
+            placeholder: `使用日期`
+          },
+          {
+            type: 'input',
+            key: 'searchKey',
+            placeholder: `请输入申请编号、发起人、藏品编号或名称`
+          },
+          {
+            type: 'time',
+            key: ['businessStartTime', 'businessEndTime'],
+            placeholder: `发起日期`
+          },
+          {
+            type: 'select',
+            key: 'status',
+            placeholder: `申请状态`,
+            options: selectObj['藏品入库申请状态']
+          }
+        ]}
+        storyTableListToprr={({ clickSearch, resetSelectFu }) => (
+          <>
+            <Button type='primary' ghost onClick={() => tableBtnFu(null, '1')}>
+              发起申请
+            </Button>
+            <Button type='primary' onClick={dataExport}>
+              数据导出
+            </Button>
+            <Button type='primary' onClick={clickSearch}>
+              查询
+            </Button>
+            <Button onClick={resetSelectFu}>重置</Button>
+          </>
+        )}
+        storyTableLastBtn={[
+          {
+            title: '操作',
+            render: (item: any) => (
+              <>
+                <Button type='text' onClick={() => tableBtnFu(item.id, '4')}>
+                  查看
+                </Button>
+                {tableListAuditBtnFu(item) ? (
+                  <Button size='small' type='text' onClick={() => tableBtnFu(item.id, '3')}>
+                    审批
+                  </Button>
+                ) : null}
+              </>
+            )
+          }
+        ]}
+      />
     </div>
   )
 }

+ 16 - 0
src/pages/Fstorehouse/F2moveStorage/F2edit/index.module.scss

@@ -0,0 +1,16 @@
+.F2edit {
+  :global {
+    .F2editStorage {
+      width: 100%;
+      border-top: 1px solid #ccc;
+      padding: 15px;
+      display: flex;
+      align-items: center;
+      gap: 15px;
+    }
+    .F2editStorageTitle {
+      font-weight: 700;
+      font-size: 18px;
+    }
+  }
+}

+ 253 - 0
src/pages/Fstorehouse/F2moveStorage/F2edit/index.tsx

@@ -0,0 +1,253 @@
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { useParams } from 'react-router-dom'
+import styles from './index.module.scss'
+import EditTop from '@/pages/Zother/EditTop'
+import EditBtn from '@/pages/Zother/EditBtn'
+import { InfoProvider, useInfo } from '@/pages/Zother/InfoContext'
+import { rowArrTemp } from '@/pages/Zother/data'
+import SonGoodsList from '@/pages/Zother/SonGoodsList'
+import { Button, Select } from 'antd'
+import { selectObj } from '@/utils/dataChange'
+import FileArchive from '@/pages/Zother/FileArchive'
+import { F1_APIgetShelfList, F1_APIgetStorageList } from '@/store/action/Fstorehouse/F1inStorage'
+import {
+  F2_APIgetClueList,
+  F2_APIgetShelfEmptyList,
+  F2API_obj
+} from '@/store/action/Fstorehouse/F2moveStorage'
+
+const rowArr = rowArrTemp('移库')
+
+function F2editContent() {
+  const { info } = useInfo() as { info: any }
+  const { key } = useParams<any>()
+  const canEdit = useMemo(() => ['1', '2'].includes(key), [key])
+  const sonGoodsListRef = useRef<any>(null)
+  const [outStorage, setoutStorage] = useState<any>(null)
+  const [inStorage, setinStorage] = useState<any>(null)
+  const [allWarehouseList, setAllWarehouseList] = useState<any[]>([])
+  const warehouseOptions = useMemo(() => {
+    return allWarehouseList.map((i: any) => ({
+      label: i.name,
+      value: i.id,
+      managerUser: i.managerUser
+    }))
+  }, [allWarehouseList])
+  const [shelfList, setShelfList] = useState<any[]>([])
+
+  const handleOutStorageChange = useCallback(async (value: string, option: any) => {
+    setoutStorage(option)
+  }, [])
+
+  const handleInStorageChange = useCallback(async (value: string, option: any) => {
+    setinStorage(option)
+    const res = await F1_APIgetShelfList({ storageId: value })
+    setShelfList(
+      res.data.map((i: any) => ({
+        label: [i.layer1, i.layer2, i.layer3, i.layer4].filter(i => Boolean(i)).join('-'),
+        value: i.id
+      }))
+    )
+  }, [])
+
+  const handleAutoAssignShelf = async () => {
+    const snaps = sonGoodsListRef.current?.snaps ?? []
+    if (!snaps.length) return
+    const res = await F2_APIgetShelfEmptyList({
+      storageId: outStorage?.value,
+      limit: snaps.length
+    })
+    const idList: { id: number }[] = Array.isArray(res) ? res : (res?.data ?? [])
+    const form = sonGoodsListRef.current?.tableRef?.current?.form
+    if (!form) return
+    const values: Record<string, number | undefined> = {}
+    snaps.forEach((snap: any, i: number) => {
+      values[`${snap.id}-storageInId`] = idList[i]?.id
+    })
+    form.setFieldsValue(values)
+  }
+
+  const getStorageList = useCallback(async () => {
+    const res = await F1_APIgetStorageList()
+    setAllWarehouseList(res.data.records)
+  }, [])
+
+  useEffect(() => {
+    getStorageList()
+  }, [getStorageList])
+
+  useEffect(() => {
+    if (!info?.storageId || !allWarehouseList.length) return
+    const opt = warehouseOptions.find((o: any) => o.value === info.storageId)
+    const outOpt = warehouseOptions.find((o: any) => o.value === info.snaps[0]?.storageOutId)
+    if (opt && outOpt) {
+      setoutStorage(outOpt)
+      setinStorage(opt)
+      F1_APIgetShelfList({ storageId: info.storageId }).then(res => {
+        setShelfList(
+          res.data.map((i: any) => ({
+            label: [i.layer1, i.layer2, i.layer3, i.layer4].filter(i => Boolean(i)).join('-'),
+            value: i.id
+          }))
+        )
+      })
+    }
+  }, [info?.storageId, allWarehouseList.length, warehouseOptions, info?.snaps])
+
+  const verifyBackFu = (info: any) => {
+    if (!outStorage) return { flag: true, txt: '请选择入库库房' }
+    const form = sonGoodsListRef.current?.tableRef?.current?.form
+    if (!form) return { flag: true, txt: '请添加藏品' }
+    const values = form.getFieldsValue()
+    const snaps = sonGoodsListRef.current?.snaps ?? []
+    const hasEmptyStorage = snaps.some((snap: any) => !values[`${snap.id}-storageInId`])
+    if (hasEmptyStorage) return { flag: true, txt: '请为藏品选择库房位置' }
+    return { flag: false, txt: '' }
+  }
+
+  const getExtraData = (info: any, snaps: any[]) => {
+    const form = sonGoodsListRef.current?.tableRef?.current?.form
+    const values = form?.getFieldsValue() ?? {}
+    const snapsArr = snaps.map((v: any) => {
+      const flag = v.pageType === 'clue' && !v.clueId
+      const siteId = values[`${v.id}-storageInId`] ?? null
+      const siteLoc = shelfList.find((s: any) => s.value === siteId)?.label ?? null
+      return {
+        goodId: v.isNew || flag ? null : v.id,
+        orderId: info.id,
+        storageOutId: outStorage?.value ?? null,
+        storageInId: inStorage?.value ?? null,
+        snap: JSON.stringify({
+          ...v,
+          id: v.isNew || flag ? null : v.id,
+          siteLoc,
+          siteId,
+          storageInId: siteId
+        })
+      }
+    })
+    return {
+      storageId: inStorage?.value ?? undefined,
+      extraInfo:
+        inStorage?.value === outStorage?.value
+          ? inStorage.label
+          : `${outStorage.label} -> ${inStorage.label}`,
+      snaps: snapsArr
+    }
+  }
+
+  return (
+    <div className={styles.F2edit} id='editBox'>
+      <div className='editMain'>
+        {/* 顶部 */}
+        {/* TODO: 借展归还待完善 */}
+        <EditTop
+          pageTxt='申请信息'
+          rowArr={rowArr}
+          APIobj={F2API_obj}
+          fileUpInfo={{ myUrl: 'cms/orderSite/move/upload', dirCode: 'moveStorage' }}
+        />
+
+        <div className='F2editStorage'>
+          <p className='F2editStorageTitle'>*移出库房</p>
+          <Select
+            style={{ width: 200 }}
+            options={warehouseOptions}
+            placeholder='请选择'
+            value={outStorage?.value}
+            onChange={handleOutStorageChange}
+            disabled={!canEdit}
+          />
+
+          <p className='F2editStorageTitle'>*移入库房</p>
+          <Select
+            style={{ width: 200 }}
+            options={warehouseOptions}
+            placeholder='请选择'
+            value={inStorage?.value}
+            onChange={handleInStorageChange}
+            disabled={!canEdit}
+          />
+        </div>
+
+        {/* 藏品清单 */}
+        <SonGoodsList
+          ref={sonGoodsListRef}
+          needEdit={true}
+          btnTxt='选择藏品'
+          addShow={false}
+          customRightBtn={
+            <Button
+              disabled={!inStorage?.value || !canEdit}
+              type='primary'
+              ghost
+              onClick={handleAutoAssignShelf}
+            >
+              自动分配空置位置
+            </Button>
+          }
+          goodsSonTable={[
+            ['txt', '藏品登记号', 'num'],
+            ['img', '封面', 'thumb'],
+            ['txtCTag', '藏品标签', 'tagDictId'],
+            ['txt', '藏品名称', 'name'],
+            ['select', '级别', 'level', selectObj['藏品级别']],
+            ['txtC', '类别', 'typeDictId'],
+            ['txtC', '年代', 'ageDictId'],
+            ['txtC', '质地', 'textureDictId'],
+            ['select', '完残程度', 'tornLevel', selectObj['完残程度']],
+            ['ping', '数量', 'pcs', 'pcsUnitDictId'],
+            [
+              'custom',
+              '移入位置',
+              'storageInId',
+              {
+                render(_readOnly?: boolean) {
+                  return (
+                    <Select
+                      allowClear
+                      options={shelfList}
+                      disabled={!canEdit}
+                      placeholder='请选择'
+                    />
+                  )
+                }
+              }
+            ]
+          ]}
+          fileUpInfo={{ myUrl: 'cms/orderSite/in/upload', dirCode: 'inStorageGoods' }}
+          selectApi={F2_APIgetClueList}
+          isClueSelect={false}
+          clueShowBtnDisabled={!outStorage?.value}
+          selectGoodsParams={{
+            storageId: outStorage?.value
+          }}
+        />
+
+        {/* 附件归档 */}
+        <FileArchive />
+
+        {/* 底部按钮 */}
+        <EditBtn
+          path='/moveStorage'
+          APIobj={F2API_obj}
+          checkListTxt='请添加藏品'
+          verifyBackFu={verifyBackFu}
+          getExtraData={getExtraData}
+        />
+      </div>
+    </div>
+  )
+}
+
+function F2edit() {
+  return (
+    <InfoProvider>
+      <F2editContent />
+    </InfoProvider>
+  )
+}
+
+const MemoF2edit = React.memo(F2edit)
+
+export default MemoF2edit

+ 122 - 1
src/pages/Fstorehouse/F2moveStorage/index.tsx

@@ -1,9 +1,130 @@
-import React from 'react'
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import styles from './index.module.scss'
+import TableList from '@/pages/Zother/TableList'
+import { F2_APIgetList } from '@/store/action/Fstorehouse/F2moveStorage'
+import { tableListAuditBtnFu } from '@/utils/authority'
+import { moveStorageTableC } from '@/utils/tableData'
+import { Button } from 'antd'
+import { baseFormData } from '@/pages/Zother/data'
+import { RootState } from '@/store'
+import { F1_APIgetStorageList } from '@/store/action/Fstorehouse/F1inStorage'
+import { selectObj } from '@/utils/dataChange'
+import { useSelector } from 'react-redux'
+import { useHistory } from 'react-router-dom'
+
+const F2baseFormData = baseFormData()
+
 function F2moveStorage() {
+  const tableListRef = useRef<any>(null)
+  const history = useHistory()
+  // 从仓库拿数据
+  const tableInfo = useSelector((state: RootState) => state.F2moveStorage.tableInfo)
+  const [allWarehouseList, setAllWarehouseList] = useState<any[]>([])
+  const warehouseOptions = useMemo(() => {
+    return allWarehouseList.map((i: any) => ({
+      label: i.name,
+      value: i.id
+    }))
+  }, [allWarehouseList])
+  const SEARCH_DOM = useMemo(
+    () => [
+      {
+        type: 'time',
+        key: ['startTime', 'endTime'],
+        placeholder: `移库时间`
+      },
+      {
+        type: 'select',
+        key: 'storageId',
+        placeholder: `相关库房`,
+        options: warehouseOptions
+      },
+      {
+        type: 'input',
+        key: 'searchKey',
+        placeholder: `请输入申请编号、发起人或藏品编号`
+      },
+      {
+        type: 'time',
+        key: ['businessStartTime', 'businessEndTime'],
+        placeholder: `发起日期`
+      },
+      {
+        type: 'select',
+        key: 'status',
+        placeholder: `申请状态`,
+        options: selectObj['藏品入库申请状态']
+      }
+    ],
+    [warehouseOptions]
+  )
+
+  const dataExport = () => {
+    console.log('数据导出了')
+  }
+
+  const getStorageList = async () => {
+    const res = await F1_APIgetStorageList()
+    setAllWarehouseList(res.data.records)
+  }
+
+  const tableBtnFu = useCallback(
+    (id: number | null, key: string) => {
+      history.push(`/moveStorage_edit/${key}/${id}`)
+    },
+    [history]
+  )
+
+  useEffect(() => {
+    getStorageList()
+  }, [])
+
   return (
     <div className={styles.F2moveStorage}>
       <div className='pageTitle'>藏品移库</div>
+
+      <TableList
+        ref={tableListRef}
+        baseFormData={F2baseFormData}
+        getListAPI={F2_APIgetList}
+        pageKey='position'
+        tableInfo={tableInfo}
+        columnsTemp={moveStorageTableC}
+        rightBtnWidth={340}
+        yHeight={585}
+        searchDom={SEARCH_DOM}
+        storyTableListToprr={({ clickSearch, resetSelectFu }) => (
+          <>
+            <Button type='primary' ghost onClick={() => tableBtnFu(null, '1')}>
+              发起申请
+            </Button>
+            <Button type='primary' onClick={dataExport}>
+              数据导出
+            </Button>
+            <Button type='primary' onClick={clickSearch}>
+              查询
+            </Button>
+            <Button onClick={resetSelectFu}>重置</Button>
+          </>
+        )}
+        storyTableLastBtn={[
+          {
+            title: '操作',
+            render: (item: any) => (
+              <>
+                <Button type='text' onClick={() => tableBtnFu(item.id, '4')}>
+                  查看
+                </Button>
+                {tableListAuditBtnFu(item) ? (
+                  <Button size='small' type='text' onClick={() => tableBtnFu(item.id, '3')}>
+                    审批
+                  </Button>
+                ) : null}
+              </>
+            )
+          }
+        ]}
+      />
     </div>
   )
 }

+ 15 - 8
src/pages/Fstorehouse/F4check/F4edit/index.tsx

@@ -7,7 +7,7 @@ import { InfoProvider, useInfo } from '@/pages/Zother/InfoContext'
 import { rowArrTemp } from '@/pages/Zother/data'
 import SonGoodsList from '@/pages/Zother/SonGoodsList'
 import { F1_APIgetStorageList, F1API_obj } from '@/store/action/Fstorehouse/F1inStorage'
-import { Button, Dropdown, MenuProps, Select } from 'antd'
+import { Button, Dropdown, Select } from 'antd'
 import { selectObj } from '@/utils/dataChange'
 import FileArchive from '@/pages/Zother/FileArchive'
 import {
@@ -21,18 +21,21 @@ import { GoodsType } from '@/pages/Zother/SonGoodsList/data'
 import { openLink } from '@/utils/history'
 
 const rowArr = rowArrTemp('入库')
-const registerMenu: MenuProps['items'] = [
+const registerMenu = [
   {
     key: 'accident',
-    label: '事故登记'
+    label: '事故登记',
+    type: 'SG'
   },
   {
     key: 'actuality',
-    label: '现状登记'
+    label: '现状登记',
+    type: 'XZ'
   },
   {
     key: 'repair',
-    label: '修复登记'
+    label: '修复登记',
+    type: 'XF'
   }
 ]
 
@@ -144,7 +147,7 @@ function F1editContent() {
     if (!isLook || !info.num) return
     F4_APIgetRelatedOrderList(info.num).then((res: any) => {
       if (res.code === 0) {
-        setRelatedOrderList(res.data.records)
+        setRelatedOrderList(res.data)
       }
     })
   }, [info.num, isLook])
@@ -258,12 +261,16 @@ function F1editContent() {
             lastBtn={[
               {
                 title: '操作',
-                render: (item: GoodsType) => {
+                render: (item: any) => {
                   return (
                     <Button
                       size='small'
                       type='text'
-                      onClick={() => openLink(`/goodsLook/${item.id}`)}
+                      onClick={() =>
+                        openLink(
+                          `/${registerMenu.find(v => v.type === item.type)?.key}_edit/4/${item.id}?pNum=${`${item.num},${item.id}`}`
+                        )
+                      }
                     >
                       查看
                     </Button>

+ 77 - 0
src/pages/Fstorehouse/F5staff/F5edit/components/StaffModal.tsx

@@ -0,0 +1,77 @@
+import React, { useEffect } from 'react'
+import { Form, Input, Modal } from 'antd'
+import { decodeIfEncoded } from '@/utils/pass'
+
+export type StaffFormValues = {
+  name: string
+  papers: string
+  phone: string
+  unit: string
+}
+
+type Props = {
+  open: boolean
+  editingStaff: Partial<StaffFormValues> | null
+  onOk: (values: StaffFormValues) => void
+  onCancel: () => void
+}
+
+function StaffModal({ open, editingStaff, onOk, onCancel }: Props) {
+  const [form] = Form.useForm<StaffFormValues>()
+
+  useEffect(() => {
+    if (open) {
+      if (editingStaff) {
+        form.setFieldsValue({
+          name: editingStaff.name ?? '',
+          papers: decodeIfEncoded(editingStaff.papers ?? ''),
+          phone: decodeIfEncoded(editingStaff.phone ?? ''),
+          unit: editingStaff.unit ?? ''
+        })
+      } else {
+        form.resetFields()
+      }
+    }
+  }, [open, editingStaff, form])
+
+  const handleOk = () => {
+    form.validateFields().then(values => {
+      onOk(values)
+      form.resetFields()
+    })
+  }
+
+  const handleCancel = () => {
+    form.resetFields()
+    onCancel()
+  }
+
+  return (
+    <Modal
+      destroyOnClose
+      title={editingStaff ? '编辑人员' : '新增人员'}
+      open={open}
+      onOk={handleOk}
+      onCancel={handleCancel}
+      okText='确定'
+      cancelText='取消'
+    >
+      <Form form={form} layout='vertical'>
+        <Form.Item label='姓名' name='name' rules={[{ required: true, message: '请输入姓名' }]}>
+          <Input placeholder='请输入姓名' />
+        </Form.Item>
+        <Form.Item label='证件信息' name='papers'>
+          <Input placeholder='请输入证件信息' />
+        </Form.Item>
+        <Form.Item label='联系方式' name='phone'>
+          <Input placeholder='请输入联系方式' />
+        </Form.Item>
+        <Form.Item label='所在单位' name='unit'>
+          <Input placeholder='请输入所在单位' />
+        </Form.Item>
+      </Form>
+    </Modal>
+  )
+}
+
+export default StaffModal

+ 2 - 0
src/pages/Fstorehouse/F5staff/F5edit/components/index.ts

@@ -0,0 +1,2 @@
+export { default as StaffModal } from './StaffModal'
+export type { StaffFormValues } from './StaffModal'

+ 22 - 0
src/pages/Fstorehouse/F5staff/F5edit/index.module.scss

@@ -0,0 +1,22 @@
+.F5edit {
+  :global {
+    .F5editStorage {
+      width: 100%;
+      border-top: 1px solid #ccc;
+      padding: 15px;
+      display: flex;
+      align-items: center;
+      gap: 15px;
+    }
+    .F5editStorageTitle {
+      font-weight: 700;
+      font-size: 18px;
+    }
+    .F5editStorageTitleBox {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+    }
+  }
+}

+ 266 - 0
src/pages/Fstorehouse/F5staff/F5edit/index.tsx

@@ -0,0 +1,266 @@
+import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import { useParams } from 'react-router-dom'
+import styles from './index.module.scss'
+import EditTop from '@/pages/Zother/EditTop'
+import EditBtn from '@/pages/Zother/EditBtn'
+import { InfoProvider, useInfo } from '@/pages/Zother/InfoContext'
+import { F1_APIgetStorageList } from '@/store/action/Fstorehouse/F1inStorage'
+import { Button, Select, Space } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import FileArchive from '@/pages/Zother/FileArchive'
+import { F5API_obj } from '@/store/action/Fstorehouse/F5staff'
+import { getDictFu } from '@/utils/dataChange'
+import encodeStr, { getStaffDisplayPapers, getStaffDisplayPhone } from '@/utils/pass'
+import MyTable from '@/components/MyTable'
+import { StaffModal } from './components'
+
+const rowArr = [
+  {
+    name: `人员出入库`,
+    type: 'txt'
+  },
+  {
+    name: `出入日期`,
+    must: true,
+    key: 'date',
+    type: 'DatePicker'
+  },
+  {
+    name: '申请编号',
+    must: true,
+    key: 'num',
+    type: 'Input',
+    noNull: true //不允许输入空格
+  },
+  {
+    name: '申请类型',
+    key: 'dictIdApply',
+    type: 'Cascader',
+    options: getDictFu('人员出入库')
+  },
+  {
+    name: '事由说明',
+    full: true,
+    key: 'reason',
+    type: 'TextArea'
+  },
+  {
+    name: '备注',
+    full: true,
+    key: 'remark',
+    type: 'TextArea'
+  }
+]
+
+function F5editContent() {
+  const { info, setSnapsFu, snaps } = useInfo() as {
+    info: any
+    setSnapsFu: (snaps: any[]) => void
+    snaps: any[]
+  }
+  const { key } = useParams<any>()
+  const canEdit = useMemo(() => ['1', '2'].includes(key), [key])
+  const [selectStorage, setSelectStorage] = useState<any>(null)
+  const [allWarehouseList, setAllWarehouseList] = useState<any[]>([])
+  const warehouseOptions = useMemo(() => {
+    return allWarehouseList.map((i: any) => ({
+      label: i.name,
+      value: i.id,
+      managerUser: i.managerUser
+    }))
+  }, [allWarehouseList])
+
+  const handleStorageChange = useCallback(async (value: string, option: any) => {
+    setSelectStorage(option)
+  }, [])
+
+  const getStorageList = useCallback(async () => {
+    const res = await F1_APIgetStorageList()
+    setAllWarehouseList(res.data.records)
+  }, [])
+
+  useEffect(() => {
+    getStorageList()
+  }, [getStorageList])
+
+  const [staffModalOpen, setStaffModalOpen] = useState(false)
+  const [editingStaff, setEditingStaff] = useState<any>(null)
+  const staffList = snaps
+
+  const openAddStaff = useCallback(() => {
+    setEditingStaff(null)
+    setStaffModalOpen(true)
+  }, [])
+
+  const openEditStaff = useCallback((item: any) => {
+    setEditingStaff(item)
+    setStaffModalOpen(true)
+  }, [])
+
+  const handleStaffModalOk = useCallback(
+    (values: { name: string; papers: string; phone: string; unit: string }) => {
+      const staffItem = {
+        name: values.name,
+        papers: encodeStr(values.papers),
+        phone: encodeStr(values.phone),
+        unit: values.unit
+      }
+      if (editingStaff) {
+        const next = staffList.map((v: any) =>
+          (v.idTemp ?? v.id) === (editingStaff.idTemp ?? editingStaff.id)
+            ? { ...v, ...staffItem }
+            : v
+        )
+        setSnapsFu(next as any)
+      } else {
+        setSnapsFu([...staffList, { ...staffItem, idTemp: Date.now() }] as any)
+      }
+      setStaffModalOpen(false)
+    },
+    [editingStaff, staffList, setSnapsFu]
+  )
+
+  const handleDeleteStaff = useCallback(
+    (item: any) => {
+      setSnapsFu(
+        staffList.filter((v: any) => (v.idTemp ?? v.id) !== (item.idTemp ?? item.id)) as any
+      )
+    },
+    [staffList, setSnapsFu]
+  )
+
+  const verifyBackFu = (info: any) => {
+    if (!selectStorage) return { flag: true, txt: '请选择相关库房' }
+    if (!staffList.length) return { flag: true, txt: '请添加人员' }
+    return { flag: false, txt: '' }
+  }
+
+  const getExtraData = (info: any, snaps: any[]) => {
+    const snapsArr = snaps.map((v: any) => ({
+      orderId: info.id,
+      snap: JSON.stringify({
+        name: v.name,
+        papers: v.papers,
+        phone: v.phone,
+        unit: v.unit
+      })
+    }))
+    return {
+      storageId: selectStorage?.value ?? undefined,
+      snaps: snapsArr
+    }
+  }
+
+  useEffect(() => {
+    if (!info?.storageId || !allWarehouseList.length) return
+    const opt = warehouseOptions.find((o: any) => o.value === info.storageId)
+    if (opt) {
+      setSelectStorage(opt)
+    }
+  }, [info?.storageId, allWarehouseList.length, warehouseOptions])
+
+  return (
+    <div className={styles.F5edit} id='editBox'>
+      <div className='editMain'>
+        <EditTop
+          pageTxt='人员出入库'
+          rowArr={rowArr}
+          APIobj={F5API_obj}
+          fileUpInfo={{ myUrl: 'cms/orderSite/user/upload', dirCode: 'staff' }}
+        />
+
+        <div className='F5editStorage'>
+          <p className='F5editStorageTitle'>*相关库房</p>
+          <Select
+            style={{ width: 200 }}
+            options={warehouseOptions}
+            placeholder='请选择'
+            value={selectStorage?.value}
+            onChange={handleStorageChange}
+            disabled={!canEdit}
+          />
+        </div>
+
+        <div className='F5editStorage' style={{ flexDirection: 'column' }}>
+          <div className='F5editStorageTitleBox'>
+            <p className='F5editStorageTitle'>人员信息</p>
+            <Button type='primary' onClick={openAddStaff} disabled={!canEdit}>
+              新增人员
+            </Button>
+          </div>
+          <MyTable
+            classKey='F5staff'
+            list={staffList}
+            columnsTemp={[
+              ['txt', '姓名', 'name'],
+              ['custom', '证件信息', (item: any) => getStaffDisplayPapers(item.papers)],
+              ['custom', '联系方式', (item: any) => getStaffDisplayPhone(item.phone)],
+              ['txt', '所在单位', 'unit']
+            ]}
+            lastBtn={
+              canEdit
+                ? [
+                    {
+                      title: '操作',
+                      render: (item: any) => (
+                        <Space>
+                          <Button size='small' type='link' onClick={() => openEditStaff(item)}>
+                            编辑
+                          </Button>
+                          <MyPopconfirm
+                            txtK='删除'
+                            onConfirm={() => handleDeleteStaff(item)}
+                            Dom={
+                              <Button size='small' type='link' danger>
+                                删除
+                              </Button>
+                            }
+                          />
+                        </Space>
+                      )
+                    }
+                  ]
+                : []
+            }
+            pagingInfo={false}
+            rowKey='idTemp'
+          />
+        </div>
+
+        <StaffModal
+          open={staffModalOpen}
+          editingStaff={editingStaff}
+          onOk={handleStaffModalOk}
+          onCancel={() => {
+            setStaffModalOpen(false)
+            setEditingStaff(null)
+          }}
+        />
+
+        {/* 附件归档 */}
+        <FileArchive />
+
+        {/* 底部按钮 */}
+        <EditBtn
+          path='/staff'
+          APIobj={F5API_obj}
+          checkListTxt='请添加人员'
+          verifyBackFu={verifyBackFu}
+          getExtraData={getExtraData}
+        />
+      </div>
+    </div>
+  )
+}
+
+function F5edit() {
+  return (
+    <InfoProvider>
+      <F5editContent />
+    </InfoProvider>
+  )
+}
+
+const MemoF5edit = React.memo(F5edit)
+
+export default MemoF5edit

+ 122 - 1
src/pages/Fstorehouse/F5staff/index.tsx

@@ -1,9 +1,130 @@
-import React from 'react'
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import styles from './index.module.scss'
+import TableList from '@/pages/Zother/TableList'
+import { F5_APIgetList } from '@/store/action/Fstorehouse/F5staff'
+import { tableListAuditBtnFu } from '@/utils/authority'
+import { staffTableC } from '@/utils/tableData'
+import { Button } from 'antd'
+import { baseFormData } from '@/pages/Zother/data'
+import { RootState } from '@/store'
+import { F1_APIgetStorageList } from '@/store/action/Fstorehouse/F1inStorage'
+import { selectObj } from '@/utils/dataChange'
+import { useSelector } from 'react-redux'
+import { useHistory } from 'react-router-dom'
+
+const F5baseFormData = baseFormData()
+
 function F5staff() {
+  const tableListRef = useRef<any>(null)
+  const history = useHistory()
+  // 从仓库拿数据
+  const tableInfo = useSelector((state: RootState) => state.F5staff.tableInfo)
+  const [allWarehouseList, setAllWarehouseList] = useState<any[]>([])
+  const warehouseOptions = useMemo(() => {
+    return allWarehouseList.map((i: any) => ({
+      label: i.name,
+      value: i.id
+    }))
+  }, [allWarehouseList])
+  const SEARCH_DOM = useMemo(
+    () => [
+      {
+        type: 'time',
+        key: ['startTime', 'endTime'],
+        placeholder: `出入时间`
+      },
+      {
+        type: 'select',
+        key: 'storageId',
+        placeholder: `相关库房`,
+        options: warehouseOptions
+      },
+      {
+        type: 'input',
+        key: 'searchKey',
+        placeholder: `请输入申请编号、发起人或藏品编号`
+      },
+      {
+        type: 'time',
+        key: ['businessStartTime', 'businessEndTime'],
+        placeholder: `发起日期`
+      },
+      {
+        type: 'select',
+        key: 'status',
+        placeholder: `申请状态`,
+        options: selectObj['藏品入库申请状态']
+      }
+    ],
+    [warehouseOptions]
+  )
+
+  const dataExport = () => {
+    console.log('数据导出了')
+  }
+
+  const getStorageList = async () => {
+    const res = await F1_APIgetStorageList()
+    setAllWarehouseList(res.data.records)
+  }
+
+  const tableBtnFu = useCallback(
+    (id: number | null, key: string) => {
+      history.push(`/staff_edit/${key}/${id}`)
+    },
+    [history]
+  )
+
+  useEffect(() => {
+    getStorageList()
+  }, [])
+
   return (
     <div className={styles.F5staff}>
       <div className='pageTitle'>人员出入库</div>
+
+      <TableList
+        ref={tableListRef}
+        baseFormData={F5baseFormData}
+        getListAPI={F5_APIgetList}
+        pageKey='position'
+        tableInfo={tableInfo}
+        columnsTemp={staffTableC}
+        rightBtnWidth={340}
+        yHeight={585}
+        searchDom={SEARCH_DOM}
+        storyTableListToprr={({ clickSearch, resetSelectFu }) => (
+          <>
+            <Button type='primary' ghost onClick={() => tableBtnFu(null, '1')}>
+              发起申请
+            </Button>
+            <Button type='primary' onClick={dataExport}>
+              数据导出
+            </Button>
+            <Button type='primary' onClick={clickSearch}>
+              查询
+            </Button>
+            <Button onClick={resetSelectFu}>重置</Button>
+          </>
+        )}
+        storyTableLastBtn={[
+          {
+            title: '操作',
+            render: (item: any) => (
+              <>
+                <Button type='text' onClick={() => tableBtnFu(item.id, '4')}>
+                  查看
+                </Button>
+                {tableListAuditBtnFu(item) ? (
+                  <Button size='small' type='text' onClick={() => tableBtnFu(item.id, '3')}>
+                    审批
+                  </Button>
+                ) : null}
+              </>
+            )
+          }
+        ]}
+      />
     </div>
   )
 }

+ 7 - 4
src/pages/Gmaintain/G1accident/G1edit/index.tsx

@@ -5,7 +5,7 @@ import { InfoProvider } from '@/pages/Zother/InfoContext'
 import EditTop from '@/pages/Zother/EditTop'
 import { G1_APIgetClueList, G1API_obj } from '@/store/action/Gmaintain/G1accident'
 import EditBtn from '@/pages/Zother/EditBtn'
-import { getPanDianListFu } from '../data'
+import { G1moreList, getPanDianListFu } from '../data'
 import FileArchive from '@/pages/Zother/FileArchive'
 
 const rowArr = [
@@ -20,9 +20,12 @@ function G1edit() {
   const [info, setInfo] = useState<any>({ list: [], loding: false })
 
   useEffect(() => {
-    getPanDianListFu(list => {
-      setInfo({ list, loding: true })
-    })
+    getPanDianListFu(
+      list => {
+        setInfo({ list, loding: true })
+      },
+      list => G1moreList(list)
+    )
   }, [])
 
   return (

+ 2 - 2
src/pages/Gmaintain/G1accident/data.ts

@@ -1,12 +1,12 @@
 import { F4_APIgetList } from '@/store/action/Fstorehouse/F4check'
 
-export const getPanDianListFu = async (back: (list: any[]) => void) => {
+export const getPanDianListFu = async (back: (list: any[]) => void, resFu: (val: any) => any) => {
   // 获取盘点单列表
   const res = await F4_APIgetList({}, true)
   if (res.code === 0) {
     let list = res.data.records || []
     list = list.map((v: any) => ({ value: v.num, label: `${v.num} - ${v.storageName}` }))
-    const listRes: any[] = G1moreList(list)
+    const listRes: any[] = resFu(list)
     back(listRes)
   }
 }

+ 4 - 0
src/pages/Gmaintain/G2actuality/G2edit/index.module.scss

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

+ 74 - 0
src/pages/Gmaintain/G2actuality/G2edit/index.tsx

@@ -0,0 +1,74 @@
+import React, { useEffect, useState } from 'react'
+import styles from './index.module.scss'
+import { rowArrTemp } from '@/pages/Zother/data'
+import { getPanDianListFu } from '../../G1accident/data'
+import { G2moreList } from '../data'
+import { InfoProvider } from '@/pages/Zother/InfoContext'
+import EditTop from '@/pages/Zother/EditTop'
+import { G2_APIgetClueList, G2API_obj } from '@/store/action/Gmaintain/G2actuality'
+import FileArchive from '@/pages/Zother/FileArchive'
+import EditBtn from '@/pages/Zother/EditBtn'
+
+const rowArr = [
+  {
+    name: `现状登记`,
+    type: 'txt'
+  },
+  ...rowArrTemp('登记', undefined, '现状登记').slice(1)
+]
+
+function G2edit() {
+  const [info, setInfo] = useState<any>({ list: [], loding: false })
+
+  useEffect(() => {
+    getPanDianListFu(
+      list => {
+        setInfo({ list, loding: true })
+      },
+      list => G2moreList(list)
+    )
+  }, [])
+
+  return (
+    <>
+      {info.loding ? (
+        <InfoProvider>
+          <div className={styles.G2edit} id='editBox'>
+            <div className='editMain'>
+              {/* 顶部 */}
+              <EditTop
+                pageTxt='现状登记'
+                rowArr={rowArr}
+                APIobj={G2API_obj}
+                fileUpInfo={{ myUrl: 'cms/orderCurrent/upload', dirCode: 'actuality' }}
+                // 第二个模块
+                moreDom={{
+                  txt: '现状报告',
+                  API: G2_APIgetClueList,
+                  domList: info.list,
+                  myUrl: 'cms/orderCurrent/son/upload',
+                  dirCode: 'actualitySon'
+                }}
+              />
+
+              {/* 附件归档 */}
+              <FileArchive />
+
+              {/* 底部按钮 */}
+              <EditBtn
+                path='/actuality'
+                APIobj={G2API_obj}
+                checkListTxt='请选择关联藏品'
+                isTow={true}
+              />
+            </div>
+          </div>
+        </InfoProvider>
+      ) : null}
+    </>
+  )
+}
+
+const MemoG2edit = React.memo(G2edit)
+
+export default MemoG2edit

+ 28 - 0
src/pages/Gmaintain/G2actuality/data.ts

@@ -0,0 +1,28 @@
+export const G2moreList = (list: any[]) => {
+  return [
+    {
+      name: '关联盘点',
+      type: 'Select',
+      key: 'oderNum',
+      placeholder: '请搜索盘点申请编号',
+      options: list
+    },
+    {
+      name: '经手人',
+      type: 'Input',
+      key: 'userName'
+    },
+    {
+      name: '现状描述',
+      type: 'TextArea',
+      key: 'currentInfo',
+      full: true
+    },
+    {
+      name: '备注',
+      type: 'TextArea',
+      key: 'remark',
+      full: true
+    }
+  ]
+}

+ 4 - 4
src/pages/Gmaintain/G2actuality/index.module.scss

@@ -1,4 +1,4 @@
-.G2actuality {
-  :global {
-  }
-}
+// .G2actuality {
+//   :global {
+//   }
+// }

+ 24 - 0
src/pages/Gmaintain/G2actuality/index.tsx

@@ -1,9 +1,33 @@
 import React from 'react'
 import styles from './index.module.scss'
+import { baseFormData, topSearch } from '@/pages/Zother/data'
+import { useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import TableList from '@/pages/Zother/TableList'
+import { G2_APIgetList } from '@/store/action/Gmaintain/G2actuality'
+import { baseTableC } from '@/utils/tableData'
+
+const search = topSearch('登记')
+
+const baseFormDataRes = baseFormData()
+
 function G2actuality() {
+  // 从仓库拿数据
+  const tableInfo = useSelector((state: RootState) => state.G2actuality.tableInfo)
+
   return (
     <div className={styles.G2actuality}>
       <div className='pageTitle'>现状登记</div>
+
+      <TableList
+        baseFormData={baseFormDataRes}
+        getListAPI={G2_APIgetList}
+        pageKey='actuality'
+        tableInfo={tableInfo}
+        columnsTemp={baseTableC('登记')}
+        yHeight={585}
+        searchDom={search}
+      />
     </div>
   )
 }

+ 5 - 0
src/pages/Gmaintain/G3repair/G3edit/index.module.scss

@@ -0,0 +1,5 @@
+// .G3edit{
+//   :global{
+
+//   }
+// }

+ 74 - 0
src/pages/Gmaintain/G3repair/G3edit/index.tsx

@@ -0,0 +1,74 @@
+import React, { useEffect, useState } from 'react'
+import styles from './index.module.scss'
+import { rowArrTemp } from '@/pages/Zother/data'
+import { getPanDianListFu } from '../../G1accident/data'
+import { G3moreList } from '../data'
+import { InfoProvider } from '@/pages/Zother/InfoContext'
+import EditTop from '@/pages/Zother/EditTop'
+import { G3_APIgetClueList, G3API_obj } from '@/store/action/Gmaintain/G3repair'
+import FileArchive from '@/pages/Zother/FileArchive'
+import EditBtn from '@/pages/Zother/EditBtn'
+
+const rowArr = [
+  {
+    name: `修复登记`,
+    type: 'txt'
+  },
+  ...rowArrTemp('修复', undefined, '修复登记').slice(1)
+]
+
+function G3edit() {
+  const [info, setInfo] = useState<any>({ list: [], loding: false })
+
+  useEffect(() => {
+    getPanDianListFu(
+      list => {
+        setInfo({ list, loding: true })
+      },
+      list => G3moreList(list)
+    )
+  }, [])
+
+  return (
+    <>
+      {info.loding ? (
+        <InfoProvider>
+          <div className={styles.G3edit} id='editBox'>
+            <div className='editMain'>
+              {/* 顶部 */}
+              <EditTop
+                pageTxt='修复登记'
+                rowArr={rowArr}
+                APIobj={G3API_obj}
+                fileUpInfo={{ myUrl: 'cms/orderFix/upload', dirCode: 'repair' }}
+                // 第二个模块
+                moreDom={{
+                  txt: '修复报告',
+                  API: G3_APIgetClueList,
+                  domList: info.list,
+                  myUrl: 'cms/orderFix/son/upload',
+                  dirCode: 'repairSon'
+                }}
+              />
+
+              {/* 附件归档 */}
+              <FileArchive />
+
+              {/* 底部按钮 */}
+              <EditBtn
+                path='/repair'
+                APIobj={G3API_obj}
+                checkListTxt='请选择关联藏品'
+                isTow={true}
+              />
+            </div>
+          </div>
+        </InfoProvider>
+      ) : null}
+    </>
+  )
+}
+
+const MemoG3edit = React.memo(G3edit)
+
+export default MemoG3edit

+ 46 - 0
src/pages/Gmaintain/G3repair/data.ts

@@ -0,0 +1,46 @@
+export const G3moreList = (list: any[]) => {
+  return [
+    {
+      name: '关联盘点',
+      type: 'Select',
+      key: 'oderNum',
+      placeholder: '请搜索盘点申请编号',
+      options: list
+    },
+    {
+      name: '修复人',
+      type: 'Input',
+      key: 'userName'
+    },
+    {
+      name: '修复原因',
+      type: 'TextArea',
+      key: 'reason',
+      full: true
+    },
+    {
+      name: '修复前&emsp;<br/>藏品状态',
+      type: 'TextArea',
+      key: 'beforeInfo',
+      full: true
+    },
+    {
+      name: '修复后&emsp;<br/>藏品状态',
+      type: 'TextArea',
+      key: 'afterInfo',
+      full: true
+    },
+    {
+      name: '修复过程',
+      type: 'TextArea',
+      key: 'process',
+      full: true
+    },
+    {
+      name: '备注',
+      type: 'TextArea',
+      key: 'remark',
+      full: true
+    }
+  ]
+}

+ 4 - 4
src/pages/Gmaintain/G3repair/index.module.scss

@@ -1,4 +1,4 @@
-.G3repair {
-  :global {
-  }
-}
+// .G3repair {
+//   :global {
+//   }
+// }

+ 24 - 0
src/pages/Gmaintain/G3repair/index.tsx

@@ -1,9 +1,33 @@
 import React from 'react'
 import styles from './index.module.scss'
+import { baseFormData, topSearch } from '@/pages/Zother/data'
+import { useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import TableList from '@/pages/Zother/TableList'
+import { G3_APIgetList } from '@/store/action/Gmaintain/G3repair'
+import { baseTableC } from '@/utils/tableData'
+
+const search = topSearch('修复')
+
+const baseFormDataRes = baseFormData()
+
 function G3repair() {
+  // 从仓库拿数据
+  const tableInfo = useSelector((state: RootState) => state.G3repair.tableInfo)
+
   return (
     <div className={styles.G3repair}>
       <div className='pageTitle'>修复登记</div>
+
+      <TableList
+        baseFormData={baseFormDataRes}
+        getListAPI={G3_APIgetList}
+        pageKey='repair'
+        tableInfo={tableInfo}
+        columnsTemp={baseTableC('修复')}
+        yHeight={585}
+        searchDom={search}
+      />
     </div>
   )
 }

+ 1 - 1
src/pages/Isystem/I7user/I7add/index.tsx

@@ -129,7 +129,7 @@ function I7add({ id, closePage, upTableList, addTableList, formOld }: Props) {
             name='userName'
             rules={[
               { required: true, message: '请输入账号名!' },
-              { min: 6, message: '最少6个字!' }
+              { min: window.location.href.includes('?k=4DAGE') ? 5 : 6, message: '最少6个字!' }
             ]}
             getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
           >

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

@@ -135,7 +135,7 @@ function I7user() {
       {
         title: '操作',
         render: (item: UserTableListType) => {
-          return item.isAdmin === 1 ? (
+          return item.isAdmin === 1 && !window.location.href.includes('?k=4DAGE') ? (
             '-'
           ) : (
             <>

+ 31 - 1
src/pages/Layout/data.ts

@@ -154,7 +154,7 @@ const tabLeftArr: RouterType = [
         name: '资源使用',
         path: '/resource',
         Com: React.lazy(() => import('../Dmanage/D4resource')),
-        pageType: 'SY'
+        pageType: 'ZY'
       }
     ]
   },
@@ -376,12 +376,30 @@ export const routerSon: RouterTypeRow[] = [
     Com: React.lazy(() => import('../Dmanage/D3writeOff/D3edit'))
   },
   {
+    id: 440,
+    name: '资源使用-详情页',
+    path: '/resource_edit/:key/:id',
+    Com: React.lazy(() => import('../Dmanage/D4resource/D4edit'))
+  },
+  {
     id: 510,
     name: '事故登记-详情页',
     path: '/accident_edit/:key/:id',
     Com: React.lazy(() => import('../Gmaintain/G1accident/G1edit'))
   },
   {
+    id: 540,
+    name: '现状登记-详情页',
+    path: '/actuality_edit/:key/:id',
+    Com: React.lazy(() => import('../Gmaintain/G2actuality/G2edit'))
+  },
+  {
+    id: 550,
+    name: '修复登记-详情页',
+    path: '/repair_edit/:key/:id',
+    Com: React.lazy(() => import('../Gmaintain/G3repair/G3edit'))
+  },
+  {
     id: 602,
     name: '故事管理-详情页',
     path: '/story_edit/:key/:id',
@@ -394,6 +412,12 @@ export const routerSon: RouterTypeRow[] = [
     Com: React.lazy(() => import('../Fstorehouse/F1inStorage/F1edit'))
   },
   {
+    id: 1020,
+    name: '藏品移库-详情页',
+    path: '/moveStorage_edit/:key/:id',
+    Com: React.lazy(() => import('../Fstorehouse/F2moveStorage/F2edit'))
+  },
+  {
     id: 1030,
     name: '藏品出库-详情页',
     path: '/outStorage_edit/:key/:id',
@@ -404,5 +428,11 @@ export const routerSon: RouterTypeRow[] = [
     name: '藏品盘点-详情页',
     path: '/check_edit/:key/:id',
     Com: React.lazy(() => import('../Fstorehouse/F4check/F4edit'))
+  },
+  {
+    id: 1050,
+    name: '人员出入库-详情页',
+    path: '/staff_edit/:key/:id',
+    Com: React.lazy(() => import('../Fstorehouse/F5staff/F5edit'))
   }
 ]

+ 9 - 3
src/pages/Layout/index.module.scss

@@ -135,13 +135,19 @@
 
           .userNameBox {
             cursor: pointer;
-            background: url('../../assets/img/user.png') no-repeat left center;
-            background-size: 40px 40px;
-            padding-left: 46px;
+            // background: url('../../assets/img/user.png') no-repeat left center;
+            // background-size: 40px 40px;
+            // padding-left: 46px;
             height: 60px;
             display: flex;
             align-items: center;
             color: #fff;
+            img {
+              border-radius: 50%;
+              width: 40px;
+              height: 40px;
+              margin-right: 20px;
+            }
           }
 
           .userInco {

+ 36 - 17
src/pages/Layout/index.tsx

@@ -8,20 +8,23 @@ import { Button, Form, Input, Modal } from 'antd'
 import { Base64 } from 'js-base64'
 import encodeStr from '@/utils/pass'
 import { passWordEditAPI } from '@/store/action/layout'
-import { changSetFu, getTokenInfo, removeTokenInfo } from '@/utils/storage'
+import { getTokenInfo, removeTokenInfo } from '@/utils/storage'
 import { MessageFu } from '@/utils/message'
 import NotFound from '@/components/NotFound'
 import classNames from 'classnames'
 import tabLeftArr, { routerSon, RouterType, RouterTypeRow } from './data'
 import MyPopconfirm from '@/components/MyPopconfirm'
-import store from '@/store'
+import store, { RootState } from '@/store'
 import SpinLodingSon from '@/components/SpinLodingSon'
 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 { useDispatch, useSelector } from 'react-redux'
 import { I2_APIgetDict } from '@/store/action/Isystem/I2dict'
 import { E1_APIgetTree } from '@/store/action/Eculture/E1tag'
+import { baseURL } from '@/utils/http'
+import baseTouXiangImg from '@/assets/img/user.png'
+import { ZFbaseFu } from '@/store/reducer/ZformData'
 
 function Layout() {
   const [loding, setLoding] = useState(false)
@@ -39,8 +42,12 @@ function Layout() {
   }, [dispatch])
 
   useEffect(() => {
+    // 用户信息存到仓库
+    store.dispatch({ type: 'layout/userInfo', payload: (getTokenInfo() || {}).user })
     getListFu()
   }, [getListFu])
+  // 获取用户信息
+  const { userInfo, passEditShow } = useSelector((state: RootState) => state.A0Layout)
 
   // 当前路径选中的左侧菜单
   const location = useLocation()
@@ -123,20 +130,23 @@ function Layout() {
       const tempArr: RouterTypeRow[] = []
 
       // 权限数据存到仓库
-      const roleArrStoreArr: RouterTypeRow[] = []
+      const roleArrStoreArr: RouterType = []
 
       tabLeftArr.forEach(v1 => {
         if (v1.son && v1.son[0]) {
+          const obj = {
+            ...v1,
+            son: [] as RouterTypeRow[]
+          }
+
           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) obj.son.push({ ...v2, authority: true })
             }
           })
+          roleArrStoreArr.push(obj)
         }
       })
 
@@ -194,13 +204,13 @@ function Layout() {
 
   // 点击跳转
   const pathCutFu = useCallback((item: RouterTypeRow) => {
+    if (item.name === '工作台') {
+      ZFbaseFu()
+    }
     history.push(item.path)
-    if (item.name !== '工作台') changSetFu(item)
+    // if (item.name !== '工作台') changSetFu(item)
   }, [])
 
-  // 修改密码相关
-  const [open, setOpen] = useState(false)
-
   // 拿到新密码的输入框的值
   const oldPasswordValue = useRef('')
 
@@ -219,6 +229,7 @@ function Layout() {
     const res: any = await passWordEditAPI(obj)
     if (res.code === 0) {
       MessageFu.success('修改成功!')
+      store.dispatch({ type: 'layout/passEditShow', payload: false })
       loginExit()
     }
   }
@@ -298,7 +309,9 @@ function Layout() {
             onMouseLeave={() => setIsUserBtnShow(false)}
           >
             <div className='userNameBox' onClick={() => setIsUserBtnShow(true)}>
-              {getTokenInfo().user.realName || getTokenInfo().user.userName || '匿名'}
+              <img src={userInfo.thumb ? baseURL + userInfo.thumb : baseTouXiangImg} alt='' />
+
+              {userInfo.realName || userInfo.userName || '匿名'}
 
               <div className='userInco userInco2'>
                 <CaretRightOutlined />
@@ -307,7 +320,11 @@ function Layout() {
 
             <div className='userSet'>
               <div>
-                <span onClick={() => setOpen(true)}>修改密码</span>
+                <span
+                  onClick={() => store.dispatch({ type: 'layout/passEditShow', payload: true })}
+                >
+                  修改密码
+                </span>
                 <MyPopconfirm txtK='退出登录' onConfirm={loginExit} Dom='退出登录' loc='bottom' />
               </div>
             </div>
@@ -340,9 +357,9 @@ function Layout() {
       {/* 点击修改密码打开的对话框 */}
       <Modal
         destroyOnClose
-        open={open}
+        open={passEditShow}
         title='修改密码'
-        onCancel={() => setOpen(false)}
+        onCancel={() => store.dispatch({ type: 'layout/passEditShow', payload: false })}
         footer={
           [] // 设置footer为空,去掉 取消 确定默认按钮
         }
@@ -389,7 +406,9 @@ function Layout() {
           </Form.Item>
 
           <Form.Item wrapperCol={{ offset: 14, span: 16 }}>
-            <Button onClick={() => setOpen(false)}>取消</Button>
+            <Button onClick={() => store.dispatch({ type: 'layout/passEditShow', payload: false })}>
+              取消
+            </Button>
             &emsp;
             <Button type='primary' htmlType='submit'>
               确定

+ 2 - 2
src/pages/ZgoodsInfo/GItab5/index.tsx

@@ -52,7 +52,7 @@ function GItab5({ goodId }: Props) {
               size='small'
               type='text'
               onClick={() => {
-                console.log(item)
+                // console.log(item)
                 const obj = list.find(v => v.value === item.type)
                 if (obj) {
                   authorityFu(obj.id, obj.label, () =>
@@ -111,7 +111,7 @@ function GItab5({ goodId }: Props) {
         classKey='GItab5'
         yHeight={560}
         list={tableList}
-        columnsTemp={GI5tableC}
+        columnsTemp={GI5tableC()}
         lastBtn={tableLastBtn}
         staBtn={staBtn}
         pagingInfo={false}

+ 6 - 3
src/pages/Zother/EditBtn/index.tsx

@@ -23,7 +23,7 @@ type Props = {
   // 其他需要校验的回调函数,返回 flag为true 表示校验不通过,txt为提示语
   verifyBackFu?: (info: Typetable) => { flag: boolean; txt: string; info?: any }
   // 页面特有数据,如 storageId,会合并到提交的 obj 中
-  getExtraData?: (info: Typetable, snaps: GoodsType[]) => { storageId?: number; snaps?: any[] }
+  getExtraData?: (info: Typetable, snaps: GoodsType[]) => Record<string, any>
   // 第二个模块
   isTow?: boolean
   // 藏品修改模块
@@ -167,8 +167,11 @@ function EditBtn({
 
         if (getExtraData) {
           const extra = getExtraData(info, snaps)
-          if (extra.storageId != null) obj = { ...obj, storageId: extra.storageId } as typeof obj
-          if (extra.snaps) obj = { ...obj, snaps: extra.snaps } as typeof obj
+          if (extra) {
+            const { snaps, ...rest } = extra
+            obj = { ...obj, ...rest } as typeof obj
+            if (snaps) obj = { ...obj, snaps: snaps } as typeof obj
+          }
         }
 
         // if (1 + 1 === 2) {

+ 59 - 1
src/pages/Zother/EditInput/index.tsx

@@ -2,9 +2,11 @@ import React, { useCallback, useMemo } from 'react'
 import classNames from 'classnames'
 import dayjs from 'dayjs'
 import { useInfo } from '../InfoContext'
-import { Cascader, DatePicker, Input, Select } from 'antd'
+import { Cascader, DatePicker, Input, Radio, Select } from 'antd'
 import TextArea from 'antd/es/input/TextArea'
 
+const { RangePicker } = DatePicker
+
 type Props = {
   item: any
   isLook: boolean
@@ -39,6 +41,22 @@ function EditInput({ item, isLook, isTow }: Props) {
         setInfoFu({ ...infoRes, dictIdApply: val ? val.join(',') : '' }, isTow)
       } else if (type === 'Select') {
         setInfoFu({ ...infoRes, [key]: val }, isTow)
+      } else if (type === 'DatePicker2') {
+        const keys = Array.isArray(key) ? key : [key]
+        const modeKey = item.modeKey
+        if (val?.type === 'longterm') {
+          const update: any = { [keys[0]]: '', [keys[1]]: '' }
+          if (modeKey) update[modeKey] = 'longterm'
+          setInfoFu({ ...infoRes, ...update }, isTow)
+        } else if (val?.type === 'range') {
+          const [start, end] = val?.dates || [null, null]
+          const update: any = {
+            [keys[0]]: start ? dayjs(start).format('YYYY-MM-DD') : '',
+            [keys[1]]: end ? dayjs(end).format('YYYY-MM-DD') : ''
+          }
+          if (modeKey) update[modeKey] = 'range'
+          setInfoFu({ ...infoRes, ...update }, isTow)
+        }
       }
     },
     [infoRes, isTow, setInfoFu]
@@ -109,6 +127,46 @@ function EditInput({ item, isLook, isTow }: Props) {
             options={item.options}
             allowClear={!item.must}
           />
+        ) : item.type === 'DatePicker2' ? (
+          (() => {
+            const keys = Array.isArray(item.key) ? item.key : [item.key]
+            const modeKey = item.modeKey as string | undefined
+            const startVal = infoRes[keys[0] as keyof typeof infoRes]
+            const endVal = infoRes[keys[1] as keyof typeof infoRes]
+            const modeVal = modeKey ? infoRes[modeKey as keyof typeof infoRes] : null
+            const isLongterm = modeVal === 'longterm' || (!modeVal && !startVal && !endVal)
+            const rangeValue = startVal && endVal ? [dayjs(startVal), dayjs(endVal)] : null
+            return (
+              <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
+                <Radio.Group
+                  disabled={isLook}
+                  value={isLongterm ? 'longterm' : 'range'}
+                  onChange={e => {
+                    const v = e.target.value
+                    dataChangeFu(
+                      v === 'longterm'
+                        ? { type: 'longterm' }
+                        : { type: 'range', dates: [null, null] },
+                      item
+                    )
+                  }}
+                >
+                  <Radio value='longterm'>长期</Radio>
+                  <Radio value='range'>定期</Radio>
+                </Radio.Group>
+                {!isLongterm && (
+                  <RangePicker
+                    disabled={isLook}
+                    allowClear={!item.must}
+                    value={rangeValue as [dayjs.Dayjs, dayjs.Dayjs]}
+                    onChange={dates =>
+                      dataChangeFu({ type: 'range', dates: dates || [null, null] }, item)
+                    }
+                  />
+                )}
+              </div>
+            )
+          })()
         ) : null}
       </div>
     </div>

+ 2 - 0
src/pages/Zother/EditTop/index.module.scss

@@ -36,6 +36,8 @@
           }
         }
         .Edtop1rr {
+          display: flex;
+          align-items: center;
           width: calc(100% - 100px);
           & > div {
             width: 100%;

+ 1 - 1
src/pages/Zother/EditTop/index.tsx

@@ -125,7 +125,7 @@ function EditTop({ rowArr, pageTxt, APIobj, fileUpInfo, moreDom }: Props) {
           const obj = JSON.parse(v.snap || '{}')
 
           const flag = v.pageType === 'clue' && !v.clueId
-          if (obj.id === null || obj.isNew || flag)
+          if (obj.id == null || obj.isNew || flag)
             obj.id = ['藏品登记', '藏品入馆'].includes(pageTxt) ? v.goodId : Date.now() + i
 
           obj.idTemp = obj.id

+ 26 - 0
src/store/action/Abench/A2bench.ts

@@ -0,0 +1,26 @@
+import http from '@/utils/http'
+
+/**
+ * 工作台-编辑用户信息
+ */
+export const A2_APIeditUser = (data: any) => {
+  return http.post('sys/user/editInfo', data)
+}
+
+/**
+ * 工作台-修改常用功能
+ */
+export const A2_APIsetStock = (id: number, permRtf: string) => {
+  const data = {
+    userId: id,
+    permRtf
+  }
+  return http.post('cms/workBench/permSave', data)
+}
+
+/**
+ * 工作台-获取分页列表
+ */
+export const A2_APIgetList = (data: any) => {
+  return http.post('cms/workBench/orderPage', data)
+}

+ 38 - 0
src/store/action/Dmanage/D4resource.ts

@@ -0,0 +1,38 @@
+import { AppDispatch } from '@/store'
+import http from '@/utils/http'
+import { APIbase } from '../layout'
+
+/**
+ * 资源使用 - 分页列表
+ */
+export const D4_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('cms/order/resource/page', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'D4/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 藏品总账列表-分页
+ */
+export const D4_APIgetClueList = (data: any) => {
+  return http.post('cms/order/resource/good/page', data)
+}
+
+export const D4API_obj = {
+  创建订单: () => APIbase('get', 'cms/order/resource/create'),
+  获取详情: (id: number) => APIbase('get', `cms/order/resource/detail/${id}`),
+  草稿: (data: any) => APIbase('post', `cms/order/resource/saveDraft`, data),
+  发起: (data: any) => APIbase('post', `cms/order/resource/saveApply`, data),
+  重新发起: (id: number) => APIbase('get', `cms/order/resource/reissue/${id}`),
+  审批: (data: any) => APIbase('post', `cms/order/resource/audit`, data),
+  撤回: (id: number) => APIbase('get', `cms/order/resource/revocation/${id}`),
+  删除: (id: number) => APIbase('get', `cms/order/resource/remove/${id}`)
+}

+ 45 - 0
src/store/action/Fstorehouse/F2moveStorage.ts

@@ -0,0 +1,45 @@
+import { AppDispatch } from '@/store'
+import http from '@/utils/http'
+import { APIbase } from '../layout'
+
+/**
+ * 藏品移库 - 分页列表
+ */
+export const F2_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('cms/orderSite/move/page', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'F2/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 藏品总账列表-分页
+ */
+export const F2_APIgetClueList = (data: any) => {
+  return http.post('cms/orderSite/move/good/page', data)
+}
+
+export const F2API_obj = {
+  创建订单: () => APIbase('get', 'cms/orderSite/move/create'),
+  获取详情: (id: number) => APIbase('get', `cms/orderSite/move/detail/${id}`),
+  草稿: (data: any) => APIbase('post', `cms/orderSite/move/saveDraft`, data),
+  发起: (data: any) => APIbase('post', `cms/orderSite/move/saveApply`, data),
+  重新发起: (id: number) => APIbase('get', `cms/orderSite/move/reissue/${id}`),
+  审批: (data: any) => APIbase('post', `cms/orderSite/move/audit`, data),
+  撤回: (id: number) => APIbase('get', `cms/orderSite/move/revocation/${id}`),
+  删除: (id: number) => APIbase('get', `cms/orderSite/move/remove/${id}`)
+}
+
+/**
+ * 自动分配空置仓位
+ */
+export const F2_APIgetShelfEmptyList = (params: any) => {
+  return http.get('cms/orderSite/move/getStorageEmpty', { params })
+}

+ 31 - 0
src/store/action/Fstorehouse/F5staff.ts

@@ -0,0 +1,31 @@
+import { AppDispatch } from '@/store'
+import http from '@/utils/http'
+import { APIbase } from '../layout'
+
+/**
+ * 人员出入库 - 分页列表
+ */
+export const F5_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('cms/orderSite/user/page', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'F5/getList', payload: obj })
+    }
+  }
+}
+
+export const F5API_obj = {
+  创建订单: () => APIbase('get', 'cms/orderSite/user/create'),
+  获取详情: (id: number) => APIbase('get', `cms/orderSite/user/detail/${id}`),
+  草稿: (data: any) => APIbase('post', `cms/orderSite/user/saveDraft`, data),
+  发起: (data: any) => APIbase('post', `cms/orderSite/user/saveApply`, data),
+  重新发起: (id: number) => APIbase('get', `cms/orderSite/user/reissue/${id}`),
+  审批: (data: any) => APIbase('post', `cms/orderSite/user/audit`, data),
+  撤回: (id: number) => APIbase('get', `cms/orderSite/user/revocation/${id}`),
+  删除: (id: number) => APIbase('get', `cms/orderSite/user/remove/${id}`)
+}

+ 38 - 0
src/store/action/Gmaintain/G2actuality.ts

@@ -0,0 +1,38 @@
+import { AppDispatch } from '@/store'
+import http from '@/utils/http'
+import { APIbase } from '../layout'
+
+/**
+ * 现状登记 -获取分页列表
+ */
+export const G2_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('cms/orderCurrent/page', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'G2/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 现状登记-藏品列表(取总账数据)-分页
+ */
+export const G2_APIgetClueList = (data: any) => {
+  return http.post('cms/orderCurrent/goodPage', data)
+}
+
+export const G2API_obj = {
+  创建订单: () => APIbase('get', 'cms/orderCurrent/create'),
+  获取详情: (id: number) => APIbase('get', `cms/orderCurrent/detail/${id}`),
+  草稿: (data: any) => APIbase('post', `cms/orderCurrent/saveDraft`, data),
+  发起: (data: any) => APIbase('post', `cms/orderCurrent/saveApply`, data),
+  重新发起: (id: number) => APIbase('get', `cms/orderCurrent/reissue/${id}`),
+  审批: (data: any) => APIbase('post', `cms/orderCurrent/audit`, data),
+  撤回: (id: number) => APIbase('get', `cms/orderCurrent/revocation/${id}`),
+  删除: (id: number) => APIbase('get', `cms/orderCurrent/remove/${id}`)
+}

+ 38 - 0
src/store/action/Gmaintain/G3repair.ts

@@ -0,0 +1,38 @@
+import { AppDispatch } from '@/store'
+import http from '@/utils/http'
+import { APIbase } from '../layout'
+
+/**
+ * 修复登记 -获取分页列表
+ */
+export const G3_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('cms/orderFix/page', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+
+      dispatch({ type: 'G3/getList', payload: obj })
+    }
+  }
+}
+
+/**
+ * 修复登记-藏品列表(取总账数据)-分页
+ */
+export const G3_APIgetClueList = (data: any) => {
+  return http.post('cms/orderFix/goodPage', data)
+}
+
+export const G3API_obj = {
+  创建订单: () => APIbase('get', 'cms/orderFix/create'),
+  获取详情: (id: number) => APIbase('get', `cms/orderFix/detail/${id}`),
+  草稿: (data: any) => APIbase('post', `cms/orderFix/saveDraft`, data),
+  发起: (data: any) => APIbase('post', `cms/orderFix/saveApply`, data),
+  重新发起: (id: number) => APIbase('get', `cms/orderFix/reissue/${id}`),
+  审批: (data: any) => APIbase('post', `cms/orderFix/audit`, data),
+  撤回: (id: number) => APIbase('get', `cms/orderFix/revocation/${id}`),
+  删除: (id: number) => APIbase('get', `cms/orderFix/remove/${id}`)
+}

+ 28 - 0
src/store/reducer/Dmanage/D4resource.ts

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

+ 28 - 0
src/store/reducer/Fstorehouse/F2moveStorage.ts

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

+ 28 - 0
src/store/reducer/Fstorehouse/F5staff.ts

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

+ 28 - 0
src/store/reducer/Gmaintain/G2actuality.ts

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

+ 28 - 0
src/store/reducer/Gmaintain/G3repair.ts

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

+ 41 - 0
src/store/reducer/ZformData.ts

@@ -0,0 +1,41 @@
+import store from '..'
+
+const ZFbaseData = {
+  A2formData: {
+    pageNum: 1,
+    pageSize: 10,
+    auditType: '1',
+    type: '',
+    num: '',
+    startTime: '',
+    endTime: '',
+    status: ''
+  }
+} as any
+
+// 初始化状态
+const initState = {
+  A2formData: ZFbaseData.A2formData
+}
+
+// 定义 action 类型
+type Props = {
+  type: 'ZF/A2formData'
+  payload: any
+}
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    case 'ZF/A2formData':
+      return { ...state, A2formData: action.payload }
+
+    default:
+      return state
+  }
+}
+
+// 初始化数据
+export const ZFbaseFu = () => {
+  store.dispatch({ type: 'ZF/A2formData', payload: ZFbaseData.A2formData })
+}

+ 16 - 1
src/store/reducer/index.ts

@@ -14,12 +14,17 @@ import C4file from './Cledger/C4file'
 import D1register from './Dmanage/D1register'
 import D2edit from './Dmanage/D2edit'
 import D3writeOff from './Dmanage/D3writeOff'
+import D4resource from './Dmanage/D4resource'
 import E1tag from './Eculture/E1tag'
 import E2story from './Eculture/E2story'
 import G1accident from './Gmaintain/G1accident'
+import G2actuality from './Gmaintain/G2actuality'
+import G3repair from './Gmaintain/G3repair'
 import F1inStorage from './Fstorehouse/F1inStorage'
+import F2moveStorage from './Fstorehouse/F2moveStorage'
 import F3outStorage from './Fstorehouse/F3outStorage'
 import F4check from './Fstorehouse/F4check'
+import F5staff from './Fstorehouse/F5staff'
 import I1storageSet from './Isystem/I1storageSet'
 import I2dict from './Isystem/I2dict'
 import I3numSet from './Isystem/I3numSet'
@@ -29,6 +34,9 @@ import I6role from './Isystem/I6role'
 import I7user from './Isystem/I7user'
 import I8log from './Isystem/I8log'
 
+// 所有列表回调需要保存当前筛选数据
+import ZformData from './ZformData'
+
 // 合并 reducer
 const rootReducer = combineReducers({
   A0Layout,
@@ -43,14 +51,19 @@ const rootReducer = combineReducers({
   D1register,
   D2edit,
   D3writeOff,
+  D4resource,
   E1tag,
   E2story,
 
   G1accident,
+  G2actuality,
+  G3repair,
 
   F1inStorage,
+  F2moveStorage,
   F3outStorage,
   F4check,
+  F5staff,
   I1storageSet,
   I2dict,
   I3numSet,
@@ -58,7 +71,9 @@ const rootReducer = combineReducers({
   I5organization,
   I6role,
   I7user,
-  I8log
+  I8log,
+
+  ZformData
 })
 
 // 默认导出

+ 16 - 3
src/store/reducer/layout.ts

@@ -1,4 +1,5 @@
-import { LookDomType, RouterTypeRow } from '@/pages/Layout/data'
+import { UserTableListType } from '@/pages/Isystem/I7user/data'
+import { LookDomType, RouterType } from '@/pages/Layout/data'
 import { MessageType } from '@/utils/message'
 
 // 初始化状态
@@ -29,7 +30,11 @@ const initState = {
   authorityIds: [] as number[],
 
   // 用户工作台常用功能
-  userRolePermissions: [] as RouterTypeRow[]
+  userRolePermissions: [] as RouterType,
+  // 用户信息
+  userInfo: {} as UserTableListType,
+  // 修改密码
+  passEditShow: false
 }
 
 // 定义 action 类型
@@ -38,7 +43,9 @@ type LayoutActionType =
   | { type: 'layout/lookDom'; payload: LookDomType }
   | { type: 'layout/message'; payload: MessageType }
   | { type: 'layout/authorityIds'; payload: number[] }
-  | { type: 'layout/userRolePermissions'; payload: RouterTypeRow[] }
+  | { type: 'layout/userRolePermissions'; payload: RouterType }
+  | { type: 'layout/userInfo'; payload: UserTableListType }
+  | { type: 'layout/passEditShow'; payload: boolean }
   | {
       type: 'layout/closeUpFile'
       payload: {
@@ -68,6 +75,12 @@ export default function layoutReducer(state = initState, action: LayoutActionTyp
     // 用户工作台常用功能
     case 'layout/userRolePermissions':
       return { ...state, userRolePermissions: action.payload }
+    // 设置用户信息
+    case 'layout/userInfo':
+      return { ...state, userInfo: action.payload }
+    // 修改密码
+    case 'layout/passEditShow':
+      return { ...state, passEditShow: action.payload }
 
     default:
       return state

+ 5 - 0
src/utils/http.ts

@@ -12,6 +12,11 @@ const baseUrlTemp = 'http://192.168.20.61:8112' // 线下环境
 
 const baseFlag = baseUrlTemp.includes('https://')
 
+// 工作台图标/其他静态图 前缀地址
+export const iconUrl = envFlag
+  ? `https://sit-qingdaobeer.4dage.com/backstage/tabImg`
+  : '/backstage/tabImg'
+
 // 请求基地址
 export const baseURL = envFlag ? `${baseUrlTemp}${baseFlag ? '' : '/api'}` : ''
 

+ 122 - 85
src/utils/pass.ts

@@ -1,100 +1,137 @@
 function randomWord(randomFlag: boolean, min: number, max: number = 15) {
-  let str = "";
-  let range = min;
+  let str = ''
+  let range = min
   const arr = [
-    "0",
-    "1",
-    "2",
-    "3",
-    "4",
-    "5",
-    "6",
-    "7",
-    "8",
-    "9",
-    "a",
-    "b",
-    "c",
-    "d",
-    "e",
-    "f",
-    "g",
-    "h",
-    "i",
-    "j",
-    "k",
-    "l",
-    "m",
-    "n",
-    "o",
-    "p",
-    "q",
-    "r",
-    "s",
-    "t",
-    "u",
-    "v",
-    "w",
-    "x",
-    "y",
-    "z",
-    "A",
-    "B",
-    "C",
-    "D",
-    "E",
-    "F",
-    "G",
-    "H",
-    "I",
-    "J",
-    "K",
-    "L",
-    "M",
-    "N",
-    "O",
-    "P",
-    "Q",
-    "R",
-    "S",
-    "T",
-    "U",
-    "V",
-    "W",
-    "X",
-    "Y",
-    "Z",
-  ];
+    '0',
+    '1',
+    '2',
+    '3',
+    '4',
+    '5',
+    '6',
+    '7',
+    '8',
+    '9',
+    'a',
+    'b',
+    'c',
+    'd',
+    'e',
+    'f',
+    'g',
+    'h',
+    'i',
+    'j',
+    'k',
+    'l',
+    'm',
+    'n',
+    'o',
+    'p',
+    'q',
+    'r',
+    's',
+    't',
+    'u',
+    'v',
+    'w',
+    'x',
+    'y',
+    'z',
+    'A',
+    'B',
+    'C',
+    'D',
+    'E',
+    'F',
+    'G',
+    'H',
+    'I',
+    'J',
+    'K',
+    'L',
+    'M',
+    'N',
+    'O',
+    'P',
+    'Q',
+    'R',
+    'S',
+    'T',
+    'U',
+    'V',
+    'W',
+    'X',
+    'Y',
+    'Z'
+  ]
   // 随机产生
   if (randomFlag) {
-    range = Math.round(Math.random() * (max - min)) + min;
+    range = Math.round(Math.random() * (max - min)) + min
   }
   for (var i = 0; i < range; i++) {
-    const pos = Math.round(Math.random() * (arr.length - 1));
-    str += arr[pos];
+    const pos = Math.round(Math.random() * (arr.length - 1))
+    str += arr[pos]
   }
-  return str;
+  return str
 }
 
-const encodeStr = (str: string, strv = "") => {
-  const NUM = 2;
-  const front = randomWord(false, 8);
-  const middle = randomWord(false, 8);
-  const end = randomWord(false, 8);
+const encodeStr = (str: string, strv = '') => {
+  const NUM = 2
+  const front = randomWord(false, 8)
+  const middle = randomWord(false, 8)
+  const end = randomWord(false, 8)
 
-  const str1 = str.substring(0, NUM);
-  const str2 = str.substring(NUM);
+  const str1 = str.substring(0, NUM)
+  const str2 = str.substring(NUM)
 
   if (strv) {
-    const strv1 = strv.substring(0, NUM);
-    const strv2 = strv.substring(NUM);
-    return [
-      front + str2 + middle + str1 + end,
-      front + strv2 + middle + strv1 + end,
-    ];
+    const strv1 = strv.substring(0, NUM)
+    const strv2 = strv.substring(NUM)
+    return [front + str2 + middle + str1 + end, front + strv2 + middle + strv1 + end]
   }
 
-  return front + str2 + middle + str1 + end;
-};
+  return front + str2 + middle + str1 + end
+}
+
+const decodeOne = (str: string) => {
+  const str1 = str.substring(str.length - 10, str.length - 8)
+  const str2 = str.substring(8, str.length - 18)
+  return str1 + str2
+}
+
+const decodeStr = (encoded: string | [string, string]) => {
+  if (Array.isArray(encoded)) {
+    return [decodeOne(encoded[0]), decodeOne(encoded[1])]
+  }
+  return decodeOne(encoded)
+}
+
+/** 判断是否为 encodeStr 加密后的字符串(长度>=26) */
+const isEncoded = (str: string) => str && str.length >= 26
+
+/** 解密或返回原值(兼容未加密的旧数据) */
+export const decodeIfEncoded = (str: string): string => (isEncoded(str) ? decodeOne(str) : str)
+
+/** 脱敏:papers 保留前2位、后2位 */
+export const maskPapers = (str: string) => {
+  if (!str) return str
+  if (str.length <= 4) return str
+  return str.substring(0, 2) + '*'.repeat(str.length - 4) + str.substring(str.length - 2)
+}
+
+/** 脱敏:phone 保留前3位、后4位 */
+export const maskPhone = (str: string) => {
+  if (!str) return str
+  if (str.length <= 7) return str
+  return str.substring(0, 3) + '*'.repeat(str.length - 7) + str.substring(str.length - 4)
+}
+
+/** 列表显示:papers 解密后脱敏 */
+export const getStaffDisplayPapers = (val: string) => maskPapers(decodeIfEncoded(val || ''))
+
+/** 列表显示:phone 解密后脱敏 */
+export const getStaffDisplayPhone = (val: string) => maskPhone(decodeIfEncoded(val || ''))
 
-export default encodeStr;
+export default encodeStr
+export { decodeStr }

+ 19 - 22
src/utils/storage.ts

@@ -1,7 +1,4 @@
 // ------------------------------------token的本地存储------------------------------------
-
-import { RouterTypeRow } from '@/pages/Layout/data'
-
 // 用户 Token 的本地缓存键名,自己定义
 const TOKEN_KEY = 'QING_DAO_PI_JIU_GOODS_HOUTAI_USETINFO'
 
@@ -41,29 +38,29 @@ export const getTokenFu = (): string => {
   return getTokenInfo().token
 }
 
-// --------------------业务中心-常用功能存储
-const CHANG_KEY = 'QING_DAO_PI_JIU_GOODS_HT_CHANG_ARR'
+// // --------------------工作台-常用功能存储
+// const CHANG_KEY = 'QING_DAO_PI_JIU_GOODS_HT_CHANG_ARR'
 
-// 存
-export const changSetFu = (info: RouterTypeRow): void => {
-  const oldArr = changGetFu()
+// // 存
+// export const changSetFu = (info: RouterTypeRow): void => {
+//   const oldArr = changGetFu()
 
-  let newArr: RouterTypeRow[] = []
+//   let newArr: RouterTypeRow[] = []
 
-  // 已经存在了
-  const oldIds = oldArr.map(v => v.id)
-  if (oldIds.includes(info.id)) newArr = oldArr
-  else {
-    if (oldArr.length <= 2) newArr = [...oldArr, info]
-    else newArr = [...oldArr.slice(-2), info]
-  }
+//   // 已经存在了
+//   const oldIds = oldArr.map(v => v.id)
+//   if (oldIds.includes(info.id)) newArr = oldArr
+//   else {
+//     if (oldArr.length <= 2) newArr = [...oldArr, info]
+//     else newArr = [...oldArr.slice(-2), info]
+//   }
 
-  localStorage.setItem(CHANG_KEY, JSON.stringify(newArr))
-}
-// 取
-export const changGetFu = (): RouterTypeRow[] => {
-  return JSON.parse(localStorage.getItem(CHANG_KEY) || '[]')
-}
+//   localStorage.setItem(CHANG_KEY, JSON.stringify(newArr))
+// }
+// // 取
+// export const changGetFu = (): RouterTypeRow[] => {
+//   return JSON.parse(localStorage.getItem(CHANG_KEY) || '[]')
+// }
 
 // ------------------藏品详情id,回跳需要
 const GOODPAGE_KEY = 'QING_DAO_PI_JIU_GOODPAGE_KEY'

+ 45 - 9
src/utils/tableData.ts

@@ -191,15 +191,19 @@ export const GI4tableC = [
   ['txt', '编辑人', 'creatorName']
 ]
 
-// 藏品详情----藏品日志
-export const GI5tableC = [
-  ['dateRes', '业务发生日期', 'date'],
-  ['txt', '申请编号', 'num'],
-  ['txt', '发起部门', 'deptName'],
-  ['txt', '发起人', 'creatorName'],
-  ['txt', '发起日期', 'date'],
-  ['select', '申请状态', 'status', selectObj['藏品入库申请状态']]
-]
+// 藏品详情----藏品日志 / 工作台
+export const GI5tableC = (flag?: boolean) => {
+  let arr = [
+    ['dateRes', '业务发生日期', 'date'],
+    ['txt', '申请编号', 'num'],
+    ['txt', '发起部门', 'deptName'],
+    ['txt', '发起人', 'creatorName'],
+    ['txt', '发起日期', 'date'],
+    ['select', '申请状态', 'status', selectObj['藏品入库申请状态']]
+  ]
+  if (flag) arr.shift()
+  return arr
+}
 
 // 流程中心
 export const flowCenterTableC = [
@@ -239,3 +243,35 @@ export const importDataTableC = [
   ['txt', '导入用户', 'creatorName'],
   ['txt', '导入结果', 'fileSize']
 ]
+
+// 资源使用
+export const resourceTableC = [
+  ['txt', '使用日期', 'createTime'],
+  ['txt', '申请编号', 'num'],
+  ['txt', '发起部门', 'deptName'],
+  ['txt', '发起人', 'creatorName'],
+  ['txt', '发起日期', 'date'],
+  ['select', '申请状态', 'status', selectObj['藏品入库申请状态']]
+]
+
+// 藏品移库
+export const moveStorageTableC = [
+  ['txt', '移库日期', 'createTime'],
+  ['txt', '移库库房', 'extraInfo'],
+  ['txt', '申请编号', 'num'],
+  ['txt', '发起部门', 'deptName'],
+  ['txt', '发起人', 'creatorName'],
+  ['txt', '发起日期', 'date'],
+  ['select', '申请状态', 'status', selectObj['藏品入库申请状态']]
+]
+
+// 人员出入库
+export const staffTableC = [
+  ['txt', '出入日期', 'createTime'],
+  ['txt', '相关库房', 'storageName'],
+  ['txt', '申请编号', 'num'],
+  ['txt', '发起部门', 'deptName'],
+  ['txt', '发起人', 'creatorName'],
+  ['txt', '发起日期', 'date'],
+  ['select', '申请状态', 'status', selectObj['藏品入库申请状态']]
+]