licp
2024-12-20 8b8e088d012550a662aca3aad96afaf6958efedf
完成投诉迁移
已修改1个文件
已添加1个文件
639 ■■■■■ 文件已修改
src/assets/api/controller.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/view/a7-complaint.vue 628 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/api/controller.js
@@ -62,6 +62,7 @@
    qualityMonitor,
    measuresAddressRisksOpportunities,
    processReport,
    processComplain,
  }
}
@@ -816,4 +817,14 @@
  getProcessReport:'/processReport/getProcessReport',//查看
  doProcessReport:'/processReport/doProcessReport',//修改
  exportProcessReport:'/processReport/exportProcessReport',//导出
}
// æŠ•诉
const processComplain = {
  pageProcessComplain:'/processComplain/pageProcessComplain',//投诉处理分页
  addProcessComplain:'/processComplain/addProcessComplain',//投诉处理新增
  delProcessComplain:'/processComplain/delProcessComplain',//投诉处理删除
  getProcessComplain:'/processComplain/getProcessComplain',//投诉处理详情
  doProcessComplain:'/processComplain/doProcessComplain',//投诉处理修改
  exportProcessComplain :'/processComplain/exportProcessComplain ',//投诉处理导出
}
src/components/view/a7-complaint.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,628 @@
<template>
  <div class="Complaint">
    <el-row class="title">
      <el-col :span="12" style="padding-left: 20px;text-align: left;">投诉</el-col>
      <el-col :span="12" style="text-align: right;">
        <el-button size="medium" type="primary" @click="handleDown" :loading="outLoading" v-if="outPower">导出</el-button>
        <el-button size="medium" type="primary" @click="openAdd" v-if="addPower">新增</el-button>
      </el-col>
    </el-row>
    <div class="search">
      <div class="search_thing">
        <div class="search_label">样品编号:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.sampleCode"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">投诉名称:</div>
        <div class="search_input">
          <!-- <el-date-picker
            v-model="componentData.entity.createTime"
            type="date"
            size="small"
            placeholder="选择日期"
            format="yyyy-MM-dd HH:mm:ss"
            value-format="yyyy-MM-dd HH:mm:ss" @change="refreshTable()">
          </el-date-picker> -->
          <el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.complainName"
            @keyup.enter.native="refreshTable()"></el-input>
        </div>
      </div>
      <div class="search_thing" style="padding-left: 30px;">
        <el-button size="small" @click="refresh()">重 ç½®</el-button>
        <el-button size="small" type="primary" @click="refreshTable()">查 è¯¢</el-button>
      </div>
    </div>
    <div class="table">
      <ValueTable ref="ValueTable" :url="$api.processComplain.pageProcessComplain"
        :delUrl="$api.processComplain.delProcessComplain"
        :componentData="componentData" :key="upIndex"/>
    </div>
    <el-dialog
      title="新增"
      :visible.sync="addDialogVisible"
      width="400px">
      <el-row>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">投诉方名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.complainName"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">检验报告编号:</div>
            <div class="search_input">
              <el-input size="small" placeholder="请输入" clearable v-model="addInfo.code"></el-input>
              <!-- <el-select v-model="addInfo.insReportId" filterable placeholder="请选择" size="small" style="width: 100%;">
                <el-option
                  v-for="item in reportList"
                  :key="item.id"
                  :label="item.code"
                  :value="item.id">
                </el-option>
              </el-select> -->
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">样品编号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.sampleCode"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24">
          <div class="search_thing">
            <div class="search_label">投诉方式:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.complainMethod"></el-input></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog
      :title="title"
      :visible.sync="handleDialogVisible"
      width="800px" :class="{downPdf:title=='导出'}" :modal="title!='导出'">
      <div class="dialog-body">
        <div id="dialogBody">
          <h4 style="display: flex;align-items: center;flex-direction: column;justify-content: center;">
          <span style="font-size: 20px;">客户投诉受理单</span>
          <span>Customer complaint receipts</span>
        </h4>
        <p style="display: flex;justify-content: space-between;margin-top: 16px;">
          <span>{{ currentInfo0.complainNo }}</span>
          <span>NO:</span>
        </p>
        <table border="1" class="tables" cellpadding="10">
          <tr>
            <td colspan="3">
              <p>投诉方名称</p>
              <p class="en">Name of the complaining party</p>
            </td>
            <td colspan="3">{{ currentInfo0.complainName }}</td>
          </tr>
          <tr>
            <td>
              <p>检测报告编号</p>
              <p class="en">Test report number</p>
            </td>
            <td colspan="3">{{ currentInfo0.code }}</td>
            <td >
              <p>样品编号</p>
              <p class="en">Sample number</p>
            </td>
            <td>{{ currentInfo0.sampleCode }}</td>
          </tr>
          <tr>
            <td>
              <p>投诉人</p>
              <p class="en">Complainant</p>
            </td>
            <td>{{ currentInfo0.createUser }}</td>
            <td>
              <p>电话</p>
              <p class="en">Phone</p>
            </td>
            <td>{{ currentInfo0.phone }}</td>
            <td>
              <p>E-Mail</p>
              <p class="en">E-mail</p>
            </td>
            <td>{{ currentInfo0.email }}</td>
          </tr>
          <tr>
            <td>
              <p>投诉方式</p>
              <p class="en">Complaint method</p>
            </td>
            <td colspan="3">{{ currentInfo0.complainMethod }}</td>
            <td >
              <p>投诉日期</p>
              <p class="en">Date of complaint</p>
            </td>
            <td>{{ currentInfo0.createTime?currentInfo0.createTime.split(' ')[0]:'' }}</td>
          </tr>
          <tr>
            <td>
              <p>问题记录</p>
              <p class="en">Problem logging</p>
            </td>
            <td colspan="5">
              <div class="user-content">
                <el-input
                  type="textarea"
                  :rows="3"
                  placeholder="请输入内容"
                  v-model="currentInfo0.problemRecords" v-if="title=='处理投诉'">
                </el-input>
                <p v-else style="text-align: left;line-height: 26px;">{{ currentInfo0.problemRecords }}</p>
              </div>
              <div class="user-info" v-if="title!='处理投诉'">
                <div style="width: 200px;margin-right: 10px;">
                  <p style="text-align: end;">质量负责人:</p>
                  <p class="en" style="text-align: end;">Quality Manager:</p>
                </div>
                <span>{{ currentInfo0.problemRecordsUserName }}</span>
                <div style="width: 70px;">
                  <p>日期:</p>
                  <p class="en">Date:</p>
                </div>
                <span style="margin-right: 16px;">{{ currentInfo0.problemRecordsTime }}</span>
              </div>
            </td>
          </tr>
          <tr>
            <td>
              <p>责任归属及投诉是否成立</p>
              <p class="en">Attribution of responsibility and whether the complaint is established</p>
            </td>
            <td colspan="5">
              <div class="user-content">
                <el-input
                  type="textarea"
                  :rows="3"
                  placeholder="请输入内容"
                  v-model="currentInfo0.dutyOwnership" v-if="title=='处理投诉'">
                </el-input>
                <p v-else style="text-align: left;line-height: 26px;">{{ currentInfo0.dutyOwnership }}</p>
              </div>
              <div class="user-info" v-if="title!='处理投诉'">
                <div style="width: 200px;margin-right: 10px;">
                  <p style="text-align: end;">质量负责人:</p>
                  <p class="en" style="text-align: end;">Quality Manager:</p>
                </div>
                <span>{{ currentInfo0.dutyOwnershipUserName }}</span>
                <div style="width: 70px;">
                  <p>日期:</p>
                  <p class="en">Date:</p>
                </div>
                <span style="margin-right: 16px;">{{ currentInfo0.dutyOwnershipTime }}</span>
              </div>
            </td>
          </tr>
          <tr>
            <td>
              <p>原因分析</p>
              <p class="en">Cause analysis</p>
            </td>
            <td colspan="5">
              <div class="user-content">
                <el-input
                  type="textarea"
                  :rows="3"
                  placeholder="请输入内容"
                  v-model="currentInfo0.causeAnalysis" v-if="title=='处理投诉'">
                </el-input>
                <p v-else style="text-align: left;line-height: 26px;">{{ currentInfo0.causeAnalysis }}</p>
              </div>
              <div class="user-info" v-if="title!='处理投诉'">
                <div style="width: 200px;margin-right: 10px;">
                  <p style="text-align: end;">责任部门负责人:</p>
                  <p class="en" style="text-align: end;">Head of Responsible Department:</p>
                </div>
                <span>{{ currentInfo0.causeAnalysisUserName }}</span>
                <div style="width: 70px;">
                  <p>日期:</p>
                  <p class="en">Date:</p>
                </div>
                <span style="margin-right: 16px;">{{ currentInfo0.causeAnalysisTime }}</span>
              </div>
            </td>
          </tr>
          <tr>
            <td>
              <p>纠正措施</p>
              <p class="en">Corrective actions</p>
            </td>
            <td colspan="5">
              <div class="user-content">
                <el-input
                  type="textarea"
                  :rows="3"
                  placeholder="请输入内容"
                  v-model="currentInfo0.correctiveAction" v-if="title=='处理投诉'">
                </el-input>
                <p v-else style="text-align: left;line-height: 26px;">{{ currentInfo0.correctiveAction }}</p>
              </div>
              <div class="user-info" v-if="title!='处理投诉'">
                <div style="width: 200px;margin-right: 10px;">
                  <p style="text-align: end;">责任部门负责人:</p>
                  <p class="en" style="text-align: end;">Head of Responsible Department:</p>
                </div>
                <span>{{ currentInfo0.correctiveActionUserName }}</span>
                <div style="width: 70px;">
                  <p>日期:</p>
                  <p class="en">Date:</p>
                </div>
                <span style="margin-right: 16px;">{{ currentInfo0.correctiveActionTime }}</span>
              </div>
            </td>
          </tr>
          <tr>
            <td>
              <p>纠正措施确认</p>
              <p class="en">Corrective actions confirmation</p>
            </td>
            <td colspan="5">
              <div class="user-content">
                <el-input
                  type="textarea"
                  :rows="3"
                  placeholder="请输入内容"
                  v-model="currentInfo0.correctiveActionConfirmation" v-if="title=='处理投诉'">
                </el-input>
                <p v-else style="text-align: left;line-height: 26px;">{{ currentInfo0.correctiveActionConfirmation }}</p>
              </div>
              <div class="user-info" v-if="title!='处理投诉'">
                <div style="width: 200px;margin-right: 10px;">
                  <p style="text-align: end;">质量负责人:</p>
                  <p class="en" style="text-align: end;">Quality Manager:</p>
                </div>
                <span>{{ currentInfo0.correctiveActionConfirmationUserName }}</span>
                <div style="width: 70px;">
                  <p>日期:</p>
                  <p class="en">Date:</p>
                </div>
                <span style="margin-right: 16px;">{{ currentInfo0.correctiveActionConfirmationTime }}</span>
              </div>
            </td>
          </tr>
        </table>
        </div>
      </div>
      <span slot="footer" class="dialog-footer" v-if="title=='处理投诉'">
        <el-button @click="handleDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="submit" :loading="addLoading">提 äº¤</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import ValueTable from '../tool/value-table.vue'
