WXL (wul)
2 天以前 4879058b6fb8fd51ba2b4d87f241defb7c9f04fc
src/views/satisfaction.vue
@@ -1,5 +1,44 @@
<template>
  <div class="questionnaire" :class="'survey-type-' + surveyType">
    <!-- 加载状态 -->
    <div v-if="loading" class="loading-state">
      <div class="loading-spinner">
        <i class="el-icon-loading"></i>
        <p>问卷加载中...</p>
      </div>
    </div>
    <!-- 无数据状态 -->
    <div v-else-if="isEmptyData" class="empty-state">
      <div class="empty-content">
        <i class="el-icon-document" style="font-size: 64px; color: #909399"></i>
        <h3>暂无问卷数据</h3>
        <p>当前没有可用的问卷,请联系管理员或稍后重试</p>
        <el-button
          type="primary"
          @click="loadSurveyData"
          icon="el-icon-refresh"
        >
          重新加载
        </el-button>
      </div>
    </div>
    <!-- 错误状态 -->
    <div v-else-if="hasError" class="error-state">
      <div class="error-content">
        <i class="el-icon-warning" style="font-size: 64px; color: #f56c6c"></i>
        <h3>数据加载失败</h3>
        <p>{{ errorMessage }}</p>
        <el-button
          type="primary"
          @click="loadSurveyData"
          icon="el-icon-refresh"
        >
          重新尝试
        </el-button>
      </div>
    </div>
    <div class="CONTENT" v-if="!accomplish">
      <div class="preview-left">
        <div class="toptitle">
@@ -7,6 +46,31 @@
          <div style="font-size: 22px; margin-bottom: 20px; line-height: 1.5">
            {{ surveyDescription }}
          </div>
        </div>
        <div v-if="showDeptSelect" class="dept-select-container">
          <el-form>
            <el-form>
              <el-form-item label="选择科室">
                <el-select
                  v-model="selectedDept"
                  filterable
                  clearable
                  placeholder="请选择科室或输入关键词搜索"
                  @change="handleDeptChange"
                  popper-class="dept-select-dropdown"
                >
                  <el-option
                    v-for="dept in filteredDeptList"
                    :key="dept.code"
                    :label="`${dept.name} (${dept.code})`"
                    :value="dept.name"
                  >
                    <span>{{ dept.name }}</span>
                  </el-option>
                </el-select>
              </el-form-item>
            </el-form>
          </el-form>
        </div>
        <el-divider></el-divider>
@@ -90,7 +154,7 @@
              <el-input
                type="textarea"
                :rows="3"
                placeholder="请输入您的意见或建议"
                placeholder="请输入"
                v-model="item.scriptResult"
                clearable
              >
@@ -113,7 +177,7 @@
    <div class="CONTENT" v-else>
      <div class="preview-lefts">
        <div class="completion-message">
          <div class="thank-you">{{ this.accomplish||'感谢您的配合!' }}</div>
          <div class="thank-you">{{ this.accomplish || "感谢您的配合!" }}</div>
          <div class="feedback-message">{{ completionMessage }}</div>
        </div>
      </div>
