Ver código fonte

Merge branch 'develop' of http://120.55.44.4:10080/xujunjie/gt_client_pad into develop

Renxy 1 ano atrás
pai
commit
1171f5469e

+ 18 - 3
.umirc.ts

@@ -26,8 +26,8 @@ export default defineConfig({
   ],
   proxy: {
     '/api': {
-      // target: 'http://47.96.12.136:8888/',
-      target: 'http://47.96.12.136:8788/',
+      target: 'http://47.96.12.136:8888/',
+      // target: 'http://47.96.12.136:8788/',
       // target: 'http://120.55.44.4:8903/',
       // target: 'https://work.greentech.com.cn/',
       changeOrigin: true,
@@ -134,7 +134,7 @@ export default defineConfig({
       component: './EqSelfInspection/Statistics',
     },
     {
-      name: '任务管理',
+      name: '任务管理 - 工单管理',
       path: '/task-manage/:projectID',
       component: './TaskManage',
     },
@@ -148,11 +148,26 @@ export default defineConfig({
       path: '/task-manage/list/detail',
       component: './TaskManage/Detail/TaskDetail/TaskDetail',
     },
+    {
+      name: '工单列表',
+      path: '/task-manage/work-order/list',
+      component: './TaskManage/Detail/WorkOrderList/WorkOrderList',
+    },
     {
       name: '任务关联工单详情',
       path: '/task-manage/list/order-detail',
       component: './TaskManage/Detail/TaskOrder/TaskOrder',
     },
+    {
+      name: '任务弹窗',
+      path: '/task-manage/pop/:projectID',
+      component: './TaskManage/Popup',
+    },
+    {
+      name: '工单详情弹窗',
+      path: '/task-manage/pop/work-order/:projectID',
+      component: './TaskManage/Popup/WorkOrderModal',
+    },
     {
       name: '消息中心',
       path: '/message/:projectId',

+ 25 - 16
src/pages/EqSelfInspection/index.js

@@ -157,9 +157,7 @@ const EqSelfInspection = (props) => {
                 一键自检
               </Button>
             </div>
-            <div className={styles.logoFont}>
-              系统自检中
-            </div>
+            <div className={styles.logoFont}>系统自检中</div>
           </div>
         </div>
         <Item name="设备自检" status={patrolStatus}></Item>
@@ -169,19 +167,30 @@ const EqSelfInspection = (props) => {
             <WarningItem label={item.label} status={item.status} />
           ))}
         </Item>
-        <Button
-          className={styles.reportBtn}
-          type="primary"
-          onClick={() => {
-            history.push(
-              `/self-inspection/detail/${projectId}/${
-                autoReport?.Id
-              }?JWT-TOKEN=${GetTokenFromUrl()}`,
-            );
-          }}
-        >
-          查看自检报告
-        </Button>
+        <div className={styles.btnContainer}>
+          <Button
+            className={styles.reportBtn}
+            type="primary"
+            onClick={() => {
+              // 打开任务弹窗
+            }}
+          >
+            查看任务
+          </Button>
+          <Button
+            className={styles.reportBtn}
+            type="primary"
+            onClick={() => {
+              history.push(
+                `/self-inspection/detail/${projectId}/${
+                  autoReport?.Id
+                }?JWT-TOKEN=${GetTokenFromUrl()}`,
+              );
+            }}
+          >
+            查看自检报告
+          </Button>
+        </div>
 
         <Modal
           title="选择巡检路线"

+ 8 - 2
src/pages/EqSelfInspection/index.less

@@ -127,11 +127,17 @@
   background: url('@/assets/icon-success.png') no-repeat;
   background-size: 100% 100%;
 }
+
+.btnContainer {
+  display: flex;
+  justify-content: space-between;
+}
+
 .reportBtn {
   margin-top: 40px;
-  width: 100%;
+  width: 45%;
   height: 86px;
-  display: block;
+  display: inline-block;
   font-size: 30px;
   font-weight: 400;
   color: #ffffff;

+ 54 - 64
src/pages/Smart/OptimizationTasks.js

@@ -5,72 +5,41 @@ import {
   queryMandate,
   queryMandateChildList,
   querySimulationProfit,
-  queryUserList,
 } from '@/services/SmartOps';
-import { history, useLocation, useParams, useRequest } from '@umijs/max';
-import { Col, Row, Table } from 'antd';
+import { useParams, useRequest } from '@umijs/max';
+import { Table } from 'antd';
 import dayjs from 'dayjs';
-import { useMemo } from 'react';
+import { useState } from 'react';
 import styles from './OptimizationTasks.less';
 
 const OptimizationTasks = (props) => {
   const { projectId } = useParams();
-  const { score } = useLocation();
 
   const { data, run } = useRequest(queryMandate, {
     manual: true,
   });
-  const { data: userList } = useRequest(queryUserList, {
-    defaultParams: [{ projectId }],
-  });
-
-  const ResponsiblePeople = useMemo(() => {
-    if (!data || !userList) return '-';
-    let user = userList.find((item) => item.ID == data.ResponsiblePeople);
-    return user?.CName || '-';
-  }, [data, userList]);
-
-  const status = { 0: '未处理', 2: '已完成', 4: '已忽略', 5: '已派遣' };
 
   return (
     <PageContent closeable={false}>
-      <PageTitle returnable>优化任务</PageTitle>
-      <div className={styles.pageCard}>
-        <div style={{ padding: 20 }}>
-          <Produce
-            projectId={projectId}
-            score={score}
-            queryMandate={run}
-            mandate={data}
-          />
+      <PageTitle returnable>
+        <div className={styles.navigateTitle}>
+          <div>优化任务</div>
+          <div className={styles.titleTime}>
+            {dayjs().format('MM月DD日 HH:mm')}
+          </div>
+        </div>
+      </PageTitle>
+      <div>
+        <div>
+          <Produce projectId={projectId} />
           <Cost projectId={projectId} />
         </div>
-
-        {data && (
-          <div className={styles.bottom}>
-            <Row gutter={16}>
-              <Col span={8}>
-                <div className={styles.bottomText}>任务类型:系统发送</div>
-              </Col>
-              <Col span={8}>
-                <div className={styles.bottomText}>
-                  任务负责人:{ResponsiblePeople}
-                </div>
-              </Col>
-              <Col span={8}>
-                <div className={styles.bottomText}>
-                  任务状态:{status[data?.Status]}
-                </div>
-              </Col>
-            </Row>
-          </div>
-        )}
       </div>
     </PageContent>
   );
 };
 
-const Produce = ({ projectId, queryMandate }) => {
+const Produce = ({ projectId }) => {
   const columns = [
     {
       title: '参数',
@@ -82,6 +51,8 @@ const Produce = ({ projectId, queryMandate }) => {
     },
   ];
 
+  const [mandateID, setMandateID] = useState();
+
   const { data } = useRequest(queryMandateChildList, {
     defaultParams: [
       {
@@ -89,24 +60,32 @@ const Produce = ({ projectId, queryMandate }) => {
         mandateClass: 1,
       },
     ],
-    onSuccess(data) {
-      if (data.length > 0) {
-        queryMandate({
-          mandate_id: data[0]?.MandateId,
-        });
-      }
+    onSuccess: (data) => {
+      setMandateID(data[0].MandateId);
     },
   });
 
+  const openDetail = () => {
+    // send message to unity with mandate_id
+    if (!mandateID) {
+      return;
+    }
+    console.log(mandateID);
+  };
+
   return (
-    <div style={{ marginBottom: 30 }}>
-      <h3 className={styles.title}>
-        <i />
-        生产调度类
+    <div className={styles.pageCard}>
+      <h3 className={styles.title} style={{ justifyContent: 'space-between' }}>
+        <div>
+          <i />
+          生产调度类
+        </div>
+        <div className={styles.btnBlue} onClick={openDetail}>
+          查看任务
+        </div>
       </h3>
       {data?.length > 0 && (
         <>
-          <div className={styles.orderIcon}>任务已发送</div>
           <div
             className={styles.content}
             style={{ backgroundColor: '#B1D2F3' }}
@@ -153,6 +132,8 @@ const Cost = ({ projectId }) => {
     },
   ];
 
+  const [mandateID, setMandateID] = useState();
+
   const { data: profit } = useRequest(querySimulationProfit, {
     defaultParams: [
       {
@@ -163,13 +144,13 @@ const Cost = ({ projectId }) => {
     ],
     formatResult(data) {
       if (!data?.info) return '-';
-
       return Object.values(data.info).reduce(
         (total, currentValue) => total + currentValue,
         0,
       );
     },
   });
+
   const { data } = useRequest(queryMandateChildList, {
     defaultParams: [
       {
@@ -177,19 +158,28 @@ const Cost = ({ projectId }) => {
         mandateClass: 2,
       },
     ],
+    onSuccess: (data) => {
+      setMandateID(data[0].MandateId);
+    },
   });
+
+  const openDetail = () => {
+    // send message to unity
+    if (!mandateID) {
+      return;
+    }
+    console.log(mandateID);
+  };
+
   return (
-    <div>
+    <div className={styles.pageCard}>
       <h3 className={styles.title} style={{ justifyContent: 'space-between' }}>
         <div>
           <i style={{ background: '#F5A623' }} />
           成本节约类
         </div>
-        <div
-          className={styles.btn}
-          onClick={() => history.push(`/smart/simulate/${projectId}`)}
-        >
-          模拟评估
+        <div className={styles.btnOrange} onClick={openDetail}>
+          查看任务
         </div>
       </h3>
       {data?.length > 0 && (

+ 29 - 2
src/pages/Smart/OptimizationTasks.less

@@ -1,3 +1,17 @@
+.navigateTitle {
+  width: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  align-items: center;
+  .titleTime {
+    height: 50px;
+    font-size: 26px;
+    line-height: 26px;
+    display: flex;
+    align-items: flex-end;
+  }
+}
 .title {
   font-size: 32px;
   margin-bottom: 16px;
@@ -49,12 +63,12 @@
   color: #fff;
 }
 .pageCard {
+  padding: 20px;
   margin-top: 30px;
   overflow: hidden;
   border-radius: 26px;
   box-shadow: 2px 0 8px 0 rgba(0, 0, 0, 0.3);
   border: 1px solid #eee;
-  position: relative;
   background: rgb(255, 255, 255);
 }
 .bottom {
@@ -69,7 +83,7 @@
     text-align: center;
   }
 }
-.btn {
+.btnOrange {
   width: 120px;
   height: 56px;
   background: rgba(245, 166, 35, 0.75);
@@ -80,6 +94,19 @@
   line-height: 56px;
   text-align: center;
 }
+
+.btnBlue {
+  width: 120px;
+  height: 56px;
+  background: rgba(74, 144, 226, 0.75);
+  border-radius: 5px;
+  font-size: 24px;
+  font-weight: 400;
+  color: #ffffff;
+  line-height: 56px;
+  text-align: center;
+}
+
 .table2 {
   :global {
     .ant-table-thead {

+ 62 - 74
src/pages/TaskManage/Detail/TaskOrder/TaskOrder.tsx

@@ -7,11 +7,12 @@ import {
   getCraftRecordList,
   getMaintainRecordList,
   getRepairRecordList,
+  getWorkOrderFlow,
   queryReagentDetail,
 } from '@/services/TaskManage';
 import { useLocation } from '@@/exports';
 import { connect, useRequest } from '@umijs/max';
-import { Col, Row } from 'antd';
+import { Col, Row, Steps } from 'antd';
 import dayjs from 'dayjs';
 import { DefaultOptionType } from 'rc-select/es/Select';
 import React, { useEffect, useState } from 'react';
@@ -42,6 +43,11 @@ interface IOrderInfo {
   MandateImages?: any[];
 }
 
+interface IStepInfo {
+  content: string;
+  time: string;
+}
+
 const TaskOrder: React.FC<IPropsType> = (props) => {
   const { userList, dispatch } = props;
 
@@ -50,10 +56,11 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
   const project_id = Number(queryParams.get('project_id'));
   const order_id = Number(queryParams.get('order_id'));
   const order_type = Number(queryParams.get('order_type'));
-  const mandate_class = Number(queryParams.get('mandate_class'));
+  // const mandate_class = Number(queryParams.get('mandate_class'));
 
   const [orderInfo, setOrderInfo] = useState<IOrderInfo>();
   const [additionalInfo, setAdditionalInfo] = useState<any>({});
+  const [stepInfo, setStepInfo] = useState<IStepInfo[]>();
 
   // 根据type请求详情
   const { run: getMaintainDetail } = useRequest(getMaintainRecordList, {
@@ -61,9 +68,15 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
     formatResult: (result) => {
       const temp = result.data.list[0];
       const tempDetail = {
-        CreateTime: dayjs(temp.CreateTime).format('YYYY-MM-DD HH:mm'),
-        PlanTime: dayjs(temp.PlanTime).format('YYYY-MM-DD HH:mm'),
-        RepairTime: dayjs(temp.RepairTime).format('YYYY-MM-DD HH:mm') || '-',
+        CreateTime: temp?.CreateTime
+          ? dayjs(temp?.CreateTime).format('YYYY-MM-DD HH:mm')
+          : '-',
+        PlanTime: temp?.PlanTime
+          ? dayjs(temp.PlanTime).format('YYYY-MM-DD HH:mm')
+          : '-',
+        RepairTime: temp?.RepairTime
+          ? dayjs(temp.RepairTime).format('YYYY-MM-DD HH:mm')
+          : '-',
         Reason: temp.Note,
         Lubrication: temp.Lubrication,
         Fasten: temp.Fasten,
@@ -82,7 +95,6 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
         MandateImages:
           temp?.mandate_images?.length > 0
             ? temp.mandate_images.map((item: any) => {
-                console.log(item);
                 if (item.type === 2) {
                   return {
                     src: item.val,
@@ -141,31 +153,6 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
     },
   });
 
-  const renderReason = (detail: any) => {
-    const title = detail.match(/^(.*?)(?=\{)/g)[0];
-    const content = JSON.parse(detail.match(/\{.*\}/g)[0]);
-    console.log(content, title);
-    console.log(Object.values(content));
-    const result = [];
-    result.push(
-      <Row className={[styles.fontS28, styles.rowMargin].join(' ')}>
-        {title}
-      </Row>,
-    );
-    Object.values(content).forEach((item: any) => {
-      result.push(
-        <Row className={[styles.fontS28, styles.rowMargin].join(' ')}>
-          {item['item_alias'] +
-            ' 现有数值:' +
-            item['old_value'] +
-            ' 建议调整数值' +
-            item['new_value']}
-        </Row>,
-      );
-    });
-    return result;
-  };
-
   // 根据type请求详情
   const { run: getCraftDetail } = useRequest(getCraftRecordList, {
     manual: true,
@@ -178,7 +165,7 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
           (temp.actual_end_time &&
             dayjs(temp.actual_end_time).format('YYYY-MM-DD HH:mm')) ||
           '-',
-        Reason: mandate_class !== 2 ? temp.detail : renderReason(temp.detail),
+        Reason: temp.detail,
         Repairman: userList.find((item) => item.ID === temp.checker_id) || '-',
         DispatchMan:
           userList.find((item) => item.ID === temp.operator_id) || '-',
@@ -212,6 +199,17 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
     },
   });
 
+  // 获取工单流程信息
+  const { run: getOrderFlow } = useRequest(getWorkOrderFlow, {
+    // manual: true,
+    defaultParams: [{ work_type: order_type, work_id: order_id }],
+    formatResult(res: IStepInfo[]) {
+      if (res && res?.length) {
+        setStepInfo(res);
+      }
+    },
+  });
+
   useEffect(() => {
     if (userList.length === 0) {
       dispatch({
@@ -237,11 +235,6 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
     }
   }, []);
 
-  const image = [];
-  // JSON.parse(
-  //   '[{"name":"1694762306412_Screenshot_20230815_180902_uni.UNI7E61B21.jpg","path":"work_order_files/1694762306412_Screenshot_20230815_180902_uni.UNI7E61B21.jpg","created_time":"2023-09-15 15:18:29","url":"https://water-service-test.oss-cn-hangzhou.aliyuncs.com/work_order_files/1694762306412_Screenshot_20230815_180902_uni.UNI7E61B21.jpg"},{"name":"1694762306230_Screenshot_20230815_180907_uni.UNI7E61B21.jpg","path":"work_order_files/1694762306230_Screenshot_20230815_180907_uni.UNI7E61B21.jpg","created_time":"2023-09-15 15:18:29","url":"https://water-service-test.oss-cn-hangzhou.aliyuncs.com/work_order_files/1694762306230_Screenshot_20230815_180907_uni.UNI7E61B21.jpg"}]',
-  // );
-
   const renderImg = () => {
     return (
       <PhotoProvider>
@@ -277,24 +270,24 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
           />
           <div style={{ padding: '15px', letterSpacing: '1.5px' }}>
             <Row className={styles.rowMargin}>
-              <Col className={styles.fontS28} span={16}>
-                {/*// @ts-ignore*/}
+              <Col className={styles.fontS28} span={15}>
+                {/* @ts-ignore */}
                 工单类型:
                 {OrderType.find((item) => item.value === order_type)?.label ||
                   '-'}
               </Col>
-              <Col className={styles.fontS28} span={8}>
-                {/*// @ts-ignore*/}
+              <Col className={styles.fontS28} span={9}>
+                {/* @ts-ignore */}
                 工单负责人:{orderInfo?.Repairman?.CName || '-'}
               </Col>
             </Row>
             <Row className={styles.rowMargin}>
-              <Col className={styles.fontS28} span={16}>
-                {/*// @ts-ignore*/}
+              <Col className={styles.fontS28} span={15}>
+                {/*  @ts-ignore */}
                 工单状态:{orderInfo?.OrderStatus?.label}
               </Col>
-              <Col className={styles.fontS28} span={8}>
-                {/*// @ts-ignore*/}
+              <Col className={styles.fontS28} span={9}>
+                {/* @ts-ignore */}
                 派单人员:{orderInfo?.DispatchMan?.CName}
               </Col>
             </Row>
@@ -327,6 +320,7 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
                 </Col>
               </Row>
             )}
+            {/* @ts-ignore */}
             {orderInfo?.MandateImages?.length > 0 && (
               <Row className={styles.rowMarginTop}>
                 <Col className={styles.fontS28}>任务图片:</Col>
@@ -364,35 +358,29 @@ const TaskOrder: React.FC<IPropsType> = (props) => {
             </div>
           </div>
         )}
-
-        {/*<div>*/}
-        {/*  <SubTitle title="工单流程" />*/}
-        {/*  <div style={{ padding: '15px' }}>*/}
-        {/*    <Steps*/}
-        {/*      direction="vertical"*/}
-        {/*      style={{ fontSize: '14px' }}*/}
-        {/*      current={1}*/}
-        {/*      items={[*/}
-        {/*        {*/}
-        {/*          title: '工单已派遣至值班人员张**',*/}
-        {/*          description: '2023-08-02 13:23',*/}
-        {/*        },*/}
-        {/*        {*/}
-        {/*          title: '张**接收工单',*/}
-        {/*          description: '2023-08-02 13:23',*/}
-        {/*        },*/}
-        {/*        {*/}
-        {/*          title: '张**提交处理结果',*/}
-        {/*          description: '2023-08-02 13:23',*/}
-        {/*        },*/}
-        {/*        {*/}
-        {/*          title: '工单审批通过',*/}
-        {/*          description: '2023-08-02 13:23',*/}
-        {/*        },*/}
-        {/*      ]}*/}
-        {/*    />*/}
-        {/*  </div>*/}
-        {/*</div>*/}
+        {/* @ts-ignore */}
+        {stepInfo?.length > 0 && (
+          <div>
+            <SubTitle title="工单流程" />
+            <div style={{ padding: '15px 20px' }}>
+              <Steps
+                direction="vertical"
+                current={stepInfo?.length ? stepInfo.length - 1 : 0}
+                progressDot
+                items={stepInfo?.map((item) => {
+                  return {
+                    title: (
+                      <span className={styles.fontS24}>{item.content}</span>
+                    ),
+                    description: (
+                      <span className={styles.fontS20}>{item.time}</span>
+                    ),
+                  };
+                })}
+              />
+            </div>
+          </div>
+        )}
       </div>
     </PageContent>
   );

+ 186 - 0
src/pages/TaskManage/Detail/WorkOrderList/WorkOrderList.js

@@ -0,0 +1,186 @@
+import PageContent from '@/components/PageContent';
+import PageTitle from '@/components/PageTitle';
+import {
+  getCraftRecordList,
+  getMaintainRecordList,
+  getRepairRecordList,
+} from '@/services/TaskManage';
+import { connect, useLocation, useNavigate, useRequest } from '@umijs/max';
+import { Button, Col, Empty, Row, Tabs } from 'antd';
+import dayjs from 'dayjs';
+import { useEffect, useState } from 'react';
+import { OrderStatus, OrderType } from '../../constent';
+import styles from './WorkOrderList.less';
+
+const { TabPane } = Tabs;
+
+const WorkOrderList = (props) => {
+  const { userList, dispatch } = props;
+  const location = useLocation();
+  const queryParams = new URLSearchParams(location.search);
+  const project_id = Number(queryParams.get('project_id'));
+  const order_type = Number(queryParams.get('order_type'));
+
+  const navigate = useNavigate();
+
+  useEffect(() => {
+    if (userList.length === 0) {
+      dispatch({
+        type: 'taskUser/fetchUserList',
+        payload: { project_id },
+      });
+    }
+  }, []);
+
+  const [activedStatus, setActivedStatus] = useState();
+  const [pagination, setPagination] = useState({
+    pageSize: 20,
+    currentPage: 1,
+    total: 0,
+  });
+  const [workOrderList, setWorkOrderList] = useState(null);
+
+  const goWorkOrderDetail = (order) => {
+    const orderID = order.id || order.Id;
+    navigate(
+      `/task-manage/list/order-detail?project_id=${project_id}&order_id=${orderID}&order_type=${order_type}`,
+    );
+  };
+
+  const renderTabPannal = (list) => {
+    if (list?.length === 0) {
+      setWorkOrderList(<Empty />);
+      return;
+    }
+    const tempNode = list.map((workOrder) => {
+      return (
+        <div
+          key={workOrder.id || workOrder.Id}
+          className={styles.workOrderCard}
+        >
+          <Row justify="space-between" style={{ marginBottom: '20px' }}>
+            <Col className={styles.fontS24}>{workOrder?.CreateTime}</Col>
+            <Col className={styles.fontS24}>
+              工单负责人:{workOrder?.Repairman?.CName || '-'}
+            </Col>
+          </Row>
+          <Row justify="space-between">
+            <Col className={styles.fontS24}>
+              工单状态:{workOrder?.OrderStatus?.label}
+            </Col>
+            <Col className={styles.detailBtnContainer}>
+              <Button
+                type="primary"
+                style={{ height: '40px', fontSize: '24px' }}
+                onClick={() => goWorkOrderDetail(workOrder)}
+              >
+                工单详情
+              </Button>
+            </Col>
+          </Row>
+        </div>
+      );
+    });
+    setWorkOrderList(tempNode);
+  };
+
+  const { run: getWorkOrderList } = useRequest(
+    (status) => {
+      switch (order_type) {
+        case 1:
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+          return getCraftRecordList({
+            project_id,
+            status: status || 0,
+          });
+        case 2:
+          return getRepairRecordList({
+            project_id,
+            acceptanceStatus: status || 0,
+          });
+        case 3:
+          return getMaintainRecordList({ project_id, status: status || 0 });
+      }
+    },
+    {
+      throwOnError: true,
+      formatResult: (result) => {
+        if (result?.data?.list) {
+          const temp = result.data.list.map((item) => {
+            return {
+              ...item,
+              CreateTime: dayjs(item.start_time).format('YYYY-MM-DD HH:mm'),
+              Repairman: userList.find((user) => {
+                let temp = -1;
+                if (order_type === 2) {
+                  temp = item.Repairman;
+                } else if (order_type === 3) {
+                  temp = item.MaintenancePerson;
+                } else {
+                  temp = item.checker_id;
+                }
+                return temp === user.ID;
+              }),
+              OrderStatus: OrderStatus.find((status) => {
+                let temp = -1;
+                if (order_type === 2) {
+                  temp = item.AcceptanceStatus;
+                } else if (order_type === 3) {
+                  temp = item.Status;
+                } else {
+                  temp = item.status;
+                }
+                return status.value === temp;
+              }),
+            };
+          });
+          renderTabPannal(temp);
+        }
+        if (result?.data?.pagination) {
+          setPagination({
+            pageSize: result.data.pagination.PageSize,
+            currentPage: result.data.pagination.Current,
+            total: result.data.pagination.Total,
+          });
+        }
+      },
+    },
+  );
+
+  const onTabChange = (key) => {
+    setActivedStatus(key);
+    getWorkOrderList(Number(key));
+  };
+
+  return (
+    <PageContent closeable={false}>
+      <PageTitle returnable>
+        {OrderType.find((item) => item.value === order_type)?.label || ''}
+      </PageTitle>
+      <Tabs
+        size="large"
+        activeKey={activedStatus}
+        defaultActiveKey={String(OrderStatus[0].value)}
+        className={styles.identifyTab}
+        onChange={onTabChange}
+      >
+        {OrderStatus.map((item) => {
+          return (
+            <TabPane tab={item.label} key={String(item.value)}>
+              {workOrderList}
+            </TabPane>
+          );
+        })}
+      </Tabs>
+    </PageContent>
+  );
+};
+
+export default connect(({ taskUser }) => {
+  return {
+    userList: taskUser.userList,
+  };
+})(WorkOrderList);

+ 26 - 0
src/pages/TaskManage/Detail/WorkOrderList/WorkOrderList.less

@@ -0,0 +1,26 @@
+.identifyTab :global {
+  .ant-tabs-nav-list {
+    justify-content: space-around;
+    width: 100%;
+    .ant-tabs-tab-btn {
+      font-size: 24px;
+    }
+  }
+}
+
+.workOrderCard {
+  padding: 20px;
+  margin-bottom: 10px;
+  border-radius: 10px;
+  box-shadow: 0px 0px 8px 2px rgba(191, 191, 191, 0.2);
+}
+
+.detailBtnContainer {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.fontS24 {
+  font-size: 24px;
+}

+ 335 - 0
src/pages/TaskManage/Popup/WorkOrderModal.js

@@ -0,0 +1,335 @@
+import {
+  getCraftRecordList,
+  getMaintainRecordList,
+  getRepairRecordList,
+  getWorkOrderFlow,
+} from '@/services/TaskManage';
+import { CloseOutlined } from '@ant-design/icons';
+import { connect, useLocation, useParams, useRequest } from '@umijs/max';
+import { Button, Col, Row, Steps } from 'antd';
+import dayjs from 'dayjs';
+import { useEffect, useState } from 'react';
+import { PhotoProvider, PhotoView } from 'react-photo-view';
+import SubTitle from '../components/SubTitle';
+import { OrderStatus, OrderType } from '../constent';
+import styles from './WorkOrderModal.less';
+
+import 'react-photo-view/dist/react-photo-view.css';
+
+const WorkOrderModal = (props) => {
+  const { userList, dispatch } = props;
+
+  const { projectID } = useParams();
+  const location = useLocation();
+  const queryParams = new URLSearchParams(location.search);
+  const order_id = Number(queryParams.get('order_id'));
+  const order_type = Number(queryParams.get('order_type'));
+  const mandate_class = Number(queryParams.get('mandate_class'));
+
+  const [orderInfo, setOrderInfo] = useState({});
+  const [stepInfo, setStepInfo] = useState([]);
+
+  const { run: getCraftDetail } = useRequest(getCraftRecordList, {
+    manual: true,
+    formatResult: (result) => {
+      if (result?.data?.list) {
+        const temp = result.data.list[0];
+        const tempDetail = {
+          ...temp,
+          CreateTime: dayjs(temp.start_time).format('YYYY-MM-DD HH:mm'),
+          PlanTime: dayjs(temp.plan_end_time).format('YYYY-MM-DD HH:mm'),
+          RepairTime:
+            (temp.actual_end_time &&
+              dayjs(temp.actual_end_time).format('YYYY-MM-DD HH:mm')) ||
+            '-',
+          Reason: mandate_class !== 2 ? temp.detail : renderReason(temp.detail),
+          Repairman:
+            userList.find((item) => item.ID === temp.checker_id) || '-',
+          DispatchMan:
+            userList.find((item) => item.ID === temp.operator_id) || '-',
+          OrderStatus:
+            OrderStatus.find((item) => item.value === temp.status) || '-',
+          MandateImages:
+            temp?.mandate_images?.length > 0
+              ? temp.mandate_images.map((item) => {
+                  console.log(item);
+                  if (item.type === 2) {
+                    return {
+                      src: item.val,
+                    };
+                  }
+                  return {
+                    src: `data:image/png;base64,${item.val}`,
+                  };
+                })
+              : [],
+        };
+        setOrderInfo(tempDetail);
+        // 根据不同的工单类型查询工单操作详情
+      }
+    },
+  });
+
+  const { run: getRepairDetail } = useRequest(getRepairRecordList, {
+    manual: true,
+    formatResult: (result) => {
+      if (result?.data?.list) {
+        const temp = result.data.list[0];
+
+        const tempDetail = {
+          ...temp,
+          CreateTime: dayjs(temp.CreateTime).format('YYYY-MM-DD HH:mm'),
+          PlanTime: dayjs(temp.PlanTime).format('YYYY-MM-DD HH:mm'),
+          RepairTime:
+            (temp.RepairTime &&
+              dayjs(temp.RepairTime).format('YYYY-MM-DD HH:mm')) ||
+            '-',
+          Reason: temp.Reason,
+          Repairman: userList.find((item) => item.ID === temp.Repairman) || '-',
+          DispatchMan:
+            userList.find((item) => {
+              item.ID === temp.operator_id;
+            }) || '-',
+          OrderStatus:
+            OrderStatus.find((item) => item.value === temp.AcceptanceStatus) ||
+            '-',
+          MandateImages:
+            temp?.mandate_images?.length > 0
+              ? temp.mandate_images.map((item) => {
+                  if (item.type === 2) {
+                    return {
+                      src: item.val,
+                    };
+                  }
+                  return {
+                    src: `data:image/png;base64,${item.val}`,
+                  };
+                })
+              : [],
+        };
+        setOrderInfo(tempDetail);
+      }
+    },
+  });
+
+  const { run: getMaintainDetail } = useRequest(getMaintainRecordList, {
+    manual: true,
+    formatResult: (result) => {
+      if (result?.data?.list) {
+        const temp = result.data.list[0];
+        const tempDetail = {
+          ...temp,
+          CreateTime: dayjs(temp.CreateTime).format('YYYY-MM-DD HH:mm'),
+          PlanTime: dayjs(temp.PlanTime).format('YYYY-MM-DD HH:mm'),
+          RepairTime: dayjs(temp.RepairTime).format('YYYY-MM-DD HH:mm') || '-',
+          Reason: temp.Note,
+          Repairman:
+            userList.find((item) => item.ID === temp.MaintenancePerson) || '-',
+          DispatchMan:
+            userList.find(
+              (item) => (item.ID = temp.Operators[0]?.Operator?.ID),
+            ) || '-',
+          OrderStatus:
+            OrderStatus.find((item) => item.value === temp.Status) || '-',
+          MandateImages:
+            temp?.mandate_images?.length > 0
+              ? temp.mandate_images.map((item) => {
+                  if (item.type === 2) {
+                    return {
+                      src: item.val,
+                    };
+                  }
+                  return {
+                    src: `data:image/png;base64,${item.val}`,
+                  };
+                })
+              : [],
+        };
+        setOrderInfo(tempDetail);
+      }
+    },
+  });
+
+  const { run: getOrderFlow } = useRequest(getWorkOrderFlow, {
+    defaultParams: [{ work_type: order_type, work_id: order_id }],
+    formatResult(res) {
+      if (res && res?.length) {
+        setStepInfo(res);
+      }
+    },
+  });
+
+  const closePage = () => {
+    // ToDo: send message to unity to close this page
+  };
+
+  const renderImg = () => {
+    return (
+      <PhotoProvider>
+        <Col className={styles.fontS24} span={20}>
+          {orderInfo?.MandateImages?.map((photo) => (
+            <PhotoView src={photo.src}>
+              <img
+                style={{
+                  maxWidth: `${Math.floor(
+                    100 / (orderInfo?.MandateImages?.length || 1),
+                  )}%`,
+                }}
+                src={photo.src}
+                alt=""
+              />
+            </PhotoView>
+          ))}
+        </Col>
+      </PhotoProvider>
+    );
+  };
+
+  useEffect(() => {
+    switch (order_type) {
+      case 1:
+      case 4:
+      case 5:
+      case 6:
+        getCraftDetail({ project_id: projectID, work_id: order_id });
+        break;
+      case 2:
+        getRepairDetail({ project_id: projectID, id: order_id });
+        break;
+      case 3:
+        getMaintainDetail({ project_id: projectID, id: order_id });
+        break;
+      default:
+        break;
+    }
+  }, []);
+
+  return (
+    <div className={styles.modalContainer}>
+      <div className={styles.modalTitle}>工单信息</div>
+      <Button
+        className={styles.closeModalBtn}
+        type="text"
+        icon={<CloseOutlined style={{ fontSize: '24px' }} />}
+        onClick={closePage}
+      />
+      <div
+        style={{
+          marginTop: '20px',
+          borderRadius: '8px',
+          boxShadow: '2px 0 8px 0 rgba(0, 0, 0, 30%)',
+        }}
+      >
+        <div>
+          <SubTitle
+            title="工单信息"
+            titleFontSize={24}
+            showStatus={orderInfo?.OrderStatus?.value === 2}
+            radius
+          />
+          <div className={styles.basicalInfo}>
+            <Row>
+              <Col span={16} className={styles.fontS24}>
+                工单类型:
+                {OrderType.find((item) => item.value === order_type)?.label ||
+                  '-'}
+              </Col>
+              <Col span={8} className={styles.fontS24}>
+                {/*// @ts-ignore*/}
+                工单负责人:{orderInfo?.Repairman?.CName || '-'}
+              </Col>
+            </Row>
+            <Row>
+              <Col span={16} className={styles.fontS24}>
+                工单状态:{orderInfo?.OrderStatus?.label}
+              </Col>
+              <Col span={8} className={styles.fontS24}>
+                派单人员:{orderInfo?.DispatchMan?.CName}
+              </Col>
+            </Row>
+            <Row>
+              <Col className={styles.fontS24}>
+                派单时间:{orderInfo?.CreateTime || '-'}
+              </Col>
+            </Row>
+            <Row>
+              <Col className={styles.fontS24}>
+                计划完成时间:{orderInfo?.PlanTime || '-'}
+              </Col>
+            </Row>
+            <Row>
+              <Col className={styles.fontS24}>
+                实际完成时间:{orderInfo?.RepairTime || '-'}
+              </Col>
+            </Row>
+            {orderInfo?.MandateImages?.length > 0 && (
+              <Row>
+                <Col className={styles.fontS24} span={4}>
+                  任务图片:
+                </Col>
+                {renderImg()}
+              </Row>
+            )}
+          </div>
+        </div>
+        {order_type === 3 && (
+          <div>
+            <SubTitle title="操作内容" titleFontSize={24} />
+            <div className={styles.additionInfo}>
+              <Row justify={'space-around'}>
+                <Col className={styles.fontS24} span={8}>
+                  是否润滑/加油:{orderInfo?.Lubrication === 1 ? '是' : '否'}
+                </Col>
+                <Col className={styles.fontS24} span={8}>
+                  是否拆检:{orderInfo?.Check === 1 ? '是' : '否'}
+                </Col>
+                <Col className={styles.fontS24} span={8}>
+                  是否清洁:{orderInfo?.Clean === 1 ? '是' : '否'}
+                </Col>
+              </Row>
+              <Row justify={'space-around'}>
+                <Col className={styles.fontS24} span={8}>
+                  是否紧固:{orderInfo?.Fasten === 1 ? '是' : '否'}
+                </Col>
+                <Col className={styles.fontS24} span={8}>
+                  是否除锈:{orderInfo?.AntiCorrosive === 1 ? '是' : '否'}
+                </Col>
+                <Col className={styles.fontS24} span={8}>
+                  是否防腐:{orderInfo?.RustRemoval === 1 ? '是' : '否'}
+                </Col>
+              </Row>
+            </div>
+          </div>
+        )}
+        {stepInfo.length > 0 && (
+          <div>
+            <SubTitle title="工单流程" titleFontSize={24} />
+            <div style={{ padding: '15px 20px' }}>
+              <Steps
+                direction="vertical"
+                progressDot
+                current={1}
+                items={stepInfo?.map((item) => {
+                  return {
+                    title: (
+                      <span className={styles.fontS24}>{item.content}</span>
+                    ),
+                    description: (
+                      <span className={styles.fontS20}>{item.time}</span>
+                    ),
+                  };
+                })}
+              />
+            </div>
+          </div>
+        )}
+      </div>
+    </div>
+  );
+};
+
+export default connect(({ taskUser }) => {
+  return {
+    userList: taskUser.userList,
+  };
+})(WorkOrderModal);

+ 35 - 0
src/pages/TaskManage/Popup/WorkOrderModal.less

@@ -0,0 +1,35 @@
+.modalContainer {
+  padding: 0 30px;
+}
+
+.closeModalBtn {
+  position: absolute;
+  top: 15px;
+  right: 20px;
+}
+
+.modalTitle {
+  font-size: 28px;
+  font-weight: 600;
+  padding: 10px 0;
+}
+
+.basicalInfo {
+  padding: 0 15px 15px 15px;
+}
+
+.basicalInfo > * {
+  margin-top: 20px;
+}
+
+.additionInfo {
+  padding: 0 15px 15px 15px;
+}
+
+.additionInfo > * {
+  margin-top: 20px;
+}
+
+.fontS24 {
+  font-size: 24px;
+}

+ 100 - 0
src/pages/TaskManage/Popup/index.js

@@ -0,0 +1,100 @@
+import { CloseOutlined } from '@ant-design/icons';
+import { connect, useLocation, useParams } from '@umijs/max';
+import { Button, Tabs } from 'antd';
+import { useEffect, useState } from 'react';
+import MandateDetail from '../components/MandateDetail';
+import styles from './index.less';
+
+const TaskModal = (props) => {
+  const { projectID } = useParams();
+  const location = useLocation();
+  const queryParams = new URLSearchParams(location.search);
+
+  const mandateIDs =
+    queryParams.get('mandate_id')?.split(',').length === 1
+      ? queryParams.get('mandate_id')
+      : queryParams.get('mandate_id')?.split(',');
+
+  const { userList, dispatch } = props;
+
+  const [modalTitle, setModalTitle] = useState(null);
+  const [tabItems, setTabItems] = useState([]);
+  const [activeKey, setActiveKey] = useState();
+
+  const onTabChange = (key) => {
+    setActiveKey(String(key));
+  };
+
+  const closePage = () => {
+    // send message to unity close this modal page
+  };
+
+  useEffect(() => {
+    if (mandateIDs !== undefined) {
+      if (Array.isArray(mandateIDs)) {
+        setModalTitle(null);
+        setTabItems(
+          mandateIDs.map((item, index) => {
+            return {
+              key: String(item),
+              label: <span className={styles.fontS24}>任务{index + 1}</span>,
+              children: (
+                <MandateDetail
+                  key={item}
+                  mandateID={item}
+                  userList={userList}
+                  projectID={projectID}
+                />
+              ),
+            };
+          }),
+        );
+      } else {
+        setModalTitle(<div className={styles.modalTitle}>任务详情</div>);
+      }
+    }
+  }, []);
+
+  useEffect(() => {
+    if (userList.length === 0) {
+      dispatch({
+        type: 'taskUser/fetchUserList',
+        payload: { project_id: projectID },
+      });
+    }
+  }, []);
+
+  return (
+    <div className={styles.modalContainer}>
+      <Button
+        className={styles.closeModalBtn}
+        type="text"
+        icon={<CloseOutlined style={{ fontSize: '24px' }} />}
+        onClick={closePage}
+      />
+      {mandateIDs && Array.isArray(mandateIDs) ? (
+        <Tabs
+          defaultActiveKey={String(mandateIDs[0])}
+          activeKey={activeKey}
+          items={tabItems}
+          onChange={onTabChange}
+        />
+      ) : (
+        <>
+          {modalTitle}
+          <MandateDetail
+            mandateID={mandateIDs}
+            userList={userList}
+            projectID={projectID}
+          />
+        </>
+      )}
+    </div>
+  );
+};
+
+export default connect(({ taskUser }) => {
+  return {
+    userList: taskUser.userList,
+  };
+})(TaskModal);

+ 65 - 0
src/pages/TaskManage/Popup/index.less

@@ -0,0 +1,65 @@
+.modalContainer {
+  padding: 0 30px;
+}
+
+.closeModalBtn {
+  position: absolute;
+  top: 15px;
+  right: 20px;
+}
+
+.mandate > * {
+  margin-top: 15px;
+}
+
+.modalTitle {
+  font-size: 28px;
+  font-weight: 600;
+  padding: 10px 0;
+}
+
+.footerConstainer {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-end;
+  .footerBtn {
+    height: 50px;
+    width: 125px;
+    font-size: 20px;
+    border: 0;
+    color: #5697e4;
+    background-color: #e5effa;
+  }
+}
+
+.footerConstainer > * {
+  margin-left: 10px;
+}
+
+.relatedOrder {
+  margin-bottom: 20px;
+  background-color: #e5effa;
+  border-radius: 8px;
+  display: flex;
+  align-items: center;
+  padding: 15px;
+  .leftInfo {
+    width: 80%;
+  }
+  .leftInfo > * {
+    padding: 5px;
+  }
+  .rightButton {
+    flex: auto;
+    color: #5697e4;
+    font-size: 24px;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+}
+
+.fontS24 {
+  font-size: 24px;
+}

+ 359 - 0
src/pages/TaskManage/components/MandateDetail.js

@@ -0,0 +1,359 @@
+import { queryMandate } from '@/services/SmartOps';
+import { useRequest } from '@umijs/max';
+import {
+  Button,
+  Col,
+  ConfigProvider,
+  Divider,
+  Form,
+  Input,
+  Modal,
+  Row,
+  Select,
+  Table,
+  message,
+} from 'antd';
+import dayjs from 'dayjs';
+import { useEffect, useState } from 'react';
+import styles from '../Popup/index.less';
+import {
+  MandateClass,
+  MandateStatus,
+  MandateType,
+  OrderStatus,
+  OrderType,
+  ignoreReason,
+} from '../constent';
+
+import zhCN from 'antd/es/locale/zh_CN';
+
+const MandateDetail = (props) => {
+  const { projectID, mandateID, userList } = props;
+  const [mandateDetail, setMandateDetail] = useState();
+  const [mandateChild, setMandateChild] = useState([]);
+  const [handledWorkOrder, setHandledWorkOrder] = useState([]);
+
+  const [ignoreModalOpen, setIgnoreModalOpen] = useState(false);
+  const [autoHandleModalOpen, setAutoHandleModalOpen] = useState(false);
+  const [dispatchModalOpen, setDispatchModalOpen] = useState(false);
+
+  const columns = [
+    {
+      title: '参数',
+      dataIndex: 'Title',
+    },
+    {
+      title: '调整内容',
+      dataIndex: 'Content',
+    },
+  ];
+
+  const { run: getMandateInfo } = useRequest(queryMandate, {
+    manual: true,
+    formatResult: (result) => {
+      if (result?.data) {
+        const tempMandate = {
+          ...result.data,
+          Status: MandateStatus.find(
+            (item) => item.value === result.data.Status,
+          ),
+          MandateClass: MandateClass.find(
+            (item) => item.value === result.data.MandateClass,
+          ),
+          MandateType: MandateType.find(
+            (item) => item.value === result.data.MandateType,
+          ),
+          ResponsiblePeople: userList.find(
+            (item) => item.ID === result.data.ResponsiblePeople,
+          ),
+          CreateTime: dayjs(result.data.CreateTime).format('YYYY-MM-DD HH:mm'),
+        };
+        const workOrder = result.data.Records.map((item) => {
+          return {
+            ...item,
+            CreateTime: dayjs(item.CreateTime).format('YYYY-MM-DD HH:mm'),
+            Status: OrderStatus.find((status) => status.value === item.Status),
+            RecordType: OrderType.find(
+              (type) => type.value === item.RecordType,
+            ),
+            Responsible: userList.find((user) => user.ID === item.Responsible),
+          };
+        });
+        setMandateDetail(tempMandate);
+        setMandateChild(tempMandate.MandateChild);
+        setHandledWorkOrder(workOrder);
+      }
+    },
+  });
+
+  const onIgnoreClick = () => {
+    setIgnoreModalOpen(true);
+  };
+
+  const onDispatchClick = () => {
+    setDispatchModalOpen(true);
+  };
+
+  const onAutoHandleClick = () => {
+    setAutoHandleModalOpen(true);
+  };
+
+  const onManualHandleClick = () => {
+    console.log('manual handle click');
+  };
+
+  const onIgnoreConfirm = (text) => {
+    console.log(text);
+    // 调用ignore
+    setIgnoreModalOpen(false);
+  };
+
+  const onAutoHandleConfirm = (text) => {
+    console.log(text);
+    setAutoHandleModalOpen(false);
+  };
+
+  const onManualHandleConfirm = () => {
+    console.log('manual handle Confirm');
+  };
+
+  const onDispatchConfirm = () => {
+    console.log('ignore Confirm');
+    setDispatchModalOpen(false);
+  };
+
+  useEffect(() => {
+    getMandateInfo({ mandate_id: mandateID });
+  }, []);
+
+  return (
+    <div>
+      <div className={styles.mandate}>
+        <Row>
+          <Col className={styles.fontS24} span={4}>
+            任务内容:{' '}
+          </Col>
+          <Col className={styles.fontS24} span={20}>
+            <Table
+              columns={columns}
+              dataSource={mandateChild}
+              pagination={false}
+            />
+          </Col>
+        </Row>
+        <Row>
+          <Col className={styles.fontS24} span={14}>
+            任务时间:{mandateDetail?.CreateTime || '-'}
+          </Col>
+          <Col className={styles.fontS24}>
+            任务类别:{mandateDetail?.MandateClass.label || '-'}
+          </Col>
+        </Row>
+        <Row>
+          <Col className={styles.fontS24} span={14}>
+            任务状态:{' '}
+            <span style={{ color: ' #5697e4' }}>
+              {mandateDetail?.Status.label}
+            </span>
+          </Col>
+          <Col className={styles.fontS24}>
+            任务负责人:{mandateDetail?.ResponsiblePeople?.CName || '-'}
+          </Col>
+        </Row>
+      </div>
+      {handledWorkOrder?.length > 0 && <Divider />}
+      {handledWorkOrder?.map((item) => {
+        return (
+          <div key={item.Id} className={styles.relatedOrder}>
+            <div className={styles.leftInfo}>
+              <Row>
+                <Col span={12} className={styles.fontS24}>
+                  工单类型:{item?.RecordType?.label}
+                </Col>
+                <Col className={styles.fontS24}>时间:{item?.CreateTime}</Col>
+              </Row>
+              <Row>
+                <Col span={12} className={styles.fontS24}>
+                  工单状态:
+                  <span style={{ color: ' #5697e4' }}>
+                    {item?.Status?.label}
+                  </span>
+                </Col>
+                <Col className={styles.fontS24}>
+                  工单负责人:{item?.Responsible?.CName}
+                </Col>
+              </Row>
+            </div>
+            <Divider type="vertical" style={{ height: '40px' }} />
+            <div className={styles.rightButton}>查看工单</div>
+          </div>
+        );
+      })}
+      {mandateDetail?.Status?.value === 0 && <Divider />}
+      {mandateDetail?.Status?.value === 0 && (
+        <div className={styles.footerConstainer}>
+          <Button
+            className={styles.footerBtn}
+            shape="round"
+            onClick={onIgnoreClick}
+          >
+            忽略
+          </Button>
+          <Button
+            className={styles.footerBtn}
+            shape="round"
+            onClick={onManualHandleClick}
+          >
+            手动处理
+          </Button>
+          <Button
+            className={styles.footerBtn}
+            shape="round"
+            onClick={onAutoHandleClick}
+          >
+            自动处理
+          </Button>
+          <Button
+            className={styles.footerBtn}
+            shape="round"
+            onClick={onDispatchClick}
+          >
+            派单
+          </Button>
+        </div>
+      )}
+      <ConfigProvider locale={zhCN}>
+        <IgnoreTaskModal
+          open={ignoreModalOpen}
+          onCancel={() => setIgnoreModalOpen(false)}
+          onOk={onIgnoreConfirm}
+        />
+        <AutoHandleModal
+          open={autoHandleModalOpen}
+          onCancel={() => setAutoHandleModalOpen(false)}
+          onOk={onAutoHandleConfirm}
+        />
+        <DispatchModa
+          open={dispatchModalOpen}
+          onCancel={() => setDispatchModalOpen(false)}
+          onOk={onDispatchConfirm}
+        />
+      </ConfigProvider>
+    </div>
+  );
+};
+
+export default MandateDetail;
+
+const IgnoreTaskModal = (params) => {
+  const { open, onCancel, onOk } = params;
+
+  const [ignoreReasonText, setIgnoreReasonText] = useState('');
+  const [selectedReason, setSelectedReason] = useState({});
+  const [showInput, setShowInput] = useState(false);
+
+  const onReasonChange = (reason, option) => {
+    if (reason !== 4) {
+      setSelectedReason(option);
+      setShowInput(false);
+    } else {
+      setShowInput(true);
+    }
+  };
+
+  const onReasonTextChange = (e) => {
+    setIgnoreReasonText(e.target.value);
+  };
+
+  const confirmIgnore = () => {
+    if (showInput) {
+      if (!ignoreReasonText.length) {
+        message.warning('请输入忽略理由');
+      } else {
+        onOk(ignoreReasonText);
+      }
+    } else {
+      if (selectedReason?.label) {
+        onOk(selectedReason.label);
+      } else {
+        message.warning('请选择忽略理由');
+      }
+    }
+  };
+
+  return (
+    <Modal
+      title="忽略"
+      open={open}
+      onCancel={onCancel}
+      onOk={confirmIgnore}
+      destroyOnClose
+    >
+      <div style={{ padding: '15px' }}>
+        <Form layout="vertical">
+          <Form.Item label="忽略理由:">
+            <Select
+              className={styles.fontS24}
+              options={ignoreReason}
+              onChange={onReasonChange}
+              allowClear
+            />
+          </Form.Item>
+          {showInput && (
+            <Form.Item label="输入理由:">
+              <Input placeholder="请输入理由" onChange={onReasonTextChange} />
+            </Form.Item>
+          )}
+        </Form>
+      </div>
+    </Modal>
+  );
+};
+
+const AutoHandleModal = (props) => {
+  const { open, onCancel, onOk } = props;
+
+  const [automation, setAutomation] = useState('');
+
+  const confirmAutoHandle = () => {
+    if (automation.length) {
+      onOk(automation);
+    } else {
+      message.warning('请输入口令');
+    }
+  };
+
+  return (
+    <Modal
+      title="自动处理"
+      open={open}
+      onCancel={onCancel}
+      onOk={confirmAutoHandle}
+      destroyOnClose
+    >
+      <div style={{ padding: '15px' }}>
+        <Form layout="vertical">
+          <Form.Item label="口令:">
+            {
+              <Input
+                placeholder="请输入口令"
+                onChange={(e) => {
+                  setAutomation(e.target.value);
+                }}
+              />
+            }
+          </Form.Item>
+        </Form>
+      </div>
+    </Modal>
+  );
+};
+
+const DispatchModa = (props) => {
+  const { open, onCancel } = props;
+  return (
+    <Modal title="工单派遣" open={open} onCancel={onCancel}>
+      派单
+    </Modal>
+  );
+};

+ 5 - 3
src/pages/TaskManage/components/SubTitle.tsx

@@ -4,6 +4,7 @@ interface IPropsType {
   title: string;
   statusStr?: string;
   showStatus?: boolean;
+  titleFontSize?: number | string;
   radius?: boolean;
 }
 
@@ -11,6 +12,7 @@ const SubTitle: React.FC<IPropsType> = ({
   title,
   statusStr = '',
   showStatus = false,
+  titleFontSize = '30',
   radius = false,
 }) => {
   const img = require('@/assets/TaskManage/yiwancheng.png');
@@ -25,8 +27,8 @@ const SubTitle: React.FC<IPropsType> = ({
         paddingLeft: '20px',
         paddingRight: '10px',
         backgroundColor: '#d9e7f9',
-        fontSize: '30px',
-        height: '80px',
+        fontSize: String(titleFontSize) + 'px',
+        height: String(Number(titleFontSize) + 40) + 'px',
         borderRadius: radius ? '8px 8px 0 0 ' : 'unset',
       }}
     >
@@ -42,7 +44,7 @@ const SubTitle: React.FC<IPropsType> = ({
             style={{
               position: 'relative',
               left: '10px',
-              bottom:"10px"
+              bottom: '10px',
             }}
           />
         </div>

+ 11 - 9
src/pages/TaskManage/index.less

@@ -1,5 +1,7 @@
 .taskList {
   border: none;
+  max-height: calc(100vh - 140px);
+  overflow-y: scroll;
 
   .listItem {
     margin: 20px 20px 20px 0;
@@ -26,11 +28,11 @@
 
 .ant-select-clear {
   opacity: 1 !important;
-  margin-top: -12px!important;
-  width: 24px!important;
-  height: 24px!important;
-  font-size: 24px!important;
-  color: black!important;
+  margin-top: -12px !important;
+  width: 24px !important;
+  height: 24px !important;
+  font-size: 24px !important;
+  color: black !important;
 }
 
 .antdSelect .ant-select-selection-item,
@@ -40,12 +42,12 @@
   color: black;
   margin-right: 10px;
 }
-.ant-select-item-option{
-  padding: 8px!important;
+.ant-select-item-option {
+  padding: 8px !important;
 }
 .ant-select-arrow {
-  font-size: 24px!important;
-  color: black!important;
+  font-size: 24px !important;
+  color: black !important;
 }
 
 .fontS28 {

+ 73 - 27
src/pages/TaskManage/index.tsx

@@ -1,6 +1,5 @@
 import PageContent from '@/components/PageContent';
-import PageTitle from '@/components/PageTitle';
-import { MandateType } from '@/pages/TaskManage/constent';
+import TabsContent from '@/components/TabsContent';
 import styles from '@/pages/TaskManage/index.less';
 import { getMandateList } from '@/services/TaskManage';
 import { RightOutlined } from '@ant-design/icons';
@@ -9,6 +8,7 @@ import { List, Spin } from 'antd';
 import { BaseOptionType } from 'rc-select/es/Select';
 import { useEffect, useState } from 'react';
 import { useNavigate } from 'umi';
+import { MandateType, OrderType } from './constent';
 
 const TaskManage = () => {
   const { projectID } = useParams();
@@ -17,6 +17,7 @@ const TaskManage = () => {
 
   const [mandateCount, setMandateCount] = useState<number[]>([0, 0, 0]);
   const [loading, setLoading] = useState(false);
+  const [tab, setTab] = useState(localStorage.taskTab || '1');
 
   useEffect(() => {
     const requests = [];
@@ -53,8 +54,13 @@ const TaskManage = () => {
   const goTaskList = (item: number) => {
     navigate(`/task-manage/list?project_id=${project_id}&mandateType=${item}`);
   };
+  const goWorkOrderList = (item: number) => {
+    navigate(
+      `/task-manage/work-order/list?project_id=${project_id}&order_type=${item}`,
+    );
+  };
 
-  const makeList = (item: BaseOptionType, index: number) => {
+  const makeTaskList = (item: BaseOptionType, index: number) => {
     return (
       <List.Item
         className={styles.listItem}
@@ -74,33 +80,73 @@ const TaskManage = () => {
     );
   };
 
-  return (
-    <PageContent>
-      <PageTitle clo>任务管理</PageTitle>
-      <Spin spinning={loading}>
-        <List
-          className={styles.taskList}
-          bordered
-          itemLayout="horizontal"
-          dataSource={MandateType}
-          renderItem={makeList}
-          pagination={false}
+  const makeWorkOrderList = (item: BaseOptionType, index: number) => {
+    return (
+      <List.Item
+        className={styles.listItem}
+        onClick={() => {
+          goWorkOrderList(item.value);
+        }}
+      >
+        <List.Item.Meta
+          title={<span className={styles.fontS28}>{item.label}</span>}
         />
-      </Spin>
+        {/* <div className={styles.itemCount}>
+          <div className={styles.countNumber}>{mandateCount[index]}</div>
+          <div className={styles.fontS22}>任务数量</div>
+        </div> */}
+        <RightOutlined />
+      </List.Item>
+    );
+  };
+
+  const onTabChange = (key: string) => {
+    setTab(key);
+    localStorage.setItem('taskTab', key);
+  };
+
+  return (
+    <PageContent tabs>
+      <TabsContent
+        defaultActiveKey={tab}
+        onChange={onTabChange}
+        items={[
+          {
+            label: `任务管理`,
+            key: '1',
+            children: (
+              <Spin spinning={loading}>
+                <List
+                  className={styles.taskList}
+                  bordered
+                  itemLayout="horizontal"
+                  dataSource={MandateType}
+                  renderItem={makeTaskList}
+                  pagination={false}
+                />
+              </Spin>
+            ),
+          },
+          {
+            label: `工单管理`,
+            key: '2',
+            children: (
+              <Spin spinning={loading}>
+                <List
+                  className={styles.taskList}
+                  bordered
+                  itemLayout="horizontal"
+                  dataSource={OrderType}
+                  renderItem={makeWorkOrderList}
+                  pagination={false}
+                />
+              </Spin>
+            ),
+          },
+        ]}
+      />
     </PageContent>
   );
 };
 
 export default TaskManage;
-
-// export default connect(
-//   ({
-//     mandate,
-//     loading,
-//   }: any): { mandateList: IMandateType[]; loading: boolean } => {
-//     return {
-//       mandateList: mandate.mandateList,
-//       loading: loading.models['mandate'],
-//     };
-//   },
-// )(TaskManage);

+ 12 - 0
src/services/TaskManage.js

@@ -106,6 +106,7 @@ export async function getRepairRecordList(data) {
 
 /**
  * 获取工艺工单列表
+ * @param {object} data
  * @param data.project_id
  * @param data.work_id 工单id
  * @returns {Promise<*>}
@@ -127,3 +128,14 @@ export async function queryReagentDetail(data) {
   const res = await request(`/api/v1/reagent/detail?${stringify(data)}`);
   return res.data;
 }
+
+/**
+ * 获取工单审批流程
+ * @param {object} params
+ * @param {number} params.work_type 工单类型:1-工艺工单,2-维修工单,3-保养工单,4-巡检,5-加药,6-备品备件,7-盘点
+ * @param {number} params.work_id 工单id
+ */
+export async function getWorkOrderFlow(params) {
+  const res = await request(`/api/v1/work_order/flow?${stringify(params)}`);
+  return res.data;
+}