import {getYearAndMonthAndDays} from '../../util/date'
import {exportHtmlToPDF} from '../../util/downHtmlToPDF'
export default {
  components: {
    ValueTable
  },
  data() {
    return {
      addPower:false,
      outLoading:false,
      addDialogVisible:false,
      addLoading:false,
      handleDialogVisible:false,
      title:'处理投诉',
      componentData: {
          entity: {
            sampleCode: null,
            complainName: null,
            orderBy: {
              field: 'id',
              order: 'asc'
            }
          },
          isIndex: true,
          showSelect: false,
          select: false,
          do: [{
            id: 'handleLook',
            font: '查看',
            type: 'text',
            method: 'handleLook',
          }, {
            id: 'delete',
            font: '删除',
            type: 'text',
            method: 'doDiy'
          }, {
            id: 'handleWork',
            font: '处理',
            type: 'text',
            method: 'handleWork'
          }, {
            id: 'handleOut',
            font: '导出',
            type: 'text',
            method: 'handleOut'
          }],
          tagField: {},
          selectField: {
          },
          requiredAdd: [],
          requiredUp: [],
          needSort: [],
          inputType: ''
        },
        entityCopy: {},
        upIndex: 0,
        addInfo:{},//新增信息
        currentInfo:null,//接口请求回来的信息
        currentInfo0:{},//用户编辑过后的信息
        reportList:[],//报告列表
        outPower:false,
    };
  },
  mounted() {
    this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getPower()
  },
  methods: {
    // æƒé™åˆ†é…
    getPower() {
      let power = JSON.parse(sessionStorage.getItem('power'))
      let up = false
      let del = false
      let add = false
      let out = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'doProcessComplain') {
          up = true
        }
        if (power[i].menuMethod == 'addProcessComplain') {
          add = true
        }
        if (power[i].menuMethod == 'delProcessComplain') {
          del = true
        }
        if (power[i].menuMethod == 'exportProcessComplain') {
          out = true
        }
      }
      if (!up) {
        this.componentData.do.splice(2, 1)
      }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      this.outPower = out
      this.addPower = add
    },
    getPageInsReport(){
      this.$axios.post(this.$api.insReport.pageInsReport,
      {
        entity:{
          orderBy:{
            field: "id",
            order: "desc"
          }
        },
        page:{
          current:-1,
          size:-1
        }
      },{headers: { 'Content-Type': 'application/json' }}).then((res)=>{
        this.reportList = res.data.body.records
      })
    },
    openAdd() {
      this.addInfo = {}
      this.addDialogVisible = true
    },
    handleAdd(){
      this.addLoading = true
      this.$axios.post(this.$api.processComplain.addProcessComplain,
      this.addInfo ,{headers: { 'Content-Type': 'application/json' }}
    ).then((res)=>{
        this.addLoading = false
        if(res.code==201){
          this.$message({
            type: 'error',
            message: '新增失败'
          })
          return
        }
        this.$message({
          type: 'success',
          message: '新增成功'
        })
        this.addDialogVisible = false
        this.refresh()
      })
    },
    // å¤„理投诉
    handleWork(row){
      this.$axios.post(this.$api.processComplain.getProcessComplain,
      {id:row.id}).then((res)=>{
        this.currentInfo = res.data
        this.currentInfo0 = this.HaveJson(res.data)
        this.title = '处理投诉'
        this.handleDialogVisible = true
      })
    },
    submit(){
      this.handleParam('problemRecords')
      this.handleParam('dutyOwnership')
      this.handleParam('causeAnalysis')
      this.handleParam('correctiveAction')
      this.handleParam('correctiveActionConfirmation')
      this.addLoading = true
      for(let i in this.currentInfo0){
        if(!this.currentInfo0[i]){
          delete this.currentInfo0[i]
        }
      }
      this.$axios.post(this.$api.processComplain.doProcessComplain,
      this.currentInfo0 ,{headers: { 'Content-Type': 'application/json' }}
    ).then((res)=>{
        this.addLoading = false
        if(res.code==201){
          this.$message({
            type: 'error',
            message: '提交失败'
          })
          return
        }
        this.$message({
          type: 'success',
          message: '提交成功'
        })
        this.handleDialogVisible = false
        this.refresh()
      })
    },
    /**
     * å¤„理参数
     *
     * @param {string} type - éœ€è¦å¤„理的参数类型
     */
    handleParam(type){
      if(this.currentInfo0[type]!=this.currentInfo[type]){
        this.currentInfo0[type+'User'] = JSON.parse(localStorage.getItem("user")).userId
        this.currentInfo0[type+'Time'] = getYearAndMonthAndDays()
      }
    },
    // æŸ¥çœ‹æŠ•诉
    handleLook(row){
      this.$axios.post(this.$api.processComplain.getProcessComplain,
      {id:row.id}).then((res)=>{
        this.currentInfo = res.data
        this.currentInfo0 = this.HaveJson(res.data)
        this.title = '查看投诉'
        this.handleDialogVisible = true
      })
    },
    refreshTable() {
      this.$refs['ValueTable'].selectList()
    },
    refresh() {
      this.componentData.entity = this.HaveJson(this.entityCopy)
      this.upIndex++
      this.refreshTable()
    },
    handleDown(){
      this.outLoading = true
      this.$axios.post(this.$api.processComplain.exportProcessComplain,{entity:{sampleCode:this.componentData.entity.sampleCode,complainName:this.componentData.entity.complainName}},{responseType: "blob",headers: { 'Content-Type': 'application/json' }}).then(res => {
        this.outLoading = false
        if(res.code==201){
          return
        }
        this.$message.success('导出成功')
        const blob = new Blob([res],{ type: 'application/octet-stream' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = '投诉情况汇总表.xlsx';
        link.click();
      })
    },
    handleOut(row){
      this.$axios.post(this.$api.processComplain.getProcessComplain,
      {id:row.id}).then((res)=>{
        if(res.code==201){
          return
        }
        this.currentInfo = res.data
        this.currentInfo0 = this.HaveJson(res.data)
        this.title = '导出'
        this.handleDialogVisible = true
        setTimeout(() => {
          this.$nextTick(() => {
            const element = document.getElementById("dialogBody");
            exportHtmlToPDF(element,'投诉详情').then(res=>{
              this.handleDialogVisible = false
            })
          })
        }, 500);
      })
    }
  },
}
</script>
<style scoped>
  .title {
    height: 60px;
    line-height: 60px;
  }
  .search {
    background-color: #fff;
    height: 80px;
    display: flex;
    align-items: center;
  }
  .search_thing {
    width: 350px;
    display: flex;
    align-items: center;
  }
  .search_label {
    width: 110px;
    font-size: 14px;
    text-align: right;
  }
  .search_input {
    width: calc(100% - 110px);
  }
  .table {
    margin-top: 10px;
    background-color: #fff;
    width: calc(100% - 40px);
    height: calc(100% - 60px - 80px - 10px - 40px);
    padding: 20px;
  }
  .dialog-body{
    max-height: 75vh;
    overflow-y: auto;
  }
  .tables {
    table-layout: fixed;
    width: 100%;
    margin-top: 10px;
  }
  .tables td {
    height: 40px;
    width: 100px;
    text-align: center;
    font-size: 14px;
    word-wrap: break-word;
    white-space: normal;
  }
  .en{
    font-size: 12px;
    word-break: break-word; /* è‡ªåŠ¨æ–­è¡Œ */
    overflow-wrap: break-word; /* é˜²æ­¢æº¢å‡º */
    white-space: normal; /* é»˜è®¤æ¢è¡Œ */
  }
  .user-info{
    display: flex;
    align-items: center;
    justify-content: end;
  }
  .user-content{
    min-height: 60px;
  }
  .downPdf{
    opacity: 0 !important;
  }
</style>