Bläddra i källkod

feat: 新增安全巡检审批流程-审批通过功能

lanjianrong 4 år sedan
förälder
incheckning
d80581033b

+ 16 - 0
src/assets/css/common.scss

@@ -435,6 +435,22 @@
   }
 }
 
+.pi-circle-red {
+  position: relative;
+  padding-left: 14px;
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 12px;
+    height: 12px;
+    background-color: $pi-red;
+    border-radius: 50%;
+  }
+}
 .pi-pointer {
   cursor: pointer;
 }

+ 169 - 166
src/components/AuditContent/index.tsx

@@ -1,5 +1,6 @@
 import { iAuditHistoryState, iAuditor, iLatestAuditorState } from '@/types/safe'
 import { iAccountGroupItem, iUserInfo } from '@/types/setting'
+import { auditConsts } from '@/utils/common/constStatus'
 import { getUserGroup } from '@/utils/common/user'
 import { formatDate } from '@/utils/util'
 import { Input, Popover } from 'antd'
@@ -12,7 +13,7 @@ import './index.scss'
 interface iGroupItem extends iAccountGroupItem {
   onSelect: (item: iUserInfo) => void
 }
-const GroupItem: React.FC<iGroupItem> = props => {
+export const GroupItem: React.FC<iGroupItem> = props => {
   const { onSelect } = props
   const [ visible, setVisible ] = useState<boolean>(true)
 
@@ -53,10 +54,11 @@ interface iAuditContentProps {
   auditors: iAuditor[]
   auditHistory: iAuditHistoryState[][]
   status: number
+  uName: string
 }
 
 const Index: React.FC<iAuditContentProps> = props => {
-  const { onSelect, auditors, onDelete, status, auditHistory } = props
+  const { onSelect, auditors, onDelete, status, auditHistory, uName } = props
   const [ visible, setVisible ] = useState({
     check: false,
     reCheck: false
@@ -116,7 +118,7 @@ const Index: React.FC<iAuditContentProps> = props => {
                       </p>
                       <small className="text-muted">{item.company}</small>
                     </div>
-                    <span className="pi-red pi-pointer" onClick={() => onDelete(item.audit_id, "0")}>
+                    <span className="pi-red pi-pointer" onClick={() => onDelete(item.audit_id, '0')}>
                       移除
                     </span>
                   </li>
@@ -134,7 +136,7 @@ const Index: React.FC<iAuditContentProps> = props => {
                       </p>
                       <small className="text-muted">{item.company}</small>
                     </div>
-                    <span className="pi-red pi-pointer" onClick={() => onDelete(item.audit_id, "2")}>
+                    <span className="pi-red pi-pointer" onClick={() => onDelete(item.audit_id, '2')}>
                       移除
                     </span>
                   </li>
@@ -180,7 +182,7 @@ const Index: React.FC<iAuditContentProps> = props => {
 
   const renderStatusEle = (status: number, progress: string) => {
     let text = ''
-    let textClass = 'pi-color-green'
+    let textClass = 'pi-green'
     if (progress === '0') {
       switch (status) {
         case 1:
@@ -239,6 +241,164 @@ const Index: React.FC<iAuditContentProps> = props => {
     }
     return { text, textClass }
   }
+
+  const renderLeftAuditors = (status: number) => {
+    // 整改人所需信息
+    const len = auditors.filter(item => item.progress === '0').length
+
+    return (
+      <tbody>
+        <tr>
+          <td className="pi-text-center">检查人</td>
+          <td>
+            <SvgIcon type="xxh-play-circle"></SvgIcon>
+            <span className="pi-mg-left-3">{auditors[0]?.name}</span>
+            <small className="text-muted pi-mg-left-3">{auditors[0]?.position}</small>
+          </td>
+        </tr>
+        {auditors
+          .filter(item => item.progress === '0')
+          .map((item, idx) => {
+            return idx === 0 ? (
+              <tr key={item.audit_id}>
+                <td rowSpan={auditors.filter(item => item.progress === '0').length} className="pi-text-center">
+                  审批
+                </td>
+                <td>
+                  <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
+                  <span className="pi-mg-left-3">{item.name}</span>
+                  <small className="text-muted pi-mg-left-3">{item.position}</small>
+                </td>
+              </tr>
+            ) : (
+              <tr key={item.audit_id}>
+                <td>
+                  <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
+                  <span className="pi-mg-left-3">{item.name}</span>
+                  <small className="text-muted pi-mg-left-3">{item.position}</small>
+                </td>
+              </tr>
+            )
+          })}
+        <tr>
+          <td className="pi-text-center">整改人</td>
+          <td>
+            <SvgIcon type={status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
+            {status ? (
+              auditors.find(item => item.progress === '1') ? (
+                <>
+                  <span className="pi-mg-left-3">{auditors.find(item => item.progress === '1')?.name}</span>
+                  <small className="text-muted pi-mg-left-3">{auditors.find(item => item.progress === '1')?.position}</small>
+                </>
+              ) : (
+                <span className="pi-mg-left-3">由 {auditors.filter(item => item.progress === '0')[len - 1]?.name} 指派</span>
+              )
+            ) : (
+              <span className="pi-mg-left-3">由<span className="pi-mg-3">{auditors.filter(item => item.progress === '0').length ? auditors.filter(item => item.progress === '0')[len - 1]?.name : '最后一个审批人'}</span>指派</span>
+            )}
+          </td>
+        </tr>
+        {auditors
+          .filter(item => item.progress === '2')
+          .map((item, idx) => {
+            return idx === 0 ? (
+              <tr key={item.audit_id}>
+                <td rowSpan={auditors.filter(item => item.progress === '2').length} className="pi-text-center">
+                  复查
+                </td>
+                <td>
+                  <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
+                  <span className="pi-mg-left-3">{item.name}</span>
+                  <small className="text-muted pi-mg-left-3">{item.position}</small>
+                </td>
+              </tr>
+            ) : (
+              <tr key={item.audit_id}>
+                <td>
+                  <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
+                  <span className="pi-mg-left-3">{item.name}</span>
+                  <small className="text-muted pi-mg-left-3">{item.position}</small>
+                </td>
+              </tr>
+            )
+          })}
+      </tbody>
+    )
+  }
+
+  const renderHistory = () => {
+    return (
+      <>
+      {auditHistory?.map((item, index) => {
+        return (
+          <ul className="timeline-list" key={index}>
+            {item?.map((auditor, idx) => (
+              <div key={idx}>
+                {index === 0 && idx === 0 ? (
+                  <li className="timeline-list-item">
+                    <div className="timeline-item-date pi-flex-column" dangerouslySetInnerHTML={{ __html: formatDate(auditor.create_time) }}></div>
+                    <div className={item.length - 1 === idx ? '' : 'timeline-item-tail'}></div>
+                    {renderStatusIcon(auditor.status, true)}
+                    <div className="timeline-item-content">
+                      <div className="card-container">
+                        <div className="card-content">
+                          <div className="pi-justify-between label">
+                            <span>{uName}</span>
+                            <span className="pi-green">上报审批</span>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </li>
+                ) : null}
+                <li className="timeline-list-item" >
+                  {auditor.status ? (
+                    <div
+                      className="timeline-item-date pi-flex-column"
+                      dangerouslySetInnerHTML={{ __html: formatDate(auditor.status === auditConsts.checked || auditor.status === auditConsts.close? auditor.end_time : auditor.create_time) }}></div>
+                  ) : null}
+                  <div className={item.length - 1 === idx ? '' : 'timeline-item-tail'}></div>
+                  {renderStatusIcon(auditor.status, false)}
+                  <div className="timeline-item-content">
+                    <div className="card-container">
+                      <div className="card-content">
+                        <div className="pi-justify-between label">
+                          <span>{auditor.name}</span>
+                          <span className={renderStatusEle(auditor.status, auditor.progress).textClass}>{renderStatusEle(auditor.status, auditor.progress).text}</span>
+                        </div>
+                        <div className="text-muted">{auditor.position}</div>
+                      </div>
+                      {auditor.opinion ? (
+                        <div className="textarea">
+                          <span>{auditor.opinion}</span>
+                        </div>
+                      ) : null}
+                    </div>
+                  </div>
+                </li>
+                {idx === item.filter(item => item.progress === '0').length - 1 && !auditors.find(item => item.progress === '1')? (
+                  <li className="timeline-list-item" >
+                    <div className="timeline-item-tail"></div>
+                    {renderStatusIcon(0, false)}
+                    <div className="timeline-item-content">
+                      <div className="card-container">
+                        <div className="card-content">
+                          <div className="pi-justify-between label">
+                            <span>待指派</span>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </li>
+                ) : null}
+              </div>
+            ))}
+          </ul>
+        )
+      })}
+      </>
+    )
+  }
   return (
     <table className="pi-table pi-bordered mt-3">
       <thead>
@@ -253,66 +413,7 @@ const Index: React.FC<iAuditContentProps> = props => {
           {!status ? (
             <>
               <td width="30%">
-                <table className="table table-bordered">
-                  <tbody>
-                    <tr>
-                      <td className="pi-text-center">检查人</td>
-                      <td>
-                        <SvgIcon type="xxh-play-circle"></SvgIcon>
-                        <span className="pi-mg-left-3">{auditors[0]?.name}</span>
-                        <small className="text-muted pi-mg-left-3">{auditors[0]?.position}</small>
-                      </td>
-                    </tr>
-                    {auditors
-                      .filter(item => item.progress === '0')
-                      .map((item, idx) => {
-                        return idx === 0 ? (
-                          <tr key={item.audit_id}>
-                            <td rowSpan={auditors.filter(item => item.progress === '0').length} className="pi-text-center">
-                              审批
-                            </td>
-                            <td>
-                              <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
-                              <span className="pi-mg-left-3">{item.name}</span>
-                              <small className="text-muted pi-mg-left-3">{item.position}</small>
-                            </td>
-                          </tr>
-                        ) : (
-                          <tr key={item.audit_id}>
-                            <td>
-                              <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
-                              <span className="pi-mg-left-3">{item.name}</span>
-                              <small className="text-muted pi-mg-left-3">{item.position}</small>
-                            </td>
-                          </tr>
-                        )
-                      })}
-                    {auditors
-                      .filter(item => item.progress === '2')
-                      .map((item, idx) => {
-                        return idx === 0 ? (
-                          <tr key={item.audit_id}>
-                            <td rowSpan={auditors.filter(item => item.progress === '2').length} className="pi-text-center">
-                              复查
-                            </td>
-                            <td>
-                              <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
-                              <span className="pi-mg-left-3">{item.name}</span>
-                              <small className="text-muted pi-mg-left-3">{item.position}</small>
-                            </td>
-                          </tr>
-                        ) : (
-                          <tr key={item.audit_id}>
-                            <td>
-                              <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
-                              <span className="pi-mg-left-3">{item.name}</span>
-                              <small className="text-muted pi-mg-left-3">{item.position}</small>
-                            </td>
-                          </tr>
-                        )
-                      })}
-                  </tbody>
-                </table>
+                <table className="table table-bordered">{renderLeftAuditors(status)}</table>
               </td>
               <td width="70%">
                 <div className="pi-justify-end">
@@ -333,7 +434,7 @@ const Index: React.FC<iAuditContentProps> = props => {
                 </div>
                 <div className="audit-card">
                   <div className="card-header">审批流程</div>
-                  {renderAuditorSelectItem()}
+                  {renderAuditorSelectItem('check')}
                 </div>
                 <div className="audit-card">
                   <div className="card-header">整改流程</div>
@@ -369,108 +470,10 @@ const Index: React.FC<iAuditContentProps> = props => {
             <td>
               <div className="pi-flex-row">
                 <div className="pi-flex-sub pi-mg-right-15 pi-mg-top-5 pi-mg-left-5">
-                  <table className="table table-bordered pi-width-100P">
-                    <tbody>
-                      {auditors?.map((item, idx) => {
-                        if (!item.progress) {
-                          return (
-                            <tr key={item.audit_id}>
-                              <td className="pi-text-center">检查人</td>
-                              <td>
-                                <SvgIcon type="xxh-play-circle"></SvgIcon>
-                                <span className="pi-mg-left-3">{item.name}</span>
-                                <small className="text-muted pi-mg-left-3">{item.position}</small>
-                              </td>
-                            </tr>
-                          )
-                        } else if (item.progress === '0') {
-                          return auditors[idx - 1].progress === '0' ? (
-                            <tr key={item.audit_id}>
-                              <td>
-                                <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
-                                <span className="pi-mg-left-3">{item.name}</span>
-                                <small className="text-muted pi-mg-left-3">{item.position}</small>
-                              </td>
-                            </tr>
-                          ) : (
-                            <tr key={item.audit_id}>
-                              <td rowSpan={2} className="pi-text-center">
-                                审批
-                              </td>
-                              <td>
-                                <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
-                                <span className="pi-mg-left-3">{item.name}</span>
-                                <small className="text-muted pi-mg-left-3">{item.position}</small>
-                              </td>
-                            </tr>
-                          )
-                        } else if (item.progress === '1' || !auditors.find(item => item.progress === '1')) {
-                          return !auditors.find(item => item.progress === '1') ? (
-                            <tr key={item.audit_id}>
-                              <td className="pi-text-center">整改</td>
-                              <td>
-                                <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
-                                <span>由 {auditors[idx - 1].name} 指派</span>
-                              </td>
-                            </tr>
-                          ) : (
-                            <tr key={item.audit_id}>
-                              <td className="pi-text-center">整改</td>
-                              <td>
-                                <SvgIcon type={item.status === 0 ? 'xxh-stop-circle' : 'xxh-chevron-circle-down'}></SvgIcon>
-                                <span className="pi-mg-left-3">{item.name}</span>
-                                <small className="text-muted pi-mg-left-3">{item.position}</small>
-                              </td>
-                            </tr>
-                          )
-                        } else {
-                          return (
-                            <tr key={item.audit_id}>
-                              <td className="pi-text-center">复查</td>
-                              <td>
-                                <SvgIcon type="xxh-stop-circle"></SvgIcon>
-                                <span className="pi-mg-left-3">{item.name}</span>
-                                <small className="text-muted pi-mg-left-3">{item.position}</small>
-                              </td>
-                            </tr>
-                          )
-                        }
-                      })}
-                    </tbody>
-                  </table>
+                  <table className="table table-bordered pi-width-100P">{renderLeftAuditors(status)}</table>
                 </div>
                 <div className="pi-flex-treble pi-mg-left-15">
-                  {auditHistory?.map((item, idx) => {
-                    return (
-                      <ul className="timeline-list" key={idx}>
-                        {item?.map((auditor, idx) => (
-                          <li className="timeline-list-item" key={auditor.id}>
-                            <div className="timeline-item-date pi-flex-column" dangerouslySetInnerHTML={{ __html: formatDate(auditor.create_time) }}></div>
-                            <div className={item.length - 1 === idx ? '' : 'timeline-item-tail'}></div>
-                            {renderStatusIcon(auditor.status, idx === 0 ? true : false)}
-                            <div className="timeline-item-content">
-                              <div className="card-container">
-                                <div className="card-content">
-                                  <div className="pi-justify-between label">
-                                    <span>{auditor.name}</span>
-                                    <span className={renderStatusEle(auditor.status, auditor.progress).textClass}>
-                                      {idx === 0 ? '上报审批' : renderStatusEle(auditor.status, auditor.progress).text}
-                                    </span>
-                                  </div>
-                                  <div className="text-muted">{auditor.position}</div>
-                                </div>
-                                {auditor.opinion ? (
-                                  <div className="textarea">
-                                    <span>{auditor.opinion}</span>
-                                  </div>
-                                ) : null}
-                              </div>
-                            </div>
-                          </li>
-                        ))}
-                      </ul>
-                    )
-                  })}
+                  {renderHistory()}
                 </div>
               </div>
             </td>

+ 159 - 45
src/pages/Safe/Content/Info/Detail/components/Modal/index.tsx

@@ -1,44 +1,100 @@
-import { ZhAuditBackButton, ZhCloseButton, ZhSubmitButton } from '@/components/Button'
-import { Button, Form, Input, Modal } from 'antd'
-import React from 'react'
-
-interface iAuditModalProps{
+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
-  onCreate: () => void
+  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
 }
 const AuditModal: React.FC<iAuditModalProps> = props => {
   const [ form ] = Form.useForm()
-  const { visible, type, onCancel, onCreate } = props
-  const textObj = {
-    start: {
-      title: '提交审批',
-      okText: '确认提交'
-    },
-    delete: {
-      title: '删除巡检',
-      okText: '确认删除'
-    },
-    close: {
-      title: '审批关闭',
-      okText: '确认关闭'
-    },
-    back: {
-      title: '审批退回',
-      okText: '确认退回'
-    },
-    pass: {
-      title: '审批通过',
-      okText: '确认通过'
+  const { visible, type, onCancel, onCreate, auditors, curAuditor } = props
+  const [ modal, setModal ] = useState<iModalObjState>({
+    searchValue: '',
+    visible: false
+  })
+  // 是否是审批组的最后一个审核人
+  const isLastAuditor = useMemo(() => {
+    if (auditors.length && auditors[auditors.length - 1].auditor_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()
-      onCreate()
+      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') || type === 'back') {
+      initGroupList()
+    }
+  }, [ visible ])
+  const initGroupList = async (serach?: string) => {
+    const data = await getUserGroup(serach)
+    setGroups(data)
+  }
+
   const renderOkBtn = (type: string) => {
     if (type === 'start' || type === 'pass') {
       return (
@@ -53,9 +109,42 @@ const AuditModal: React.FC<iAuditModalProps> = props => {
         </Button>
       )
     } else if (type === 'back') {
-      return <ZhAuditBackButton size="small" onClick={comfirmBtnClick}>{textObj[type]?.okText}</ZhAuditBackButton>
+      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) => {
+    setUser({ ...user, ...item })
+    setModal({ ...modal, visible: false })
+  }
+
+  const handleVisibleChange = (visible: boolean) => {
+    setModal({ ...modal, visible })
+  }
+
+  const showPopover = () => {
+    setModal({ ...modal, visible: true })
+  }
+
   return (
     <Modal
       visible={visible}
@@ -70,7 +159,7 @@ const AuditModal: React.FC<iAuditModalProps> = props => {
           {renderOkBtn(type)}
         </div>
       }>
-      <Form form={form}>
+      <Form form={form} layout="vertical">
         {type === 'delete' ? (
           <>
             <p className="mb-2">删除后,数据无法恢复,请谨慎操作。</p>
@@ -93,22 +182,47 @@ const AuditModal: React.FC<iAuditModalProps> = props => {
             </Form.Item>
           </>
         ) : null}
-      {
-        type === 'start'? (
-          <p>请确认审批流程及信息无误。</p>
-        ) : null
-      }
-      {
-        type === 'close' ? (
+        {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>
+            <Form.Item name="opinion" label="审批意见">
+              <Input.TextArea rows={5}></Input.TextArea>
+            </Form.Item>
+            <p className="pi-warning">审批关闭,将直接停止该巡检流程。</p>
           </>
-        ) : null
-      }
+        ) : 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) => itemSelectHandler(item)}></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>
   )

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

@@ -10,6 +10,7 @@ import { iFile } from '@/types/file'
 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, message, Pagination, Tooltip } from 'antd'
@@ -22,6 +23,7 @@ import AuditModal from './components/Modal'
 import styles from './index.module.scss'
 const { TextArea } = Input
 interface iDetailState {
+  times: number
   auditName: string
   auditors: iAuditor[]
   bidsectionId: string
@@ -76,7 +78,7 @@ const Detail: React.FC<RouteComponentProps> = props => {
     inspectionDetail: '',
     position: '',
     status: 0,
-    checkOrder: {
+    checkOrder: { // 整改单
       name: '',
       status: 0,
       opinion: '',
@@ -85,18 +87,23 @@ const Detail: React.FC<RouteComponentProps> = props => {
     auditHistory: [],
     rectifiedInfo: [],
     latestAuditor: {
+      id: '',
       audit_id: '',
       status: 0,
       progress: ''
-    }
+    },
+    times: 0
   })
   useEffect(() => {
     initData()
   }, [ saveId ])
   const initData = async () => {
-    const { code = -1, data = {}, checkOrder = {} } = await apiGetSafeDetail(saveId)
+    const { code = -1, data = {} } = await apiGetSafeDetail(saveId)
     if (code === consts.RET_CODE.SUCCESS) {
-      setDetail({ ...detail, ...data, checkOrder })
+      setDetail({ ...detail, ...data })
+    }
+    if (!userStore.groupList.length) {
+      userStore.getGroupList()
     }
   }
   const onCreate = async (fileList: iFile[]) => {
@@ -157,23 +164,35 @@ const Detail: React.FC<RouteComponentProps> = props => {
   const btnClick = (type: string) => {
     setVisible({ ...visible, auditType: type, auditModal: true })
   }
-  const onModalConfirm = () => {
-    let payload: any = { safe_id: detail.id, bidsection_id: detail.bidsectionId }
+  const onModalConfirm = (values?: object) => {
+    let payload: any = { safe_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('审批人或整改人不能为空!')
+        return message.error('审批人或复查人不能为空!')
       }
     }
+
     if (visible.auditType === 'delete') {
       payload = { id: detail.id }
     }
+
+    if (visible.auditType === 'pass') {
+      payload.id = detail.latestAuditor.id
+      detail.latestAuditor.progress === '1' && (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 apiResfulSafeAudit(type, payload)
     if (code === consts.RET_CODE.SUCCESS) {
+      setVisible({ ...visible, auditModal: false })
       if (type === 'delete') {
         props.history.goBack()
       } else {
@@ -189,15 +208,15 @@ const Detail: React.FC<RouteComponentProps> = props => {
           <ZhSubmitButton size="small" className="pi-mg-left-5" onClick={() => btnClick('start')}>提交审批</ZhSubmitButton>
         </div>
       )
-    } else if(status === 1) {
+    } 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('sclose')}>关闭</Button>
+          <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 {
+    } else if (status === auditProgress.checked) {
       return (
         <div className="pi-flex-row pi-align-center">
           <ZhAuditBackButton size="small" onClick={() => btnClick('back')}>审批退回</ZhAuditBackButton>
@@ -262,7 +281,7 @@ const Detail: React.FC<RouteComponentProps> = props => {
             </tbody>
           </table>
           {
-            detail.rectifiedInfo.length ?
+            detail.latestAuditor.progress === '1' && detail.rectifiedInfo.length ?
             <table className="pi-table pi-bordered">
             <thead>
               <tr>
@@ -275,7 +294,7 @@ const Detail: React.FC<RouteComponentProps> = props => {
               <tr>
                 <th style={{ width: '150px' }}>整改情况</th>
                 <td>
-                  <TextArea value={detail.checkOrder.opinion}></TextArea>
+                  <TextArea value={detail.checkOrder.opinion} onChange={(e) => setDetail({ ...detail, checkOrder: { ...detail.checkOrder, opinion: e.currentTarget.value } })}></TextArea>
                 </td>
               </tr>
               <tr>
@@ -361,6 +380,7 @@ const Detail: React.FC<RouteComponentProps> = props => {
             latest={detail.latestAuditor}
             auditHistory={detail.auditHistory}
             status={detail.status}
+            uName={detail.auditName}
             ></AuditContent>
         </div>
       </div>
@@ -375,6 +395,8 @@ const Detail: React.FC<RouteComponentProps> = props => {
         visible={visible.auditModal}
         onCancel={() => setVisible({ ...visible, auditModal: false })}
         onCreate={onModalConfirm}
+        auditors={detail.auditors.filter(item => item.progress === '0')}
+        curAuditor={detail.latestAuditor}
         ></AuditModal>
     </div>
   )

+ 1 - 0
src/store/mobx/user/index.ts

@@ -40,6 +40,7 @@ class UserState {
     return this.userInfo.isAdmin ? 'ADMIN' : 'USER'
   }
 
+
   @action login(values: iFromValues) {
     apiLogin(values).then(({ code = -1, data }) => {
       if (code === consts.RET_CODE.SUCCESS) {

+ 2 - 0
src/types/safe.d.ts

@@ -32,10 +32,12 @@ export interface iLatestAuditorState {
   audit_id: string;
   status: number;
   progress: string;
+  id: string
 }
 
 export interface iAuditor {
   audit_id: string
+  auditor_id?: string
   name: string
   position: string
   progress: string

+ 12 - 3
src/utils/common/constStatus.ts

@@ -37,16 +37,24 @@ const safeStatus = {
   },
   4: {
     className: 'pi-circle-green',
-    text: '完成'
+    text: '完成'
   },
   5: {
     className: 'pi-circle-red',
-    text: '关闭'
+    text: '关闭'
   }
 }
 const auditConsts = {
   uncheck: 0, // 未提交
   checking: 1, //审批中
+  checked: 2, // 通过
+  checkNo: 3, // 待复查
+  close: 4 // 关闭
+}
+
+const auditProgress = {
+  uncheck: 0, // 未提交
+  checking: 1, //审批中
   checked: 2, // 待整改
   checkNo: 3, // 待复查
   finish: 4, //完成
@@ -57,6 +65,7 @@ export {
   contractConsts,
   contractTreeBaseId,
   safeStatus,
-  auditConsts
+  auditConsts,
+  auditProgress
 }
 

+ 3 - 3
src/utils/common/user.ts

@@ -41,9 +41,9 @@ export const getUserGroupName = (key: number): iGroup | undefined =>{
 
 // 根据group对用户列表进行分组
 export const getUserGroup = async (name?: string) => {
-  if (!userStore.groupList.length) {
-    userStore.getGroupList()
-  }
+  // if (!userStore.groupList.length) {
+  //   userStore.getGroupList()
+  // }
   const { code = -1, data = [] } = await apiGetAccountWithSearch(name)
   const accountGroup: iAccountGroupItem[] = []
   if (code === consts.RET_CODE.SUCCESS) {