소스 검색

初步封装

shaogen1995 22 시간 전
부모
커밋
98c19d8b33

+ 5 - 0
src/assets/styles/base.css

@@ -180,3 +180,8 @@ textarea {
 .ant-table-body .ant-table-cell {
   border-color: #ccc !important;
 }
+.editMain {
+  width: 100%;
+  height: calc(100% - 60px);
+  overflow-y: auto;
+}

+ 16 - 2
src/assets/styles/base.less

@@ -18,8 +18,16 @@ html {
 }
 
 body {
-  font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB',
-    'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
+  font:
+    1em/1.4 'Microsoft Yahei',
+    'PingFang SC',
+    'Avenir',
+    'Segoe UI',
+    'Hiragino Sans GB',
+    'STHeiti',
+    'Microsoft Sans Serif',
+    'WenQuanYi Micro Hei',
+    sans-serif;
   height: 100%;
   color: var(--themeColor) !important;
 }
@@ -304,3 +312,9 @@ textarea {
 //     stroke: var(--themeColor) !important;
 //   }
 // }
+
+.editMain {
+  width: 100%;
+  height: calc(100% - 60px);
+  overflow-y: auto;
+}

+ 4 - 3
src/components/MyPopconfirm.tsx

@@ -2,7 +2,7 @@ import React, { useMemo } from 'react'
 import { Button, Popconfirm } from 'antd'
 
 type Props = {
-  txtK: '删除' | '删除2' | '取消' | '返回' | '重置密码' | '退出登录' | '重新提交'
+  txtK: '删除' | '删除2' | '取消' | '返回' | '重置密码' | '退出登录' | '重新提交' | '撤回'
   onConfirm: () => void
   Dom?: React.ReactNode
   loc?: 'bottom'
@@ -13,12 +13,13 @@ function MyPopconfirm({ txtK, onConfirm, Dom, loc, disabled }: Props) {
   const txt = useMemo(() => {
     const obj = {
       删除: ['删除后无法恢复,是否删除?', '删除'],
-      删除2: ['确定发起删除订单吗?', '确定'],
+      删除2: ['确定删除吗?', '确定'],
       取消: ['放弃编辑后,信息将不会保存!', '放弃'],
       返回: ['放弃编辑后,信息将不会保存!', '放弃'],
       重置密码: ['密码重制后为Aa147852,是否重置?', '重置'],
       退出登录: ['确定退出吗?', '确定'],
-      重新提交: ['确定重新提交吗?', '确定']
+      重新提交: ['确定重新提交吗?', '确定'],
+      撤回: ['确定撤回吗?', '确定']
     }
     return Reflect.get(obj, txtK) || ['', '']
   }, [txtK])

+ 4 - 2
src/pages/Dmanage/D1register/D1edit/index.module.scss

@@ -1,4 +1,6 @@
 .D1edit {
-  :global {
-  }
+  font-size: 16px;
+  background-color: var(--boxBcaColor);
+  border-radius: 10px;
+  // :global {}
 }

+ 52 - 2
src/pages/Dmanage/D1register/D1edit/index.tsx

@@ -1,9 +1,59 @@
-import React from 'react'
+import React, { useCallback, useEffect, useRef, useState } from 'react'
 import styles from './index.module.scss'
+import { D1_APIcreate, D1_APIgetInfo } from '@/store/action/Dmanage/D1register'
+import EditTop from '@/pages/Zother/EditTop'
+import EditBtn from '@/pages/Zother/EditBtn'
+import { rowArrTemp, TypeD1table } from '../data'
+import { useParams } from 'react-router-dom'
+
+const rowArr = rowArrTemp('登记')
+
 function D1edit() {
+  // key:1 新增 2编辑 3审批 4查看
+  const { key, id } = useParams<any>()
+
+  const [info, setInfo] = useState({} as TypeD1table)
+  const setInfoFu = useCallback((info: TypeD1table) => {
+    setInfo(info)
+  }, [])
+
+  // 用于按钮鉴权,只修改一次,减少重构
+  const [btnPow, setBenPow] = useState({} as TypeD1table)
+
+  // 创建订单
+  const createFu = useCallback(async () => {
+    const res = await D1_APIcreate()
+    if (res.code === 0) {
+      setInfo(res.data)
+      setBenPow(res.data)
+    }
+  }, [])
+
+  // 获取详情
+  const getInfoFu = useCallback(async (id: number) => {
+    const res = await D1_APIgetInfo(id)
+    if (res.code === 0) {
+      setInfo(res.data)
+      setBenPow(res.data)
+    }
+  }, [])
+
+  useEffect(() => {
+    if (key === '1') createFu()
+    else getInfoFu(id)
+  }, [createFu, getInfoFu, id, key])
+
   return (
     <div className={styles.D1edit}>
-      <h1>D1edit</h1>
+      <div className='editMain'>
+        {/* 顶部 */}
+        <EditTop pageTxt='藏品登记' rowArr={rowArr} info={info} setInfo={setInfoFu} />
+
+        {/* 藏品清单 */}
+
+        {/* 底部按钮 */}
+        <EditBtn path='/register' btnPow={btnPow} info={info} />
+      </div>
     </div>
   )
 }

+ 43 - 1
src/pages/Dmanage/D1register/data.ts

@@ -1,4 +1,4 @@
-import { selectObj } from '@/utils/dataChange'
+import { getDictFu, selectObj } from '@/utils/dataChange'
 
 export type TypeD1table = {
   auditUserIds: string
@@ -24,6 +24,7 @@ export type TypeD1table = {
   status: number
   type: string
   updateTime: string
+  deptName: string
 }
 export type D1formType = {
   pageSize: number
@@ -72,3 +73,44 @@ export const D1search = [
     style: { width: 200 }
   }
 ]
+
+// 查看页面顶部字段 通用部分
+export const rowArrTemp = (txt: string) => {
+  return [
+    {
+      name: `藏品${txt}`,
+      type: 'txt'
+    },
+    {
+      name: `${txt}日期`,
+      must: true,
+      key: 'date',
+      type: 'DatePicker'
+    },
+    {
+      name: '申请编号',
+      must: true,
+      key: 'num',
+      type: 'Input',
+      noNull: true //不允许输入空格
+    },
+    {
+      name: '申请类型',
+      key: 'dictIdApply',
+      type: 'Cascader',
+      options: getDictFu(`藏品${txt}`)
+    },
+    {
+      name: '事由说明',
+      full: true,
+      key: 'reason',
+      type: 'TextArea'
+    },
+    {
+      name: '备注',
+      full: true,
+      key: 'remark',
+      type: 'TextArea'
+    }
+  ]
+}

+ 1 - 0
src/pages/Dmanage/D1register/index.module.scss

@@ -3,3 +3,4 @@
 
 //   }
 // }
+// 这里先保留,某些时候可能需要 覆盖一下子组件的样式

+ 0 - 2
src/pages/Dmanage/D1register/index.tsx

@@ -2,9 +2,7 @@ import React from 'react'
 import styles from './index.module.scss'
 import { useSelector } from 'react-redux'
 import { D1baseFormData, D1search } from './data'
-
 import { RootState } from '@/store'
-
 import { D1tableC } from '@/utils/tableData'
 import { D1_APIgetList } from '@/store/action/Dmanage/D1register'
 import TableList from '@/pages/Zother/TableList'

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

@@ -323,4 +323,11 @@ export default tabLeftArr
 
 // 里面的页面,不是左边的tab栏
 // 这里的id要和tab栏的id相同,不然没有权限进入页面
-export const routerSon: RouterTypeRow[] = []
+export const routerSon: RouterTypeRow[] = [
+  {
+    id: 410,
+    name: '藏品登记-详情页',
+    path: '/register_edit/:key/:id',
+    Com: React.lazy(() => import('../Dmanage/D1register/D1edit'))
+  }
+]

+ 15 - 0
src/pages/Zother/EditBtn/index.module.scss

@@ -0,0 +1,15 @@
+.EditBtn {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 60px;
+  display: flex;
+  align-items: center;
+  padding-left: 40px;
+  :global {
+    .ant-btn {
+      margin-right: 15px;
+    }
+  }
+}

+ 102 - 0
src/pages/Zother/EditBtn/index.tsx

@@ -0,0 +1,102 @@
+import React, { useCallback, useEffect, useState } from 'react'
+import styles from './index.module.scss'
+import { Button } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { backPageFu } from '@/utils/history'
+import { useParams } from 'react-router-dom'
+import { TypeD1table } from '@/pages/Dmanage/D1register/data'
+import { editBtnShowFu, pageSkitFu } from '@/utils/authority'
+
+type Props = {
+  path: string
+  info: TypeD1table
+  btnPow: TypeD1table
+}
+
+function EditBtn({ path, info, btnPow }: Props) {
+  // key:1 新增 2编辑 3审批 4查看
+  const { key, id } = useParams<any>()
+
+  const [btnPowArr, setBtnPowArr] = useState<string[]>([])
+
+  useEffect(() => {
+    if (btnPow.id) {
+      const arr = editBtnShowFu(btnPow)
+      setBtnPowArr(arr)
+    }
+  }, [btnPow])
+
+  // 点击按钮触发事件
+  const sonClick = useCallback(
+    (val: string, flag?: string) => {
+      // console.log('点击按钮', val, flag)
+
+      if (flag) pageSkitFu(path, val, id, flag)
+      else {
+        // 各种操作按钮逻辑待完善sg
+      }
+    },
+    [id, path]
+  )
+
+  return (
+    <div className={styles.EditBtn}>
+      {['1', '2'].includes(key) ? (
+        <>
+          <Button type='primary' onClick={() => sonClick('草稿')}>
+            存草稿
+          </Button>
+          <Button type='primary' onClick={() => sonClick('发起')}>
+            提交
+          </Button>
+          <MyPopconfirm txtK='取消' onConfirm={() => backPageFu(path)} />
+        </>
+      ) : key === '3' ? (
+        <>
+          <Button type='primary' onClick={() => sonClick('审批')}>
+            审批
+          </Button>
+          <Button onClick={() => backPageFu(path)}>返回</Button>
+        </>
+      ) : key === '4' ? (
+        <>
+          {btnPowArr.includes('重新发起') ? (
+            <Button type='primary' onClick={() => sonClick('发起')}>
+              重新发起
+            </Button>
+          ) : null}
+          {btnPowArr.includes('撤回') ? (
+            <MyPopconfirm
+              txtK='撤回'
+              onConfirm={() => sonClick('撤回')}
+              Dom={<Button danger>撤回</Button>}
+            />
+          ) : null}
+          {btnPowArr.includes('编辑') ? (
+            <Button type='primary' onClick={() => sonClick('2', '编辑')}>
+              编辑
+            </Button>
+          ) : null}
+          {btnPowArr.includes('发起') ? (
+            <Button type='primary' onClick={() => sonClick('发起')}>
+              发起
+            </Button>
+          ) : null}
+          {btnPowArr.includes('删除') ? (
+            <MyPopconfirm
+              txtK='删除2'
+              onConfirm={() => sonClick('删除')}
+              Dom={<Button danger>删除</Button>}
+            />
+          ) : null}
+
+          <Button onClick={() => backPageFu(path)}>返回</Button>
+        </>
+      ) : null}
+    </div>
+  )
+}
+
+const MemoEditBtn = React.memo(EditBtn)
+
+export default MemoEditBtn

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

@@ -0,0 +1,45 @@
+.EditTop {
+  :global {
+    .EdTit {
+      padding: 15px;
+      font-weight: 700;
+      font-size: 18px;
+      .ant-btn {
+        pointer-events: none;
+      }
+    }
+
+    .Edtop1 {
+      border-top: 1px solid #ccc;
+      padding: 15px;
+      display: flex;
+      justify-content: space-between;
+      flex-wrap: wrap;
+      .Edtop1row {
+        display: flex;
+        width: 48%;
+        margin-bottom: 15px;
+        min-height: 32px;
+        line-height: 32px;
+        .Edtop1ll {
+          font-weight: 700;
+          width: 100px;
+          text-align: right;
+
+          span {
+            color: #ff4d4f;
+          }
+        }
+        .Edtop1rr {
+          width: calc(100% - 100px);
+          & > div {
+            width: 100%;
+          }
+        }
+      }
+      .Edtop1rowFull {
+        width: 100%;
+      }
+    }
+  }
+}

+ 148 - 0
src/pages/Zother/EditTop/index.tsx

@@ -0,0 +1,148 @@
+import { useCallback, useMemo } from 'react'
+import styles from './index.module.scss'
+import { selectObj } from '@/utils/dataChange'
+import { useParams } from 'react-router-dom'
+import { TypeD1table } from '@/pages/Dmanage/D1register/data'
+import dayjs from 'dayjs'
+import { Button, Cascader, DatePicker, Input } from 'antd'
+import classNames from 'classnames'
+import TextArea from 'antd/es/input/TextArea'
+
+const pageKeyTxtObj = {
+  1: '新增',
+  2: '编辑',
+  3: '审批',
+  4: '查看'
+}
+
+type Props = {
+  // 顶部信息录入
+  rowArr: any[]
+  // 页面字段
+  pageTxt: string
+  // 数据
+  info: TypeD1table
+  // 修改数据
+  setInfo: (info: TypeD1table) => void
+}
+
+function EditTop({ rowArr, pageTxt, info, setInfo }: Props) {
+  const { key } = useParams<any>()
+  // key:1 新增 2编辑 3审批 4查看
+  const pageKeyTxt = useMemo(() => {
+    return Reflect.get(pageKeyTxtObj, key)
+  }, [key])
+
+  // 数据改变
+  const dataChangeFu = useCallback(
+    (val: any, item: any) => {
+      const type = item.type
+      const key = item.key
+
+      if (type === 'DatePicker') {
+        setInfo({ ...info, [key]: dayjs(val).format('YYYY-MM-DD') })
+      } else if (['TextArea', 'Input'].includes(type)) {
+        const varRes = item.noNull ? val.replace(/\s+/g, '') : val
+        setInfo({
+          ...info,
+          [key]: varRes
+        })
+      } else if (type === 'Cascader') {
+        setInfo({ ...info, dictIdApply: val ? val.join(',') : '' })
+      }
+    },
+    [info, setInfo]
+  )
+
+  // 订单申请状态
+  const statusTxt = useMemo(() => {
+    let txt = ''
+    const obj = selectObj['订单审批状态'].find(v => v.value === info.status)
+
+    // 新增的时候看不到状态
+    if (key !== '1' && obj) txt = obj.label
+    return txt
+  }, [info.status, key])
+
+  return (
+    <div className={styles.EditTop}>
+      <div className='pageTitle'>
+        {pageTxt}-{pageKeyTxt}
+      </div>
+
+      {info.id ? (
+        <>
+          <div className='EdTit'>
+            申请信息&emsp;{statusTxt ? <Button type='dashed'>{statusTxt}</Button> : null}
+          </div>
+          <div className='Edtop1'>
+            {rowArr.map((item, index) => (
+              <div
+                key={index}
+                className={classNames('Edtop1row', item.full ? 'Edtop1rowFull' : '')}
+              >
+                <div className='Edtop1ll'>
+                  {item.must ? <span>* </span> : null}
+                  {item.name}:
+                </div>
+                <div className='Edtop1rr'>
+                  {item.type === 'txt' ? (
+                    <>
+                      {dayjs(info.createTime).format('YYYY年MM月DD日')}-{info.deptName}-
+                      {info.creatorName}
+                    </>
+                  ) : item.type === 'DatePicker' ? (
+                    <DatePicker
+                      disabled={['3', '4'].includes(key)}
+                      allowClear={!item.must}
+                      value={dayjs(info[item.key as 'date'])}
+                      onChange={e => dataChangeFu(e, item)}
+                    />
+                  ) : item.type === 'Input' ? (
+                    <Input
+                      placeholder='请输入内容'
+                      value={info[item.key as 'date']}
+                      onChange={e => dataChangeFu(e.target.value, item)}
+                      maxLength={item.maxLength || 30}
+                      showCount
+                    />
+                  ) : item.type === 'Cascader' ? (
+                    <Cascader
+                      changeOnSelect
+                      options={item.options}
+                      placeholder='请选择'
+                      fieldNames={{ label: 'name', value: 'id', children: 'children' }}
+                      allowClear={!item.must}
+                      value={
+                        info[item.key as 'date']
+                          ? (info[item.key as 'date'] as string).split(',')
+                          : []
+                      }
+                      onChange={e => dataChangeFu(e, item)}
+                    />
+                  ) : item.type === 'TextArea' ? (
+                    <TextArea
+                      placeholder='请输入内容'
+                      value={info[item.key as 'date']}
+                      onChange={e => dataChangeFu(e.target.value, item)}
+                      maxLength={item.maxLength || 500}
+                      showCount
+                    />
+                  ) : null}
+                </div>
+              </div>
+            ))}
+
+            {/* 附件 */}
+            <div className='Edtop1row Edtop1rowFull'>
+              <div className='Edtop1ll'>附件:</div>
+              <div className='Edtop1rr'></div>
+            </div>
+          </div>
+        </>
+      ) : null}
+    </div>
+  )
+}
+
+export default EditTop

+ 8 - 5
src/pages/Zother/TableList/index.module.scss

@@ -1,6 +1,6 @@
 .TableListTop {
   border-radius: 10px;
-  padding: 15px 15px 0;
+  padding: 15px 15px 5px;
   background-color: var(--boxBcaColor);
   display: flex;
   justify-content: space-between;
@@ -9,10 +9,10 @@
     .TableListTopll {
       display: flex;
       flex-wrap: wrap;
-      margin-bottom: 15px;
+
       & > div {
-        margin-right: 10px;
-        flex: 1;
+        padding-right: 10px;
+        margin-bottom: 10px;
         & > div {
           width: 100%;
         }
@@ -24,8 +24,11 @@
     .TableListToprr {
       display: flex;
       flex-wrap: wrap;
-      margin-bottom: 15px;
+
       justify-content: space-between;
+      .ant-btn {
+        margin-bottom: 10px;
+      }
     }
   }
 }

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

@@ -17,7 +17,9 @@ type Props = {
   yHeight: number
   searchDom: any[]
   // 右侧按钮的宽度
-  rightBtnWidth?: 250
+  rightBtnWidth?: number
+  // 左侧每个输入框盒子的宽度
+  leftRowWidth?: string
 }
 
 function TableList({
@@ -28,7 +30,8 @@ function TableList({
   columnsTemp,
   yHeight,
   searchDom,
-  rightBtnWidth = 250
+  rightBtnWidth = 250,
+  leftRowWidth = '25%'
 }: Props) {
   const dispatch = useDispatch()
 
@@ -137,7 +140,7 @@ function TableList({
       <div className={styles.TableListTop}>
         <div className='TableListTopll' style={{ width: `calc(100% - ${rightBtnWidth + 20}px)` }}>
           {searchDom.map((item, index) => (
-            <div key={index}>
+            <div key={index} style={{ width: leftRowWidth }}>
               {item.type === 'time' ? (
                 <RangePicker
                   value={

+ 15 - 1
src/store/action/Dmanage/D1register.ts

@@ -19,8 +19,22 @@ export const D1_APIgetList = (data: any): any => {
 }
 
 /**
- * 藏品登记-列表删除
+ * 藏品登记-删除
  */
 export const D1_APIdel = (id: number) => {
   return http.get(`cms/order/register/remove/${id}`)
 }
+
+/**
+ * 藏品登记-创建订单
+ */
+export const D1_APIcreate = () => {
+  return http.get(`cms/order/register/create`)
+}
+
+/**
+ * 藏品登记-获取详情
+ */
+export const D1_APIgetInfo = (id: number) => {
+  return http.get(`cms/order/register/detail/${id}`)
+}

+ 43 - 0
src/utils/authority.ts

@@ -2,6 +2,7 @@ import store from '@/store'
 import { MessageFu } from './message'
 import { TypeD1table } from '@/pages/Dmanage/D1register/data'
 import { getTokenInfo } from './storage'
+import history from './history'
 
 // 看下有没有权限
 export const authorityFu = (id: number, txt: string, fu: () => void) => {
@@ -24,3 +25,45 @@ export const tableListAuditBtnFu = (item: TypeD1table) => {
 
   return flag
 }
+
+// 编辑页面 各个按钮的显示状态
+export const editBtnShowFu = (item: TypeD1table) => {
+  const arr: string[] = []
+  //申请单状态     申请人id      当前节点审批人
+  const { status, creatorId } = item
+
+  // 当前用户id
+  const myId = (getTokenInfo().user || { id: 0 }).id
+
+  if (creatorId === myId) {
+    //  -重新发起:未通过,且当前用户为申请创建人;点击后带入数据重新创建申请
+    if (status === 3) arr.push('重新发起')
+    // - 撤回:待审批,且当前用户为申请创建人
+    if (status === 2) arr.push('撤回')
+    // - 编辑:草稿,且当前用户为申请创建人
+    // - 发起:草稿,且当前用户为申请创建人
+    if (status === 1) {
+      arr.push('编辑')
+      arr.push('发起')
+    }
+    // - 删除:草稿/未通过,且当前用户为申请创建人
+    if ([1, 3].includes(status)) arr.push('删除')
+  }
+  return arr
+}
+
+// 详情页移动到顶部
+export const editPageToTopFu = () => {
+  const dom: HTMLDivElement = document.querySelector('.editMain')!
+
+  if (dom) {
+    dom.scrollTo({ top: 0, behavior: 'smooth' })
+  }
+}
+
+// 详情页跳转
+export const pageSkitFu = (path: string, key: string, id: number, txt?: string) => {
+  history.replace(`${path}_edit/${key}/${id}`)
+  editPageToTopFu()
+  if (txt) MessageFu.success(`已调转至${txt}页面`)
+}

+ 8 - 0
src/utils/dataChange.ts

@@ -60,3 +60,11 @@ export const selectObj = {
     { value: 0, label: '禁用' }
   ]
 }
+
+// 详情页申请类型-获取字典数据
+export const getDictFu = (key: string) => {
+  const ditcAll = store.getState().I2dict.dictAll
+  const list = ditcAll.filter(v => v.name === key)
+
+  return list[0].children
+}