src/views/CNAS/systemManagement/customerSatisfaction/components/formDialog.vue
@@ -2,29 +2,31 @@
  <div>
    <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" v-model="formDia" title="客户满意度调查表"
      width="70%" @close="closeFormDia">
      <div class="survey-intro">
        尊敬的客户:为了使本实验室的服务水平得以不断提高,特设此客户满意度调查表,烦请您拨冗填写。我们十分注重您的反馈,您的意见和建议,将为本实验室的持续改进提供重要参考,从而达到您期望的水平。请以传真或邮件方式将此表回复本实验室,多谢合作!在此非常感谢您对我们工作的支持!
      </div>
      <table border="1" cellspacing="10" class="tables">
        <colgroup>
          <col style="width: 12%" />
          <col style="width: 12%" />
          <col style="width: 12%" />
          <col style="width: 10.66%" />
          <col style="width: 10.66%" />
          <col style="width: 10.66%" />
          <col style="width: 10.66%" />
          <col style="width: 10.66%" />
          <col style="width: 10.66%" />
        </colgroup>
        <tr>
          <td class="td-title">
            <p>单位名称:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.unitName" placeholder="请输入内容" size="small">
            </el-input>
          </td>
          <td class="td-title">
            <p>日期:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-date-picker v-model="form.fillDate" format="YYYY-MM-DD" placeholder="选择日期" size="small" type="date"
              value-format="YYYY-MM-DD">
            </el-date-picker>
          <td class="section-title" colspan="9">
            <p>客 户 填 写</p>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>客户:</p>
          </td>
          <td class="td-info">
          <td class="td-info" colspan="8">
            <el-select v-model="form.orderId" filterable clearable size="small" style="width: 100%"
              popper-class="customer-select-popper" placeholder="请选择客户(已完成委托单)" @change="onCustomerChange">
              <el-option v-for="opt in customerOptions" :key="opt.id" :label="opt.company" :value="opt.id">
