WXL (wul)
昨天 feb5a669dced68415bc7e32f237f77bf9842fe8b
src/views/outsideChainwtnew.vue
@@ -1,160 +1,315 @@
<template>
  <div class="questionnaire-optimized">
    <div class="content-wrapper" v-if="!accomplish">
      <div class="questionnaire-container">
        <!-- 问卷标题区域 -->
        <div class="questionnaire-header">
          <h1 class="questionnaire-title">
            {{ taskname ? taskname : "问卷" }}
          </h1>
          <div class="questionnaire-description">
            {{
              kcb
                ? kcb
                : "亲爱的患者-家属,我们是医院的医护人员,为了更好地了解您的康复情况,请您抽一点宝贵时间,完成这份随访问卷。"
            }}
          </div>
        </div>
        <el-divider class="custom-divider"></el-divider>
        <!-- 问卷题目区域 -->
        <div class="questions-section">
          <div
            class="question-item"
            v-for="(item, index) in visibleQuestions"
            :key="item.id"
            :class="{
              'has-warning':
                item.prompt &&
                item.scriptResult &&
                (item.scriptType !== 2 || item.scriptResult.length > 0),
            }"
          >
            <!-- 题目题干 -->
            <div class="question-stem">
              <span class="question-number"
                >{{ getVisibleQuestionIndex(index) }}.</span
              >
              <span class="question-text">{{ item.scriptContent }}</span>
              <span class="question-type-tag">
                {{
                  item.scriptType === 1
                    ? "[单选]"
                    : item.scriptType === 2
                    ? "[多选]"
                    : "[问答]"
                }}
              </span>
            </div>
            <!-- 单选题目 -->
            <div
              class="question-options"
              v-if="item.scriptType == 1 && !item.ishide"
            >
              <el-radio-group class="options-group" v-model="item.scriptResult">
                <el-radio
                  v-for="(
                    option, optionIndex
                  ) in item.svyTaskTemplateTargetoptions"
                  :key="optionIndex"
                  :label="option.optioncontent"
                  :class="{
                    'abnormal-option':
                      option.isabnormal &&
                      item.scriptResult == option.optioncontent,
                  }"
                  @click.native.prevent="
                    handleRadioToggle(
                      item,
                      index,
                      item.svyTaskTemplateTargetoptions,
                      option.optioncontent
                    )
                  "
                  class="option-radio"
                >
                  <span class="option-text">{{ option.optioncontent }}</span>
                </el-radio>
              </el-radio-group>
            </div>
            <!-- 多选题目 -->
            <div class="question-options" v-if="item.scriptType == 2">
              <el-checkbox-group
                class="options-group"
                v-model="item.scriptResult"
              >
                <el-checkbox
                  v-for="(
                    option, optionIndex
                  ) in item.svyTaskTemplateTargetoptions"
                  :key="optionIndex"
                  :label="option.optioncontent"
                  :class="{
                    'abnormal-option': option.isabnormal,
                  }"
                  @change="$forceUpdate()"
                  class="option-checkbox"
                >
                  <span class="option-text">{{ option.optioncontent }}</span>
                </el-checkbox>
              </el-checkbox-group>
            </div>
            <!-- 填空题目 -->
            <div class="question-input" v-if="item.scriptType == 4">
              <el-input
                type="textarea"
                :rows="3"
                placeholder="请输入您的回答"
                v-model="item.scriptResult"
                clearable
                class="answer-textarea"
              ></el-input>
            </div>
            <!-- 提示信息 -->
            <div
              class="question-warning"
              v-show="
                item.prompt &&
                item.scriptResult &&
                (item.scriptType !== 2 || item.scriptResult.length > 0)
              "
            >
              <el-alert
                :title="item.prompt"
                type="warning"
                :closable="false"
                class="warning-alert"
              ></el-alert>
            </div>
          </div>
        </div>
        <!-- 提交按钮 -->
        <div class="submit-section">
          <el-button type="primary" @click="cache(true)" class="submit-button">
            提交问卷
          </el-button>
        </div>
    <div v-if="loading && !accomplish" class="loading-container">
      <div class="loading-content">
        <i class="el-icon-loading loading-icon"></i>
        <div class="loading-text">问卷加载中,请稍候...</div>
      </div>
    </div>
    <!-- 完成页面 -->
    <div class="completion-page" v-else>
      <div class="completion-content">
        <div class="completion-icon">✓</div>
        <h2 class="completion-title">感谢您的配合!</h2>
        <p class="completion-message">
          {{
            jsy
              ? jsy
              : "生活上要劳逸结合,注意休息和营养,适当锻炼,戒烟限酒,保持心情舒畅,定期复诊。那本次回访就到这里,祝您身体健康!"
          }}
        </p>
    <!-- 正常内容 -->
    <div v-else>
      <div class="content-wrapper" v-if="!accomplish">
        <div class="questionnaire-container">
          <!-- 问卷标题区域 -->
          <div class="questionnaire-header">
            <h1 class="questionnaire-title">
              {{ taskname ? taskname : "问卷" }}
            </h1>
            <div class="questionnaire-description">
              {{
                kcb
                  ? kcb
                  : "亲爱的患者-家属,我们是医院的医护人员,为了更好地了解您的康复情况,请您抽一点宝贵时间,完成这份随访问卷。"
              }}
            </div>
          </div>
          <el-divider class="custom-divider"></el-divider>
          <!-- 按维度分组的题目区域 -->
          <div class="dimension-section" v-if="hasDimension">
            <!-- 遍历维度分组 -->
            <div
              class="dimension-group"
              v-for="(group, dimensionKey) in dimensionGroups"
              :key="dimensionKey"
            >
              <!-- 维度标题 - 只显示有维度标签的 -->
              <div class="dimension-title" v-if="group.dimensionLabel">
                <h3>{{ group.dimensionLabel }}</h3>
              </div>
              <!-- 该维度下的题目 -->
              <div class="questions-section">
                <div
                  class="question-item"
                  v-for="(item, index) in group.questions"
                  :key="item.id"
                  :class="{
                    'has-warning':
                      item.prompt &&
                      item.scriptResult &&
                      (item.scriptType !== 2 || item.scriptResult.length > 0),
                  }"
                >
                  <!-- 题目题干 -->
                  <div class="question-stem">
                    <span class="question-number"
                      >{{ getQuestionNumber(group, index) }}.</span
                    >
                    <span class="question-text">{{ item.scriptContent }}</span>
                    <span class="question-type-tag">
                      {{
                        item.scriptType == 1
                          ? "[单选]"
                          : item.scriptType == 2
                          ? "[多选]"
                          : "[问答]"
                      }}
                    </span>
                  </div>
                  <!-- 单选题目 -->
                  <div
                    class="question-options"
                    v-if="item.scriptType == 1 && !item.ishide"
                  >
                    <el-radio-group
                      class="options-group"
                      v-model="item.scriptResult"
                    >
                      <el-radio
                        v-for="(
                          option, optionIndex
                        ) in item.svyTaskTemplateTargetoptions"
                        :key="optionIndex"
                        :label="option.optioncontent"
                        :class="{
                          'abnormal-option':
                            option.isabnormal &&
                            item.scriptResult == option.optioncontent,
                        }"
                        @click.native.prevent="
                          handleRadioToggle(
                            item,
                            getGlobalIndex(dimension, group, index),
                            item.svyTaskTemplateTargetoptions,
                            option.optioncontent
                          )
                        "
                        class="option-radio"
                      >
                        <span class="option-text">{{
                          option.optioncontent
                        }}</span>
                      </el-radio>
                    </el-radio-group>
                  </div>
                  <!-- 多选题目 -->
                  <div class="question-options" v-if="item.scriptType == 2">
                    <el-checkbox-group
                      class="options-group"
                      v-model="item.scriptResult"
                    >
                      <el-checkbox
                        v-for="(
                          option, optionIndex
                        ) in item.svyTaskTemplateTargetoptions"
                        :key="optionIndex"
                        :label="option.optioncontent"
                        :class="{
                          'abnormal-option': option.isabnormal,
                        }"
                        @change="$forceUpdate()"
                        class="option-checkbox"
                      >
                        <span class="option-text">{{
                          option.optioncontent
                        }}</span>
                      </el-checkbox>
                    </el-checkbox-group>
                  </div>
                  <!-- 填空题目 -->
                  <div class="question-input" v-if="item.scriptType == 4">
                    <el-input
                      type="textarea"
                      :rows="3"
                      placeholder="请输入您的回答"
                      v-model="item.scriptResult"
                      clearable
                      class="answer-textarea"
                    ></el-input>
                  </div>
                  <!-- 提示信息 -->
                  <div
                    class="question-warning"
                    v-show="
                      item.prompt &&
                      item.scriptResult &&
                      (item.scriptType !== 2 || item.scriptResult.length > 0)
                    "
                  >
                    <el-alert
                      :title="item.prompt"
                      type="warning"
                      :closable="false"
                      class="warning-alert"
                    ></el-alert>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- 无维度时的题目区域(保持原样) -->
          <div class="questions-section" v-else>
            <div
              class="question-item"
              v-for="(item, index) in visibleQuestions"
              :key="item.id"
              :class="{
                'has-warning':
                  item.prompt &&
                  item.scriptResult &&
                  (item.scriptType !== 2 || item.scriptResult.length > 0),
              }"
            >
              <!-- 题目题干 -->
              <div class="question-stem">
                <span class="question-number"
                  >{{ getVisibleQuestionIndex(index) }}.</span
                >
                <span class="question-text">{{ item.scriptContent }}</span>
                <span class="question-type-tag">
                  {{
                    item.scriptType == 1
                      ? "[单选]"
                      : item.scriptType == 2
                      ? "[多选]"
                      : "[问答]"
                  }}
                </span>
              </div>
              <!-- 单选题目 -->
              <div
                class="question-options"
                v-if="item.scriptType == 1 && !item.ishide"
              >
                <el-radio-group
                  class="options-group"
                  v-model="item.scriptResult"
                >
                  <el-radio
                    v-for="(
                      option, optionIndex
                    ) in item.svyTaskTemplateTargetoptions"
                    :key="optionIndex"
                    :label="option.optioncontent"
                    :class="{
                      'abnormal-option':
                        option.isabnormal &&
                        item.scriptResult == option.optioncontent,
                    }"
                    @click.native.prevent="
                      handleRadioToggle(
                        item,
                        index,
                        item.svyTaskTemplateTargetoptions,
                        option.optioncontent
                      )
                    "
                    class="option-radio"
                  >
                    <span class="option-text">{{ option.optioncontent }}</span>
                  </el-radio>
                </el-radio-group>
              </div>
              <!-- 多选题目 -->
              <div class="question-options" v-if="item.scriptType == 2">
                <el-checkbox-group
                  class="options-group"
                  v-model="item.scriptResult"
                >
                  <el-checkbox
                    v-for="(
                      option, optionIndex
                    ) in item.svyTaskTemplateTargetoptions"
                    :key="optionIndex"
                    :label="option.optioncontent"
                    :class="{
                      'abnormal-option': option.isabnormal,
                    }"
                    @change="$forceUpdate()"
                    class="option-checkbox"
                  >
                    <span class="option-text">{{ option.optioncontent }}</span>
                  </el-checkbox>
                </el-checkbox-group>
              </div>
              <!-- 填空题目 -->
              <div class="question-input" v-if="item.scriptType == 4">
                <el-input
                  type="textarea"
                  :rows="3"
                  placeholder="请输入您的回答"
                  v-model="item.scriptResult"
                  clearable
                  class="answer-textarea"
                ></el-input>
              </div>
              <!-- 提示信息 -->
              <div
                class="question-warning"
                v-show="
                  item.prompt &&
                  item.scriptResult &&
                  (item.scriptType !== 2 || item.scriptResult.length > 0)
                "
              >
                <el-alert
                  :title="item.prompt"
                  type="warning"
                  :closable="false"
                  class="warning-alert"
                ></el-alert>
              </div>
            </div>
          </div>
          <!-- 提交按钮 -->
          <div class="submit-section">
            <el-button
              type="primary"
              @click="cache(true)"
              class="submit-button"
            >
              提交问卷
            </el-button>
          </div>
        </div>
      </div>
      <!-- 完成页面 -->
      <div class="completion-page" v-else>
        <div class="completion-content">
          <div class="completion-icon">✓</div>
          <h2 class="completion-title">感谢您的配合!</h2>
          <p class="completion-message">
            {{
              jsy
                ? jsy
                : "生活上要劳逸结合,注意休息和营养,适当锻炼,戒烟限酒,保持心情舒畅,定期复诊。那本次回访就到这里,祝您身体健康!"
            }}
          </p>
        </div>
      </div>
    </div>
  </div>
