Bladeren bron

feat: 质量巡检初始化

lanjianrong 4 jaren geleden
bovenliggende
commit
8002fabea6

+ 5 - 11
src/components/OssUpload/index.tsx

@@ -28,7 +28,9 @@ const UploadModal:React.FC<iUploadModalProps> = (props) => {
   })
   useEffect(() => {
     if (props.visible) {
+      // 初始化时要将上次上次的文件清除掉
       setFileList([])
+      setFiles([])
       initOssData()
     }
   }, [ props.visible ])
@@ -39,19 +41,11 @@ const UploadModal:React.FC<iUploadModalProps> = (props) => {
       // console.log(info.file, info.fileList)
     }
     if (status === 'done') {
-      // message.success(`${info.file.name} 上传成功!`)
       console.log(info)
-      const newFileList = [ ...fileList ]
-      newFileList.push(info.file)
+      const newFileList = [ ...fileList, ...info.fileList ]
+      // newFileList.push(info.file)
       setFileList(newFileList)
-      // const newFileList: iFile[] = info.fileList.map((item: UploadFile) => {
-      //   return {
-      //     createTime: new Date(),
-      //     filepath: item.url,
-      //     filename: item.name
-      //   }
-      // })
-      const newFiles = [ ...files, { createTime: new Date(), filepath: info.file.url,filename: info.file.name } ]
+      const newFiles = [ ...files, ...info.fileList.map(item => ({ createTime: new Date(), filepath: item.url,filename: item.name })) ]
       setFiles(newFiles)
     } else if (status === 'error') {
       message.error(`${info.file.name} 上传失败!`)

+ 21 - 12
src/pages/Quality/Content/Info/Detail/api.ts

@@ -1,22 +1,31 @@
-import { iFile } from "@/types/file"
+import { iAuditHistoryState } from "@/types/safe"
 import request from "@/utils/common/request"
 
 /**
  * 获取安全巡检详情
  * @param id - 安全巡检id
  */
-export async function apiGetSafeDetail(id: string) {
-  const { data } = await request.get('/api/safe/detail', { id })
+export async function apiGetQualityDetail(id: string) {
+  const { data } = await request.get('/api/quality/detail', { id })
+  const auditHistory: iAuditHistoryState[][] = []
+  for (const key in data?.data?.auditHistory) {
+    if (Object.prototype.hasOwnProperty.call(data?.data?.auditHistory, key)) {
+      const history = data?.data?.auditHistory[key]
+      auditHistory.unshift(history)
+    }
+  }
+  data.data.auditHistory = auditHistory
   return data
 }
 
-/**
- *
- * @param fileList - 附件数组
- * @param dataType - 类型
- * @param dataId - 数据id
- */
-export async function apiSaveFileInfo(fileList: iFile[], dataType: number, dataId: string) {
-  const { data } = await request.post('/api/file', { fileList, dataType, dataId })
-  return data
+// 安全巡检审批
+export async function apiResfulQualityAudit(type: string, payload: object) {
+  if (type === 'delete') {
+    // 删除巡检记录
+    const { data } = await request.del('/api/quality', payload)
+    return data
+  } else {
+    const { data } = await request.post(`/api/quality_audit/${type}`, payload)
+    return data
+  }
 }

+ 328 - 0
src/pages/Quality/Content/Info/Detail/components/Modal/index.tsx

@@ -0,0 +1,328 @@
+import { GroupItem } from '@/components/AuditContent'
+import { ZhAuditBackButton, ZhButton, ZhCloseButton, ZhSubmitButton } from '@/components/Button'
+import { userStore } from '@/store/mobx'
+import { iAuditor, iLatestAuditorState } from '@/types/safe'
+import { iAccountGroupItem, iUserInfo } from '@/types/setting'
+import { getUserGroup } from '@/utils/common/user'
+import { Button, Form, Input, message, Modal, Popover } from 'antd'
+import React, { ChangeEvent, useEffect, useMemo, useState } from 'react'
+interface iAuditModalProps {
+  visible: boolean
+  onCancel: () => void
+  type: string
+  auditors: iAuditor[]
+  onCreate: (values?: any) => void
+  curAuditor: iLatestAuditorState
+}
+const textObj = {
+  start: {
+    title: '提交审批',
+    okText: '确认提交'
+  },
+  delete: {
+    title: '删除巡检',
+    okText: '确认删除'
+  },
+  close: {
+    title: '审批关闭',
+    okText: '确认关闭'
+  },
+  back: {
+    title: '审批退回',
+    okText: '确认退回'
+  },
+  pass: {
+    title: '审批通过',
+    okText: '确认通过'
+  }
+}
+
+interface iModalObjState {
+  searchValue: string
+  visible: boolean
+  auditType: string
+}
+const AuditModal: React.FC<iAuditModalProps> = props => {
+  const [ form ] = Form.useForm()
+  const { visible, type, onCancel, onCreate, auditors, curAuditor } = props
+  const [ modal, setModal ] = useState<iModalObjState>({
+    searchValue: '',
+    visible: false,
+    auditType: ''
+  })
+  // 是否是审批组的最后一个审核人
+  const isLastAuditor = useMemo(() => {
+    const len = auditors.filter(item => item.progress === '0').length
+    if (len && auditors.filter(item => item.progress === '0')[len - 1].audit_id === userStore.userInfo.id) {
+      return true
+    }
+    return false
+  }, [ auditors ])
+  const [ groups, setGroups ] = useState<Array<iAccountGroupItem>>([])
+  const [ user, setUser ] = useState<iUserInfo>({
+    account: '',
+    accountGroup: 0,
+    company: '',
+    csrf: '',
+    enable: 0,
+    id: '',
+    isAdmin: 0,
+    mobile: '',
+    name: '',
+    password: '',
+    position: '',
+    projectId: '',
+    role: '',
+    telephone: ''
+  })
+  const comfirmBtnClick = () => {
+    form.validateFields().then(values => {
+      form.resetFields()
+      if (user.id) {
+        values.audit_id = user.id
+      }
+
+      if (type === 'pass' && isLastAuditor && curAuditor.progress === '0' && !user.id) {
+        return message.error('请指定整改人!')
+      }
+      onCreate(values)
+    })
+  }
+
+  useEffect(() => {
+    if (visible && isLastAuditor && type === 'pass') {
+      initGroupList()
+    }
+    if (visible && type === 'back') {
+      if (curAuditor.progress === '1') {
+        const len = auditors.filter(item => item.progress === '0').length
+        const lastChecker = auditors.filter(item => item.progress === '0')[len - 1]
+        setUser({ ...user, id: lastChecker.id, name: lastChecker.name })
+      } else {
+        const newGroup = initAuditBackGroup()
+        setGroups(newGroup)
+      }
+    }
+  }, [ visible ])
+  const initGroupList = async (serach?: string) => {
+    const data = await getUserGroup(serach)
+    setGroups(data)
+  }
+
+  // 初始化审批退回下拉选择框
+  const initAuditBackGroup = () => {
+    console.log(auditors)
+
+    const newGroup: iAccountGroupItem[] = []
+    for (let index = 0; index < 3; index++) {
+      if (index === 0) {
+        const newAuditors = auditors
+          .filter(item => item.progress === '')
+          .map(item => {
+            return mapUser(item.name, '', item.position, item.company, item.mobile)
+          })
+        newGroup.push({  value: '检查人', children: newAuditors })
+      }
+      if (index === 1) {
+        const newAuditors = auditors
+          .filter(item => item.progress === '0')
+          .map(item => {
+            return mapUser(item.name, item.id, item.position, item.company, item.mobile)
+          })
+        newGroup.push({  value: '审批', children: newAuditors })
+      }
+      if (index === 2) {
+        const newAuditors = auditors
+          .filter(item => item.progress === '1')
+          .map(item => {
+            return mapUser(item.name, item.id, item.position, item.company, item.mobile)
+          })
+        newGroup.push({ value: '整改', children: newAuditors })
+      }
+
+    }
+    function mapUser(name: string, id: string, position: string, company: string, mobile: string) {
+      return {
+        account: '',
+        accountGroup: 0,
+        company,
+        csrf: '',
+        enable: 0,
+        id,
+        isAdmin: 0,
+        mobile,
+        name,
+        password: '',
+        position,
+        projectId: '',
+        role: '',
+        telephone: ''
+      }
+    }
+    return newGroup
+  }
+
+  const renderOkBtn = (type: string) => {
+    if (type === 'start' || type === 'pass') {
+      return (
+        <ZhSubmitButton size="small" onClick={comfirmBtnClick}>
+          {textObj[type]?.okText}
+        </ZhSubmitButton>
+      )
+    } else if (type === 'delete' || type === 'close') {
+      return (
+        <Button danger size="small" onClick={comfirmBtnClick}>
+          {textObj[type]?.okText}
+        </Button>
+      )
+    } else if (type === 'back') {
+      return (
+        <ZhAuditBackButton size="small" onClick={comfirmBtnClick}>
+          {textObj[type]?.okText}
+        </ZhAuditBackButton>
+      )
+    }
+  }
+
+  const search = (value: string) => {
+    if (value != modal.searchValue) {
+      setModal({ ...modal, searchValue: value })
+      initGroupList(value)
+    }
+  }
+
+  const change = (e: ChangeEvent) => {
+    e.persist()
+    const target = e.target as HTMLTextAreaElement
+    if (!target.value) {
+      initGroupList()
+    }
+  }
+
+  const itemSelectHandler = (item: iUserInfo, type: string = '') => {
+    setUser({ ...user, ...item })
+
+    setModal({ ...modal, visible: false, auditType: type })
+  }
+
+  const handleVisibleChange = (visible: boolean) => {
+    setModal({ ...modal, visible })
+  }
+
+  const showPopover = () => {
+    setModal({ ...modal, visible: true })
+  }
+
+  return (
+    <Modal
+      visible={visible}
+      title={textObj[type]?.title}
+      onCancel={onCancel}
+      getContainer={false}
+      footer={
+        <div className="pi-justify-end">
+          <ZhCloseButton size="small" onClick={onCancel} className="pi-mg-right-5">
+            关闭
+          </ZhCloseButton>
+          {renderOkBtn(type)}
+        </div>
+      }>
+      <Form form={form} layout="vertical">
+        {type === 'back' ? (
+          <>
+            <Form.Item name="opinion" label="审批意见">
+              <Input.TextArea rows={5}></Input.TextArea>
+            </Form.Item>
+            {curAuditor.progress !== '1' ? (
+              <Popover
+                content={groups.map(item => (
+                  <GroupItem {...item} key={item.value} onSelect={(item: iUserInfo, type?: string) => itemSelectHandler(item, type)}></GroupItem>
+                ))}
+                overlayClassName="popover-card"
+                trigger="click"
+                visible={modal.visible}
+                onVisibleChange={visible => handleVisibleChange(visible)}
+                placement="bottomLeft">
+                <ZhButton size="small" onClick={showPopover}>
+                  选择退回流程
+                </ZhButton>
+              </Popover>
+            ) : null}
+
+            {user.name ? (
+              <div className="pi-bordered pi-warning">
+                <span>已选择退回流程: </span>
+                <span>{user.name}</span>
+              </div>
+            ) : null}
+          </>
+        ) : null}
+        {type === 'delete' ? (
+          <>
+            <p className="mb-2">删除后,数据无法恢复,请谨慎操作。</p>
+            <p className="mb-2">
+              请在下方文本框输入文本「<span className="pi-red">确认删除本次巡检</span>」,以此确认删除操作。
+            </p>
+            <Form.Item
+              name="warningText"
+              rules={[
+                () => ({
+                  validator(rule, value) {
+                    if (!value || value !== '确认删除本次巡检') {
+                      return Promise.reject('请按照提示信息进行删除操作!')
+                    }
+                    return Promise.resolve()
+                  }
+                })
+              ]}>
+              <Input placeholder="输入文本, 确认删除"></Input>
+            </Form.Item>
+          </>
+        ) : null}
+        {type === 'start' ? <p>请确认审批流程及信息无误。</p> : null}
+        {type === 'close' ? (
+          <>
+            <Form.Item name="opinion" label="审批意见">
+              <Input.TextArea rows={5}></Input.TextArea>
+            </Form.Item>
+            <p className="pi-warning">审批关闭,将直接停止该巡检流程。</p>
+          </>
+        ) : null}
+        {type === 'pass' ? (
+          <>
+            <Form.Item name="opinion" label="审批意见">
+              <Input.TextArea rows={5}></Input.TextArea>
+            </Form.Item>
+            {isLastAuditor && curAuditor.progress === '0' ? (
+              <Popover
+                title={<Input.Search size="small" placeholder="姓名/手机 检索" onSearch={search} onChange={e => change(e)}></Input.Search>}
+                content={groups.map(item => (
+                  <GroupItem {...item} key={item.value} onSelect={(item: iUserInfo, type?: string) => itemSelectHandler(item, type)}></GroupItem>
+                ))}
+                overlayClassName="popover-card"
+                trigger="click"
+                visible={modal.visible}
+                onVisibleChange={visible => handleVisibleChange(visible)}
+                placement="bottomLeft">
+                <ZhButton size="small" onClick={showPopover}>
+                  指派整改人
+                </ZhButton>
+              </Popover>
+            ) : null}
+
+            {user.id ? (
+              <p className="pi-bordered pi-pd-8 pi-mg-top-5">
+                <span>已指派整改人: </span>
+                <span>
+                  {user.name}-{user.position}-{user.company}
+                </span>
+              </p>
+            ) : null}
+          </>
+        ) : null}
+      </Form>
+    </Modal>
+  )
+}
+
+export default AuditModal

+ 2 - 0
src/pages/Quality/Content/Info/Detail/index.module.scss

@@ -1,6 +1,8 @@
 .detailContainer {
   width: 100%;
+  height: calc(100vh - 34px);
   margin: 0 auto;
+  overflow-y: scroll;
   .content {
     flex: 0 0 66.666667%;
     max-width: 66.666667%;

+ 389 - 87
src/pages/Quality/Content/Info/Detail/index.tsx

@@ -1,4 +1,5 @@
-import { ZhSubmitButton, ZhUploadButton } from '@/components/Button'
+import AuditContent from '@/components/AuditContent'
+import { ZhAuditBackButton, ZhCloseButton, ZhSubmitButton, ZhUploadButton } from '@/components/Button'
 import DatePicker from '@/components/DatePicker'
 import Header from '@/components/Header'
 import Slot from '@/components/Header/slot'
@@ -6,21 +7,27 @@ import OssUploadModal from '@/components/OssUpload'
 import SvgIcon from '@/components/SvgIcon'
 import { userStore } from '@/store/mobx'
 import { iFile } from '@/types/file'
-import { apiGetFileList, apiSaveFileInfo } from '@/utils/common/api'
+import { iAuditHistoryState, iAuditor, iLatestAuditorState, iRectifiedState } from '@/types/safe'
+import { iUserInfo } from '@/types/setting'
+import { apiDelFile, apiGetFileList, apiSaveFileInfo } from '@/utils/common/api'
+import { auditProgress } from '@/utils/common/constStatus'
 import consts from '@/utils/consts'
 import { dayjsFormat } from '@/utils/util'
-import { Button, Input, Pagination, Tooltip } from 'antd'
+import { Button, Input, message, Pagination, Tooltip } from 'antd'
 import locale from 'antd/es/date-picker/locale/zh_CN'
 import dayjs from 'dayjs'
-import React, { useEffect, useState } from 'react'
+import React, { useEffect, useState, useMemo } from 'react'
 import { RouteComponentProps } from 'react-router'
-import { apiGetSafeDetail } from './api'
+import { apiGetQualityDetail, apiResfulQualityAudit } from './api'
+import AuditModal from './components/Modal'
 import styles from './index.module.scss'
 const { TextArea } = Input
 interface iDetailState {
+  times: number
   auditName: string
-  auditors: any[]
+  auditors: iAuditor[]
   bidsectionId: string
+  uid: string
   code: string
   createTime: string | undefined
   demand: string
@@ -30,63 +37,258 @@ interface iDetailState {
   inspectionDetail: string
   position: string
   status: number
+  checkOrder: iModifiedOrder
+  auditHistory: iAuditHistoryState[][]
+  rectifiedInfo: iRectifiedState[]
+  latestAuditor: iLatestAuditorState
+}
+
+interface iModifiedOrder {
+  name: string
+  create_time: string | undefined
+  opinion: string
+  status: number
 }
 interface iFileState {
   fileList: any[]
   total: number
 }
-const Detail:React.FC<RouteComponentProps> = (props) => {
-  const [ visible, setVisible ] = useState<boolean>(false)
+
+interface iModalObj {
+  ossModal: boolean
+  auditModal: boolean
+  auditType: string
+  curPage: number
+}
+const Detail: React.FC<RouteComponentProps> = props => {
+  const { saveId = '' } = props.location.state as any
+  const [ visible, setVisible ] = useState<iModalObj>({
+    ossModal: false,
+    auditModal: false,
+    auditType: '',
+    curPage: 1
+  })
   const [ detail, setDetail ] = useState<iDetailState>({
-    auditName: "",
+    auditName: '',
+    uid: '',
     auditors: [],
-    bidsectionId: "",
-    code: "",
-    createTime: "",
-    demand: "",
+    bidsectionId: '',
+    code: '',
+    createTime: new Date().toDateString(),
+    demand: '',
     file: { fileList: [], total: 0 },
-    id: "",
-    inspection: "",
-    inspectionDetail: "",
-    position: "",
-    status: 0
+    id: '',
+    inspection: '',
+    inspectionDetail: '',
+    position: '',
+    status: 0,
+    checkOrder: {
+      // 整改单
+      name: '',
+      status: 0,
+      opinion: '',
+      create_time: new Date().toDateString()
+    },
+    auditHistory: [],
+    rectifiedInfo: [],
+    latestAuditor: {
+      audit_id: '',
+      audit_order: 0,
+      bidsection_id: '',
+      data_id: '',
+      data_type: 0,
+      id: '',
+      progress: '',
+      project_id: '',
+      status: 0
+    },
+    times: 0
   })
-
+  const isEdited = useMemo(() => {
+    return !!detail.status
+  }, [ detail.status ])
   useEffect(() => {
     initData()
-  }, [])
-  const initData = async() => {
-    const { saveId = "" } = props.location.state as any
-    const { code = -1, data = {} } = await apiGetSafeDetail(saveId)
+  }, [ saveId ])
+  const initData = async () => {
+    const { code = -1, data = {} } = await apiGetQualityDetail(saveId)
     if (code === consts.RET_CODE.SUCCESS) {
       setDetail({ ...detail, ...data })
     }
+    if (!userStore.groupList.length) {
+      userStore.getGroupList()
+    }
   }
   const onCreate = async (fileList: iFile[]) => {
-    const { code = -1 } = await apiSaveFileInfo(fileList, consts.DATA_TYPE.SAFE, detail.id)
+    const { code = -1 } = await apiSaveFileInfo(fileList, consts.DATA_TYPE.QUALITY, detail.id)
     if (code === consts.RET_CODE.SUCCESS) {
-      const newFiles = detail.file.fileList.concat(fileList.map(file => {
-        return { ...file, accountName: userStore.userInfo.name }
-      }))
-      setDetail({ ...detail, file: { ...detail.file, fileList: newFiles } })
-      setVisible(false)
+      const newFiles = detail.file.fileList.concat(
+        fileList.map(file => {
+          return { ...file, accountName: userStore.userInfo.name }
+        })
+      )
+      setDetail({ ...detail, file: { ...detail.file, total: newFiles.length } })
+      await fileListChange(visible.curPage)
     }
   }
-  const onShow = (show: boolean) => setVisible(show)
+  const onOssModalShow = (show: boolean) => setVisible({ ...visible, ossModal: show })
   const fileListChange = async (pageNo: number = 1, pageSize: number = 10) => {
-    const { code = -1, data } = await apiGetFileList(consts.DATA_TYPE.SAFE,detail.id, pageNo, pageSize)
+    const { code = -1, data, total } = await apiGetFileList(consts.DATA_TYPE.QUALITY, detail.id, pageNo, pageSize)
+    if (code === consts.RET_CODE.SUCCESS) {
+      setVisible({ ...visible, curPage: pageNo, ossModal: false })
+      setDetail({ ...detail, file: { ...detail.file, fileList: data, total } })
+    }
+  }
+
+  const delFile = async (id: string, isLast: boolean) => {
+    const { code = -1 } = await apiDelFile(id)
     if (code === consts.RET_CODE.SUCCESS) {
-      setDetail({ ...detail, file: { ...detail.file, fileList: data } })
+      console.log(visible.curPage - 1)
+      await fileListChange(isLast ? visible.curPage - 1 : visible.curPage)
+      isLast && (setVisible({ ...visible, curPage: visible.curPage - 1 }))
+    }
+  }
+
+  const addAuditor = (type: string, user: iUserInfo) => {
+    if (detail.auditors.find(item => item.progress === (type === 'check' ? '0' : '2') && item.audit_id === user.id)) {
+      return message.error('该审批组下已存在该审批人,请勿重复添加!')
+    }
+    if (type === 'check') {
+      const newAuditors = detail.auditors
+      const len = detail.auditors.filter((item: iAuditor) => item.progress === '0').length
+      newAuditors.push({
+        id: '',
+        mobile: '',
+        audit_id: user.id,
+        audit_order: len + 1,
+        position: user.position,
+        progress: '0',
+        name: user.name,
+        accountGroup: user.accountGroup,
+        company: user.company,
+        status: 0
+      })
+      setDetail({ ...detail, auditors: newAuditors })
+    } else {
+      const newAuditors = detail.auditors
+      const len = detail.auditors.filter((item: iAuditor) => item.progress === '2').length
+      newAuditors.push({
+        id: '',
+        audit_id: user.id,
+        mobile: '',
+        audit_order: len + 1,
+        position: user.position,
+        progress: '2',
+        name: user.name,
+        accountGroup: user.accountGroup,
+        company: user.company,
+        status: 0
+      })
+      setDetail({ ...detail, auditors: newAuditors })
+    }
+  }
+
+  const delAuditor = (id: string, progress: string) => {
+    const newAuditors = detail.auditors.filter(item => item.progress !== progress)
+    const auditor = detail.auditors.find(item => item.progress === progress && item.audit_id !== id)
+
+    if (auditor) {
+      newAuditors.push(auditor)
     }
+    setDetail({ ...detail, auditors: newAuditors })
   }
+
+  const btnClick = (type: string) => {
+    setVisible({ ...visible, auditType: type, auditModal: true })
+  }
+  const onModalConfirm = (values?: object) => {
+    let payload: any = { quality_id: detail.id, bidsection_id: detail.bidsectionId, ...values }
+    if (visible.auditType === 'start') {
+      payload.auditors = detail.auditors.filter(item => item.progress === '0').map(item => item.audit_id)
+      payload.reAuditors = detail.auditors.filter(item => item.progress === '2').map(item => item.audit_id)
+      payload.times = detail.times
+      if (!payload.auditors.length || !payload.reAuditors.length) {
+        return message.error('审批人或复查人不能为空!')
+      }
+    }
+
+    if (visible.auditType === 'delete') {
+      payload = { id: detail.id }
+    }
+
+    if (visible.auditType === 'pass' || visible.auditType === 'back') {
+      payload.id = detail.latestAuditor.id
+      if (detail.latestAuditor.progress === '1') {
+        if (!detail.checkOrder.opinion) {
+          return message.error('请填写整改单!')
+        } else {
+          payload.rectifiedInfo = detail.checkOrder.opinion
+        }
+      }
+    }
+
+    if (visible.auditType === 'close') {
+      payload.id = detail.latestAuditor.id
+    }
+    apiResful(visible.auditType, payload)
+  }
+  const apiResful = async (type: string, payload: any) => {
+    const { code } = await apiResfulQualityAudit(type, payload)
+    if (code === consts.RET_CODE.SUCCESS) {
+      setVisible({ ...visible, auditModal: false })
+      if (type === 'delete') {
+        props.history.goBack()
+      } else {
+        initData()
+      }
+    }
+  }
+  const renderHeaderBtn = (status: number) => {
+    if (!detail.latestAuditor.audit_id && userStore.userInfo.id !== detail.uid) return null
+    if (detail.latestAuditor.audit_id && userStore.userInfo.id !== detail.latestAuditor.audit_id) return null
+    if (!status) {
+      return (
+        <div className="pi-flex-row pi-align-center">
+          <ZhCloseButton size="small" onClick={() => btnClick('delete')}>
+            删除巡检
+          </ZhCloseButton>
+          <ZhSubmitButton size="small" className="pi-mg-left-5" onClick={() => btnClick('start')}>
+            提交审批
+          </ZhSubmitButton>
+        </div>
+      )
+    } else if (status === auditProgress.checking || status === auditProgress.checkNo) {
+      return (
+        <div className="pi-flex-row pi-align-center">
+          <Button type="primary" danger size="small" onClick={() => btnClick('close')}>
+            关闭
+          </Button>
+          <ZhAuditBackButton size="small" className="pi-mg-left-5" onClick={() => btnClick('back')}>
+            审批退回
+          </ZhAuditBackButton>
+          <ZhSubmitButton size="small" className="pi-mg-left-5" onClick={() => btnClick('pass')}>
+            审批通过
+          </ZhSubmitButton>
+        </div>
+      )
+    } else if (status === auditProgress.checked) {
+      return (
+        <div className="pi-flex-row pi-align-center">
+          <ZhAuditBackButton size="small" onClick={() => btnClick('back')}>
+            审批退回
+          </ZhAuditBackButton>
+          <ZhSubmitButton size="small" className="pi-mg-left-5" onClick={() => btnClick('pass')}>
+            整改完成
+          </ZhSubmitButton>
+        </div>
+      )
+    }
+  }
+
   return (
     <div className="wrap-contaniner">
       <Header title="安全巡检">
-        <Slot position="right">
-          <div>
-            <ZhSubmitButton size="small">提交审批</ZhSubmitButton>
-          </div>
-        </Slot>
+        <Slot position="right">{renderHeaderBtn(detail.status)}</Slot>
       </Header>
       <div className={styles.detailContainer}>
         <div className={styles.content}>
@@ -94,78 +296,178 @@ const Detail:React.FC<RouteComponentProps> = (props) => {
           <table className="pi-table pi-bordered">
             <thead>
               <tr>
-                <th colSpan={2} className="pi-text-center">安全巡检单</th>
+                <th colSpan={2} className="pi-text-center">
+                  安全巡检单
+                </th>
               </tr>
             </thead>
             <tbody>
-              <tr><th style={{ width: "150px" }}>检查项目</th><td><TextArea value={detail.inspection}></TextArea></td></tr>
-              <tr><th style={{ width: "150px" }}>现场检查情况</th><td><TextArea value={detail.inspectionDetail}></TextArea></td></tr>
-              <tr><th style={{ width: "150px" }}>处理要求及措施</th><td><TextArea value={detail.demand}></TextArea></td></tr>
               <tr>
-                <th style={{ width: "150px" }}>检查日期</th>
-                <td><DatePicker size="small" locale={locale} allowClear={false} value={dayjs(detail.createTime)} onChange={(value) => setDetail({ ...detail, createTime: value?.format() })}></DatePicker></td>
+                <th style={{ width: '150px' }}>检查项目</th>
+                <td>{isEdited ? <span>{detail.inspection}</span> : <TextArea value={detail.inspection}></TextArea>}</td>
+              </tr>
+              <tr>
+                <th style={{ width: '150px' }}>现场检查情况</th>
+                <td>{isEdited ? <span>{detail.inspectionDetail}</span> : <TextArea value={detail.inspectionDetail}></TextArea>}</td>
+              </tr>
+              <tr>
+                <th style={{ width: '150px' }}>处理要求及措施</th>
+                <td>{isEdited ? <span>{detail.demand}</span> : <TextArea value={detail.demand}></TextArea>}</td>
+              </tr>
+              <tr>
+                <th style={{ width: '150px' }}>检查日期</th>
+                <td>
+                  {isEdited ? (
+                    <span>{detail.createTime && dayjsFormat(detail.createTime, 'YYYY-MM-DD')}</span>
+                  ) : (
+                    <DatePicker
+                      size="small"
+                      locale={locale}
+                      allowClear={false}
+                      value={dayjs(detail.createTime)}
+                      onChange={value => setDetail({ ...detail, createTime: value?.format() })}></DatePicker>
+                  )}
+                </td>
+              </tr>
+              <tr>
+                <th style={{ width: '150px' }}>质检员</th>
+                <td>{detail.auditName}</td>
               </tr>
-              <tr><th style={{ width: "150px" }}>质检员</th><td>{detail.auditName}</td></tr>
             </tbody>
-
           </table>
+          {detail.status === auditProgress.checked && detail.latestAuditor.progress === '1' ? (
+            <table className="pi-table pi-bordered">
+              <thead>
+                <tr>
+                  <th colSpan={2} className="pi-text-center">
+                    整改单
+                  </th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr>
+                  <th style={{ width: '150px' }}>整改情况</th>
+                  <td>
+                    <TextArea
+                      value={detail.checkOrder.opinion}
+                      onChange={e => setDetail({ ...detail, checkOrder: { ...detail.checkOrder, opinion: e.currentTarget.value } })}></TextArea>
+                  </td>
+                </tr>
+                <tr>
+                  <th style={{ width: '150px' }}>整改日期</th>
+                  <td>
+                    <DatePicker
+                      size="small"
+                      locale={locale}
+                      allowClear={false}
+                      value={dayjs(detail.checkOrder.create_time)}
+                      onChange={value => setDetail({ ...detail, checkOrder: { ...detail.checkOrder, create_time: value?.format() } })}></DatePicker>
+                  </td>
+                </tr>
+                <tr>
+                  <th style={{ width: '150px' }}>整改人</th>
+                  <td>{detail.auditors.find(item => item.progress === '1')?.name}</td>
+                </tr>
+              </tbody>
+            </table>
+          ) : (
+            detail.rectifiedInfo.map(item => (
+              <table className="pi-table pi-bordered" key={item.create_time}>
+                <thead>
+                  <tr>
+                    <th colSpan={2} className="pi-text-center">
+                      整改单
+                    </th>
+                  </tr>
+                </thead>
+                <tbody>
+                  <tr>
+                    <th style={{ width: '150px' }}>整改情况</th>
+                    <td>{item.opinion}</td>
+                  </tr>
+                  <tr>
+                    <th style={{ width: '150px' }}>整改日期</th>
+                    <td>{dayjsFormat(item.create_time, 'YYYY-MM-DD')}</td>
+                  </tr>
+                  <tr>
+                    <th style={{ width: '150px' }}>整改人</th>
+                    <td>{item.name}</td>
+                  </tr>
+                </tbody>
+              </table>
+            ))
+          )}
           <table className="pi-table pi-bordered mt-3">
             <thead>
               <tr>
                 <th></th>
                 <th className="pi-text-center">附件</th>
                 <th className="pi-text-center">上传者</th>
-                <th className="pi-text-center" style={{ width: 200 }}>上传时间</th>
+                <th className="pi-text-center" style={{ width: 200 }}>
+                  上传时间
+                </th>
                 <th className="pi-text-center">操作</th>
               </tr>
             </thead>
             <tbody>
-              <tr><td colSpan={5}><ZhUploadButton size="small" icon={<SvgIcon type="xxh-cloud-upload"/>} onClick={() => setVisible(true)}>上传附件</ZhUploadButton></td></tr>
+              <tr>
+                <td colSpan={5}>
+                  <ZhUploadButton size="small" icon={<SvgIcon type="xxh-cloud-upload" />} onClick={() => setVisible({ ...visible, ossModal: true })}>
+                    上传附件
+                  </ZhUploadButton>
+                </td>
+              </tr>
 
-              {
-                detail.file.fileList?.map((file, idx) => {
-                  return (
-                    <tr key={idx}>
-                      <td className="pi-width-70">{idx+1}</td>
-                      <td style={{ width: 383, maxWidth: 383, overflow: 'hidden', whiteSpace: 'nowrap',textOverflow:'ellipsis' }}>
-                        <a href={consts.OSS_PATH.REVIEW + file.filepath} target="_blank" rel="noopener noreferrer">{file.filename}</a>
-                      </td>
-                      <td className="pi-text-center">{file.accountName}</td><td className="pi-text-center">{dayjsFormat(file.createTime)}</td>
-                      <td className="pi-text-center pi-width-90">
-                        <Tooltip title="移除">
-                          <Button size="small" type="text" icon={<SvgIcon type="xxh-times-circle1"/>} style={{ color: "#df3f45" }}></Button>
-                        </Tooltip>
-                      </td>
-                    </tr>
-                  )
-                })
-              }
-              <tr><td colSpan={5} className="pi-text-right">
-              {
-                detail.file.total ?
-                <Pagination
-                defaultCurrent={1}
-                size="small"
-                pageSize={consts.PAGE_SIZE}
-                hideOnSinglePage={true}
-                total={detail.file.total}
-                onChange={(page, pageSize) => fileListChange(page, pageSize)}
-                >
-              </Pagination>
-              : ''
-              }
-              </td></tr>
+              {detail.file.fileList?.map((file, idx) => (
+                <tr key={idx}>
+                <td className="pi-width-70">{idx + 1}</td>
+                <td style={{ width: 383, maxWidth: 383, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}>
+                  <a href={consts.OSS_PATH.REVIEW + file.filepath} target="_blank" rel="noopener noreferrer">
+                    {file.filename}
+                  </a>
+                </td>
+                <td className="pi-text-center">{file.accountName}</td>
+                <td className="pi-text-center">{dayjsFormat(file.createTime)}</td>
+                <td className="pi-text-center pi-width-90">
+                  <Tooltip title="移除">
+                    <Button size="small" type="text" icon={<SvgIcon type="xxh-times-circle1" />} style={{ color: '#df3f45' }} onClick={() => delFile(file.id, !idx)}></Button>
+                  </Tooltip>
+                </td>
+              </tr>
+              ))}
+              {detail.file.total > consts.PAGE_SIZE ? (
+                <tr>
+                  <td colSpan={5} className="pi-text-right">
+                    <Pagination
+                      current={visible.curPage}
+                      size="small"
+                      pageSize={consts.PAGE_SIZE}
+                      hideOnSinglePage={true}
+                      total={detail.file.total}
+                      onChange={(page, pageSize) => fileListChange(page, pageSize)}></Pagination>
+                  </td>
+                </tr>
+              ) : null}
             </tbody>
           </table>
+          <AuditContent
+            auditors={detail.auditors}
+            onSelect={addAuditor}
+            onDelete={delAuditor}
+            latest={detail.latestAuditor}
+            auditHistory={detail.auditHistory}
+            status={detail.status}
+            uName={detail.auditName}></AuditContent>
         </div>
       </div>
-      <OssUploadModal
-        visible={visible}
-        onCancel={() => setVisible(false)}
-        onCreate={onCreate}
-        onShow={onShow}
-        >
-      </OssUploadModal>
+      <OssUploadModal visible={visible.ossModal} onCancel={() => setVisible({ ...visible, ossModal: false })} onCreate={onCreate} onShow={onOssModalShow}></OssUploadModal>
+      <AuditModal
+        type={visible.auditType}
+        visible={visible.auditModal}
+        onCancel={() => setVisible({ ...visible, auditModal: false })}
+        onCreate={onModalConfirm}
+        auditors={detail.auditors}
+        curAuditor={detail.latestAuditor}></AuditModal>
     </div>
   )
 }

+ 4 - 4
src/pages/Quality/Content/List/api.ts

@@ -6,8 +6,8 @@ import request from "@/utils/common/request"
  * 获取当前标段的安全巡检列表
  * @param bidsectionId 标段id
  */
-export async function apiSafeList(bidsectionId: string, pageNo: number, pageSize: number) {
-  const { data } = await request.get('/api/safe', { bidsectionId, pageNo, pageSize })
+export async function apiQualityList(bidsectionId: string, pageNo: number, pageSize: number) {
+  const { data } = await request.get('/api/quality', { bidsectionId, pageNo, pageSize })
   return data
 }
 
@@ -15,8 +15,8 @@ export async function apiSafeList(bidsectionId: string, pageNo: number, pageSize
  * 创建新的安全巡检记录
  * @param payload 载荷
  */
-export async function apiCreateSafe(payload: iCreateSafe) {
-  const { data } = await request.post('/api/safe', payload)
+export async function apiCreateQuality(payload: iCreateSafe) {
+  const { data } = await request.post('/api/quality', payload)
   return data
 }
 

+ 16 - 20
src/pages/Quality/Content/List/index.tsx

@@ -4,18 +4,18 @@ import Slot from '@/components/Header/slot'
 import RuleModal from '@/components/RuleModal'
 import SvgIcon from '@/components/SvgIcon'
 import { tenderStore } from '@/store/mobx'
+import { iFileModal } from '@/types/file'
 import { iCreateSafe } from '@/types/safe'
 import { safeStatus } from '@/utils/common/constStatus'
 import consts from '@/utils/consts'
 import { dayjsFormat } from '@/utils/util'
-import { SettingOutlined } from '@ant-design/icons'
 import { Button, message, Table } from 'antd'
 import { ColumnsType } from 'antd/lib/table'
 import React, { useEffect, useState } from 'react'
 import { Link } from 'react-router-dom'
-import { apiCreateSafe, apiSafeList, apiSaveRule } from './api'
+import { apiCreateQuality, apiQualityList, apiSaveRule } from './api'
 import AddModel from './modal'
-interface iSafeList {
+interface iQualityList {
   id: string;
   code: string;
   createTime: string;
@@ -32,12 +32,8 @@ interface iModal {
   loading: boolean
 }
 
-interface iFileModal {
-  visible: boolean
-  dataType: number
-  dataId: string
-}
-const SafeList:React.FC<{}> =() => {
+
+const QualityList:React.FC<{}> =() => {
   const [ ruleModal, setRuleModal ] = useState<iModal>({
     visible: false,
     loading: false
@@ -48,13 +44,13 @@ const SafeList:React.FC<{}> =() => {
   })
   const [ fileModal, setFileModal ] = useState<iFileModal>({
     visible: false,
-    dataType: consts.DATA_TYPE.SAFE,
+    dataType: consts.DATA_TYPE.QUALITY,
     dataId: ''
   })
   useEffect(() => {
     initData()
   }, [])
-  const columns:ColumnsType<iSafeList> = [
+  const columns:ColumnsType<iQualityList> = [
     {
       title: '序号',
       // eslint-disable-next-line react/display-name
@@ -67,7 +63,7 @@ const SafeList:React.FC<{}> =() => {
       dataIndex: 'code',
       // eslint-disable-next-line react/display-name
       render: (text: string, record) => {
-        return <Link to={{ pathname: "/console/safe/content/detail/info", state: { saveId: record.id } }}>{text}</Link>
+        return <Link to={{ pathname: "/console/quality/content/detail/info", state: { saveId: record.id } }}>{text}</Link>
       }
     },
     {
@@ -111,7 +107,7 @@ const SafeList:React.FC<{}> =() => {
       }
     }
   ]
-  const [ list, setList ] = useState<iSafeList[]>([
+  const [ list, setList ] = useState<iQualityList[]>([
     {
       id: '',
       code: '',
@@ -127,7 +123,7 @@ const SafeList:React.FC<{}> =() => {
   ])
   const [ total, setTotal ] = useState<number>(0)
   const initData = (pageNo: number = 1, pageSize: number = consts.PAGE_SIZE) => {
-    apiSafeList(tenderStore.bid, pageNo, pageSize).then(({ code = -1, data = [], total = 0 }) => {
+    apiQualityList(tenderStore.bid, pageNo, pageSize).then(({ code = -1, data = [], total = 0 }) => {
       if (code === consts.RET_CODE.SUCCESS) {
         setList(data)
         setTotal(total)
@@ -139,7 +135,7 @@ const SafeList:React.FC<{}> =() => {
 
   const onRuleCreate = async (ruleValue: any) => {
     setRuleModal({ ...ruleModal, loading: true })
-    const { code = -1 } = await apiSaveRule({ bidsectionId: tenderStore.bid, type: 'safe_rule', rule: ruleValue })
+    const { code = -1 } = await apiSaveRule({ bidsectionId: tenderStore.bid, type: 'quality_rule', rule: ruleValue })
     if (code === consts.RET_CODE.SUCCESS) {
       message.success("规则更改成功!")
       initData()
@@ -149,7 +145,7 @@ const SafeList:React.FC<{}> =() => {
   const onAddCreate = async (payload: iCreateSafe) => {
     setAddModal({ ...addModal, loading: true })
     const createTime = dayjsFormat(payload.createTime)
-    const { code = -1 } = await apiCreateSafe({ ...payload, createTime })
+    const { code = -1 } = await apiCreateQuality({ ...payload, createTime })
     if (code === consts.RET_CODE.SUCCESS) {
       initData()
     }
@@ -162,7 +158,7 @@ const SafeList:React.FC<{}> =() => {
         <Slot position="right">
           {
             !list.length ?
-            <Button type="ghost" size="small" icon={<SettingOutlined />} className="pi-mg-right-3" style={{ color: '#007bff' }} onClick={() => setRuleModal({ ...ruleModal, visible: true })}>设置</Button>
+            <Button type="ghost" size="small" icon={<SvgIcon type="xxh-cog" />} className="pi-mg-right-3" style={{ color: '#007bff' }} onClick={() => setRuleModal({ ...ruleModal, visible: true })}>设置</Button>
             : ""
           }
 
@@ -184,8 +180,8 @@ const SafeList:React.FC<{}> =() => {
         >
       </Table>
       <RuleModal
-        type={consts.RULE.SAFE}
-        title="安全巡检编号设置"
+        type={consts.RULE.QUALITY}
+        title="质量巡检编号设置"
         visible={ruleModal.visible}
         onCreate={onRuleCreate}
         loading={ruleModal.loading}
@@ -209,4 +205,4 @@ const SafeList:React.FC<{}> =() => {
   )
 }
 
-export default SafeList
+export default QualityList

+ 6 - 6
src/pages/Quality/Content/List/modal.tsx

@@ -6,14 +6,14 @@ import locale from 'antd/es/date-picker/locale/zh_CN'
 import React, { useEffect } from 'react'
 import { apiAutoCode } from './api'
 import styles from './index.module.scss'
-interface iSafeCreateFormProps {
+interface iQualityCreateFormProps {
   visible: boolean;
   loading: boolean;
   onCreate: (values: any) => void;
   onCancel: () => void;
 }
 
-const SafeCreateForm: React.FC<iSafeCreateFormProps> = ({
+const QualityCreateForm: React.FC<iQualityCreateFormProps> = ({
   visible,
   loading,
   onCreate,
@@ -21,7 +21,7 @@ const SafeCreateForm: React.FC<iSafeCreateFormProps> = ({
 }) => {
   const [ form ] = Form.useForm()
   const autoCodeHandler = async () => {
-    const { code = -1, data = "" } = await apiAutoCode(tenderStore.tender.bidsectionId, 'safeRule')
+    const { code = -1, data = "" } = await apiAutoCode(tenderStore.tender.bidsectionId, 'qualityRule')
     if (code === consts.RET_CODE.SUCCESS) {
       if (data) {
         const ruleArr: string[] = []
@@ -48,7 +48,7 @@ const SafeCreateForm: React.FC<iSafeCreateFormProps> = ({
     <Modal
       getContainer={false}
       visible={visible}
-      title="新建安全巡检"
+      title="新建质量巡检"
       okText="确认添加"
       cancelText="取消"
       onCancel={onCancel}
@@ -83,7 +83,7 @@ const SafeCreateForm: React.FC<iSafeCreateFormProps> = ({
           <Input placeholder="请填写巡检项"/>
         </Form.Item>
         <Form.Item name="createTime" label="日期" rules={[ { required: true, message: '请选择日期' } ]}>
-          <DatePicker locale={locale} allowClear style={{ width: '100%' }}></DatePicker>
+          <DatePicker locale={locale} allowClear className="pi-width-100P"></DatePicker>
         </Form.Item>
         <div className={styles.warningFooter}>添加后再补充完善其余信息</div>
       </Form>
@@ -92,4 +92,4 @@ const SafeCreateForm: React.FC<iSafeCreateFormProps> = ({
 }
 
 
-export default SafeCreateForm
+export default QualityCreateForm

+ 3 - 5
src/pages/Quality/List/index.tsx

@@ -16,6 +16,8 @@ import './index.scss'
 const List: React.FC<RouteComponentProps> = (props) => {
   const { clear } = useAliveController()
   useEffect(() => {
+    // 清除所有的缓存页面
+    clear()
     getTree()
   }, [])
   const [ tree, setTree ] = useState({
@@ -49,11 +51,7 @@ const List: React.FC<RouteComponentProps> = (props) => {
   const linkHandler = (id: string, name: string) => {
     tenderStore.saveTenderInfo({ bidsectionId: id, name })
     // tenderStore.saveName(name)
-    props.history.push('/console/safe/content/summary')
-    // 清除所有的缓存页面
-    // console.log(getCachingNodes())
-
-    clear()
+    props.history.push('/console/quality/content/summary')
   }
   const columns:ColumnsType<ContractTree> = [
     {

+ 37 - 37
src/pages/Safe/Content/Info/Detail/index.tsx

@@ -58,13 +58,15 @@ interface iModalObj {
   ossModal: boolean
   auditModal: boolean
   auditType: string
+  curPage: number
 }
 const Detail: React.FC<RouteComponentProps> = props => {
   const { saveId = '' } = props.location.state as any
   const [ visible, setVisible ] = useState<iModalObj>({
     ossModal: false,
     auditModal: false,
-    auditType: ''
+    auditType: '',
+    curPage: 1
   })
   const [ detail, setDetail ] = useState<iDetailState>({
     auditName: '',
@@ -72,7 +74,7 @@ const Detail: React.FC<RouteComponentProps> = props => {
     auditors: [],
     bidsectionId: '',
     code: '',
-    createTime: '',
+    createTime: new Date().toDateString(),
     demand: '',
     file: { fileList: [], total: 0 },
     id: '',
@@ -124,23 +126,25 @@ const Detail: React.FC<RouteComponentProps> = props => {
           return { ...file, accountName: userStore.userInfo.name }
         })
       )
-      setDetail({ ...detail, file: { ...detail.file, fileList: newFiles } })
-      setVisible({ ...visible, ossModal: false })
+      setDetail({ ...detail, file: { ...detail.file, total: newFiles.length } })
+      await fileListChange(visible.curPage)
     }
   }
   const onOssModalShow = (show: boolean) => setVisible({ ...visible, ossModal: show })
   const fileListChange = async (pageNo: number = 1, pageSize: number = 10) => {
-    const { code = -1, data } = await apiGetFileList(consts.DATA_TYPE.SAFE, detail.id, pageNo, pageSize)
+    const { code = -1, data, total } = await apiGetFileList(consts.DATA_TYPE.SAFE, detail.id, pageNo, pageSize)
     if (code === consts.RET_CODE.SUCCESS) {
-      setDetail({ ...detail, file: { ...detail.file, fileList: data } })
+      setVisible({ ...visible, curPage: pageNo, ossModal: false })
+      setDetail({ ...detail, file: { ...detail.file, fileList: data, total } })
     }
   }
 
-  const delFile = async (id: string) => {
+  const delFile = async (id: string, isLast: boolean) => {
     const { code = -1 } = await apiDelFile(id)
     if (code === consts.RET_CODE.SUCCESS) {
-      const newFiles = detail.file.fileList.filter(file => file.id !== id)
-      setDetail({ ...detail, file: { ...detail.file, fileList: newFiles } })
+      console.log(visible.curPage - 1)
+      await fileListChange(isLast ? visible.curPage - 1 : visible.curPage)
+      isLast && (setVisible({ ...visible, curPage: visible.curPage - 1 }))
     }
   }
 
@@ -391,40 +395,36 @@ const Detail: React.FC<RouteComponentProps> = props => {
                 </td>
               </tr>
 
-              {detail.file.fileList?.map((file, idx) => {
-                return (
-                  <tr key={idx}>
-                    <td className="pi-width-70">{idx + 1}</td>
-                    <td style={{ width: 383, maxWidth: 383, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}>
-                      <a href={consts.OSS_PATH.REVIEW + file.filepath} target="_blank" rel="noopener noreferrer">
-                        {file.filename}
-                      </a>
-                    </td>
-                    <td className="pi-text-center">{file.accountName}</td>
-                    <td className="pi-text-center">{dayjsFormat(file.createTime)}</td>
-                    <td className="pi-text-center pi-width-90">
-                      <Tooltip title="移除">
-                        <Button size="small" type="text" icon={<SvgIcon type="xxh-times-circle1" />} style={{ color: '#df3f45' }} onClick={() => delFile(file.id)}></Button>
-                      </Tooltip>
-                    </td>
-                  </tr>
-                )
-              })}
-              <tr>
-                <td colSpan={5} className="pi-text-right">
-                  {detail.file.total ? (
+              {detail.file.fileList?.map((file, idx) => (
+                <tr key={idx}>
+                <td className="pi-width-70">{idx + 1}</td>
+                <td style={{ width: 383, maxWidth: 383, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }}>
+                  <a href={consts.OSS_PATH.REVIEW + file.filepath} target="_blank" rel="noopener noreferrer">
+                    {file.filename}
+                  </a>
+                </td>
+                <td className="pi-text-center">{file.accountName}</td>
+                <td className="pi-text-center">{dayjsFormat(file.createTime)}</td>
+                <td className="pi-text-center pi-width-90">
+                  <Tooltip title="移除">
+                    <Button size="small" type="text" icon={<SvgIcon type="xxh-times-circle1" />} style={{ color: '#df3f45' }} onClick={() => delFile(file.id, !idx)}></Button>
+                  </Tooltip>
+                </td>
+              </tr>
+              ))}
+              {detail.file.total > consts.PAGE_SIZE ? (
+                <tr>
+                  <td colSpan={5} className="pi-text-right">
                     <Pagination
-                      defaultCurrent={1}
+                      current={visible.curPage}
                       size="small"
                       pageSize={consts.PAGE_SIZE}
                       hideOnSinglePage={true}
                       total={detail.file.total}
                       onChange={(page, pageSize) => fileListChange(page, pageSize)}></Pagination>
-                  ) : (
-                    ''
-                  )}
-                </td>
-              </tr>
+                  </td>
+                </tr>
+              ) : null}
             </tbody>
           </table>
           <AuditContent

+ 1 - 1
src/router/routes.ts

@@ -185,7 +185,7 @@ export const routeConfig: RouteModel[] = [
                 component: AsyncModuleLoader(() => import('@/pages/Quality/Content/Info')),
                 auth: [ 'USER', 'ADMIN' ],
                 meta: {
-                  title: '安全巡检'
+                  title: '质量巡检'
                 },
                 childRoutes: [
                   {