@@ -36,111 +38,114 @@
              </el-option>
            </el-select>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>部门:</p>
            <p>地址:</p>
          </td>
          <td class="td-info">
            <el-input v-model="form.department" placeholder="请输入内容" size="small">
            </el-input>
          </td>
          <td class="td-title">
            <p>联系电话:</p>
          </td>
          <td class="td-info">
            <el-input v-model="form.contactNumber" placeholder="请输入内容" size="small">
          <td class="td-info" colspan="8">
            <el-input v-model="form.address" placeholder="请输入内容" size="small">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>服务态度:</p>
            <p>联系人:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-radio-group v-model="form.serviceAttitude">
              <el-radio :value="0">满意</el-radio>
              <el-radio :value="1">一般</el-radio>
              <el-radio :value="2">不满意</el-radio>
            </el-radio-group>
          <td class="td-info" colspan="3">
            <el-input v-model="form.contactPerson" placeholder="请输入内容" size="small">
            </el-input>
          </td>
          <td class="td-title">
            <p>建议:</p>
            <p>填表日期:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.serviceAttitudeSuggestion" placeholder="请输入内容" size="small">
            </el-input>
          <td class="td-info" colspan="4">
            <el-date-picker v-model="form.fillDate" format="YYYY-MM-DD" placeholder="选择日期" size="small" type="date"
              value-format="YYYY-MM-DD" style="width: 100%">
            </el-date-picker>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>技术能力:</p>
          <td class="td-title" colspan="3">
            <p>评分项</p>
          </td>
          <td class="td-info" colspan="2">
            <el-radio-group v-model="form.technicalCompetence">
              <el-radio :value="0">满意</el-radio>
              <el-radio :value="1">一般</el-radio>
              <el-radio :value="2">不满意</el-radio>
            </el-radio-group>
          <td class="score-head" colspan="2">优秀</td>
          <td class="score-head" colspan="2">一般</td>
          <td class="score-head" colspan="2">差</td>
        </tr>
        <tr>
          <td class="td-title" colspan="3">
            <p>(分值:10—5分)</p>
          </td>
          <td class="td-title">
            <p>建议:</p>
          <td class="score-head" v-for="s in scoreOptions" :key="'head-' + s">{{ s }}</td>
        </tr>
        <tr v-for="(q, qi) in questions" :key="q.key">
          <td class="td-title question-title" colspan="3">
            <p>{{ q.text }}</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.technicalCompetenceSuggestion" placeholder="请输入内容" size="small">
            </el-input>
          <td class="score-cell" v-for="s in scoreOptions" :key="s">
            <el-radio v-model="form[q.key]" :value="s" class="score-radio"></el-radio>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>检测工作:</p>
          <td class="td-title" colspan="3">
            <p>*您认为本实验室还有哪些不足,或对我们的工作还有哪些意见和建议?请说明:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-radio-group v-model="form.inspectionWork">
              <el-radio :value="0">满意</el-radio>
              <el-radio :value="1">一般</el-radio>
              <el-radio :value="2">不满意</el-radio>
            </el-radio-group>
          </td>
          <td class="td-title">
            <p>建议:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.inspectionWorkSuggestion" placeholder="请输入内容" size="small">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>收费合理性:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-radio-group v-model="form.reasonableFees">
              <el-radio :value="0">满意</el-radio>
              <el-radio :value="1">一般</el-radio>
              <el-radio :value="2">不满意</el-radio>
            </el-radio-group>
          </td>
          <td class="td-title">
            <p>建议:</p>
          </td>
          <td class="td-info" colspan="2">
            <el-input v-model="form.reasonableFeesSuggestion" placeholder="请输入内容" size="small">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>您对我们的希望:</p>
          </td>
          <td class="td-info" colspan="5">
          <td class="td-info" colspan="6">
            <el-input v-model="form.remark" :rows="4" placeholder="请输入内容" size="small" type="textarea">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="section-title" colspan="9">
            <p>实 验 室 填 写</p>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>总分:</p>
          </td>
          <td class="td-info">
            <span class="score-result">{{ scoreComplete ? totalScore : '--' }}</span> 分
          </td>
          <td class="td-title" colspan="2">
            <p>满意度评定:</p>
          </td>
          <td class="td-info" colspan="5">
            {{ scoreComplete ? satisfactionText : '填写评分后自动计算' }}
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>意见:</p>
          </td>
          <td class="td-info" colspan="8">
            <el-input v-model="form.labOpinion" :rows="3" placeholder="请输入内容" size="small" type="textarea">
            </el-input>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>质量负责人:</p>
          </td>
          <td class="td-info" colspan="3">
            <el-input v-model="form.qualityManager" placeholder="请输入内容" size="small">
            </el-input>
          </td>
          <td class="td-title">
            <p>日期:</p>
          </td>
          <td class="td-info" colspan="4">
            <el-date-picker v-model="form.labDate" format="YYYY-MM-DD" placeholder="选择日期" size="small" type="date"
              value-format="YYYY-MM-DD" style="width: 100%">
            </el-date-picker>
          </td>
        </tr>
        <tr>
          <td class="td-title">
            <p>照片:</p>
          </td>
          <td class="td-info" colspan="5">
          <td class="td-info" colspan="8">
            <lims-attachment ref="photoAttachment" inline defer-upload accept=".jpg,.jpeg,.png,.gif"
              :main-id="form.clientSatisfactionId || ''" upload-url="/clientSatisfaction/uploadAttachment"
              select-url="/clientSatisfaction/selectAttachments" delete-url="/clientSatisfaction/deleteAttachment"
@@ -148,7 +153,7 @@
          </td>
        </tr>
      </table>
      <template #footer><span  class="dialog-footer">
      <template #footer><span class="dialog-footer">
        <el-button @click="closeFormDia">取 消</el-button>
        <el-button :loading="editLoad" type="primary" @click="handleEdit">提 交</el-button>
      </span></template>