@@ -165,6 +320,7 @@
  getExternalfollowup,
  getCachequestionnaire,
  Cachequestionnaire,
  gettypeout,
  Submitaquestionnaire,
  geturlinfo,
} from "@/api/AiCentre/index";
@@ -172,6 +328,7 @@
export default {
  data() {
    return {
      loading: true,
      taskid: 355,
      patid: 265823,
      kcb: "",
@@ -179,10 +336,28 @@
      isabnormal: 0,
      taskname: "",
      questionList: [],
      param6: null,
      jsy: null,
      dialogVisible: false,
      Endornot: true,
      accomplish: false,
      dimensionTypes: [
        {
          value: 1,
          label: "维度1",
          listClass: "primary",
        },
        {
          value: 2,
          label: "维度二",
          listClass: "primary",
        },
        {
          value: 3,
          label: "维度三",
          listClass: "primary",
        },
      ],
      // 前端公钥
      publicKey:
        "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKR0yHv0rbJWQE+Sc7/FwpW66qMd9qX2k6z+SDgkSdxWh/1GbBoAP7bDQQRF6vXmoKsD2ya42H6XRLSDXAoayuMCAwEAAQ== ",
@@ -203,12 +378,89 @@
    // window.removeEventListener("beforeunload", this.cache);
  },
  created() {
    this.gettypeout();
    this.geturlinfo();
  },
  computed: {
    // 计算属性:获取所有可见的题目
    visibleQuestions() {
      if (!Array.isArray(this.questionList)) {
        return [];
      }
      return this.questionList.filter((question) => !question.ishide);
    },
    // 计算属性:检查是否有维度字段
    hasDimension() {
      if (!this.questionList || this.questionList.length == 0) {
        return false;
      }
      // 检查任意一个题目是否有dimension字段
      return this.questionList.some(
        (question) =>
          question.dimension && this.getDimensionLabel(question.dimension)
      );
    },
    // 计算属性:按维度整理题目
    dimensionGroups() {
      if (!this.questionList || this.questionList.length == 0) {
        return {};
      }
      const groups = {};
      let currentGroupKey = null;
      let groupStartIndex = 0; // 记录当前维度组的开始索引
      this.visibleQuestions.forEach((question, index) => {
        const dimensionValue = question.dimension;
        const dimensionLabel = this.getDimensionLabel(dimensionValue);
        // 生成组key:有维度用维度值,无维度用特殊标记+起始索引
        let groupKey;
        if (dimensionValue && dimensionLabel) {
          groupKey = `dimension-${dimensionValue}`;
        } else {
          // 无维度或维度映射不存在的题目单独分组
          groupKey = `no-dimension-${groupStartIndex}`;
        }
        // 创建或获取维度组
        if (!groups[groupKey]) {
          groups[groupKey] = {
            questions: [],
            startIndex: groupStartIndex,
            dimensionValue: dimensionValue, // 保存维度值用于后续处理
            dimensionLabel: dimensionLabel, // 保存维度标签
            isNoDimension: !dimensionValue || !dimensionLabel,
          };
          currentGroupKey = groupKey;
        }
        // 将题目添加到对应的维度组
        groups[groupKey].questions.push(question);
        // 如果下一个题目维度不同,重新开始计数
        const nextQuestion = this.visibleQuestions[index + 1];
        if (nextQuestion) {
          const nextDimensionValue = nextQuestion.dimension;
          const nextDimensionLabel = this.getDimensionLabel(nextDimensionValue);
          const currentDimensionLabel = this.getDimensionLabel(dimensionValue);
          // 判断维度是否相同
          if (
            dimensionValue !== nextDimensionValue ||
            (dimensionValue &&
              nextDimensionValue &&
              ((!dimensionValue && nextDimensionValue) ||
                (dimensionValue && !nextDimensionValue)))
          ) {
            groupStartIndex = index + 1;
          }
        }
      });
      return groups;
    },
  },
  methods: {
@@ -228,8 +480,26 @@
            res.data.param3,
            res.data.param5
          );
          this.param6 = res.data.param6;
        }
      });
    },
    // 获取字典
    gettypeout() {
      gettypeout("dimensionality_type").then((res) => {
        if (res.code == 200) {
          this.dimensionTypes = res.data;
        }
      });
    },
    // 根据维度值获取维度标签
    getDimensionLabel(dimensionValue) {
      if (!dimensionValue) return "";
      const dimensionType = this.dimensionTypes.find(
        (item) => item.dictValue == Number(dimensionValue)
      );
      return dimensionType ? dimensionType.dictLabel : "";
    },
    //     extractLastSegmentFromUrl(url) {
    //     // 找到最后一个'/'的位置
