jiangping
2025-04-10 d14d7109d6d8a3354577a5ae3ed7a8fd13d44e6c
代码初始化
已添加4个文件
已修改8个文件
1351 ■■■■■ 文件已修改
admin/src/api/business/category.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/assets/style/variables.scss 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaWorkorderDetailDbhWindow.vue 494 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaWorkorderDetailDcaWindow.vue 494 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaWorkorderDetailSheWindow.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/workorderDbh.vue 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/workorderDca.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/workorderShe.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/src/main/java/com/doumee/api/business/CategoryController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/src/main/java/com/doumee/dao/business/model/Workorder.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/src/main/java/com/doumee/service/business/impl/WorkorderServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/business/category.js
@@ -6,6 +6,11 @@
    trim: true
  })
}
export function allList (data) {
  return request.post('/business/category/list', data, {
    trim: true
  })
}
export function treeList (data) {
  return request.post('/business/category/tree', data, {
    trim: true
admin/src/assets/style/variables.scss
@@ -18,3 +18,11 @@
// å­—体
$font-color: #282828; // é¢œè‰²
$font-size: 12px; // å¤§å°
.el-drawer__header {
  color: #333333 !important;
}
.el-image-viewer__wrapper{
  z-index: 3000 !important;
}
admin/src/components/business/OperaWorkorderDetailDbhWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,494 @@
<template>
  <GlobalWindow
      :title="title"
      width="85%"
      :visible.sync="visible"
      :confirm-working="isWorking"
      @confirm="confirm">
    <div class="modal_wrap">
      <div class="modal_content">
        <div class="header">
          <img v-if="info.status == '3'" class="head_bg"
               src="@/assets/task/bg_shenhe_fail@2x.png" alt="">
          <img v-else-if="info.status == '4'" class="head_bg"
               src="@/assets/task/bg_shenhe_pass@2x.png" alt="">
          <img v-else class="head_bg" src="@/assets/task/bg_shenhe@2x.png" alt="">
          <div class="left">
            <div class="h1">{{ cateList[type] }}</div>
            <div class="time">提交时间:{{ info.createDate }}</div>
          </div>
          <div class="right"  :class="{ scs: info.status == '3' || info.status == '4' || info.status == '5',  msg: info.status == '6' }">{{statusMap[info.status] }}</div>
        </div>
        <div class="info">
          <div class="title">工单信息</div>
          <div class="list">
            <div class="item">
              <div class="label">员工姓名</div>
              <div class="value">{{ info.memberName }} - {{ info.memberPhone || '[无手机号]' }}</div>
            </div>
            <div class="item">
              <div class="label">所属部门</div>
              <div class="value">{{ info.companyName }} </div>
            </div>
            <div class="item">
              <div class="label">上报时间</div>
              <div class="value">{{ info.submitDate }}</div>
            </div>
            <div class="item">
              <div class="label">发生时间</div>
              <div class="value">{{ info.happenTime}}</div>
            </div>
            <div class="item">
              <div class="label">风险类型</div>
              <div class="value">{{ info.typeName }}</div>
            </div>
            <div class="item">
              <div class="label">发生地点</div>
              <div class="value">{{ info.locationName }}</div>
            </div>
            <div class="item">
              <div class="label">风险描述</div>
              <div class="value">{{ info.riskInfo }}</div>
            </div>
            <div class="item" style="width: 100%">
              <div class="label">图片</div>
              <div class="value" v-if="info.multifileList ==null || !info.multifileList.length">无</div>
              <div class="value" v-if="info.multifileList !=null && info.multifileList.length">
                <div v-for="item in info.multifileList" :key="item.id" style="display: inline;margin-right: 20px">
                  <video
                      v-if="item.fileurlFull && item.fileurlFull.endsWith('.mp4')"
                      ref="videoRef"
                      controls
                      preload="auto"
                      style="width: 80px;height: 80px;object-fit: contain;"
                      :src="item.fileurlFull"
                  />
                  <el-image
                      v-else-if="item.fileurlFull"
                      style="width:80px; height: 80px"
                      :src="item.fileurlFull"
                      :preview-src-list="[item.fileurlFull]">
                  </el-image>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="side" >
        <div class="side_title">处理流程</div>
        <div class="list" v-if=" info.logList != null && info.logList.length != 0
        ">
          <div class="item" v-for="(item, index) in info.logList" :key="item.id">
            <div class="separate" v-if="index < info.logList.length - 1"></div>
            <div class="info">
              <img src="@/assets/icons/ic_dangqian.png" class="iconnew"  />
              <div class="content">
                <div class="line">
                  <div class="name">{{ item.title }}</div>
                </div>
                <div class="line">
                  <div class="company">
                    å‘˜å·¥ï¼š<span>  {{ item.userName }} / {{item.companyName}}</span>
                    <div style="display: block" >时间:<span>{{item.createDate}}</span></div>
                    <div class="dealinfo">
                      <div style="display: block" v-if="item.param2" >处理人:<span>{{item.param2}}</span></div>
                      <div style="display: block" v-if="item.remark" >说明:<span>{{item.remark}}</span></div>
                      <div style="display: block;margin-top:10px"  v-if="item.multifileList !=null && item.multifileList.length">
                        <div v-for="item in item.multifileList" :key="item.id" style="display: inline;margin-right: 5px">
                          <video
                              v-if="item.fileurlFull && item.fileurlFull.endsWith('.mp4')"
                              ref="videoRef"
                              controls
                              preload="auto"
                              style="width: 50px;height: 50px;object-fit: contain;"
                              :src="item.fileurlFull"
                          />
                          <el-image
                              v-else-if="item.fileurlFull"
                              style="width:50px; height: 50px;"
                              :src="item.fileurlFull"
                              :preview-src-list="[item.fileurlFull]">
                          </el-image>
                        </div>
                        </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!--  -->
    <template v-slot:footer>
      <el-button @click="close">返回</el-button>
    </template>
  </GlobalWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalWindow from '@/components/common/GlobalWindow'
import { getById } from '@/api/business/workorder'
export default {
  name: 'OperaWorkorderDetailDbhWindow',
  extends: BaseOpera,
  components: { GlobalWindow },
  data () {
    return {
      id: '',
      type: null,
      title: '工单详情',
      info: {},
      statusMap: {
        0: '待分配WTS',
        1: '待分配任务',
        2: '待处理',
        3: '已解决',
        4: '已解决',
        5: '已解决'
      },
      cateList: {
        0: 'SHE事件工单',
        1: '跌绊滑事件工单',
        2: 'DCA事件提交记录',
        3: 'DCA事件工单'
      }
    }
  },
  methods: {
    open (title, target) {
      this.title = title
      this.visible = true
      this.info = target
      this.getDetail()
      this.type = this.info.type
    },
    close () {
      this.visible = false
    },
    getDetail () {
      getById(this.info.id).then(res => {
        this.info = res
        if (this.info.logList && this.info.logList.length > 0) {
          this.info.logList.forEach(item => {
            if (item.approveList && item.approveList.length == 1 && item.type !== 1) {
              item.title = item.approveList[0].title
              item.faceImg = item.approveList[0].faceImg
              item.memberName = item.approveList[0].memberName
              item.statusInfo = item.approveList[0].statusInfo
              item.approveList = []
            }
          })
        }
      })
    },
    reject () { },
    handleAvatarSuccess () { },
    beforeAvatarUpload () { }
  }
}
</script>
<style lang="scss" scoped>
@import "@/assets/style/variables.scss";
.upload_box {
  width: 84px;
  height: 84px;
  border-radius: 4px;
  background-color: #f7f7f7;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #999999;
  border: 1px solid #e4e4e4;
  .icon {
    font-size: 24px;
  }
  .text {
    font-size: 12px;
  }
}
.side_title {
  font-weight: 600;
  font-size: 18px;
  color: #111111;
  margin-bottom: 20px;
  margin-left: 20px;
  margin-top: 20px;
}
.modal_wrap {
  display: flex;
  height: 100%;
  .modal_content {
    flex: 1;
    padding: 0px 30px;
    border-radius: 8px;
    overflow: hidden;
    height: 100%;
    .title {
      font-weight: 600;
      font-size: 18px;
      color: #333333;
      margin-bottom: 20px;
      margin-top: 30px;
    }
    .info {
      .list {
        display: flex;
        flex-wrap: wrap;
        .item {
          display: flex;
          width: 40%;
          font-size: 14px;
          margin-bottom: 20px;
          &:nth-of-type(2n) {
            width: 60%;
          }
          .label {
            color: #888888;
            width: 100px;
          }
          .value {
            color: #111111;
          }
        }
      }
    }
    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      vertical-align: center;
      padding: 20px 30px;
      margin: 0 -30px;
      border-radius: 8px 8px 0 0;
      position: relative;
      .head_bg {
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        z-index: 9;
      }
      .h1 {
        font-weight: 600;
        font-size: 22px;
        color: #111111;
        margin-bottom: 8px;
      }
      .time {
        font-size: 14px;
        color: #999999;
      }
      .right {
        height: 40px;
        font-size: 16px;
        color: #ffffff;
        line-height: 40px;
        padding: 0 20px;
        background: #207ff7;
        box-shadow: 4px 4px 0px 0px rgba(32, 127, 247, 0.16);
        border-radius: 16px 0px 16px 0px;
        position: relative;
        z-index: 99;
      }
      .scs {
        background-color: #00BA67;
      }
      .msg {
        background-color: #ED4545;
      }
    }
    .table_info {
      .name_wrap {
        display: flex;
        align-items: center;
        .avatar {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          margin-right: 12px;
        }
        .content {
          .line {
            display: flex;
          }
          .tag {
            color: #b2cbf9;
            border: 1px solid #b2cbf9;
            padding: 0px 4px;
            border-radius: 4px;
            margin-left: 6px;
          }
        }
      }
    }
  }
  .side {
    height: 100%;
    width: 420px;
    background: #ffffff;
    border-left: 20px solid #f7f7f7;
    .list {
      .item {
        padding: 8px 0;
        position: relative;
        .separate {
          position: absolute;
          border-left: 2px dashed #cccccc;
          left: 31px;
          height: calc(100% - 0px);
          top: 30px;
        }
        .avatar {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          margin: 0 12px 0 16px;
          //border: 1px solid;
        }
        .childList {
          display: flex;
          flex-wrap: wrap;
          margin-left: 100px;
        }
        .company {
          font-size: 13px;
          color: #888888;
          width: calc(100% - 20px);
          .status {
            color: $primaryColor;
          }
         /* span{
            color: black;
          }*/
          .dealinfo{
            background-color: #f2f2f2;
            padding: 8px;
            display: block;
            margin-top: 5px;
            width: calc(100% - 20px);
          }
        }
        .m_content {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          margin-bottom: 4px;
        }
        .info {
          display: flex;
          /*align-items: center;*/
          margin-left: 20px;
          .icon {
            position: relative;
            z-index: 11;
            color: #53b76f;
            font-size: 24px;
          }
          .icon1 {
            position: relative;
            z-index: 11;
            color: deepskyblue;
            font-size: 24px;
          }
          .icon2 {
            position: relative;
            z-index: 11;
            color: #dc362e;
            font-size: 24px;
          }
          .iconnew {
            width: 24px;
            height: 24px;
          }
          .icon3 {
            position: relative;
            z-index: 11;
            color: gray;
            font-size: 24px;
          }
          .content {
            flex: 1;
            .line {
              display: flex;
              justify-content: space-between;
              align-content: center;
              margin-bottom: 6px;
              .status {
                color: #888888;
              }
              .padding {
                color: $primaryColor;
              }
              .name {
                font-weight: 600;
                font-size: 16px;
                color: #111111;
              }
              .time {
                color: #888888;
              }
            }
          }
        }
        .remark {
          background: #f7f7f7;
          border-radius: 4px;
          padding: 13px 15px;
          color: #666666;
          margin-left: 100px;
        }
      }
    }
  }
}
</style>
admin/src/components/business/OperaWorkorderDetailDcaWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,494 @@
<template>
  <GlobalWindow
      :title="title"
      width="85%"
      :visible.sync="visible"
      :confirm-working="isWorking"
      @confirm="confirm">
    <div class="modal_wrap">
      <div class="modal_content">
        <div class="header">
          <img v-if="info.status == '3'" class="head_bg"
               src="@/assets/task/bg_shenhe_fail@2x.png" alt="">
          <img v-else-if="info.status == '4'" class="head_bg"
               src="@/assets/task/bg_shenhe_pass@2x.png" alt="">
          <img v-else class="head_bg" src="@/assets/task/bg_shenhe@2x.png" alt="">
          <div class="left">
            <div class="h1">{{ cateList[type] }}</div>
            <div class="time">提交时间:{{ info.createDate }}</div>
          </div>
          <div class="right"  :class="{ scs: info.status == '3' || info.status == '4' || info.status == '5',  msg: info.status == '6' }">{{statusMap[info.status] }}</div>
        </div>
        <div class="info">
          <div class="title">工单信息</div>
          <div class="list">
            <div class="item">
              <div class="label">员工姓名</div>
              <div class="value">{{ info.memberName }} - {{ info.memberPhone || '[无手机号]' }}</div>
            </div>
            <div class="item">
              <div class="label">所属部门</div>
              <div class="value">{{ info.companyName }} </div>
            </div>
            <div class="item">
              <div class="label">上报时间</div>
              <div class="value">{{ info.submitDate }}</div>
            </div>
            <div class="item">
              <div class="label">发生时间</div>
              <div class="value">{{ info.happenTime}}</div>
            </div>
            <div class="item">
              <div class="label">风险类型</div>
              <div class="value">{{ info.typeName }}</div>
            </div>
            <div class="item">
              <div class="label">发生地点</div>
              <div class="value">{{ info.locationName }}</div>
            </div>
            <div class="item">
              <div class="label">风险描述</div>
              <div class="value">{{ info.riskInfo }}</div>
            </div>
            <div class="item" style="width: 100%">
              <div class="label">图片</div>
              <div class="value" v-if="info.multifileList ==null || !info.multifileList.length">无</div>
              <div class="value" v-if="info.multifileList !=null && info.multifileList.length">
                <div v-for="item in info.multifileList" :key="item.id" style="display: inline;margin-right: 20px">
                  <video
                      v-if="item.fileurlFull && item.fileurlFull.endsWith('.mp4')"
                      ref="videoRef"
                      controls
                      preload="auto"
                      style="width: 80px;height: 80px;object-fit: contain;"
                      :src="item.fileurlFull"
                  />
                  <el-image
                      v-else-if="item.fileurlFull"
                      style="width:80px; height: 80px"
                      :src="item.fileurlFull"
                      :preview-src-list="[item.fileurlFull]">
                  </el-image>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="side" >
        <div class="side_title">处理流程</div>
        <div class="list" v-if=" info.logList != null && info.logList.length != 0
        ">
          <div class="item" v-for="(item, index) in info.logList" :key="item.id">
            <div class="separate" v-if="index < info.logList.length - 1"></div>
            <div class="info">
              <img src="@/assets/icons/ic_dangqian.png" class="iconnew"  />
              <div class="content">
                <div class="line">
                  <div class="name">{{ item.title }}</div>
                </div>
                <div class="line">
                  <div class="company">
                    å‘˜å·¥ï¼š<span>  {{ item.userName }} / {{item.companyName}}</span>
                    <div style="display: block" >时间:<span>{{item.createDate}}</span></div>
                    <div class="dealinfo">
                      <div style="display: block" v-if="item.param2" >处理人:<span>{{item.param2}}</span></div>
                      <div style="display: block" v-if="item.remark" >说明:<span>{{item.remark}}</span></div>
                      <div style="display: block;margin-top:10px"  v-if="item.multifileList !=null && item.multifileList.length">
                        <div v-for="item in item.multifileList" :key="item.id" style="display: inline;margin-right: 5px">
                          <video
                              v-if="item.fileurlFull && item.fileurlFull.endsWith('.mp4')"
                              ref="videoRef"
                              controls
                              preload="auto"
                              style="width: 50px;height: 50px;object-fit: contain;"
                              :src="item.fileurlFull"
                          />
                          <el-image
                              v-else-if="item.fileurlFull"
                              style="width:50px; height: 50px;"
                              :src="item.fileurlFull"
                              :preview-src-list="[item.fileurlFull]">
                          </el-image>
                        </div>
                        </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!--  -->
    <template v-slot:footer>
      <el-button @click="close">返回</el-button>
    </template>
  </GlobalWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalWindow from '@/components/common/GlobalWindow'
import { getById } from '@/api/business/workorder'
export default {
  name: 'OperaWorkorderDetailDbhWindow',
  extends: BaseOpera,
  components: { GlobalWindow },
  data () {
    return {
      id: '',
      type: null,
      title: '工单详情',
      info: {},
      statusMap: {
        0: '待分配WTS',
        1: '待分配任务',
        2: '待处理',
        3: '已解决',
        4: '已解决',
        5: '已解决'
      },
      cateList: {
        0: 'SHE事件工单',
        1: '跌绊滑事件工单',
        2: 'DCA事件提交记录',
        3: 'DCA事件工单'
      }
    }
  },
  methods: {
    open (title, target) {
      this.title = title
      this.visible = true
      this.info = target
      this.getDetail()
      this.type = this.info.type
    },
    close () {
      this.visible = false
    },
    getDetail () {
      getById(this.info.id).then(res => {
        this.info = res
        if (this.info.logList && this.info.logList.length > 0) {
          this.info.logList.forEach(item => {
            if (item.approveList && item.approveList.length == 1 && item.type !== 1) {
              item.title = item.approveList[0].title
              item.faceImg = item.approveList[0].faceImg
              item.memberName = item.approveList[0].memberName
              item.statusInfo = item.approveList[0].statusInfo
              item.approveList = []
            }
          })
        }
      })
    },
    reject () { },
    handleAvatarSuccess () { },
    beforeAvatarUpload () { }
  }
}
</script>
<style lang="scss" scoped>
@import "@/assets/style/variables.scss";
.upload_box {
  width: 84px;
  height: 84px;
  border-radius: 4px;
  background-color: #f7f7f7;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #999999;
  border: 1px solid #e4e4e4;
  .icon {
    font-size: 24px;
  }
  .text {
    font-size: 12px;
  }
}
.side_title {
  font-weight: 600;
  font-size: 18px;
  color: #111111;
  margin-bottom: 20px;
  margin-left: 20px;
  margin-top: 20px;
}
.modal_wrap {
  display: flex;
  height: 100%;
  .modal_content {
    flex: 1;
    padding: 0px 30px;
    border-radius: 8px;
    overflow: hidden;
    height: 100%;
    .title {
      font-weight: 600;
      font-size: 18px;
      color: #333333;
      margin-bottom: 20px;
      margin-top: 30px;
    }
    .info {
      .list {
        display: flex;
        flex-wrap: wrap;
        .item {
          display: flex;
          width: 40%;
          font-size: 14px;
          margin-bottom: 20px;
          &:nth-of-type(2n) {
            width: 60%;
          }
          .label {
            color: #888888;
            width: 100px;
          }
          .value {
            color: #111111;
          }
        }
      }
    }
    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      vertical-align: center;
      padding: 20px 30px;
      margin: 0 -30px;
      border-radius: 8px 8px 0 0;
      position: relative;
      .head_bg {
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        z-index: 9;
      }
      .h1 {
        font-weight: 600;
        font-size: 22px;
        color: #111111;
        margin-bottom: 8px;
      }
      .time {
        font-size: 14px;
        color: #999999;
      }
      .right {
        height: 40px;
        font-size: 16px;
        color: #ffffff;
        line-height: 40px;
        padding: 0 20px;
        background: #207ff7;
        box-shadow: 4px 4px 0px 0px rgba(32, 127, 247, 0.16);
        border-radius: 16px 0px 16px 0px;
        position: relative;
        z-index: 99;
      }
      .scs {
        background-color: #00BA67;
      }
      .msg {
        background-color: #ED4545;
      }
    }
    .table_info {
      .name_wrap {
        display: flex;
        align-items: center;
        .avatar {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          margin-right: 12px;
        }
        .content {
          .line {
            display: flex;
          }
          .tag {
            color: #b2cbf9;
            border: 1px solid #b2cbf9;
            padding: 0px 4px;
            border-radius: 4px;
            margin-left: 6px;
          }
        }
      }
    }
  }
  .side {
    height: 100%;
    width: 420px;
    background: #ffffff;
    border-left: 20px solid #f7f7f7;
    .list {
      .item {
        padding: 8px 0;
        position: relative;
        .separate {
          position: absolute;
          border-left: 2px dashed #cccccc;
          left: 31px;
          height: calc(100% - 0px);
          top: 30px;
        }
        .avatar {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          margin: 0 12px 0 16px;
          //border: 1px solid;
        }
        .childList {
          display: flex;
          flex-wrap: wrap;
          margin-left: 100px;
        }
        .company {
          font-size: 13px;
          color: #888888;
          width: calc(100% - 20px);
          .status {
            color: $primaryColor;
          }
         /* span{
            color: black;
          }*/
          .dealinfo{
            background-color: #f2f2f2;
            padding: 8px;
            display: block;
            margin-top: 5px;
            width: calc(100% - 20px);
          }
        }
        .m_content {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          margin-bottom: 4px;
        }
        .info {
          display: flex;
          /*align-items: center;*/
          margin-left: 20px;
          .icon {
            position: relative;
            z-index: 11;
            color: #53b76f;
            font-size: 24px;
          }
          .icon1 {
            position: relative;
            z-index: 11;
            color: deepskyblue;
            font-size: 24px;
          }
          .icon2 {
            position: relative;
            z-index: 11;
            color: #dc362e;
            font-size: 24px;
          }
          .iconnew {
            width: 24px;
            height: 24px;
          }
          .icon3 {
            position: relative;
            z-index: 11;
            color: gray;
            font-size: 24px;
          }
          .content {
            flex: 1;
            .line {
              display: flex;
              justify-content: space-between;
              align-content: center;
              margin-bottom: 6px;
              .status {
                color: #888888;
              }
              .padding {
                color: $primaryColor;
              }
              .name {
                font-weight: 600;
                font-size: 16px;
                color: #111111;
              }
              .time {
                color: #888888;
              }
            }
          }
        }
        .remark {
          background: #f7f7f7;
          border-radius: 4px;
          padding: 13px 15px;
          color: #666666;
          margin-left: 100px;
        }
      }
    }
  }
}
</style>
admin/src/components/business/OperaWorkorderDetailSheWindow.vue
@@ -27,6 +27,10 @@
              <div class="value">{{ info.memberName }} - {{ info.memberPhone || '[无手机号]' }}</div>
            </div>
            <div class="item">
              <div class="label">所属部门</div>
              <div class="value">{{ info.companyName }} </div>
            </div>
            <div class="item">
              <div class="label">上报时间</div>
              <div class="value">{{ info.submitDate +' '}}</div>
            </div>
@@ -89,7 +93,7 @@
          </div>
        </div>
      </div>
      <div class="side">
      <div class="side" v-if="false">
        <div class="side_title">操作历史</div>
        <div class="list" v-if=" info.logList != null && info.logList.length != 0
        ">
admin/src/views/business/workorderDbh.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,162 @@
<template>
  <TableLayout :permissions="['business:workorder:query']">
    <!-- æœç´¢è¡¨å• -->
    <div slot="search-form">
      <el-form ref="searchForm" :model="searchForm" label-width="100px" inline>
        <el-form-item label="风险类型" prop="typeId">
          <el-cascader  v-model="searchForm.categoryList" :options="categorys" @change="handleChangeCategory" :show-all-levels="false"
                        clearable filterable :props="categoryprops"  >
            <template slot-scope="{ node, data }">
              <span>{{ data.name }}</span> <!-- è‡ªå®šä¹‰æ˜¾ç¤ºå†…容 -->
            </template>
          </el-cascader>
        </el-form-item>
        <el-form-item label="上报人员" prop="memberName">
          <el-input v-model="searchForm.memberName" clearable placeholder="人员姓名或手机号" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <el-form-item label="工单号" prop="code">
          <el-input v-model="searchForm.code" clearable placeholder="请输入工单号" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <section>
          <el-button type="primary" @click="search">搜索</el-button>
          <el-button @click="reset">重置</el-button>
        </section>
      </el-form>
    </div>
    <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
    <template v-slot:table-wrap>
      <ul class="toolbar" v-permissions="['business:workorder:exportExcel']">
        <li> <el-button type="primary" :loading="isWorking.export" @click="exportExcel">导出</el-button></li>
      </ul>
      <el-table
        :height="tableHeightNew"
        v-loading="isWorking.search"
        :data="tableData.list"
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column prop="code"  label="工单号" min-width="150px" fixed>
          <template slot-scope="{row}">
            <span style="color: #2E68EC;cursor: pointer" @click="$refs.operaWorkorderWindow.open('SHE事件工单详情', row)" >{{ row.code || '-'}}</span>
          </template>
        </el-table-column>
        <el-table-column prop="typeName" label="伤害类型" min-width="100px"></el-table-column>
        <el-table-column prop="memberName" label="上报人员" min-width="100px">
          <template slot-scope="{row}">
            <span v-if="row.memberPhone" >{{row.memberName}} - {{row.memberPhone }}</span>
            <span v-else >{{row.memberName}} </span>
          </template>
        </el-table-column>
        <el-table-column prop="companyName" label="所在部门" min-width="100px"></el-table-column>
        <el-table-column prop="status" label="状态" min-width="100px">
          <template slot-scope="{row}">
            <span v-if="row.status ==0">待处理</span>
            <span v-else-if="row.status ==3 ||row.status ==4||row.status ==5">已处理</span>
            <span v-else>处理中</span>
          </template>
        </el-table-column>
        <el-table-column prop="submitDate" label="上报时间" min-width="150px"></el-table-column>
        <el-table-column prop="happenTime" label="发现时间" min-width="150px"></el-table-column>
        <el-table-column prop="riskInfo" label="风险描述" min-width="100px"></el-table-column>
        <el-table-column prop="createDate" label="创建时间" min-width="150px"></el-table-column>
        <el-table-column
          v-if="containPermissions(['business:workorder:update', 'business:workorder:delete'])"
          label="操作"
          min-width="120"
          fixed="right"
        >
          <template slot-scope="{row}">
            <el-button type="text" @click="$refs.operaWorkorderWindow.open('跌绊滑事件工单详情', row)" icon="el-icon-zoom-out" >查看详情</el-button>
          <!--<el-button type="text" @click="deleteById(row)" icon="el-icon-delete" v-permissions="['business:workorder:delete']">删除</el-button>-->
          </template>
        </el-table-column>
      </el-table>
      <pagination
        @size-change="handleSizeChange"
        @current-change="handlePageChange"
        :pagination="tableData.pagination"
      >
      </pagination>
    </template>
    <!-- æ–°å»º/修改 -->
    <OperaWorkorderDetailDbhWindow ref="operaWorkorderWindow" @success="handlePageChange"/>
  </TableLayout>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaWorkorderDetailDbhWindow from '@/components/business/OperaWorkorderDetailDbhWindow'
import { treeList } from '@/api/business/category'
export default {
  name: 'Workorder',
  extends: BaseTable,
  components: {TableLayout, Pagination, OperaWorkorderDetailDbhWindow },
  data () {
    return {
      // æœç´¢
      searchForm: {
        type: '3',
        memberName: '',
        memberCompanyId: '',
        localtionId: '',
        typeId: '',
        code: '',
        categoryList: []
      },
      categoryprops: {
        label: 'name',
        value: 'id',
        checkStrictly: true,
        lazyLoad: this.lazyLoad
      },
      categorys: []
    }
  },
  created () {
    this.config({
      module: '工单信息表',
      api: '/business/workorder',
      'field.id': 'id',
      'field.main': 'id'
    })
    this.loadCategorys()
    this.search()
  },
  methods: {
    handleChangeCategory (value) {
      if (this.searchForm.categoryList && this.searchForm.categoryList.length >= 1) {
        this.searchForm.typeId = this.searchForm.categoryList[this.searchForm.categoryList.length - 1]
      }
    },
    loadCategorys () {
      treeList({ type: 1})
        .then(res => {
          if (res && res.length > 0) {
            res[0].fsStatus = 1
            this.categorys = this.getCategoryTree(res)
          }
        })
    },
    getCategoryTree (tree) {
      if (tree == null) {
        return []
      }
      return tree.map(item => {
        const newItem = { ...item }
        if (newItem) {
          newItem.children = newItem.childList
        }
        if (item.children && item.children.length === 0) {
          this.$delete(newItem, 'children')
        } else {
          newItem.children = this.getCategoryTree(newItem.children)
        }
        // newItem.disabled = false
        return newItem
      })
    }
  }
}
</script>
admin/src/views/business/workorderDca.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,154 @@
<template>
  <TableLayout :permissions="['business:workorder:query']">
    <!-- æœç´¢è¡¨å• -->
    <div slot="search-form">
      <el-form ref="searchForm" :model="searchForm" label-width="100px" inline>
        <el-form-item label="风险类型" prop="typeId">
          <el-select v-model="searchForm.typeId">
          <el-option  clearable filterable
              v-for="item in categorys"
              :key="item.id"
              :label="item.name"
              :value="item.id">
          </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="上报人员" prop="memberName">
          <el-input v-model="searchForm.memberName" clearable placeholder="人员姓名或手机号" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <el-form-item label="工单号" prop="code">
          <el-input v-model="searchForm.code" clearable placeholder="请输入工单号" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <section>
          <el-button type="primary" @click="search">搜索</el-button>
          <el-button @click="reset">重置</el-button>
        </section>
      </el-form>
    </div>
    <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
    <template v-slot:table-wrap>
      <ul class="toolbar" v-permissions="['business:workorder:exportExcel']">
        <li> <el-button type="primary" :loading="isWorking.export" @click="exportExcel">导出</el-button></li>
      </ul>
      <el-table
        :height="tableHeightNew"
        v-loading="isWorking.search"
        :data="tableData.list"
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column prop="code"  label="工单号" min-width="150px" fixed>
          <template slot-scope="{row}">
            <span style="color: #2E68EC;cursor: pointer" @click="$refs.operaWorkorderWindow.open('SHE事件工单详情', row)" >{{ row.code || '-'}}</span>
          </template>
        </el-table-column>
        <el-table-column prop="memberName" label="上报人员" min-width="100px">
          <template slot-scope="{row}">
            <span v-if="row.memberPhone" >{{row.memberName}} - {{row.memberPhone }}</span>
            <span v-else >{{row.memberName}} </span>
          </template>
        </el-table-column>
        <el-table-column prop="companyName" label="所在部门" min-width="100px"></el-table-column>
        <el-table-column prop="status" label="状态" min-width="100px">
          <template slot-scope="{row}">
            <span v-if="row.status ==0">待处理</span>
            <span v-else-if="row.status ==3 ||row.status ==4||row.status ==5">已处理</span>
            <span v-else>处理中</span>
          </template>
        </el-table-column>
<!--
        <el-table-column prop="typeName" label="DCA类型" min-width="100px"></el-table-column>
-->
        <el-table-column prop="problemTitle" label="观察主题" min-width="150px"></el-table-column>
        <el-table-column prop="dcaYesNum" label="观察项统计" min-width="150px">
          <template slot-scope="{row}">
            <span  style="color: #1562e2" >符合:{{row.dcaYesNum}}  ä¸ç¬¦åˆï¼š{{row.dcaNoNum}}</span>
          </template>
        </el-table-column>
        <el-table-column prop="submitDate" label="上报时间" min-width="150px"></el-table-column>
        <el-table-column prop="happenTime" label="发现时间" min-width="150px"></el-table-column>
        <el-table-column prop="createDate" label="创建时间" min-width="150px"></el-table-column>
        <el-table-column
          v-if="containPermissions(['business:workorder:update', 'business:workorder:delete'])"
          label="操作"
          min-width="120"
          fixed="right"
        >
          <template slot-scope="{row}">
            <el-button type="text" @click="$refs.operaWorkorderWindow.open('DCA事件工单详情', row)" icon="el-icon-zoom-out" >查看详情</el-button>
          <!--<el-button type="text" @click="deleteById(row)" icon="el-icon-delete" v-permissions="['business:workorder:delete']">删除</el-button>-->
          </template>
        </el-table-column>
      </el-table>
      <pagination
        @size-change="handleSizeChange"
        @current-change="handlePageChange"
        :pagination="tableData.pagination"
      >
      </pagination>
    </template>
    <!-- æ–°å»º/修改 -->
    <OperaWorkorderDetailDcaWindow ref="operaWorkorderWindow" @success="handlePageChange"/>
  </TableLayout>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaWorkorderDetailDcaWindow from '@/components/business/OperaWorkorderDetailDcaWindow'
import { allList } from '@/api/business/category'
export default {
  name: 'Workorder',
  extends: BaseTable,
  components: {TableLayout, Pagination, OperaWorkorderDetailDcaWindow },
  data () {
    return {
      // æœç´¢
      searchForm: {
        type: '1',
        memberName: '',
        memberCompanyId: '',
        localtionId: '',
        typeId: '',
        code: '',
        categoryList: []
      },
      categoryprops: {
        label: 'name',
        value: 'id',
        checkStrictly: true,
        lazyLoad: this.lazyLoad
      },
      categorys: []
    }
  },
  created () {
    this.config({
      module: '工单信息表',
      api: '/business/workorder',
      'field.id': 'id',
      'field.main': 'id'
    })
    this.loadCategorys()
    this.search()
  },
  methods: {
    handleChangeCategory (value) {
      if (this.searchForm.categoryList && this.searchForm.categoryList.length >= 1) {
        this.searchForm.typeId = this.searchForm.categoryList[this.searchForm.categoryList.length - 1]
      }
    },
    loadCategorys () {
      allList({ type: 4, isRoot:1})
        .then(res => {
          if (res && res.length > 0) {
            this.categorys = res
          }
        })
    },
  }
}
</script>
admin/src/views/business/workorderShe.vue
@@ -12,10 +12,12 @@
          </el-cascader>
        </el-form-item>
        <el-form-item label="上报人员" prop="memberName">
          <el-input v-model="searchForm.memberName" placeholder="人员姓名或手机号" @keypress.enter.native="search"></el-input>
          <el-input v-model="searchForm.memberName" clearable placeholder="人员姓名或手机号" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <el-form-item label="工单号" prop="code">
          <el-input v-model="searchForm.code" placeholder="请输入工单号" @keypress.enter.native="search"></el-input>
          <el-input v-model="searchForm.code" clearable placeholder="请输入工单号" @keypress.enter.native="search"></el-input>
        </el-form-item>
        <section>
          <el-button type="primary" @click="search">搜索</el-button>
@@ -45,14 +47,14 @@
        <el-table-column prop="status" label="状态" min-width="100px">
          <template slot-scope="{row}">
            <span v-if="row.status ==0">待处理</span>
            <span v-else-if="row.status ==4">已处理</span>
            <span v-else-if="row.status ==3">已关闭</span>
            <span v-else-if="row.status ==3 ||row.status ==4||row.status ==5">已处理</span>
            <span v-else>处理中</span>
          </template>
        </el-table-column>
        <el-table-column prop="memberName" label="上报人员" min-width="100px">
          <template slot-scope="{row}">
            <span >{{row.memberName}} - {{row.memberPhone||''}}</span>
            <span v-if="row.memberPhone" >{{row.memberName}} - {{row.memberPhone }}</span>
            <span v-else >{{row.memberName}} </span>
          </template>
        </el-table-column>
        <el-table-column prop="companyName" label="所在部门" min-width="100px"></el-table-column>
server/src/main/java/com/doumee/api/business/CategoryController.java
@@ -69,6 +69,12 @@
    public ApiResponse<PageData<Category>> findPage (@RequestBody PageWrap<Category> pageWrap) {
        return ApiResponse.success(categoryService.findPage(pageWrap));
    }
    @ApiOperation("分页查询")
    @PostMapping("/list")
    @RequiresPermissions("business:category:query")
    public ApiResponse<List<Category>> findList (@RequestBody  Category pageWrap) {
        return ApiResponse.success(categoryService.findList(pageWrap));
    }
    @ApiOperation("导出Excel")
    @PostMapping("/exportExcel")
server/src/main/java/com/doumee/dao/business/model/Workorder.java
@@ -137,18 +137,15 @@
    @ApiModelProperty(value = "风险描述", example = "1")
    @ExcelExportColumn(name="风险描述")
    private String riskInfo;
    @ApiModelProperty(value = "当前物业主管企业微信编码", example = "1")
    @ExcelExportColumn(name="当前物业主管企业微信编码")
    private String managerId;
    @ApiModelProperty(value = "当前处理人员企业微信编码", example = "1")
    @ExcelExportColumn(name="当前处理人员企业微信编码")
    private String dealerId;
    @ApiModelProperty(value = "分配时间")
    @ExcelExportColumn(name="分配时间")
    private Date dispatchTime;
    @ApiModelProperty(value = "分配备注")
server/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
@@ -199,6 +199,7 @@
                .eq(category.getType() != null, Category::getType, category.getType())
                .eq(category.getParentId() != null, Category::getParentId, category.getParentId())
                .eq(category.getNamePath() != null, Category::getNamePath, category.getNamePath())
                .isNull(category.getIsRoot() != null &&category.getIsRoot().equals(Constants.ONE), Category::getParentId)
                .eq(category.getIdPath() != null, Category::getIdPath, category.getIdPath())
                .orderByAsc( Category::getSortnum);
        return categoryMapper.selectJoinList(Category.class,queryWrapper);
server/src/main/java/com/doumee/service/business/impl/WorkorderServiceImpl.java
@@ -527,11 +527,15 @@
                .eq(pageWrap.getModel().getProblemId() != null, Workorder::getProblemId, pageWrap.getModel().getProblemId())
                .eq(pageWrap.getModel().getProblemInfo() != null, Workorder::getProblemInfo, pageWrap.getModel().getProblemInfo())
                .eq(pageWrap.getModel().getLocationName() != null, Workorder::getLocationName, pageWrap.getModel().getLocationName())
                .eq(pageWrap.getModel().getCode() != null, Workorder::getCode, pageWrap.getModel().getCode())
                .like(pageWrap.getModel().getCode() != null, Workorder::getCode, pageWrap.getModel().getCode())
                .eq(pageWrap.getModel().getDcaYesNum() != null, Workorder::getDcaYesNum, pageWrap.getModel().getDcaYesNum())
                .eq(pageWrap.getModel().getDcaNoNum() != null, Workorder::getDcaNoNum, pageWrap.getModel().getDcaNoNum())
                .eq(pageWrap.getModel().getDcaRecordId() != null, Workorder::getDcaRecordId, pageWrap.getModel().getDcaRecordId())
                .eq(pageWrap.getModel().getDcaCsIds() != null, Workorder::getDcaCsIds, pageWrap.getModel().getDcaCsIds()) ;
        if (pageWrap.getModel().getMemberName() != null) {
            queryWrapper.and( ms->ms.like(Member::getName,pageWrap.getModel().getMemberName())
                    .or().like(Member::getPhone,pageWrap.getModel().getMemberName()) );
        }
                queryWrapper.orderByDesc(Workorder::getCreateDate);
        return PageData.from(workorderMapper.selectJoinPage(page,Workorder.class, queryWrapper));
    }