@@ -163,49 +168,80 @@
} from '@/api/cnas/systemManagement/customerSatisfaction.js'
import { selectCompletedOrders } from '@/api/business/productOrder'
import limsAttachment from '@/components/Attachment/lims-attachment.vue'
const QUESTIONS = [
  { key: 'score1', text: '1.业务/接待人员的服务态度' },
  { key: 'score2', text: '2.业务/接待人员的沟通能力' },
  { key: 'score3', text: '3.业务/接待人员的响应速度或回复及时性' },
  { key: 'score4', text: '4.出具检测报告的及时性' },
  { key: 'score5', text: '5.检测结果的准确性' },
  { key: 'score6', text: '6.检测报告内容表达清晰,编排合理并易于理解' },
  { key: 'score7', text: '7.处理投诉抱怨的及时性' },
  { key: 'score8', text: '8.对投诉抱怨处理的结果' },
  { key: 'score9', text: '9.对我司服务的专业性评价' },
  { key: 'score10', text: '10.对我司服务的总体满意程度评价' }
]
function createEmptyForm() {
  const form = {
    clientSatisfactionId: '',
    orderId: '',
    unitName: '',
    userName: '',
    address: '',
    contactPerson: '',
    fillDate: '',
    remark: '',
    labOpinion: '',
    qualityManager: '',
    labDate: null,
    entrustCode: '',
    sampleName: ''
  }
  QUESTIONS.forEach(q => {
    form[q.key] = ''
  })
  return form
}
export default {
  name: 'formDialog',
  // import 引入的组件需要注入到对象中才能使用
  components: { limsAttachment },
  data() {
    // 这里存放数据
    return {
      formDia: false,
      form: {
        unitName: '',
        fillDate: '',
        userName: '',
        department: '',
        contactNumber: '',
        serviceAttitude: '',
        serviceAttitudeSuggestion: '',
        technicalCompetence: '',
        technicalCompetenceSuggestion: '',
        inspectionWork: '',
        inspectionWorkSuggestion: '',
        reasonableFees: '',
        reasonableFeesSuggestion: '',
        remark: '',
        clientSatisfactionId: '',
        orderId: '',
        entrustCode: '',
        sampleName: ''
      },
      // 客户下拉选项:只包含"已下过委托单且已完成"的数据
      form: createEmptyForm(),
      questions: QUESTIONS,
      scoreOptions: [10, 9, 8, 7, 6, 5],
      customerOptions: [],
      operationType: '',
      editLoad: false,
    };
  },
  // 方法集合
  computed: {
    scoreComplete() {
      return this.questions.every(q => this.form[q.key] !== '' && this.form[q.key] !== null && this.form[q.key] !== undefined)
    },
    totalScore() {
      return this.questions.reduce((sum, q) => sum + (Number(this.form[q.key]) || 0), 0)
    },
    satisfactionText() {
      if (!this.scoreComplete) {
        return ''
      }
      return this.totalScore >= 80 ? '满意(80分(含)以上)' : '不满意(80分以下)'
    }
  },
  methods: {
    async openDia(type, row) {
      this.formDia = true;
      this.operationType = type
      await this.loadCustomerOptions()
      if (this.operationType === 'edit') {
        this.form = { ...row }
        this.form = { ...createEmptyForm(), ...row }
        if (!this.form.unitName) {
          this.form.unitName = this.form.userName || ''
        }
        // 老数据没有关联委托单:合成一个选项把原来的值回显出来,不强制重选
        if (row.orderId == null && row.userName) {
          this.customerOptions.unshift({
@@ -229,26 +265,7 @@
      }
    },
    resetForm() {
      this.form = {
        unitName: '',
        fillDate: '',
        userName: '',
        department: '',
        contactNumber: '',
        serviceAttitude: '',
        serviceAttitudeSuggestion: '',
        technicalCompetence: '',
        technicalCompetenceSuggestion: '',
        inspectionWork: '',
        inspectionWorkSuggestion: '',
        reasonableFees: '',
        reasonableFeesSuggestion: '',
        remark: '',
        clientSatisfactionId: '',
        orderId: '',
        entrustCode: '',
        sampleName: ''
      }
      this.form = createEmptyForm()
    },
    // 下拉数据:后端只返回"已检验"的委托单(state=4)
    loadCustomerOptions() {
@@ -283,13 +300,16 @@
        this.$message.warning('请选择客户')
        return
      }
      if (!this.form.unitName) {
        this.$message.warning('请填写单位名称')
      if (!this.form.fillDate) {
        this.$message.warning('请选择填表日期')
        return
      }
      if (!this.form.department) {
        this.$message.warning('请填写部门')
        return
      for (let i = 0; i < this.questions.length; i++) {
        const score = this.form[this.questions[i].key]
        if (score === '' || score === null || score === undefined) {
          this.$message.warning('请完成第' + (i + 1) + '题评分')
          return
        }
      }
      this.editLoad = true
      const payload = { ...this.form }
@@ -351,15 +371,30 @@
  margin: 10vh auto 50px !important;
}
.survey-intro {
  margin-top: 10px;
  font-size: 13px;
  line-height: 22px;
  color: #303133;
}
.tables {
  table-layout: fixed;
  width: 100%;
  margin-top: 10px;
}
.section-title {
  height: 34px;
  text-align: center;
  font-size: 14px;
  font-weight: bold;
  background: #f5f7fa;
  padding: 6px;
}
.td-title {
  height: 40px;
  width: 170px;
  text-align: center;
  font-size: 14px;
  word-wrap: break-word;
@@ -367,17 +402,32 @@
  padding: 6px;
}
.question-title {
  text-align: left;
}
.td-info {
  padding: 6px;
}
.td-info1 {
  display: inline-block;
  width: 100%;
  text-align: left;
.score-head {
  text-align: center;
  font-size: 14px;
  word-wrap: break-word;
  white-space: normal;
  padding: 6px;
}
.score-cell {
  text-align: center;
  height: 38px;
}
.score-cell :deep(.el-radio) {
  margin-right: 0;
}
.score-result {
  font-weight: bold;
  color: #409eff;
}
.customer-card-sub {