@@ -247,6 +517,8 @@
      this.taskid = decodeURIComponent(param1);
      this.patid = decodeURIComponent(param2);
      this.taskname = decodeURIComponent(param3);
      this.loading = true;
      // let taskid =
      //   "OFp7tn/B6x7IzKJetvGWHdSWBj7msRlnlj6am9dyuHTH6sEt4uBbVCUXs5kcF/e4O2W6vqHf2Bz9K3/evbYDmw==";
      // let patid =
@@ -256,10 +528,10 @@
      // let taskids = this.encrypt(this.taskid);
      // let patids = this.encrypt(this.patid);
      // 先取缓存
      getCachequestionnaire({ param1: this.taskid, param2: this.patid }).then(
        (res) => {
      getCachequestionnaire({ param1: this.taskid, param2: this.patid })
        .then((res) => {
          if (res.code == 200) {
            this.questionList = res.data;
            this.questionList = res.data.result;
            this.accomplish = res.data.submit;
            if (this.questionList[0]) {
              this.questionList.forEach((item) => {
@@ -269,6 +541,8 @@
                  item.scriptResult = item.scriptResult.split("&");
                }
              });
              this.loading = false;
              return;
            } else {
              this.getExternalfollowup();
@@ -276,13 +550,13 @@
          } else {
            this.getExternalfollowup();
          }
        }
      );
        })
        .finally(() => {});
    },
    // 获取数据
    getExternalfollowup() {
      getExternalfollowup({ param1: this.taskid, param2: this.patid }).then(
        (res) => {
      getExternalfollowup({ param1: this.taskid, param2: this.patid })
        .then((res) => {
          if (res.code == 200) {
            this.questionList = res.data.script;
            this.jsy = res.data.jsy;
@@ -294,9 +568,12 @@
                item.scriptResult = [];
              }
            });
            this.loading = false;
          }
        }
      );
        })
        .finally(() => {
          this.loading = false;
        });
    },
    // 加密函数
    encrypt(txt) {
@@ -316,6 +593,7 @@
      let form = {
        param1: this.taskid,
        param2: this.patid,
        param6: this.param6,
        excep: this.excep,
        isabnormal: this.isabnormal,
        serviceSubtaskDetailList: [],
@@ -346,6 +624,7 @@
      let form = {
        param1: this.taskid,
        param2: this.patid,
        param6: this.param6,
        svyTaskTemplateScriptVOS: [],
      };
      const arr = structuredClone(this.questionList);
@@ -399,19 +678,42 @@
    getVisibleQuestionIndex(index) {
      return index + 1;
    },
    // 获取维度内题目的序号
    getQuestionNumber(group, index) {
      return group.startIndex + index + 1;
    },
    // 获取题目在全量数组中的索引
    getGlobalIndex(dimension, group, localIndex) {
      return group.startIndex + localIndex;
    },
    // 在模板中使用
    getDimensionLabelForDisplay(dimensionKey) {
      if (dimensionKey.startsWith("no-dimension-")) {
        return "";
      }
      const dimensionValue = dimensionKey.replace("dimension-", "");
      return this.getDimensionLabel(dimensionValue);
    },
    // 新增的切换选中/取消选中方法
    handleRadioToggle(questionItem, index, options, optionValue) {
    handleRadioToggle(questionItem, globalIndex, options, optionValue) {
      // 保存当前状态以便后续比较
      const previousState = JSON.parse(JSON.stringify(this.questionList));
      // 原有的处理逻辑
      if (questionItem.scriptResult === optionValue) {
      if (questionItem.scriptResult == optionValue) {
        questionItem.scriptResult = "";
        questionItem.isabnormal = 0;
        questionItem.showAppendInput = false;
      } else {
        questionItem.scriptResult = optionValue;
        this.handleOptionChange(optionValue, index, options, questionItem);
        this.handleOptionChange(
          optionValue,
          globalIndex,
          options,
          questionItem
        );
      }
      // 处理完成后,确保重新计算可见题目的序号
@@ -471,6 +773,8 @@
        } else {
          // 正常跳转逻辑
          const nextQuestionIndex = selectedOptionObj.nextQuestion - 1;
          console.log(nextQuestionIndex, 4);
          console.log(selectedOptionObj);
          this.questionList = this.questionList.map((item, index) => {
            // 保留当前题目之前的隐藏状态
@@ -483,12 +787,12 @@
            }
            // 当前题目总是可见
            if (index === questionIndex) {
            if (index == questionIndex) {
              return { ...item, ishide: 0, hiddenByEnd: false };
            }
            // 显示目标下一题
            if (index === nextQuestionIndex) {
            if (index == nextQuestionIndex) {
              return { ...item, ishide: 0, hiddenByEnd: false };
            }
@@ -510,8 +814,8 @@
        // 如果没有跳转,只需确保下一题可见
        this.questionList = this.questionList.map((item, index) => ({
          ...item,
          ishide: index === questionIndex + 1 ? 0 : item.ishide,
          hiddenByEnd: index === questionIndex + 1 ? false : item.hiddenByEnd,
          ishide: index == questionIndex + 1 ? 0 : item.ishide,
          hiddenByEnd: index == questionIndex + 1 ? false : item.hiddenByEnd,
        }));
      }
@@ -520,32 +824,6 @@
        this.$forceUpdate();
      });
    },
    // 处理单选选项
    // handleOptionChange(selectedvalue, index, arr) {
    //   // 查找选中的选项对象
    //   const selectedOption = arr.svyTaskTemplateTargetoptions.find(
    //     (option) => option.optioncontent == selectedvalue
    //   );
    //   if (selectedOption) {
    //     this.questionList[index].nextScriptno = selectedOption.nextQuestion;
    //     this.questionList[index].score = selectedOption.score;
    //     this.questionList[index].prompt = selectedOption.prompt;
    //   }
    // },
    // 处理多选选项
    // updateScore(selectedvalues, index, arr) {
    //   // ��加分数
    //   let score = 0;
    //   selectedvalues.forEach((value) => {
    //     const selectedOption = arr.svyTaskTemplateTargetoptions.find(
    //       (option) => option.optioncontent == value
    //     );
    //     if (selectedOption) {
    //       score += Number(selectedOption.score);
    //     }
    //   });
    //   this.questionList[index].score = score;
    // },
  },
};
</script>
@@ -598,12 +876,40 @@
  background-color: #eaeef2;
}
/* 维度分组样式 */
.dimension-section {
  margin-bottom: 20px;
}
.dimension-group {
  margin-bottom: 30px;
  &:last-child {
    margin-bottom: 0;
  }
}
.dimension-title {
  background: linear-gradient(135deg, #e8f4ff 0%, #d1e7ff 100%);
  padding: 12px 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  border-left: 4px solid #175997;
  h3 {
    color: #175997;
    font-size: 20px;
    font-weight: 600;
    margin: 0;
  }
}
.questions-section {
  margin-bottom: 40px;
  margin-bottom: 10px;
}
.question-item {
  margin-bottom: 35px;
  margin-bottom: 25px;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #eaeef2;
@@ -616,6 +922,10 @@
  &.has-warning {
    border-left: 4px solid #e6a23c;
  }
  &:last-child {
    margin-bottom: 0;
  }
}
@@ -722,6 +1032,8 @@
.submit-section {
  text-align: center;
  padding: 20px 0 10px;
  border-top: 1px solid #eaeef2;
  margin-top: 20px;
}
.submit-button {
@@ -815,6 +1127,14 @@
    padding: 15px;
  }
  .dimension-title {
    padding: 10px 15px;
    h3 {
      font-size: 18px;
    }
  }
  .completion-content {
    padding: 30px 20px;
  }
@@ -840,5 +1160,44 @@
  .completion-icon {
    font-size: 60px;
  }
  .dimension-title h3 {
    font-size: 16px;
  }
}
.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 70vh;
}
.loading-content {
  text-align: center;
  padding: 40px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.loading-icon {
  font-size: 40px;
  color: #409eff;
  margin-bottom: 15px;
  animation: rotating 2s linear infinite;
}
.loading-text {
  font-size: 16px;
  color: #606266;
}
@keyframes rotating {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>