@@ -125,6 +189,7 @@
import {
  getScriptByCondition,
  saveMYDQuestionAnswer,
  WLgetDept,
} from "@/api/AiCentre/index";
export default {
@@ -134,8 +199,14 @@
      surveyTitle: "",
      surveyDescription: "",
      questionList: [],
      deptList: [],
      completionMessage: "",
      accomplish: false,
      showDeptSelect: false,
      selectedDept: null,
      deptSearchText: "", // 保留用于本地过滤
      deptList: [],
      filteredDeptList: [],
      // 加密后的参数
      encryptedParams: {
@@ -143,8 +214,13 @@
        param2: "",
        param3: "",
        param4: "",
        param5: "",
        param6: "30001002",
      },
      isEmptyData: false, // 新增:无数据状态
      hasError: false, // 新增:错误状态
      loading: false, // 新增:加载状态
      errorMessage: "", // 新增:错误信息
      // 测试数据
      testData: {
        1: {
@@ -283,29 +359,87 @@
      // 从路由参数获取加密后的参数
      this.encryptedParams.param1 =
        this.$route.query.param1 ||
        "DBohZ1ARKfFmCdKrBKQ6JW3ddPTtDpgSaRZaKtxBMTJ4FngT06Vy-VskiwDYJJRwfvkHrPIZlkafgZybobGtKQ==";
        "WOAq2QZd43E-qg-96SvuIFsn-sdRVxQNH4M82XhpXp_Ux4PFrPaqSFXcKaeA6oxEgNhPisA86LvU9kTAEz4xvQ==";
      this.encryptedParams.param2 =
        this.$route.query.param2 ||
        "WQXniB7BIlizOwOQ4KZqITNrqWpLU3SD5vXdHLeYaviA-1T5Dtk70IJWAHbtcDUuYz-2ObYuMj4YKHfWhlCLzw==";
      this.encryptedParams.param3 = this.$route.query.param3 || null;
      this.encryptedParams.param4 = this.$route.query.param4 || "1"; // 默认为门诊
        "XWeBh42RLYlNsMcomgw9UXhUPySkRP5EneWSueSq8F84qwYznU9heXuSx4tUMUtDvRnuJ86moJivy-kWQX12Rg==";
      this.encryptedParams.param5 = this.$route.query.param3 || "2"; //  1=住院, 2=门诊, 3=投诉建议
      this.encryptedParams.param6 = this.$route.query.param4 || "30001002";
      this.surveyType = parseInt(this.encryptedParams.param4) || 1;
      this.surveyType = parseInt(this.encryptedParams.param5) || 2;
      // 加载问卷数据
      this.loadSurveyData();
      // 获取科室列表
      this.WLgetDept();
    },
    WLgetDept() {
      // 调用接口获取科室数据
      WLgetDept(this.encryptedParams.param6).then((res) => {
        this.deptList = Object.entries(res.data).map(([code, name]) => ({
          code,
          name,
        }));
        this.filteredDeptList = [...this.deptList];
    // 加载调查数据
        if (this.surveyType === 3) {
          this.showDeptSelect = true;
        }
      });
    },
    filterDeptList() {
      if (!this.deptSearchText) {
        this.filteredDeptList = [...this.deptList];
        return;
      }
      const searchText = this.deptSearchText.toLowerCase();
      this.filteredDeptList = this.deptList.filter(
        (dept) =>
          dept.name.toLowerCase().includes(searchText) ||
          dept.code.toLowerCase().includes(searchText)
      );
    },
    // 加载调查数据
    loadSurveyData() {
      this.loading = true;
      this.isEmptyData = false;
      this.hasError = false;
      this.errorMessage = "";
      // 调用接口获取问卷数据
      getScriptByCondition(this.encryptedParams)
      // 根据问卷类型设置不同的参数
      let encryptedParams = {
        param1: this.encryptedParams.param1,
      };
      // 根据surveyType设置不同的参数
      switch (this.surveyType) {
        case 1: // 住院
          encryptedParams.param2 = this.encryptedParams.param2;
          break;
        case 2: // 门诊
          encryptedParams.param3 = this.encryptedParams.param2;
          break;
        case 3: // 投诉建议
          encryptedParams.param4 = this.encryptedParams.param2;
          break;
        default:
          encryptedParams.param3 = this.encryptedParams.param2;
      }
      getScriptByCondition(encryptedParams)
        .then((res) => {
          if (res.code === 200) {
            if (res.data.result) {
              this.accomplish = res.data.result;
              return
              return;
            }
            if (
              !res.data.svyLibTemplateScriptVOS ||
              res.data.svyLibTemplateScriptVOS.length === 0
            ) {
              this.isEmptyData = true;
              this.$message.warning("暂无问卷数据");
              return;
            }
            // 处理接口返回的数据
            this.questionList = res.data.svyLibTemplateScriptVOS.map((item) => {
@@ -317,14 +451,14 @@
            // 根据surveyType设置标题和描述
            switch (this.surveyType) {
              case 1: // 门诊
              case 2: // 门诊
                this.surveyTitle = "门诊满意度调查";
                this.surveyDescription =
                  "亲爱的患者,感谢您选择我们的医疗服务。为了不断提升服务质量,请您花几分钟时间填写此问卷。";
                this.completionMessage =
                  "感谢您宝贵的意见!我们将不断改进门诊服务质量,为您提供更好的医疗服务体验。";
                break;
              case 2: // 住院
              case 1: // 住院
                this.surveyTitle = "住院满意度调查";
                this.surveyDescription =
                  "亲爱的患者及家属,感谢您选择在我院住院治疗。为了提升住院服务质量,请您填写此问卷。";
@@ -343,15 +477,26 @@
            }
          } else {
            // 接口无数据或失败,使用测试数据
            this.useTestData(this.surveyType);
            // this.useTestData(this.surveyType);
          }
        })
        .catch(() => {
          console.error("数据获取失败:", error);
          this.hasError = true;
          this.errorMessage =
            error.message || "问卷数据加载失败,请检查网络连接后重试";
          this.$message.error("数据加载失败");
          // 接口调用失败,使用测试数据
          this.useTestData(this.surveyType);
          // this.useTestData(this.surveyType);
        })
        .finally(() => {
          this.loading = false;
        });
    },
    handleDeptChange(value) {
      this.selectedDept = value;
      // 可以在这里添加其他处理逻辑
    },
    // 使用测试数据
    useTestData(surveyType) {
      const type = [1, 2, 3].includes(surveyType) ? surveyType : 1;
@@ -376,7 +521,7 @@
        const res = await saveMYDQuestionAnswer(submitData);
        if (res.code === 200) {
          this.accomplish = false;
          this.accomplish = "问卷已提交";
          this.$message.success("提交成功!感谢您的反馈。");
        } else {
          this.$message.error(res.msg || "提交失败,请稍后再试");
@@ -401,26 +546,39 @@
    },
    // 准备提交数据
    // 准备提交数据
    prepareSubmitData() {
      // 创建科室选择问题对象
      const deptQuestion = {
        scriptId: "dept_selection", // 自定义ID
        scriptType: 4, // 4表示问答类型
        scriptContent: "选择的科室",
        scriptResult: this.selectedDept || "", // 存储选择的科室名称
        required: false, // 非必填
        sort: 999,
        nextScriptno: "1",
      };
      return {
        taskId: this.encryptedParams.param1,
        serialnum: this.encryptedParams.param2 || this.encryptedParams.param3,
        mzzy: this.surveyType, // 1=门诊, 2=住院, 3=投诉建议
        svyLibTemplateScriptVOS: this.questionList.map((item) => {
          return {
            scriptId: item.scriptId,
            scriptType: item.scriptType,
            scriptResult:
              item.scriptType === 2
                ? (item.scriptResult || []).join("&")
                : item.scriptResult || "",
            nextScriptno: item.nextScriptno,
            score: item.score,
            prompt: item.prompt,
            ...item,
          };
        }),
        mzzy: this.surveyType,
        svyLibTemplateScriptVOS: [
          deptQuestion, // 将科室选择作为第一个问题
          ...this.questionList.map((item) => {
            return {
              scriptId: item.scriptId,
              scriptType: item.scriptType,
              scriptResult:
                item.scriptType === 2
                  ? (item.scriptResult || []).join("&")
                  : item.scriptResult || "",
              nextScriptno: item.nextScriptno,
              score: item.score,
              prompt: item.prompt,
              ...item,
            };
          }),
        ],
        excep: this.checkAbnormalOptions() ? 1 : 0,
      };
    },
@@ -518,7 +676,70 @@
    --theme-gradient: linear-gradient(135deg, #e53e3e, #f6ad55);
  }
}
.dept-select-container {
  margin: 20px 0;
  padding: 20px;
  background-color: #f8fafc;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
}
/* 调整下拉选项样式 */
.el-select-dropdown__item {
  display: flex;
  justify-content: space-between;
}
/* 下拉框样式调整 */
::v-deep .dept-select-dropdown {
  max-height: 400px; /* 限制最大高度 */
  overflow-y: auto; /* 添加滚动条 */
  .el-select-dropdown__item {
    display: flex;
    justify-content: space-between;
    padding: 0 20px;
    height: auto;
    line-height: 36px;
    span {
      display: inline-block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /* 名称部分 */
    span:first-child {
      width: 60%;
      text-align: left;
    }
    /* 编码部分 */
    span:last-child {
      width: 40%;
      text-align: right;
    }
  }
}
/* 移动端适配 */
@media (max-width: 768px) {
  ::v-deep .dept-select-dropdown {
    max-width: 100vw; /* 限制最大宽度为视口宽度 */
    width: auto !important;
    left: 10px !important;
    right: 10px !important;
    .el-select-dropdown__item {
      span:first-child {
        width: 50%;
      }
      span:last-child {
        width: 50%;
      }
    }
  }
}
.CONTENT {
  max-width: 900px;
  margin: 0 auto;
@@ -681,7 +902,99 @@
    }
  }
}
.loading-state {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 60vh;
  padding: 40px;
  .loading-spinner {
    text-align: center;
    .el-icon-loading {
      font-size: 48px;
      color: var(--primary-color);
      margin-bottom: 16px;
      animation: rotating 2s linear infinite;
    }
    p {
      color: #666;
      font-size: 16px;
    }
  }
}
.empty-state,
.error-state {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 60vh;
  padding: 40px;
  .empty-content,
  .error-content {
    text-align: center;
    max-width: 400px;
    h3 {
      color: #666;
      font-size: 20px;
      margin: 16px 0 12px;
      font-weight: 500;
    }
    p {
      color: #999;
      font-size: 14px;
      margin-bottom: 24px;
      line-height: 1.6;
    }
  }
}
.error-state {
  .error-content {
    h3 {
      color: #f56c6c;
    }
  }
}
@keyframes rotating {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
/* 响应式调整 */
@media (max-width: 768px) {
  .loading-state,
  .empty-state,
  .error-state {
    padding: 20px;
    min-height: 50vh;
    .el-icon-loading,
    .el-icon-document,
    .el-icon-warning {
      font-size: 40px !important;
    }
    h3 {
      font-size: 18px !important;
    }
    p {
      font-size: 13px !important;
    }
  }
}
::v-deep {
  .el-checkbox-group {
    display: flex;