huang_an 2 лет назад
Родитель
Сommit
4d09db67e3

+ 33 - 0
src/api/tickets/index.js

@@ -0,0 +1,33 @@
+import request from '@/utils/request';
+
+// 工单分页
+export async function getWorkOrderPage(data) {
+  const res = await request.get('/eam/workordermaintenance/page', {
+    params: data
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 获取规则名称下拉
+export async function getRule(data) {
+  let par = new URLSearchParams(data);
+  const res = await request.get(`/main/ruleinfo/page?` + par, {});
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+// 工单详情
+export async function getWordOrderDetail(workOrderId) {
+  const res = await request.get(
+    `/eam/workordermaintenance/maintenanceDetail/${workOrderId}`
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 97 - 0
src/components/Pagination/index.vue

@@ -0,0 +1,97 @@
+<template>
+  <div :class="{ hidden: hidden }" class="pagination-container">
+    <el-pagination
+      :background="background"
+      :current-page.sync="currentPage"
+      :page-size.sync="pageSize"
+      :layout="layout"
+      :page-sizes="pageSizes"
+      :total="total"
+      v-bind="$attrs"
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'Pagination',
+    props: {
+      total: {
+        required: true,
+        type: Number
+      },
+      current: {
+        type: Number,
+        default: 1
+      },
+      size: {
+        type: Number,
+        default: 10
+      },
+      pageSizes: {
+        type: Array,
+        default() {
+          return [10, 20, 30, 50];
+        }
+      },
+      layout: {
+        type: String,
+        default: 'total, sizes, prev, pager, next, jumper'
+      },
+      background: {
+        type: Boolean,
+        default: true
+      },
+      autoScroll: {
+        type: Boolean,
+        default: true
+      },
+      hidden: {
+        type: Boolean,
+        default: false
+      }
+    },
+    computed: {
+      currentPage: {
+        get() {
+          return this.current;
+        },
+        set(val) {
+          this.$emit('update:current', val);
+        }
+      },
+      pageSize: {
+        get() {
+          return this.size;
+        },
+        set(val) {
+          this.$emit('update:size', val);
+        }
+      }
+    },
+    methods: {
+      handleSizeChange(val) {
+        this.$emit('pagination', { current: this.currentPage, size: val });
+      },
+      handleCurrentChange(val) {
+        this.$emit('pagination', { current: val, size: this.pageSize });
+      }
+    }
+  };
+</script>
+
+<style scoped>
+  .pagination-container {
+    background: #fff;
+    /*padding: 5px 5px;*/
+  }
+  .el-pagination {
+    text-align: left !important;
+  }
+
+  .pagination-container.hidden {
+    display: none;
+  }
+</style>

+ 7 - 0
src/utils/dict/tickets.js

@@ -0,0 +1,7 @@
+// 工单状态
+export const ticketStatus = [
+  { id: 0, label: '待接收' },
+  { id: 1, label: '已接收' },
+  { id: 2, label: '执行中' },
+  { id: 3, label: '已完成' }
+];

+ 757 - 0
src/views/bpm/tickets/delivery/detail.vue

@@ -0,0 +1,757 @@
+<template>
+  <div class="page" v-loading="pageLoading">
+    <el-form label-width="130px">
+      <div class="content-detail" v-show="num == 1">
+        <div class="basic-details">
+          <HeaderTitle title="基本信息" size="16px">
+            <el-button
+              type="primary"
+              @click="
+                $router.push({
+                  path: '/tickets',
+                  query: { title: '量具送检工单' }
+                })
+              "
+              >返回</el-button
+            >
+          </HeaderTitle>
+          <el-row>
+            <el-col :span="12">
+              <el-col :span="12">
+                <el-form-item label="计划单号">
+                  <span> {{ infoData.planCode }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="来源计划配置单号">
+                  <span> {{ infoData.planConfigCode }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="名称">
+                  <span> {{ infoData.planName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="部门">
+                  <span>
+                    {{ infoData.executeGroupName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="人员">
+                  <span>
+                    {{ infoData.executeUserName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="计划完成时长">
+                  <span v-if="infoData.duration >= 0"
+                    >{{ infoData.duration }}分钟</span
+                  >
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="周期">
+                  <span v-if="infoData.ruleInfo">
+                    {{ infoData.ruleInfo.cycleValue
+                    }}{{
+                      getDictValue('巡点检周期', infoData.ruleInfo.cycleType)
+                    }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="设备分类">
+                  <span> {{ infoData.categoryLevelName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="规则名称">
+                  <span>
+                    {{ infoData.ruleName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建部门">
+                  <span> {{ infoData.createGroupName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建人">
+                  <span> {{ infoData.createUserName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建时间">
+                  <span> {{ infoData.createTime }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="24">
+                <el-form-item label="备注">
+                  <span> {{ infoData.remark }} </span>
+                </el-form-item>
+              </el-col>
+            </el-col>
+            <el-col :span="12">
+              <img :src="data.imageUrl" alt="" />
+            </el-col>
+          </el-row>
+        </div>
+
+        <!-- 巡点检、执行信息 -->
+        <!-- <div class="execute_info">
+          <div class="execute_info_title">
+            <span>执行信息</span>
+            <span
+              >执行人:{{ data.executeUserName }}
+              <i style="margin: 0 18px"></i> 执行时间:{{
+                data.acceptTime
+              }}</span
+            >
+          </div>
+          <HeaderTitle title="执行信息" size="16px"></HeaderTitle>
+          <el-row class="execute_row">
+            <el-col :span="8" class="column">
+              <span class="label">确认结果:</span>
+              <span class="value">{{
+                infoData.status ? infoData.status.descp : ''
+              }}</span>
+            </el-col>
+            <el-col :span="8" class="column">
+              <span class="label">实际开始时间:</span>
+              <span class="value">{{ infoData.acceptTime }}</span>
+            </el-col>
+            <el-col :span="8" class="column">
+              <span class="label">实际结束时间:</span>
+              <span class="value">{{ infoData.finishTime }}</span>
+            </el-col>
+            <el-col :span="24" class="column">
+              <span class="label">超期原因:</span>
+              <span class="value">{{ infoData.timeoutCause }}</span>
+            </el-col>
+          </el-row>
+        </div> -->
+
+        <!-- 巡点检、保养设备 -->
+        <div class="maintain_equipment_info">
+          <HeaderTitle title="巡点检设备" size="16px"></HeaderTitle>
+          <div class="maintain_equipment_info_content">
+            <div
+              class="equipment_item"
+              v-for="item in infoData.deviceList"
+              :key="item.id"
+            >
+              <div class="equipment_info" v-if="item.substance">
+                <div class="item_info">
+                  <span class="item_label">设备编码</span>
+                  <span class="item_value">{{ item.substance.code }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备名称</span>
+                  <span class="item_value">{{ item.substance.name }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备型号</span>
+                  <span class="item_value">{{ item.substance.model }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备位置</span>
+                  <span class="item_value">{{
+                    item.substance.positionNames
+                  }}</span>
+                </div>
+              </div>
+              <p>操作事项</p>
+              <div class="ruleMatters_box">
+                <el-table :data="item.workItems" border>
+                  <el-table-column label="序号" width="50">
+                    <template slot-scope="scope">
+                      <span>{{ scope.$index + 1 }}</span>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="事项" prop="name" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.name }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="内容" prop="content" width="300">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.content }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="操作指导" prop="operationGuide">
+                    <template slot-scope="scope">
+                      <div class="operationGuide_box">
+                        <div class="left_content">
+                          <template v-if="scope.row.operationGuide">
+                            <div
+                              v-for="(item, index) in scope.row.operationGuide
+                                .toolList"
+                              :key="item.id"
+                              >{{ index + 1 }}.{{ item.name }}</div
+                            >
+                          </template>
+                        </div>
+                        <div class="line"></div>
+                        <div class="right_content">
+                          <template v-if="scope.row.operationGuide">
+                            <div
+                              v-for="(item, index) in scope.row.operationGuide
+                                .procedureList"
+                              :key="item.id"
+                              >{{ index + 1 }}.{{ item.content }}</div
+                            >
+                          </template>
+                        </div>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="标准" prop="norm" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.norm }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="状态" prop="status" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ options[scope.row.status] }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="结果" prop="result" width="200">
+                  </el-table-column>
+                </el-table>
+              </div>
+            </div>
+            <!-- <div class="btnbox" v-if="$route.query.isshow">
+              <el-button class="confirm-btn" type="danger" plain @click="reject"
+                >驳回</el-button
+              >
+              <el-button class="confirm-btn" type="success" plain @click="pass"
+                >通过</el-button
+              >
+              <el-button class="cancel-btn">关闭</el-button>
+            </div> -->
+            <!-- <div class="textbox" v-if="showtext">
+              <el-input
+                type="textarea"
+                placeholder="请输入驳回原因"
+                v-model="cause"
+                maxlength="30"
+                rows="5"
+                show-word-limit
+              >
+              </el-input>
+              <div class="textbtnbox">
+                <el-button size="small" round @click="cancelreject"
+                  >取消</el-button
+                >
+                <el-button size="small" round @click="surereject"
+                  >提交</el-button
+                >
+              </div>
+            </div> -->
+          </div>
+        </div>
+
+        <!-- 巡点检、缺陷设备报修记录 -->
+        <!-- <div class="repair_notes">
+          <HeaderTitle title="缺陷设备报修记录" size="16px"></HeaderTitle>
+          <div class="repair_notes_equipment_item">
+            <el-row class="equipment_item_tilte">
+              <el-col :span="8">
+                <span class="label">设备名称:</span>
+                <span>{{ repairNotes.equiName }}</span>
+              </el-col>
+              <el-col :span="8">
+                <span class="label">规格型号:</span>
+                <span>{{ repairNotes.equiModel }}</span>
+              </el-col>
+              <el-col :span="8">
+                <span class="label">设备编码:</span>
+                <span>{{ repairNotes.equiCode }}</span>
+              </el-col>
+            </el-row>
+            <div class="main_info">
+              <div>
+                <span>报修记录编号:</span>
+                <span>{{ repairNotes.repairsCode }}</span>
+              </div>
+              <div>
+                <span>故障描述:</span>
+                <span>{{ repairNotes.repairsDescription }}</span>
+              </div>
+              <div>
+                <span>处理进度:</span>
+                <span>{{ statusObj[repairNotes.status] }}</span>
+              </div>
+            </div>
+          </div>
+        </div> -->
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+  import dictMixins from '@/mixins/dictMixins';
+  import { getWordOrderDetail } from '@/api/tickets';
+  export default {
+    mixins: [dictMixins],
+    data() {
+      return {
+        options: {
+          0: '正常',
+          '-1': '缺陷'
+        },
+        num: 1,
+        infoData: {},
+        dialogVisible: false,
+        data: {},
+        repairNotes: {},
+        pageLoading: false,
+        typeValue: null,
+        contract_type: [],
+        status: [
+          {
+            value: true,
+            label: '失效'
+          },
+          {
+            value: false,
+            label: '生效'
+          }
+        ],
+        ruleItem: [],
+        cause: '',
+        showtext: false,
+        from: null
+      };
+    },
+    created() {
+      this.requestDict('巡点检周期');
+      this.getInfo();
+    },
+    methods: {
+      // getStatus: useDictLabel(patrolMatterStatus),
+      delete() {},
+      // 点击切换事件
+      tab(index) {
+        this.num = index;
+      },
+      goBack() {
+        window.sessionStorage.setItem('patrolTabType', 'work');
+        if (this.form) {
+          this.$router.push({
+            path: '/workspace/workOrder',
+            query: { activeName: 'polling' }
+          });
+        } else {
+          this.$router.go(-1);
+        }
+      },
+      // 表格数据
+      getInfo() {
+        this.pageLoading = true;
+        getWordOrderDetail(this.$route.query.id)
+          .then((data) => {
+            this.infoData = data;
+            // if (res.success) {
+            //   this.data = res.data;
+            //   this.data.planEquiList = this.data.planEquiList.filter(
+            //     (item) => item.itemList && item.itemList.length > 0
+            //   );
+            //   // 获取 缺陷设备报修记录
+            //   const repairId = res.data.planEquiList[0].repairId;
+            //   if (repairId) {
+            //     this.getRepairNotes(repairId);
+            //   }
+            // }
+            this.pageLoading = false;
+          })
+          .catch(() => {
+            this.pageLoading = false;
+          });
+      },
+      // 获取 缺陷设备报修记录
+      async getRepairNotes(repairId) {
+        const res = await repair.getInfo(repairId);
+        if (res?.success) {
+          console.log('缺陷设备报修记录:', res.data);
+          this.repairNotes = res.data;
+        }
+      },
+      //通过按钮事件
+      pass() {
+        let params = {
+          planId: this.$route.query.id,
+          checked: 2,
+          myHandleId: this.$route.query.dbid,
+          cause: this.cause,
+          type: 2, //1维修;2保养,巡点检
+          handleType: 0 //办理类型(0 审批 1 验收)
+        };
+        sendAudit(params).then((res) => {
+          if (res.success) {
+            this.$message.success('审批通过!');
+            this.$router.back();
+          }
+        });
+      },
+      //驳回按钮事件
+      reject() {
+        this.showtext = true;
+      },
+      cancelreject() {
+        this.showtext = false;
+        this.cause = '';
+      },
+      surereject() {
+        if (!this.cause) {
+          this.$message.info('请填写驳回原因!');
+        } else {
+          let params = {
+            id: this.$route.query.id,
+            checked: 0,
+            myHandleId: this.$route.query.dbid,
+            cause: this.cause,
+            type: 2, //1维修;2保养,巡点检
+            handleType: 0 //办理类型(0 审批 1 验收)
+          };
+          sendAudit(params).then((res) => {
+            if (res.success) {
+              this.$message.error('审批驳回!');
+              this.$router.back();
+            }
+          });
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  // @import '@/assets/css/oaa.scss';
+  .page {
+    padding: 10px;
+  }
+  .page-title {
+    background: #fff;
+    font-size: 18px;
+    padding: 6px 20px;
+    font-weight: 500;
+    .page-title-div {
+      margin: 5px 0;
+      height: 30px;
+      line-height: 30px;
+      border-bottom: 1px solid #eaeefb;
+      .title-div-no {
+        margin-left: 10px;
+        font-weight: 400;
+        color: #909090;
+        font-size: 14px;
+      }
+    }
+  }
+  .page-data {
+    padding-top: 10px;
+  }
+  .content-detail {
+    background: #fff;
+    padding: 20px;
+  }
+  .flows {
+    .flow-left {
+      width: 156px;
+      height: 70px;
+      border: 1px dashed #ccc;
+      padding: 10px;
+    }
+    .row {
+      margin-top: 13px;
+    }
+  }
+  .basic-details-title {
+    margin-bottom: 12px;
+    margin-top: 20px;
+    border-bottom: 1px solid #1890ff;
+    padding-bottom: 8px;
+    display: flex;
+    justify-content: space-between;
+  }
+  .basic-details-title .border-span {
+    height: 18px;
+    font-size: 16px;
+    border-left: 4px solid #1890ff;
+    padding-left: 8px;
+
+    font-weight: 500;
+  }
+  .heade-right {
+    // float: right;
+    .heade-right-content {
+      margin-right: 12px;
+      font-size: 14px;
+      display: inline-block;
+      .content-key {
+        color: #3e3e3e;
+        margin-right: 12px;
+        font-weight: 500;
+      }
+      .content-value {
+        color: #000;
+      }
+    }
+  }
+  .list-title {
+    font-size: 14px;
+    color: #3e3e3e;
+    margin: 10px 0px;
+  }
+  .goods {
+    background: #a30014;
+    border: 1px solid #a30014;
+  }
+  .details-title {
+    display: inline-block;
+    color: #6e6e6e;
+    font-size: 14px;
+    font-weight: bold;
+    margin-right: 13px;
+    width: 70px;
+    text-align: right;
+  }
+  .details-con {
+    color: #3e3e3e;
+    font-size: 14px;
+  }
+  .detailed-tab {
+    margin-left: 10px;
+    margin-top: 10px;
+  }
+  ::v-deep .el-form-item--medium .el-form-item__label {
+    color: #6e6e6e;
+    font-size: 14px;
+    font-weight: bold;
+  }
+  .warehouse {
+    display: block;
+    border-bottom: 1px solid #eaeefb;
+    padding: 10px 0;
+  }
+  .box-card {
+    .store-box {
+      width: 80%;
+      .store-box-span {
+        display: inline-block;
+        font-size: 14px;
+        height: 50px;
+        width: 50px;
+        text-align: center;
+        line-height: 50px;
+        color: #fff;
+        margin: 2px;
+      }
+    }
+  }
+  .vacant {
+    background: #3196fb;
+  }
+  .inUse {
+    background: #157a2c;
+  }
+  .invalid {
+    background: #cccccc;
+  }
+  .full {
+    background: #cc3300;
+  }
+
+  .maintain_equipment_info {
+    .maintain_equipment_info_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      > span {
+        display: inline-block;
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .maintain_equipment_info_content {
+      padding: 0 30px;
+      .equipment_item {
+        border: 1px solid #ccc;
+        font-size: 14px;
+        padding: 15px;
+        margin-bottom: 30px;
+        .equipment_info {
+          display: flex;
+          flex-wrap: wrap;
+          border: 1px solid #ddd;
+          .item_info {
+            width: 33.33%;
+            height: 24px;
+            line-height: 24px;
+            display: flex;
+            .item_label {
+              width: 90px;
+              text-align: center;
+              background-color: #f2f2f2;
+              font-weight: 700;
+            }
+            .item_value {
+              border-bottom: 1px solid #f2f2f2;
+              flex: 1;
+              padding-left: 5px;
+            }
+            &:last-child {
+              width: 100%;
+              .item_value {
+                border: 0;
+              }
+            }
+          }
+        }
+        > p {
+          margin-top: 20px;
+          color: #797979;
+        }
+        .matter_info {
+          ::v-deep .el-table {
+            th.el-table__cell {
+              background-color: #f2f2f2;
+              padding: 0;
+            }
+            td.el-table__cell {
+              padding: 0;
+            }
+          }
+        }
+        .ruleMatters_box {
+          flex: 3;
+          height: 100%;
+          display: flex;
+          flex-direction: column;
+          .divider {
+            flex: 0 0 50px;
+            .title {
+              height: 35px;
+            }
+          }
+          .el-table {
+            overflow: auto;
+            .operationGuide_box {
+              width: 100%;
+              display: flex;
+              position: relative;
+              .left_content {
+                flex: 0 0 300px;
+                padding: 10px;
+                margin-right: 10px;
+                overflow-y: auto;
+              }
+              .line {
+                position: absolute;
+                top: -10px;
+                left: 300px;
+                bottom: -10px;
+                height: 110%;
+                width: 1px;
+                background-color: #ededed;
+              }
+              .right_content {
+                flex: 1;
+                padding: 10px;
+                overflow-y: auto;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  .execute_info {
+    margin: 30px 0;
+    .execute_info_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      display: flex;
+      justify-content: space-between;
+      > span:first-child {
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .execute_row {
+      padding: 0 30px;
+      .column {
+        display: flex;
+        font-size: 14px;
+        margin-bottom: 20px;
+        .label {
+          // width: 110px;
+          text-align: center;
+          font-weight: 700;
+        }
+      }
+    }
+  }
+  .repair_notes {
+    .repair_notes_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      > span {
+        display: inline-block;
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .repair_notes_equipment_item {
+      padding: 0 20px;
+      .equipment_item_tilte {
+        background-color: #f7f7f7;
+        height: 36px;
+        line-height: 36px;
+        .label {
+          font-weight: 700;
+        }
+      }
+      .main_info {
+        font-size: 14px;
+        margin-top: 15px;
+        > div {
+          margin-bottom: 10px;
+        }
+      }
+    }
+  }
+  .btnbox {
+    display: flex;
+    justify-content: center;
+  }
+  ::v-deep .el-button {
+    padding: 10px 20px;
+    margin-right: 10px;
+  }
+  .textbtnbox {
+    margin-top: 10px;
+    display: flex;
+    justify-content: center;
+  }
+</style>

+ 282 - 0
src/views/bpm/tickets/delivery/index.vue

@@ -0,0 +1,282 @@
+<!-- 巡点检工单 -->
+<template>
+  <div class="patrolInspection">
+    <div class="search">
+      <el-form label-width="120px">
+        <el-row>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="工单编号">
+              <el-input
+                v-model="searchForm.code"
+                placeholder="请输入"
+                size="small"
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="规则名称">
+              <el-select
+                v-model="searchForm.ruleId"
+                size="small"
+                clearable
+                style="width: 100%"
+                filterable
+              >
+                <el-option
+                  v-for="item in ruleNameList"
+                  :key="item.id"
+                  :value="item.id"
+                  :label="item.name"
+                ></el-option> </el-select></el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="状态">
+              <el-select
+                filterable
+                clearable
+                v-model="searchForm.orderStatus"
+                size="small"
+              >
+                <el-option
+                  v-for="item in ticketStatus"
+                  :key="item.id"
+                  :value="item.id"
+                  :label="item.label"
+                ></el-option>
+              </el-select> </el-form-item
+          ></el-col>
+          <el-col :md="8" :sm="8" :xs="8">
+            <el-form-item label="开始结束时间">
+              <el-date-picker
+                class="form-input"
+                size="small"
+                v-model="searchForm.date"
+                type="daterange"
+                range-separator="至"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期"
+                value-format="yyyy-MM-dd HH:mm:ss"
+                :default-time="['00:00:00', '23:59:59']"
+              >
+              </el-date-picker> </el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="16" :xs="16" style="text-align: right">
+            <el-button icon="el-icon-refresh-left" size="small" @click="rest"
+              >重置</el-button
+            >
+            <el-button
+              type="primary"
+              icon="el-icon-search"
+              size="small"
+              @click="search"
+              >搜索</el-button
+            ></el-col
+          >
+        </el-row>
+      </el-form>
+    </div>
+    <div class="table">
+      <el-table
+        :data="tableData"
+        border
+        height="99%"
+        tooltip-effect="dark"
+        :header-cell-style="{ background: '#F0F3F3', border: 'none' }"
+        @row-dblclick="openDetail"
+      >
+        <el-table-column
+          width="80px"
+          label="序号"
+          type="index"
+          :index="indexMethod"
+        >
+        </el-table-column>
+        <el-table-column prop="planCode" label="工单编号" />
+        <el-table-column prop="planName" label="计划单号" />
+        <el-table-column prop="planName" label="量具送检名称" />
+        <!-- <el-table-column prop="createTime" label="设备分类" /> -->
+        <el-table-column prop="ruleName" label="规则名称" />
+        <el-table-column prop="createUserName" label="创建人" />
+        <el-table-column prop="createTime" label="创建时间" />
+        <el-table-column prop="acceptTime" label="开始时间" />
+        <el-table-column prop="finishTime" label="结束时间" />
+        <el-table-column prop="planFinishTime" label="计划完成时间" />
+        <el-table-column prop="orderStatus" label="状态">
+          <template slot-scope="{ row }">
+            {{
+              ticketStatus.filter((item) => item.id == row.orderStatus)[0].label
+            }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="practicalTime" label="实际工时">
+          <template slot-scope="{ row }">
+            {{ time_interval(row.acceptTime, row.finishTime) }}
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="table-footer">
+      <el-pagination
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+        :page-sizes="[15, 30, 50, 100, 500]"
+        :page-size.sync="pages.size"
+        :current-page.sync="pages.page"
+        @current-change="handleCurrentChange"
+        @size-change="handleSizeChange"
+      >
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+  import { ticketStatus } from '@/utils/dict/tickets';
+  import { getWorkOrderPage, getRule } from '@/api/tickets';
+  import pagenation from '@/components/Pagination';
+  export default {
+    components: { pagenation },
+    data() {
+      return {
+        ruleNameList: [],
+        tableData: [],
+        statusOptions: [],
+        ticketStatus,
+        searchForm: {
+          code: '',
+          ruleId: '',
+          date: '',
+          startTime: '',
+          endTime: '',
+          type: 5
+        },
+        pages: {
+          page: 1,
+          size: 15
+        },
+        total: 0
+      };
+    },
+    created() {
+      this.getRuleNameList();
+      this.getData();
+    },
+    methods: {
+      openDetail({ id }) {
+        this.$router.push({
+          path: '/tickets/delivery/detail',
+          query: {
+            id
+          }
+        });
+      },
+      // 获取规则名列表(设备保养)
+      async getRuleNameList() {
+        const res = await getRule({
+          status: 1,
+          type: 5,
+          pageNum: 1,
+          size: -1
+        });
+        if (res.list) {
+          this.ruleNameList = res.list || [];
+        }
+      },
+      // 实现分页序号连贯
+      indexMethod(index) {
+        index = index + 1 + (this.pages.page - 1) * this.pages.size;
+        return index;
+      },
+      getData() {
+        let userId = localStorage.getItem('userId');
+        console.log(userId);
+        let par = {
+          ...this.pages,
+          ...this.searchForm,
+          executeUserId: userId
+        };
+        if (this.searchForm.date) {
+          par.startTime = this.searchForm.date[0];
+          par.endTime = this.searchForm.date[1];
+        }
+        delete par.date;
+        getWorkOrderPage(par).then((res) => {
+          this.tableData = res.list;
+          this.total = res.total;
+        });
+      },
+      search() {
+        this.pages.page = 1;
+        this.getData();
+      },
+      rest() {
+        this.searchForm = {
+          code: '',
+          ruleId: '',
+          date: '',
+          startTime: '',
+          endTime: '',
+          type: 5
+        };
+        this.pages.page = 1;
+        this.getData();
+      },
+      handleCurrentChange() {
+        this.getData();
+      },
+      handleSizeChange() {
+        this.pages.page = 1;
+        this.getData();
+      },
+      // 计算实际工时
+      time_interval(dt1, dt2) {
+        if (!dt1 || !dt2) {
+          return '';
+        }
+        if (typeof dt1 == 'string') {
+          dt1 = new Date(dt1.replace(/-/, '/'));
+          dt2 = new Date(dt2.replace(/-/, '/'));
+        }
+        var res = dt2 - dt1;
+        if (isNaN(res)) throw Error('invalid dates arguments');
+        let re = res / (1000 * 60 * 60);
+
+        var h = parseInt(re);
+        var m = parseInt((re - h) * 60);
+        let result = '';
+        if (h) {
+          result += `${h} 小时`;
+        }
+        if (m) {
+          result += `${m} 分钟`;
+        }
+        return result;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .patrolInspection {
+    height: 100%;
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    .search {
+      flex: 0 0 50px;
+    }
+    .table {
+      flex: 1;
+      .el-table {
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+      }
+    }
+    .table-footer {
+      flex: 0 0 30px;
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+</style>

+ 95 - 0
src/views/bpm/tickets/index.vue

@@ -0,0 +1,95 @@
+<template>
+  <div class="tickets_index">
+    <el-card :body-style="{ padding: 10 }">
+      <!-- tab切换 -->
+      <div class="switch">
+        <div class="switch_left">
+          <ul>
+            <li
+              v-for="item in tabOptions"
+              :key="item.key"
+              :class="{ active: activeComp == item.key }"
+              @click="activeComp = item.key"
+            >
+              {{ item.name }}
+            </li>
+          </ul>
+        </div>
+      </div>
+      <div class="content-wrapper" style="margin-left: 10px">
+        <component :is="activeComp"></component>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+  import patrolInspection from './patrolInspection';
+  import maintenance from './maintenance';
+  import delivery from './delivery';
+  export default {
+    components: {
+      patrolInspection,
+      maintenance,
+      delivery
+    },
+    data() {
+      return {
+        activeComp: 'patrolInspection',
+        tabOptions: [
+          { key: 'patrolInspection', name: '巡点检工单' },
+          { key: 'maintenance', name: '保养工单' },
+          { key: 'delivery', name: '量具送检工单' }
+          // { key: 'repair', name: '计划性维修工单' },
+          // { key: 'malfunction', name: '盘点工单' }
+        ]
+      };
+    },
+    mounted() {
+      switch (this.$route.query.title) {
+        case '巡点检工单':
+          this.activeComp = 'patrolInspection';
+          break;
+        case '保养工单':
+          this.activeComp = 'maintenance';
+          break;
+        case '量具送检工单':
+          this.activeComp = 'delivery';
+          break;
+        default:
+          break;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .tickets_index {
+    widows: 100%;
+    height: 100%;
+    ::v-deep .el-card {
+      height: 100%;
+      width: 100%;
+      .el-card__body {
+        height: 100%;
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+        .switch {
+          flex: 0 0 50px;
+        }
+        .content-wrapper {
+          flex: 1;
+        }
+      }
+    }
+  }
+  .content-wrapper {
+    background-color: #fff;
+  }
+  .page-title {
+    background: #fff;
+    padding: 26px 10px 15px;
+    border-bottom: 1px solid #eaeefb;
+  }
+</style>

+ 757 - 0
src/views/bpm/tickets/maintenance/detail.vue

@@ -0,0 +1,757 @@
+<template>
+  <div class="page" v-loading="pageLoading">
+    <el-form label-width="130px">
+      <div class="content-detail" v-show="num == 1">
+        <div class="basic-details">
+          <HeaderTitle title="基本信息" size="16px">
+            <el-button
+              type="primary"
+              @click="
+                $router.push({
+                  path: '/tickets',
+                  query: { title: '保养工单' }
+                })
+              "
+              >返回</el-button
+            >
+          </HeaderTitle>
+          <el-row>
+            <el-col :span="12">
+              <el-col :span="12">
+                <el-form-item label="计划单号">
+                  <span> {{ infoData.planCode }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="来源计划配置单号">
+                  <span> {{ infoData.planConfigCode }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="名称">
+                  <span> {{ infoData.planName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="部门">
+                  <span>
+                    {{ infoData.executeGroupName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="人员">
+                  <span>
+                    {{ infoData.executeUserName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="计划完成时长">
+                  <span v-if="infoData.duration >= 0"
+                    >{{ infoData.duration }}分钟</span
+                  >
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="周期">
+                  <span v-if="infoData.ruleInfo">
+                    {{ infoData.ruleInfo.cycleValue
+                    }}{{
+                      getDictValue('巡点检周期', infoData.ruleInfo.cycleType)
+                    }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="设备分类">
+                  <span> {{ infoData.categoryLevelName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="规则名称">
+                  <span>
+                    {{ infoData.ruleName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建部门">
+                  <span> {{ infoData.createGroupName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建人">
+                  <span> {{ infoData.createUserName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建时间">
+                  <span> {{ infoData.createTime }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="24">
+                <el-form-item label="备注">
+                  <span> {{ infoData.remark }} </span>
+                </el-form-item>
+              </el-col>
+            </el-col>
+            <el-col :span="12">
+              <img :src="data.imageUrl" alt="" />
+            </el-col>
+          </el-row>
+        </div>
+
+        <!-- 巡点检、执行信息 -->
+        <!-- <div class="execute_info">
+          <div class="execute_info_title">
+            <span>执行信息</span>
+            <span
+              >执行人:{{ data.executeUserName }}
+              <i style="margin: 0 18px"></i> 执行时间:{{
+                data.acceptTime
+              }}</span
+            >
+          </div>
+          <HeaderTitle title="执行信息" size="16px"></HeaderTitle>
+          <el-row class="execute_row">
+            <el-col :span="8" class="column">
+              <span class="label">确认结果:</span>
+              <span class="value">{{
+                infoData.status ? infoData.status.descp : ''
+              }}</span>
+            </el-col>
+            <el-col :span="8" class="column">
+              <span class="label">实际开始时间:</span>
+              <span class="value">{{ infoData.acceptTime }}</span>
+            </el-col>
+            <el-col :span="8" class="column">
+              <span class="label">实际结束时间:</span>
+              <span class="value">{{ infoData.finishTime }}</span>
+            </el-col>
+            <el-col :span="24" class="column">
+              <span class="label">超期原因:</span>
+              <span class="value">{{ infoData.timeoutCause }}</span>
+            </el-col>
+          </el-row>
+        </div> -->
+
+        <!-- 巡点检、保养设备 -->
+        <div class="maintain_equipment_info">
+          <HeaderTitle title="巡点检设备" size="16px"></HeaderTitle>
+          <div class="maintain_equipment_info_content">
+            <div
+              class="equipment_item"
+              v-for="item in infoData.deviceList"
+              :key="item.id"
+            >
+              <div class="equipment_info" v-if="item.substance">
+                <div class="item_info">
+                  <span class="item_label">设备编码</span>
+                  <span class="item_value">{{ item.substance.code }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备名称</span>
+                  <span class="item_value">{{ item.substance.name }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备型号</span>
+                  <span class="item_value">{{ item.substance.model }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备位置</span>
+                  <span class="item_value">{{
+                    item.substance.positionNames
+                  }}</span>
+                </div>
+              </div>
+              <p>操作事项</p>
+              <div class="ruleMatters_box">
+                <el-table :data="item.workItems" border>
+                  <el-table-column label="序号" width="50">
+                    <template slot-scope="scope">
+                      <span>{{ scope.$index + 1 }}</span>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="事项" prop="name" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.name }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="内容" prop="content" width="300">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.content }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="操作指导" prop="operationGuide">
+                    <template slot-scope="scope">
+                      <div class="operationGuide_box">
+                        <div class="left_content">
+                          <template v-if="scope.row.operationGuide">
+                            <div
+                              v-for="(item, index) in scope.row.operationGuide
+                                .toolList"
+                              :key="item.id"
+                              >{{ index + 1 }}.{{ item.name }}</div
+                            >
+                          </template>
+                        </div>
+                        <div class="line"></div>
+                        <div class="right_content">
+                          <template v-if="scope.row.operationGuide">
+                            <div
+                              v-for="(item, index) in scope.row.operationGuide
+                                .procedureList"
+                              :key="item.id"
+                              >{{ index + 1 }}.{{ item.content }}</div
+                            >
+                          </template>
+                        </div>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="标准" prop="norm" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.norm }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="状态" prop="status" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ options[scope.row.status] }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="结果" prop="result" width="200">
+                  </el-table-column>
+                </el-table>
+              </div>
+            </div>
+            <!-- <div class="btnbox" v-if="$route.query.isshow">
+              <el-button class="confirm-btn" type="danger" plain @click="reject"
+                >驳回</el-button
+              >
+              <el-button class="confirm-btn" type="success" plain @click="pass"
+                >通过</el-button
+              >
+              <el-button class="cancel-btn">关闭</el-button>
+            </div> -->
+            <!-- <div class="textbox" v-if="showtext">
+              <el-input
+                type="textarea"
+                placeholder="请输入驳回原因"
+                v-model="cause"
+                maxlength="30"
+                rows="5"
+                show-word-limit
+              >
+              </el-input>
+              <div class="textbtnbox">
+                <el-button size="small" round @click="cancelreject"
+                  >取消</el-button
+                >
+                <el-button size="small" round @click="surereject"
+                  >提交</el-button
+                >
+              </div>
+            </div> -->
+          </div>
+        </div>
+
+        <!-- 巡点检、缺陷设备报修记录 -->
+        <!-- <div class="repair_notes">
+          <HeaderTitle title="缺陷设备报修记录" size="16px"></HeaderTitle>
+          <div class="repair_notes_equipment_item">
+            <el-row class="equipment_item_tilte">
+              <el-col :span="8">
+                <span class="label">设备名称:</span>
+                <span>{{ repairNotes.equiName }}</span>
+              </el-col>
+              <el-col :span="8">
+                <span class="label">规格型号:</span>
+                <span>{{ repairNotes.equiModel }}</span>
+              </el-col>
+              <el-col :span="8">
+                <span class="label">设备编码:</span>
+                <span>{{ repairNotes.equiCode }}</span>
+              </el-col>
+            </el-row>
+            <div class="main_info">
+              <div>
+                <span>报修记录编号:</span>
+                <span>{{ repairNotes.repairsCode }}</span>
+              </div>
+              <div>
+                <span>故障描述:</span>
+                <span>{{ repairNotes.repairsDescription }}</span>
+              </div>
+              <div>
+                <span>处理进度:</span>
+                <span>{{ statusObj[repairNotes.status] }}</span>
+              </div>
+            </div>
+          </div>
+        </div> -->
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+  import dictMixins from '@/mixins/dictMixins';
+  import { getWordOrderDetail } from '@/api/tickets';
+  export default {
+    mixins: [dictMixins],
+    data() {
+      return {
+        options: {
+          0: '正常',
+          '-1': '缺陷'
+        },
+        num: 1,
+        infoData: {},
+        dialogVisible: false,
+        data: {},
+        repairNotes: {},
+        pageLoading: false,
+        typeValue: null,
+        contract_type: [],
+        status: [
+          {
+            value: true,
+            label: '失效'
+          },
+          {
+            value: false,
+            label: '生效'
+          }
+        ],
+        ruleItem: [],
+        cause: '',
+        showtext: false,
+        from: null
+      };
+    },
+    created() {
+      this.requestDict('巡点检周期');
+      this.getInfo();
+    },
+    methods: {
+      // getStatus: useDictLabel(patrolMatterStatus),
+      delete() {},
+      // 点击切换事件
+      tab(index) {
+        this.num = index;
+      },
+      goBack() {
+        window.sessionStorage.setItem('patrolTabType', 'work');
+        if (this.form) {
+          this.$router.push({
+            path: '/workspace/workOrder',
+            query: { activeName: 'polling' }
+          });
+        } else {
+          this.$router.go(-1);
+        }
+      },
+      // 表格数据
+      getInfo() {
+        this.pageLoading = true;
+        getWordOrderDetail(this.$route.query.id)
+          .then((data) => {
+            this.infoData = data;
+            // if (res.success) {
+            //   this.data = res.data;
+            //   this.data.planEquiList = this.data.planEquiList.filter(
+            //     (item) => item.itemList && item.itemList.length > 0
+            //   );
+            //   // 获取 缺陷设备报修记录
+            //   const repairId = res.data.planEquiList[0].repairId;
+            //   if (repairId) {
+            //     this.getRepairNotes(repairId);
+            //   }
+            // }
+            this.pageLoading = false;
+          })
+          .catch(() => {
+            this.pageLoading = false;
+          });
+      },
+      // 获取 缺陷设备报修记录
+      async getRepairNotes(repairId) {
+        const res = await repair.getInfo(repairId);
+        if (res?.success) {
+          console.log('缺陷设备报修记录:', res.data);
+          this.repairNotes = res.data;
+        }
+      },
+      //通过按钮事件
+      pass() {
+        let params = {
+          planId: this.$route.query.id,
+          checked: 2,
+          myHandleId: this.$route.query.dbid,
+          cause: this.cause,
+          type: 2, //1维修;2保养,巡点检
+          handleType: 0 //办理类型(0 审批 1 验收)
+        };
+        sendAudit(params).then((res) => {
+          if (res.success) {
+            this.$message.success('审批通过!');
+            this.$router.back();
+          }
+        });
+      },
+      //驳回按钮事件
+      reject() {
+        this.showtext = true;
+      },
+      cancelreject() {
+        this.showtext = false;
+        this.cause = '';
+      },
+      surereject() {
+        if (!this.cause) {
+          this.$message.info('请填写驳回原因!');
+        } else {
+          let params = {
+            id: this.$route.query.id,
+            checked: 0,
+            myHandleId: this.$route.query.dbid,
+            cause: this.cause,
+            type: 2, //1维修;2保养,巡点检
+            handleType: 0 //办理类型(0 审批 1 验收)
+          };
+          sendAudit(params).then((res) => {
+            if (res.success) {
+              this.$message.error('审批驳回!');
+              this.$router.back();
+            }
+          });
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  // @import '@/assets/css/oaa.scss';
+  .page {
+    padding: 10px;
+  }
+  .page-title {
+    background: #fff;
+    font-size: 18px;
+    padding: 6px 20px;
+    font-weight: 500;
+    .page-title-div {
+      margin: 5px 0;
+      height: 30px;
+      line-height: 30px;
+      border-bottom: 1px solid #eaeefb;
+      .title-div-no {
+        margin-left: 10px;
+        font-weight: 400;
+        color: #909090;
+        font-size: 14px;
+      }
+    }
+  }
+  .page-data {
+    padding-top: 10px;
+  }
+  .content-detail {
+    background: #fff;
+    padding: 20px;
+  }
+  .flows {
+    .flow-left {
+      width: 156px;
+      height: 70px;
+      border: 1px dashed #ccc;
+      padding: 10px;
+    }
+    .row {
+      margin-top: 13px;
+    }
+  }
+  .basic-details-title {
+    margin-bottom: 12px;
+    margin-top: 20px;
+    border-bottom: 1px solid #1890ff;
+    padding-bottom: 8px;
+    display: flex;
+    justify-content: space-between;
+  }
+  .basic-details-title .border-span {
+    height: 18px;
+    font-size: 16px;
+    border-left: 4px solid #1890ff;
+    padding-left: 8px;
+
+    font-weight: 500;
+  }
+  .heade-right {
+    // float: right;
+    .heade-right-content {
+      margin-right: 12px;
+      font-size: 14px;
+      display: inline-block;
+      .content-key {
+        color: #3e3e3e;
+        margin-right: 12px;
+        font-weight: 500;
+      }
+      .content-value {
+        color: #000;
+      }
+    }
+  }
+  .list-title {
+    font-size: 14px;
+    color: #3e3e3e;
+    margin: 10px 0px;
+  }
+  .goods {
+    background: #a30014;
+    border: 1px solid #a30014;
+  }
+  .details-title {
+    display: inline-block;
+    color: #6e6e6e;
+    font-size: 14px;
+    font-weight: bold;
+    margin-right: 13px;
+    width: 70px;
+    text-align: right;
+  }
+  .details-con {
+    color: #3e3e3e;
+    font-size: 14px;
+  }
+  .detailed-tab {
+    margin-left: 10px;
+    margin-top: 10px;
+  }
+  ::v-deep .el-form-item--medium .el-form-item__label {
+    color: #6e6e6e;
+    font-size: 14px;
+    font-weight: bold;
+  }
+  .warehouse {
+    display: block;
+    border-bottom: 1px solid #eaeefb;
+    padding: 10px 0;
+  }
+  .box-card {
+    .store-box {
+      width: 80%;
+      .store-box-span {
+        display: inline-block;
+        font-size: 14px;
+        height: 50px;
+        width: 50px;
+        text-align: center;
+        line-height: 50px;
+        color: #fff;
+        margin: 2px;
+      }
+    }
+  }
+  .vacant {
+    background: #3196fb;
+  }
+  .inUse {
+    background: #157a2c;
+  }
+  .invalid {
+    background: #cccccc;
+  }
+  .full {
+    background: #cc3300;
+  }
+
+  .maintain_equipment_info {
+    .maintain_equipment_info_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      > span {
+        display: inline-block;
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .maintain_equipment_info_content {
+      padding: 0 30px;
+      .equipment_item {
+        border: 1px solid #ccc;
+        font-size: 14px;
+        padding: 15px;
+        margin-bottom: 30px;
+        .equipment_info {
+          display: flex;
+          flex-wrap: wrap;
+          border: 1px solid #ddd;
+          .item_info {
+            width: 33.33%;
+            height: 24px;
+            line-height: 24px;
+            display: flex;
+            .item_label {
+              width: 90px;
+              text-align: center;
+              background-color: #f2f2f2;
+              font-weight: 700;
+            }
+            .item_value {
+              border-bottom: 1px solid #f2f2f2;
+              flex: 1;
+              padding-left: 5px;
+            }
+            &:last-child {
+              width: 100%;
+              .item_value {
+                border: 0;
+              }
+            }
+          }
+        }
+        > p {
+          margin-top: 20px;
+          color: #797979;
+        }
+        .matter_info {
+          ::v-deep .el-table {
+            th.el-table__cell {
+              background-color: #f2f2f2;
+              padding: 0;
+            }
+            td.el-table__cell {
+              padding: 0;
+            }
+          }
+        }
+        .ruleMatters_box {
+          flex: 3;
+          height: 100%;
+          display: flex;
+          flex-direction: column;
+          .divider {
+            flex: 0 0 50px;
+            .title {
+              height: 35px;
+            }
+          }
+          .el-table {
+            overflow: auto;
+            .operationGuide_box {
+              width: 100%;
+              display: flex;
+              position: relative;
+              .left_content {
+                flex: 0 0 300px;
+                padding: 10px;
+                margin-right: 10px;
+                overflow-y: auto;
+              }
+              .line {
+                position: absolute;
+                top: -10px;
+                left: 300px;
+                bottom: -10px;
+                height: 110%;
+                width: 1px;
+                background-color: #ededed;
+              }
+              .right_content {
+                flex: 1;
+                padding: 10px;
+                overflow-y: auto;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  .execute_info {
+    margin: 30px 0;
+    .execute_info_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      display: flex;
+      justify-content: space-between;
+      > span:first-child {
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .execute_row {
+      padding: 0 30px;
+      .column {
+        display: flex;
+        font-size: 14px;
+        margin-bottom: 20px;
+        .label {
+          // width: 110px;
+          text-align: center;
+          font-weight: 700;
+        }
+      }
+    }
+  }
+  .repair_notes {
+    .repair_notes_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      > span {
+        display: inline-block;
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .repair_notes_equipment_item {
+      padding: 0 20px;
+      .equipment_item_tilte {
+        background-color: #f7f7f7;
+        height: 36px;
+        line-height: 36px;
+        .label {
+          font-weight: 700;
+        }
+      }
+      .main_info {
+        font-size: 14px;
+        margin-top: 15px;
+        > div {
+          margin-bottom: 10px;
+        }
+      }
+    }
+  }
+  .btnbox {
+    display: flex;
+    justify-content: center;
+  }
+  ::v-deep .el-button {
+    padding: 10px 20px;
+    margin-right: 10px;
+  }
+  .textbtnbox {
+    margin-top: 10px;
+    display: flex;
+    justify-content: center;
+  }
+</style>

+ 282 - 0
src/views/bpm/tickets/maintenance/index.vue

@@ -0,0 +1,282 @@
+<!-- 巡点检工单 -->
+<template>
+  <div class="patrolInspection">
+    <div class="search">
+      <el-form label-width="120px">
+        <el-row>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="工单编号">
+              <el-input
+                v-model="searchForm.code"
+                placeholder="请输入"
+                size="small"
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="规则名称">
+              <el-select
+                v-model="searchForm.ruleId"
+                size="small"
+                clearable
+                style="width: 100%"
+                filterable
+              >
+                <el-option
+                  v-for="item in ruleNameList"
+                  :key="item.id"
+                  :value="item.id"
+                  :label="item.name"
+                ></el-option> </el-select></el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="状态">
+              <el-select
+                filterable
+                clearable
+                v-model="searchForm.orderStatus"
+                size="small"
+              >
+                <el-option
+                  v-for="item in ticketStatus"
+                  :key="item.id"
+                  :value="item.id"
+                  :label="item.label"
+                ></el-option>
+              </el-select> </el-form-item
+          ></el-col>
+          <el-col :md="8" :sm="8" :xs="8">
+            <el-form-item label="开始结束时间">
+              <el-date-picker
+                class="form-input"
+                size="small"
+                v-model="searchForm.date"
+                type="daterange"
+                range-separator="至"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期"
+                value-format="yyyy-MM-dd HH:mm:ss"
+                :default-time="['00:00:00', '23:59:59']"
+              >
+              </el-date-picker> </el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="16" :xs="16" style="text-align: right">
+            <el-button icon="el-icon-refresh-left" size="small" @click="rest"
+              >重置</el-button
+            >
+            <el-button
+              type="primary"
+              icon="el-icon-search"
+              size="small"
+              @click="search"
+              >搜索</el-button
+            ></el-col
+          >
+        </el-row>
+      </el-form>
+    </div>
+    <div class="table">
+      <el-table
+        :data="tableData"
+        border
+        height="99%"
+        tooltip-effect="dark"
+        :header-cell-style="{ background: '#F0F3F3', border: 'none' }"
+        @row-dblclick="openDetail"
+      >
+        <el-table-column
+          width="80px"
+          label="序号"
+          type="index"
+          :index="indexMethod"
+        >
+        </el-table-column>
+        <el-table-column prop="planCode" label="工单编号" />
+        <el-table-column prop="planName" label="计划单号" />
+        <el-table-column prop="planName" label="保养名称" />
+        <!-- <el-table-column prop="createTime" label="设备分类" /> -->
+        <el-table-column prop="ruleName" label="规则名称" />
+        <el-table-column prop="createUserName" label="创建人" />
+        <el-table-column prop="createTime" label="创建时间" />
+        <el-table-column prop="acceptTime" label="开始时间" />
+        <el-table-column prop="finishTime" label="结束时间" />
+        <el-table-column prop="planFinishTime" label="计划完成时间" />
+        <el-table-column prop="orderStatus" label="状态">
+          <template slot-scope="{ row }">
+            {{
+              ticketStatus.filter((item) => item.id == row.orderStatus)[0].label
+            }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="practicalTime" label="实际工时">
+          <template slot-scope="{ row }">
+            {{ time_interval(row.acceptTime, row.finishTime) }}
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="table-footer">
+      <el-pagination
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+        :page-sizes="[15, 30, 50, 100, 500]"
+        :page-size.sync="pages.size"
+        :current-page.sync="pages.page"
+        @current-change="handleCurrentChange"
+        @size-change="handleSizeChange"
+      >
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+  import { ticketStatus } from '@/utils/dict/tickets';
+  import { getWorkOrderPage, getRule } from '@/api/tickets';
+  import pagenation from '@/components/Pagination';
+  export default {
+    components: { pagenation },
+    data() {
+      return {
+        ruleNameList: [],
+        tableData: [],
+        statusOptions: [],
+        ticketStatus,
+        searchForm: {
+          code: '',
+          ruleId: '',
+          date: '',
+          startTime: '',
+          endTime: '',
+          type: 2
+        },
+        pages: {
+          page: 1,
+          size: 15
+        },
+        total: 0
+      };
+    },
+    created() {
+      this.getRuleNameList();
+      this.getData();
+    },
+    methods: {
+      openDetail({ id }) {
+        this.$router.push({
+          path: '/tickets/maintenance/detail',
+          query: {
+            id
+          }
+        });
+      },
+      // 获取规则名列表(设备保养)
+      async getRuleNameList() {
+        const res = await getRule({
+          status: 1,
+          type: 2,
+          pageNum: 1,
+          size: -1
+        });
+        if (res.list) {
+          this.ruleNameList = res.list || [];
+        }
+      },
+      // 实现分页序号连贯
+      indexMethod(index) {
+        index = index + 1 + (this.pages.page - 1) * this.pages.size;
+        return index;
+      },
+      getData() {
+        let userId = localStorage.getItem('userId');
+        console.log(userId);
+        let par = {
+          ...this.pages,
+          ...this.searchForm,
+          executeUserId: userId
+        };
+        if (this.searchForm.date) {
+          par.startTime = this.searchForm.date[0];
+          par.endTime = this.searchForm.date[1];
+        }
+        delete par.date;
+        getWorkOrderPage(par).then((res) => {
+          this.tableData = res.list;
+          this.total = res.total;
+        });
+      },
+      search() {
+        this.pages.page = 1;
+        this.getData();
+      },
+      rest() {
+        this.searchForm = {
+          code: '',
+          ruleId: '',
+          date: '',
+          startTime: '',
+          endTime: '',
+          type: 2
+        };
+        this.pages.page = 1;
+        this.getData();
+      },
+      handleCurrentChange() {
+        this.getData();
+      },
+      handleSizeChange() {
+        this.pages.page = 1;
+        this.getData();
+      },
+      // 计算实际工时
+      time_interval(dt1, dt2) {
+        if (!dt1 || !dt2) {
+          return '';
+        }
+        if (typeof dt1 == 'string') {
+          dt1 = new Date(dt1.replace(/-/, '/'));
+          dt2 = new Date(dt2.replace(/-/, '/'));
+        }
+        var res = dt2 - dt1;
+        if (isNaN(res)) throw Error('invalid dates arguments');
+        let re = res / (1000 * 60 * 60);
+
+        var h = parseInt(re);
+        var m = parseInt((re - h) * 60);
+        let result = '';
+        if (h) {
+          result += `${h} 小时`;
+        }
+        if (m) {
+          result += `${m} 分钟`;
+        }
+        return result;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .patrolInspection {
+    height: 100%;
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    .search {
+      flex: 0 0 50px;
+    }
+    .table {
+      flex: 1;
+      .el-table {
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+      }
+    }
+    .table-footer {
+      flex: 0 0 30px;
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+</style>

+ 757 - 0
src/views/bpm/tickets/patrolInspection/detail.vue

@@ -0,0 +1,757 @@
+<template>
+  <div class="page" v-loading="pageLoading">
+    <el-form label-width="130px">
+      <div class="content-detail" v-show="num == 1">
+        <div class="basic-details">
+          <HeaderTitle title="基本信息" size="16px">
+            <el-button
+              type="primary"
+              @click="
+                $router.push({
+                  path: '/tickets',
+                  query: { title: '巡点检工单' }
+                })
+              "
+              >返回</el-button
+            >
+          </HeaderTitle>
+          <el-row>
+            <el-col :span="12">
+              <el-col :span="12">
+                <el-form-item label="计划单号">
+                  <span> {{ infoData.planCode }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="来源计划配置单号">
+                  <span> {{ infoData.planConfigCode }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="名称">
+                  <span> {{ infoData.planName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="部门">
+                  <span>
+                    {{ infoData.executeGroupName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="人员">
+                  <span>
+                    {{ infoData.executeUserName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="计划完成时长">
+                  <span v-if="infoData.duration >= 0"
+                    >{{ infoData.duration }}分钟</span
+                  >
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="周期">
+                  <span v-if="infoData.ruleInfo">
+                    {{ infoData.ruleInfo.cycleValue
+                    }}{{
+                      getDictValue('巡点检周期', infoData.ruleInfo.cycleType)
+                    }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="设备分类">
+                  <span> {{ infoData.categoryLevelName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="规则名称">
+                  <span>
+                    {{ infoData.ruleName }}
+                  </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建部门">
+                  <span> {{ infoData.createGroupName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建人">
+                  <span> {{ infoData.createUserName }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="12">
+                <el-form-item label="创建时间">
+                  <span> {{ infoData.createTime }} </span>
+                </el-form-item>
+              </el-col>
+              <el-col :span="24">
+                <el-form-item label="备注">
+                  <span> {{ infoData.remark }} </span>
+                </el-form-item>
+              </el-col>
+            </el-col>
+            <el-col :span="12">
+              <img :src="data.imageUrl" alt="" />
+            </el-col>
+          </el-row>
+        </div>
+
+        <!-- 巡点检、执行信息 -->
+        <!-- <div class="execute_info">
+          <div class="execute_info_title">
+            <span>执行信息</span>
+            <span
+              >执行人:{{ data.executeUserName }}
+              <i style="margin: 0 18px"></i> 执行时间:{{
+                data.acceptTime
+              }}</span
+            >
+          </div>
+          <HeaderTitle title="执行信息" size="16px"></HeaderTitle>
+          <el-row class="execute_row">
+            <el-col :span="8" class="column">
+              <span class="label">确认结果:</span>
+              <span class="value">{{
+                infoData.status ? infoData.status.descp : ''
+              }}</span>
+            </el-col>
+            <el-col :span="8" class="column">
+              <span class="label">实际开始时间:</span>
+              <span class="value">{{ infoData.acceptTime }}</span>
+            </el-col>
+            <el-col :span="8" class="column">
+              <span class="label">实际结束时间:</span>
+              <span class="value">{{ infoData.finishTime }}</span>
+            </el-col>
+            <el-col :span="24" class="column">
+              <span class="label">超期原因:</span>
+              <span class="value">{{ infoData.timeoutCause }}</span>
+            </el-col>
+          </el-row>
+        </div> -->
+
+        <!-- 巡点检、保养设备 -->
+        <div class="maintain_equipment_info">
+          <HeaderTitle title="巡点检设备" size="16px"></HeaderTitle>
+          <div class="maintain_equipment_info_content">
+            <div
+              class="equipment_item"
+              v-for="item in infoData.deviceList"
+              :key="item.id"
+            >
+              <div class="equipment_info" v-if="item.substance">
+                <div class="item_info">
+                  <span class="item_label">设备编码</span>
+                  <span class="item_value">{{ item.substance.code }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备名称</span>
+                  <span class="item_value">{{ item.substance.name }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备型号</span>
+                  <span class="item_value">{{ item.substance.model }}</span>
+                </div>
+                <div class="item_info">
+                  <span class="item_label">设备位置</span>
+                  <span class="item_value">{{
+                    item.substance.positionNames
+                  }}</span>
+                </div>
+              </div>
+              <p>操作事项</p>
+              <div class="ruleMatters_box">
+                <el-table :data="item.workItems" border>
+                  <el-table-column label="序号" width="50">
+                    <template slot-scope="scope">
+                      <span>{{ scope.$index + 1 }}</span>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="事项" prop="name" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.name }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="内容" prop="content" width="300">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.content }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="操作指导" prop="operationGuide">
+                    <template slot-scope="scope">
+                      <div class="operationGuide_box">
+                        <div class="left_content">
+                          <template v-if="scope.row.operationGuide">
+                            <div
+                              v-for="(item, index) in scope.row.operationGuide
+                                .toolList"
+                              :key="item.id"
+                              >{{ index + 1 }}.{{ item.name }}</div
+                            >
+                          </template>
+                        </div>
+                        <div class="line"></div>
+                        <div class="right_content">
+                          <template v-if="scope.row.operationGuide">
+                            <div
+                              v-for="(item, index) in scope.row.operationGuide
+                                .procedureList"
+                              :key="item.id"
+                              >{{ index + 1 }}.{{ item.content }}</div
+                            >
+                          </template>
+                        </div>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="标准" prop="norm" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ scope.row.norm }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="状态" prop="status" width="100">
+                    <template slot-scope="scope">
+                      <div>
+                        <span>{{ options[scope.row.status] }}</span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="结果" prop="result" width="200">
+                  </el-table-column>
+                </el-table>
+              </div>
+            </div>
+            <!-- <div class="btnbox" v-if="$route.query.isshow">
+              <el-button class="confirm-btn" type="danger" plain @click="reject"
+                >驳回</el-button
+              >
+              <el-button class="confirm-btn" type="success" plain @click="pass"
+                >通过</el-button
+              >
+              <el-button class="cancel-btn">关闭</el-button>
+            </div> -->
+            <!-- <div class="textbox" v-if="showtext">
+              <el-input
+                type="textarea"
+                placeholder="请输入驳回原因"
+                v-model="cause"
+                maxlength="30"
+                rows="5"
+                show-word-limit
+              >
+              </el-input>
+              <div class="textbtnbox">
+                <el-button size="small" round @click="cancelreject"
+                  >取消</el-button
+                >
+                <el-button size="small" round @click="surereject"
+                  >提交</el-button
+                >
+              </div>
+            </div> -->
+          </div>
+        </div>
+
+        <!-- 巡点检、缺陷设备报修记录 -->
+        <!-- <div class="repair_notes">
+          <HeaderTitle title="缺陷设备报修记录" size="16px"></HeaderTitle>
+          <div class="repair_notes_equipment_item">
+            <el-row class="equipment_item_tilte">
+              <el-col :span="8">
+                <span class="label">设备名称:</span>
+                <span>{{ repairNotes.equiName }}</span>
+              </el-col>
+              <el-col :span="8">
+                <span class="label">规格型号:</span>
+                <span>{{ repairNotes.equiModel }}</span>
+              </el-col>
+              <el-col :span="8">
+                <span class="label">设备编码:</span>
+                <span>{{ repairNotes.equiCode }}</span>
+              </el-col>
+            </el-row>
+            <div class="main_info">
+              <div>
+                <span>报修记录编号:</span>
+                <span>{{ repairNotes.repairsCode }}</span>
+              </div>
+              <div>
+                <span>故障描述:</span>
+                <span>{{ repairNotes.repairsDescription }}</span>
+              </div>
+              <div>
+                <span>处理进度:</span>
+                <span>{{ statusObj[repairNotes.status] }}</span>
+              </div>
+            </div>
+          </div>
+        </div> -->
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+  import dictMixins from '@/mixins/dictMixins';
+  import { getWordOrderDetail } from '@/api/tickets';
+  export default {
+    mixins: [dictMixins],
+    data() {
+      return {
+        options: {
+          0: '正常',
+          '-1': '缺陷'
+        },
+        num: 1,
+        infoData: {},
+        dialogVisible: false,
+        data: {},
+        repairNotes: {},
+        pageLoading: false,
+        typeValue: null,
+        contract_type: [],
+        status: [
+          {
+            value: true,
+            label: '失效'
+          },
+          {
+            value: false,
+            label: '生效'
+          }
+        ],
+        ruleItem: [],
+        cause: '',
+        showtext: false,
+        from: null
+      };
+    },
+    created() {
+      this.requestDict('巡点检周期');
+      this.getInfo();
+    },
+    methods: {
+      // getStatus: useDictLabel(patrolMatterStatus),
+      delete() {},
+      // 点击切换事件
+      tab(index) {
+        this.num = index;
+      },
+      goBack() {
+        window.sessionStorage.setItem('patrolTabType', 'work');
+        if (this.form) {
+          this.$router.push({
+            path: '/workspace/workOrder',
+            query: { activeName: 'polling' }
+          });
+        } else {
+          this.$router.go(-1);
+        }
+      },
+      // 表格数据
+      getInfo() {
+        this.pageLoading = true;
+        getWordOrderDetail(this.$route.query.id)
+          .then((data) => {
+            this.infoData = data;
+            // if (res.success) {
+            //   this.data = res.data;
+            //   this.data.planEquiList = this.data.planEquiList.filter(
+            //     (item) => item.itemList && item.itemList.length > 0
+            //   );
+            //   // 获取 缺陷设备报修记录
+            //   const repairId = res.data.planEquiList[0].repairId;
+            //   if (repairId) {
+            //     this.getRepairNotes(repairId);
+            //   }
+            // }
+            this.pageLoading = false;
+          })
+          .catch(() => {
+            this.pageLoading = false;
+          });
+      },
+      // 获取 缺陷设备报修记录
+      async getRepairNotes(repairId) {
+        const res = await repair.getInfo(repairId);
+        if (res?.success) {
+          console.log('缺陷设备报修记录:', res.data);
+          this.repairNotes = res.data;
+        }
+      },
+      //通过按钮事件
+      pass() {
+        let params = {
+          planId: this.$route.query.id,
+          checked: 2,
+          myHandleId: this.$route.query.dbid,
+          cause: this.cause,
+          type: 2, //1维修;2保养,巡点检
+          handleType: 0 //办理类型(0 审批 1 验收)
+        };
+        sendAudit(params).then((res) => {
+          if (res.success) {
+            this.$message.success('审批通过!');
+            this.$router.back();
+          }
+        });
+      },
+      //驳回按钮事件
+      reject() {
+        this.showtext = true;
+      },
+      cancelreject() {
+        this.showtext = false;
+        this.cause = '';
+      },
+      surereject() {
+        if (!this.cause) {
+          this.$message.info('请填写驳回原因!');
+        } else {
+          let params = {
+            id: this.$route.query.id,
+            checked: 0,
+            myHandleId: this.$route.query.dbid,
+            cause: this.cause,
+            type: 2, //1维修;2保养,巡点检
+            handleType: 0 //办理类型(0 审批 1 验收)
+          };
+          sendAudit(params).then((res) => {
+            if (res.success) {
+              this.$message.error('审批驳回!');
+              this.$router.back();
+            }
+          });
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  // @import '@/assets/css/oaa.scss';
+  .page {
+    padding: 10px;
+  }
+  .page-title {
+    background: #fff;
+    font-size: 18px;
+    padding: 6px 20px;
+    font-weight: 500;
+    .page-title-div {
+      margin: 5px 0;
+      height: 30px;
+      line-height: 30px;
+      border-bottom: 1px solid #eaeefb;
+      .title-div-no {
+        margin-left: 10px;
+        font-weight: 400;
+        color: #909090;
+        font-size: 14px;
+      }
+    }
+  }
+  .page-data {
+    padding-top: 10px;
+  }
+  .content-detail {
+    background: #fff;
+    padding: 20px;
+  }
+  .flows {
+    .flow-left {
+      width: 156px;
+      height: 70px;
+      border: 1px dashed #ccc;
+      padding: 10px;
+    }
+    .row {
+      margin-top: 13px;
+    }
+  }
+  .basic-details-title {
+    margin-bottom: 12px;
+    margin-top: 20px;
+    border-bottom: 1px solid #1890ff;
+    padding-bottom: 8px;
+    display: flex;
+    justify-content: space-between;
+  }
+  .basic-details-title .border-span {
+    height: 18px;
+    font-size: 16px;
+    border-left: 4px solid #1890ff;
+    padding-left: 8px;
+
+    font-weight: 500;
+  }
+  .heade-right {
+    // float: right;
+    .heade-right-content {
+      margin-right: 12px;
+      font-size: 14px;
+      display: inline-block;
+      .content-key {
+        color: #3e3e3e;
+        margin-right: 12px;
+        font-weight: 500;
+      }
+      .content-value {
+        color: #000;
+      }
+    }
+  }
+  .list-title {
+    font-size: 14px;
+    color: #3e3e3e;
+    margin: 10px 0px;
+  }
+  .goods {
+    background: #a30014;
+    border: 1px solid #a30014;
+  }
+  .details-title {
+    display: inline-block;
+    color: #6e6e6e;
+    font-size: 14px;
+    font-weight: bold;
+    margin-right: 13px;
+    width: 70px;
+    text-align: right;
+  }
+  .details-con {
+    color: #3e3e3e;
+    font-size: 14px;
+  }
+  .detailed-tab {
+    margin-left: 10px;
+    margin-top: 10px;
+  }
+  ::v-deep .el-form-item--medium .el-form-item__label {
+    color: #6e6e6e;
+    font-size: 14px;
+    font-weight: bold;
+  }
+  .warehouse {
+    display: block;
+    border-bottom: 1px solid #eaeefb;
+    padding: 10px 0;
+  }
+  .box-card {
+    .store-box {
+      width: 80%;
+      .store-box-span {
+        display: inline-block;
+        font-size: 14px;
+        height: 50px;
+        width: 50px;
+        text-align: center;
+        line-height: 50px;
+        color: #fff;
+        margin: 2px;
+      }
+    }
+  }
+  .vacant {
+    background: #3196fb;
+  }
+  .inUse {
+    background: #157a2c;
+  }
+  .invalid {
+    background: #cccccc;
+  }
+  .full {
+    background: #cc3300;
+  }
+
+  .maintain_equipment_info {
+    .maintain_equipment_info_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      > span {
+        display: inline-block;
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .maintain_equipment_info_content {
+      padding: 0 30px;
+      .equipment_item {
+        border: 1px solid #ccc;
+        font-size: 14px;
+        padding: 15px;
+        margin-bottom: 30px;
+        .equipment_info {
+          display: flex;
+          flex-wrap: wrap;
+          border: 1px solid #ddd;
+          .item_info {
+            width: 33.33%;
+            height: 24px;
+            line-height: 24px;
+            display: flex;
+            .item_label {
+              width: 90px;
+              text-align: center;
+              background-color: #f2f2f2;
+              font-weight: 700;
+            }
+            .item_value {
+              border-bottom: 1px solid #f2f2f2;
+              flex: 1;
+              padding-left: 5px;
+            }
+            &:last-child {
+              width: 100%;
+              .item_value {
+                border: 0;
+              }
+            }
+          }
+        }
+        > p {
+          margin-top: 20px;
+          color: #797979;
+        }
+        .matter_info {
+          ::v-deep .el-table {
+            th.el-table__cell {
+              background-color: #f2f2f2;
+              padding: 0;
+            }
+            td.el-table__cell {
+              padding: 0;
+            }
+          }
+        }
+        .ruleMatters_box {
+          flex: 3;
+          height: 100%;
+          display: flex;
+          flex-direction: column;
+          .divider {
+            flex: 0 0 50px;
+            .title {
+              height: 35px;
+            }
+          }
+          .el-table {
+            overflow: auto;
+            .operationGuide_box {
+              width: 100%;
+              display: flex;
+              position: relative;
+              .left_content {
+                flex: 0 0 300px;
+                padding: 10px;
+                margin-right: 10px;
+                overflow-y: auto;
+              }
+              .line {
+                position: absolute;
+                top: -10px;
+                left: 300px;
+                bottom: -10px;
+                height: 110%;
+                width: 1px;
+                background-color: #ededed;
+              }
+              .right_content {
+                flex: 1;
+                padding: 10px;
+                overflow-y: auto;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  .execute_info {
+    margin: 30px 0;
+    .execute_info_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      display: flex;
+      justify-content: space-between;
+      > span:first-child {
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .execute_row {
+      padding: 0 30px;
+      .column {
+        display: flex;
+        font-size: 14px;
+        margin-bottom: 20px;
+        .label {
+          // width: 110px;
+          text-align: center;
+          font-weight: 700;
+        }
+      }
+    }
+  }
+  .repair_notes {
+    .repair_notes_title {
+      border-bottom: 1px solid #1890ff;
+      padding-bottom: 3px;
+      margin-bottom: 20px;
+      > span {
+        display: inline-block;
+        line-height: 16px;
+        border-left: 6px solid #1890ff;
+        padding-left: 6px;
+      }
+    }
+    .repair_notes_equipment_item {
+      padding: 0 20px;
+      .equipment_item_tilte {
+        background-color: #f7f7f7;
+        height: 36px;
+        line-height: 36px;
+        .label {
+          font-weight: 700;
+        }
+      }
+      .main_info {
+        font-size: 14px;
+        margin-top: 15px;
+        > div {
+          margin-bottom: 10px;
+        }
+      }
+    }
+  }
+  .btnbox {
+    display: flex;
+    justify-content: center;
+  }
+  ::v-deep .el-button {
+    padding: 10px 20px;
+    margin-right: 10px;
+  }
+  .textbtnbox {
+    margin-top: 10px;
+    display: flex;
+    justify-content: center;
+  }
+</style>

+ 282 - 0
src/views/bpm/tickets/patrolInspection/index.vue

@@ -0,0 +1,282 @@
+<!-- 巡点检工单 -->
+<template>
+  <div class="patrolInspection">
+    <div class="search">
+      <el-form label-width="120px">
+        <el-row>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="工单编号">
+              <el-input
+                v-model="searchForm.code"
+                placeholder="请输入"
+                size="small"
+              ></el-input> </el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="规则名称">
+              <el-select
+                v-model="searchForm.ruleId"
+                size="small"
+                clearable
+                style="width: 100%"
+                filterable
+              >
+                <el-option
+                  v-for="item in ruleNameList"
+                  :key="item.id"
+                  :value="item.id"
+                  :label="item.name"
+                ></el-option> </el-select></el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="8" :xs="8">
+            <el-form-item label="状态">
+              <el-select
+                filterable
+                clearable
+                v-model="searchForm.orderStatus"
+                size="small"
+              >
+                <el-option
+                  v-for="item in ticketStatus"
+                  :key="item.id"
+                  :value="item.id"
+                  :label="item.label"
+                ></el-option>
+              </el-select> </el-form-item
+          ></el-col>
+          <el-col :md="8" :sm="8" :xs="8">
+            <el-form-item label="开始结束时间">
+              <el-date-picker
+                class="form-input"
+                size="small"
+                v-model="searchForm.date"
+                type="daterange"
+                range-separator="至"
+                start-placeholder="开始日期"
+                end-placeholder="结束日期"
+                value-format="yyyy-MM-dd HH:mm:ss"
+                :default-time="['00:00:00', '23:59:59']"
+              >
+              </el-date-picker> </el-form-item
+          ></el-col>
+          <el-col :md="4" :sm="16" :xs="16" style="text-align: right">
+            <el-button icon="el-icon-refresh-left" size="small" @click="rest"
+              >重置</el-button
+            >
+            <el-button
+              type="primary"
+              icon="el-icon-search"
+              size="small"
+              @click="search"
+              >搜索</el-button
+            ></el-col
+          >
+        </el-row>
+      </el-form>
+    </div>
+    <div class="table">
+      <el-table
+        :data="tableData"
+        border
+        height="99%"
+        tooltip-effect="dark"
+        :header-cell-style="{ background: '#F0F3F3', border: 'none' }"
+        @row-dblclick="openDetail"
+      >
+        <el-table-column
+          width="80px"
+          label="序号"
+          type="index"
+          :index="indexMethod"
+        >
+        </el-table-column>
+        <el-table-column prop="planCode" label="工单编号" />
+        <el-table-column prop="planName" label="计划单号" />
+        <el-table-column prop="planName" label="巡点检名称" />
+        <!-- <el-table-column prop="createTime" label="设备分类" /> -->
+        <el-table-column prop="ruleName" label="规则名称" />
+        <el-table-column prop="createUserName" label="创建人" />
+        <el-table-column prop="createTime" label="创建时间" />
+        <el-table-column prop="acceptTime" label="开始时间" />
+        <el-table-column prop="finishTime" label="结束时间" />
+        <el-table-column prop="planFinishTime" label="计划完成时间" />
+        <el-table-column prop="orderStatus" label="状态">
+          <template slot-scope="{ row }">
+            {{
+              ticketStatus.filter((item) => item.id == row.orderStatus)[0].label
+            }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="practicalTime" label="实际工时">
+          <template slot-scope="{ row }">
+            {{ time_interval(row.acceptTime, row.finishTime) }}
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+    <div class="table-footer">
+      <el-pagination
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="total"
+        :page-sizes="[15, 30, 50, 100, 500]"
+        :page-size.sync="pages.size"
+        :current-page.sync="pages.page"
+        @current-change="handleCurrentChange"
+        @size-change="handleSizeChange"
+      >
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+  import { ticketStatus } from '@/utils/dict/tickets';
+  import { getWorkOrderPage, getRule } from '@/api/tickets';
+  import pagenation from '@/components/Pagination';
+  export default {
+    components: { pagenation },
+    data() {
+      return {
+        ruleNameList: [],
+        tableData: [],
+        statusOptions: [],
+        ticketStatus,
+        searchForm: {
+          code: '',
+          ruleId: '',
+          date: '',
+          startTime: '',
+          endTime: '',
+          type: 1
+        },
+        pages: {
+          page: 1,
+          size: 15
+        },
+        total: 0
+      };
+    },
+    created() {
+      this.getRuleNameList();
+      this.getData();
+    },
+    methods: {
+      openDetail({ id }) {
+        this.$router.push({
+          path: '/tickets/patrolInspection/detail',
+          query: {
+            id
+          }
+        });
+      },
+      // 获取规则名列表(设备保养)
+      async getRuleNameList() {
+        const res = await getRule({
+          status: 1,
+          type: 1,
+          pageNum: 1,
+          size: -1
+        });
+        if (res.list) {
+          this.ruleNameList = res.list || [];
+        }
+      },
+      // 实现分页序号连贯
+      indexMethod(index) {
+        index = index + 1 + (this.pages.page - 1) * this.pages.size;
+        return index;
+      },
+      getData() {
+        let userId = localStorage.getItem('userId');
+        console.log(userId);
+        let par = {
+          ...this.pages,
+          ...this.searchForm,
+          executeUserId: userId
+        };
+        if (this.searchForm.date) {
+          par.startTime = this.searchForm.date[0];
+          par.endTime = this.searchForm.date[1];
+        }
+        delete par.date;
+        getWorkOrderPage(par).then((res) => {
+          this.tableData = res.list;
+          this.total = res.total;
+        });
+      },
+      search() {
+        this.pages.page = 1;
+        this.getData();
+      },
+      rest() {
+        this.searchForm = {
+          code: '',
+          ruleId: '',
+          date: '',
+          startTime: '',
+          endTime: '',
+          type: 1
+        };
+        this.pages.page = 1;
+        this.getData();
+      },
+      handleCurrentChange() {
+        this.getData();
+      },
+      handleSizeChange() {
+        this.pages.page = 1;
+        this.getData();
+      },
+      // 计算实际工时
+      time_interval(dt1, dt2) {
+        if (!dt1 || !dt2) {
+          return '';
+        }
+        if (typeof dt1 == 'string') {
+          dt1 = new Date(dt1.replace(/-/, '/'));
+          dt2 = new Date(dt2.replace(/-/, '/'));
+        }
+        var res = dt2 - dt1;
+        if (isNaN(res)) throw Error('invalid dates arguments');
+        let re = res / (1000 * 60 * 60);
+
+        var h = parseInt(re);
+        var m = parseInt((re - h) * 60);
+        let result = '';
+        if (h) {
+          result += `${h} 小时`;
+        }
+        if (m) {
+          result += `${m} 分钟`;
+        }
+        return result;
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .patrolInspection {
+    height: 100%;
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    .search {
+      flex: 0 0 50px;
+    }
+    .table {
+      flex: 1;
+      .el-table {
+        width: 100%;
+        display: flex;
+        flex-direction: column;
+      }
+    }
+    .table-footer {
+      flex: 0 0 30px;
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+</style>