WXL (wul)
5 天以前 70e4d2c33cc2e3af590d1816c0c703da341538cf
src/views/Satisfaction/configurationmyd/batch.vue
@@ -11,14 +11,11 @@
            icon="el-icon-check"
            @click="handleBatchSubmit"
            :loading="batchProcessing"
            :disabled="selectedExceptionIds.length === 0"
          >
            批量提交处理
            批量提交处理 ({{ selectedExceptionIds.length }})
          </el-button>
          <el-button
            type="warning"
            icon="el-icon-back"
            @click="handleGoBack"
          >
          <el-button type="warning" icon="el-icon-back" @click="handleGoBack">
            返回异常列表
          </el-button>
        </div>
@@ -37,29 +34,40 @@
          >
            <el-form-item label="负责科室">
              <el-select
                v-model="filterParams.deptId"
                v-model="filterParams.todeptcode"
                placeholder="请选择科室"
                clearable
                filterable
                style="width: 200px"
              >
                <el-option
                  v-for="dept in deptList"
                  :key="dept.id"
                  :label="dept.name"
                  :value="dept.id"
                  :key="dept.deptCode"
                  :label="dept.label"
                  :value="dept.deptCode"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="处理状态">
              <el-select
                v-model="filterParams.status"
                v-model="filterParams.handleFlag"
                placeholder="请选择状态"
                clearable
                style="width: 200px"
              >
                <el-option label="待处理" :value="0" />
                <el-option label="处理中" :value="1" />
                <el-option label="已处理" :value="2" />
                <el-option label="未处理" :value="'0'" />
                <el-option label="已处理" :value="'1'" />
              </el-select>
            </el-form-item>
            <el-form-item label="满意度类型">
              <el-select
                v-model="filterParams.templateType"
                placeholder="请选择模板类型"
                clearable
                style="width: 200px"
              >
                <el-option label="语音模板" :value="1" />
                <el-option label="问卷模板" :value="2" />
              </el-select>
            </el-form-item>
            <el-form-item>
@@ -70,10 +78,7 @@
              >
                筛选
              </el-button>
              <el-button
                icon="el-icon-refresh"
                @click="handleResetFilter"
              >
              <el-button icon="el-icon-refresh" @click="handleResetFilter">
                重置
              </el-button>
            </el-form-item>
@@ -86,13 +91,10 @@
          :border="true"
          style="width: 100%"
          @selection-change="handleSelectionChange"
          row-key="id"
          class="exception-table"
        >
          <el-table-column
            type="selection"
            width="55"
            align="center"
          />
          <el-table-column type="selection" width="55" align="center" />
          <el-table-column
            label="序号"
@@ -103,73 +105,79 @@
          <el-table-column
            label="负责科室"
            prop="responsibilityDept"
            width="120"
            prop="todeptname"
            width="200"
            align="center"
          >
            <template slot-scope="{ row }">
              <el-tag type="primary">{{ row.responsibilityDept }}</el-tag>
              <el-tag type="primary" v-if="row.todeptname">{{
                row.todeptname
              }}</el-tag>
              <span v-else class="no-data">未分配</span>
            </template>
          </el-table-column>
          <el-table-column
            label="不满意详情"
            prop="unsatisfactoryDetail"
            min-width="200"
            align="center"
          >
          <el-table-column label="不满意详情" min-width="250" align="center">
            <template slot-scope="{ row }">
              <div class="detail-content">
                {{ row.unsatisfactoryDetail }}
                <div class="question-text">
                  <strong>问题:</strong>{{ row.questiontext }}
                </div>
                <div class="answer-text">
                  <strong>回答:</strong>{{ row.asrtext || "无回答" }}
                </div>
                <div class="matched-text" v-if="row.matchedtext">
                  <strong>解析值:</strong>{{ row.matchedtext }}
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column
            label="患者信息"
            width="300"
            align="center"
          >
          <el-table-column label="患者信息" width="300" align="center">
            <template slot-scope="{ row }">
              <div class="patient-info">
                <div class="patient-item">
                  <span class="label">姓名:</span>
                  <span class="value">{{ row.patientName }}</span>
                <div class="patient-row">
                  <div class="patient-item">
                    <span class="label">姓名:</span>
                    <span class="value">{{ row.patdescJson.sendname }}</span>
                  </div>
                  <div class="patient-item">
                    <span class="label">性别:</span>
                    <span class="value">{{ row.patdescJson.sex }}</span>
                  </div>
                  <div class="patient-item">
                    <span class="label">年龄:</span>
                    <span class="value">{{ row.patdescJson.age }}岁</span>
                  </div>
                </div>
                <div class="patient-item">
                  <span class="label">性别:</span>
                  <span class="value">{{ row.gender === 1 ? '男' : '女' }}</span>
                </div>
                <div class="patient-item">
                  <span class="label">年龄:</span>
                  <span class="value">{{ row.age }}岁</span>
                </div>
                <div class="patient-item">
                  <span class="label">电话:</span>
                  <span class="value">{{ row.phone }}</span>
                <div class="patient-row">
                  <div class="patient-item full-width">
                    <span class="label">电话:</span>
                    <span class="value">{{ row.patdescJson.phone }}</span>
                  </div>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column
            label="出院信息"
            width="250"
            align="center"
          >
          <el-table-column label="填写信息" width="180" align="center">
            <template slot-scope="{ row }">
              <div class="discharge-info">
              <div class="fill-info">
                <div class="info-item">
                  <span class="label">科室:</span>
                  <span class="value">{{ row.dischargeDept }}</span>
                  <span class="label">填报时间:</span>
                  <span class="value time">{{
                    formatDateTime(row.createTime)
                  }}</span>
                </div>
                <div class="info-item">
                  <span class="label">病区:</span>
                  <span class="value">{{ row.dischargeWard }}</span>
                </div>
                <div class="info-item">
                  <span class="label">填写时间:</span>
                  <span class="value time">{{ row.fillTime }}</span>
                <div v-if="row.recordurl" class="info-item">
                  <el-button
                    type="text"
                    size="small"
                    @click="handlePlayAudio(row.recordurl)"
                    icon="el-icon-headset"
                  >
                    播放录音
                  </el-button>
                </div>
              </div>
            </template>
@@ -177,23 +185,42 @@
          <el-table-column
            label="处理状态"
            prop="processStatus"
            prop="handleFlag"
            width="100"
            align="center"
          >
            <template slot-scope="{ row }">
              <el-tag
                :type="getStatusTagType(row.processStatus)"
                effect="dark"
              >
                {{ getStatusText(row.processStatus) }}
              <el-tag :type="getStatusTagType(row.handleFlag)" effect="dark">
                {{ getStatusText(row.handleFlag) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="最新处理信息" width="180" align="center">
            <template slot-scope="{ row }">
              <div v-if="row.handleTime" class="handle-info">
                <div class="info-item">
                  <span class="label">处理人:</span>
                  <span class="value">{{ row.handleBy || "系统" }}</span>
                </div>
                <div class="info-item">
                  <span class="label">处理时间:</span>
                  <span class="value time">{{
                    formatDateTime(row.handleTime)
                  }}</span>
                </div>
                <div class="info-item">
                  <span class="label">处理说明:</span>
                  <span class="value">{{ formatHandledesc(row.handledesc) }}</span>
                </div>
              </div>
              <span v-else class="no-data">未处理</span>
            </template>
          </el-table-column>
          <el-table-column
            label="操作"
            width="180"
            width="210"
            align="center"
            fixed="right"
          >
@@ -211,7 +238,7 @@
                size="small"
                icon="el-icon-edit"
                @click="handleProcess(row)"
                :disabled="row.processStatus === 2"
                :disabled="row.handleresult === 'resolved'"
              >
                处理
              </el-button>
@@ -239,80 +266,261 @@
    <el-dialog
      title="处理异常反馈"
      :visible.sync="processDialogVisible"
      width="600px"
      width="60%"
      top="6vh"
      center
    >
      <el-form
        :model="processForm"
        :rules="processRules"
        ref="processForm"
        label-width="100px"
        size="medium"
      >
        <el-form-item label="处理状态" prop="status">
          <el-select
            v-model="processForm.status"
            placeholder="请选择处理状态"
            style="width: 100%"
      <div class="flow-dialog-body">
        <!-- 左半部分:处理信息 -->
        <div class="flow-left">
          <el-form
            :model="processForm"
            :rules="processRules"
            ref="processForm"
            label-width="100px"
            size="medium"
          >
            <el-option label="处理中" :value="1" />
            <el-option label="已处理" :value="2" />
            <el-option label="已驳回" :value="3" />
          </el-select>
        </el-form-item>
            <el-form-item label="是否流转" prop="isFlow">
              <el-switch
                v-model="processForm.isFlow"
                active-value="1"
                inactive-value="0"
                active-text="流转"
                inactive-text="不流转"
              />
            </el-form-item>
        <el-form-item label="报备科室" prop="reportDepts">
          <el-select
            v-model="processForm.reportDepts"
            placeholder="请选择报备科室"
            multiple
            filterable
            collapse-tags
            style="width: 100%"
          >
            <el-option
              v-for="dept in deptList"
              :key="dept.id"
              :label="dept.name"
              :value="dept.id"
            />
          </el-select>
        </el-form-item>
            <el-form-item label="处理状态" prop="handleFlag">
              <el-select
                v-model="processForm.handleFlag"
                placeholder="请选择处理状态"
                style="width: 100%"
              >
                <el-option label="已处理" :value="'1'" />
                <el-option label="取消处理" :value="'0'" />
              </el-select>
            </el-form-item>
        <el-form-item label="处理备注" prop="remark">
          <el-input
            v-model="processForm.remark"
            type="textarea"
            :rows="4"
            placeholder="请输入处理备注(最多500字)"
            maxlength="500"
            show-word-limit
          />
        </el-form-item>
            <el-form-item label="报备科室" prop="ccdepts">
              <el-select
                v-model="processForm.ccdepts"
                placeholder="请选择报备科室"
                multiple
                filterable
                collapse-tags
                style="width: 100%"
                :disabled="processForm.handleFlag !== '1'"
              >
                <el-option
                  v-for="dept in deptList"
                  :key="dept.deptCode"
                  :label="dept.label"
                  :value="dept.deptCode"
                />
              </el-select>
            </el-form-item>
        <el-form-item label="附件上传">
          <el-upload
            class="upload-demo"
            action="#"
            :on-preview="handlePreview"
            :on-remove="handleRemove"
            :before-remove="beforeRemove"
            :limit="3"
            :on-exceed="handleExceed"
            :file-list="fileList"
          >
            <el-button size="small" type="primary">点击上传</el-button>
            <div slot="tip" class="el-upload__tip">支持上传图片、文档等附件,单个文件不超过10MB</div>
          </el-upload>
        </el-form-item>
      </el-form>
            <el-form-item label="处理结果" prop="handleresult">
              <el-select
                v-model="processForm.handleresult"
                placeholder="请选择处理结果"
                style="width: 100%"
                :disabled="processForm.handleFlag !== '1'"
              >
                <el-option label="已解决" value="resolved" />
                <el-option label="已解释" value="explained" />
                <el-option label="已转交" value="transferred" />
                <el-option label="需改进" value="improvement" />
                <el-option label="已驳回" value="rejected" />
              </el-select>
            </el-form-item>
            <el-form-item label="处理说明" prop="handledesc">
              <el-input
                v-model="processForm.handledesc"
                type="textarea"
                :rows="4"
                placeholder="请输入处理说明(最多500字)"
                maxlength="500"
                show-word-limit
                :disabled="processForm.handleFlag !== '1'"
              />
            </el-form-item>
            <el-form-item
              label="最终意见"
              prop="finaloption"
              v-if="hasQualityPermission"
            >
              <el-input
                v-model="processForm.finaloption"
                type="textarea"
                :rows="3"
                placeholder="请输入最终处理意见(最多300字)"
                maxlength="300"
                show-word-limit
              />
            </el-form-item>
          </el-form>
        </div>
        <!-- 右半部分:流转时间线(选中流转后展开) -->
        <div class="flow-right" v-if="processForm.isFlow === '1'">
          <el-timeline>
            <el-timeline-item type="primary" placement="top" color="#5788fe">
              <div class="flow-step-title">第一步 · 流转发起</div>
              <el-form label-width="90px" size="small" class="flow-step-form">
                <el-form-item label="流转人">
                  <el-input
                    v-model="processForm.flowPerson"
                    placeholder="流转人(默认当前用户)"
                  />
                </el-form-item>
                <el-form-item label="流转人编号">
                  <el-input
                    v-model="processForm.flowPersonCode"
                    placeholder="流转人编号(默认当前用户工号)"
                  />
                </el-form-item>
                <el-form-item label="流转时间">
                  <el-date-picker
                    v-model="processForm.flowTime"
                    type="datetime"
                    value-format="yyyy-MM-dd HH:mm:ss"
                    placeholder="流转时间"
                    style="width: 100%"
                  />
                </el-form-item>
                <el-form-item label="流转说明">
                  <el-input
                    v-model="processForm.flowDesc"
                    type="textarea"
                    :rows="2"
                    placeholder="请输入流转说明"
                  />
                </el-form-item>
                <el-form-item label="流转科室">
                  <el-select
                    v-model="processForm.flowDepts"
                    multiple
                    filterable
                    collapse-tags
                    placeholder="请选择流转科室"
                    style="width: 100%"
                    @change="onFlowDeptChange"
                  >
                    <el-option
                      v-for="dept in deptList"
                      :key="dept.deptCode"
                      :label="dept.label"
                      :value="dept.deptCode"
                    />
                  </el-select>
                </el-form-item>
                <el-form-item label="流转科室code">
                  <el-select
                    v-model="processForm.flowDeptCodes"
                    multiple
                    disabled
                    placeholder="选择科室后自动生成"
                    style="width: 100%"
                  >
                    <el-option
                      v-for="code in processForm.flowDeptCodes"
                      :key="code"
                      :label="code"
                      :value="code"
                    />
                  </el-select>
                </el-form-item>
                <el-form-item label="推送负责人">
                  <el-select
                    v-model="processForm.pushUsers"
                    multiple
                    filterable
                    collapse-tags
                    placeholder="请选择推送负责人"
                    style="width: 100%"
                    @change="onPushUserChange"
                  >
                    <el-option
                      v-for="u in userList"
                      :key="u.userId"
                      :label="u.nickName || u.userName"
                      :value="u.userId"
                    />
                  </el-select>
                </el-form-item>
              </el-form>
            </el-timeline-item>
            <el-timeline-item type="primary" placement="top" color="#e6a23c">
              <div class="flow-step-title">第二步 · 科室反馈</div>
              <el-table
                :data="processForm.flowFeedbacks"
                border
                size="mini"
                v-if="processForm.flowFeedbacks.length > 0"
              >
                <el-table-column
                  label="科室"
                  prop="deptName"
                  width="120"
                  align="center"
                />
                <el-table-column label="是否同意" width="130" align="center">
                  <template slot-scope="scope">
                    <el-select
                      v-model="scope.row.agree"
                      placeholder="请选择"
                      size="mini"
                    >
                      <el-option label="同意" value="1" />
                      <el-option label="不同意" value="0" />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="具体说明" min-width="200" align="center">
                  <template slot-scope="scope">
                    <el-input
                      v-model="scope.row.desc"
                      placeholder="请输入具体说明"
                      size="mini"
                    />
                  </template>
                </el-table-column>
              </el-table>
              <div v-else class="flow-empty-tip">
                请先在第一步选择流转科室
              </div>
            </el-timeline-item>
            <el-timeline-item type="primary" placement="top" color="#67c23a">
              <div class="flow-step-title">第三步 · 处理结果</div>
              <el-form label-width="90px" size="small" class="flow-step-form">
                <el-form-item label="处理人">
                  <el-input
                    v-model="processForm.handleBy"
                    placeholder="处理人"
                  />
                </el-form-item>
                <el-form-item label="处理时间">
                  <el-date-picker
                    v-model="processForm.handleTime"
                    type="datetime"
                    value-format="yyyy-MM-dd HH:mm:ss"
                    placeholder="处理时间"
                    style="width: 100%"
                  />
                </el-form-item>
              </el-form>
            </el-timeline-item>
          </el-timeline>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="processDialogVisible = false">取消</el-button>
        <el-button
          type="primary"
          @click="submitProcess"
          :loading="processing"
        >
        <el-button type="primary" @click="submitProcess" :loading="processing">
          提交处理
        </el-button>
      </span>
@@ -332,44 +540,60 @@
        label-width="100px"
        size="medium"
      >
        <el-form-item label="处理状态" prop="status">
        <el-form-item label="处理状态" prop="handleFlag">
          <el-select
            v-model="batchProcessForm.status"
            v-model="batchProcessForm.handleFlag"
            placeholder="请选择处理状态"
            style="width: 100%"
          >
            <el-option label="处理中" :value="1" />
            <el-option label="已处理" :value="2" />
            <el-option label="已驳回" :value="3" />
            <el-option label="已处理" :value="'1'" />
            <el-option label="取消处理" :value="'0'" />
          </el-select>
        </el-form-item>
        <el-form-item label="报备科室" prop="reportDepts">
        <el-form-item label="报备科室" prop="ccdepts">
          <el-select
            v-model="batchProcessForm.reportDepts"
            v-model="batchProcessForm.ccdepts"
            placeholder="请选择报备科室"
            multiple
            filterable
            collapse-tags
            style="width: 100%"
            :disabled="batchProcessForm.handleFlag !== '1'"
          >
            <el-option
              v-for="dept in deptList"
              :key="dept.id"
              :label="dept.name"
              :value="dept.id"
              :key="dept.deptCode"
              :label="dept.label"
              :value="dept.deptCode"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="处理备注" prop="remark">
        <el-form-item label="处理结果" prop="handleresult">
          <el-select
            v-model="batchProcessForm.handleresult"
            placeholder="请选择处理结果"
            style="width: 100%"
            :disabled="batchProcessForm.handleFlag !== '1'"
          >
            <el-option label="已解决" value="resolved" />
            <el-option label="已解释" value="explained" />
            <el-option label="已转交" value="transferred" />
            <el-option label="需改进" value="improvement" />
            <el-option label="已驳回" value="rejected" />
          </el-select>
        </el-form-item>
        <el-form-item label="处理说明" prop="handledesc">
          <el-input
            v-model="batchProcessForm.remark"
            v-model="batchProcessForm.handledesc"
            type="textarea"
            :rows="4"
            placeholder="请输入处理备注(最多500字)"
            placeholder="请输入处理说明(最多500字)"
            maxlength="500"
            show-word-limit
            :disabled="batchProcessForm.handleFlag !== '1'"
          />
        </el-form-item>
      </el-form>
@@ -380,18 +604,73 @@
          @click="submitBatchProcess"
          :loading="batchProcessing"
        >
          批量提交
          批量提交 ({{ selectedExceptionIds.length }})
        </el-button>
      </span>
    </el-dialog>
    <!-- 进度对话框 -->
    <el-dialog
      title="批量处理进度"
      :visible.sync="batchProgress.visible"
      width="400px"
      :close-on-click-modal="false"
      :show-close="false"
      :close-on-press-escape="false"
    >
      <div class="progress-content">
        <el-progress
          :percentage="batchProgress.percentage"
          :status="batchProgress.percentage === 100 ? 'success' : ''"
        />
        <div class="progress-info">
          已处理 {{ batchProgress.processed }}/{{ batchProgress.total }} 条记录
        </div>
      </div>
    </el-dialog>
    <!-- 异常详情弹框 -->
    <Details-anomaly
      :visible="detailDialogVisible"
      :record-id="selectedRecordId"
      :title="detailDialogTitle"
      :record-data="selectedRecordData"
      @update:visible="handleDetailDialogClose"
      @processed="handleProcessed"
      @close="handleDetailDialogClose"
    />
    <!-- 录音播放器 -->
    <audio
      v-if="audioUrl"
      :src="audioUrl"
      ref="audioPlayer"
      controls
      style="display: none"
    />
  </div>
</template>
<script>
import DetailsAnomaly from "./components/DetailsAnomaly.vue";
import { tracelist, traceedit } from "@/api/AiCentre/index";
import dayjs from "dayjs";
import { deptTreeSelect, listUser } from "@/api/system/user";
export default {
  name: 'BatchProcess',
  name: "BatchProcess",
  components: {
    DetailsAnomaly,
  },
  data() {
    return {
      // 详情弹框相关
      detailDialogVisible: false,
      selectedRecordId: null,
      selectedRecordData: null,
      detailDialogTitle: "异常反馈详情",
      // 音频播放
      audioUrl: "",
      // 当前处理的异常ID
      currentExceptionId: null,
@@ -400,10 +679,12 @@
      // 过滤参数
      filterParams: {
        deptId: '',
        status: '',
        todeptcode: "",
        handleFlag: "",
        templateType: null,
        scriptids: null,
        pageNum: 1,
        pageSize: 10
        pageSize: 10,
      },
      // 加载状态
@@ -411,19 +692,13 @@
      processing: false,
      batchProcessing: false,
      // 权限控制
      hasQualityPermission: false, // 是否具有质管权限
      // 科室列表
      deptList: [
        { id: 1, name: '心血管内科' },
        { id: 2, name: '神经内科' },
        { id: 3, name: '普外科' },
        { id: 4, name: '骨科' },
        { id: 5, name: '妇产科' },
        { id: 6, name: '儿科' },
        { id: 7, name: '急诊科' },
        { id: 8, name: '呼吸内科' },
        { id: 9, name: '消化内科' },
        { id: 10, name: '内分泌科' }
      ],
      deptList: [],
      // 用户列表(流转负责人候选)
      userList: [],
      // 异常列表数据
      exceptionList: [],
@@ -432,183 +707,282 @@
      // 处理对话框
      processDialogVisible: false,
      processForm: {
        status: '',
        reportDepts: [],
        remark: ''
        handleFlag: "",
        ccdepts: [],
        handleresult: "",
        handledesc: "",
        finaloption: "",
        // 流转相关
        isFlow: "0",
        flowPerson: "",
        flowPersonCode: "",
        flowTime: "",
        flowDesc: "",
        flowDepts: [],
        flowDeptNames: [],
        flowDeptCodes: [],
        pushUsers: [],
        pushUserNames: [],
        pushUserNos: [],
        flowFeedbacks: [],
        handleBy: "",
        handleTime: "",
      },
      batchProgress: {
        visible: false,
        percentage: 0,
        processed: 0,
        total: 0,
      },
      processRules: {
        status: [
          { required: true, message: '请选择处理状态', trigger: 'change' }
        handleFlag: [
          { required: true, message: "请选择处理状态", trigger: "change" },
        ],
        remark: [
          { required: true, message: '请输入处理备注', trigger: 'blur' },
          { min: 5, max: 500, message: '备注长度在 5 到 500 个字符', trigger: 'blur' }
        ]
        handleresult: [
          {
            required: true,
            message: "请选择处理结果",
            trigger: "change",
            validator: (rule, value, callback) => {
              if (this.processForm.handleFlag === "1" && !value) {
                callback(new Error("请选择处理结果"));
              } else {
                callback();
              }
            },
          },
        ],
        handledesc: [
          {
            required: true,
            message: "请输入处理说明",
            trigger: "blur",
            validator: (rule, value, callback) => {
              if (
                this.processForm.handleFlag === "1" &&
                (!value || value.trim().length < 3)
              ) {
                callback(new Error("处理说明至少3个字符"));
              } else {
                callback();
              }
            },
          },
        ],
      },
      fileList: [],
      // 批量处理对话框
      batchDialogVisible: false,
      batchProcessForm: {
        status: '',
        reportDepts: [],
        remark: ''
      }
        handleFlag: "",
        ccdepts: [],
        handleresult: "",
        handledesc: "",
      },
    };
  },
  created() {
    // 从路由参数获取问题ID
    this.filterParams.scriptids =
      this.$route.query.questionId || this.$route.query.questionIds || null;
    // if (this.$route.query.questionId) {
    // } else if (this.$route.query.questionIds) {
    //   console.log(
    //     this.$route.query.questionIds,
    //     "this.$route.query.questionIds"
    //   );
    this.filterParams.templateType = Number(this.$route.query.type) || null;
    //   this.filterParams.scriptid = null;
    // }
    this.hasQualityPermission = this.checkQualityPermission();
  },
  mounted() {
    this.loadExceptionList();
    this.getDeptOptions();
    this.getUserOptions();
  },
  methods: {
    // 加载异常列表
    async loadExceptionList() {
      this.loading = true;
    // 格式化日期时间
    formatDateTime(dateTime) {
      if (!dateTime) return "";
      try {
        // Mock 数据
        await new Promise(resolve => {
          setTimeout(() => {
            this.exceptionList = [
              {
                id: 1,
                responsibilityDept: '心血管内科',
                unsatisfactoryDetail: '医生查房时间太短,沟通不够充分,对病情解释不够详细',
                patientName: '张先生',
                gender: 1,
                age: 45,
                phone: '138****1234',
                dischargeDept: '心血管内科',
                dischargeWard: '内科一病区',
                fillTime: '2024-01-15 10:30:25',
                processStatus: 0,
                questionnaireId: 1001
              },
              {
                id: 2,
                responsibilityDept: '神经内科',
                unsatisfactoryDetail: '护士打针技术不佳,扎了三次才成功,且态度不够耐心',
                patientName: '李女士',
                gender: 0,
                age: 38,
                phone: '139****5678',
                dischargeDept: '神经内科',
                dischargeWard: '内科二病区',
                fillTime: '2024-01-14 16:20:10',
                processStatus: 0,
                questionnaireId: 1002
              },
              {
                id: 3,
                responsibilityDept: '普外科',
                unsatisfactoryDetail: '术后换药不及时,伤口疼痛时没有及时处理',
                patientName: '王先生',
                gender: 1,
                age: 52,
                phone: '137****9012',
                dischargeDept: '普外科',
                dischargeWard: '外科一病区',
                fillTime: '2024-01-13 09:15:45',
                processStatus: 1,
                questionnaireId: 1003
              },
              {
                id: 4,
                responsibilityDept: '骨科',
                unsatisfactoryDetail: '康复指导不够专业,对恢复过程描述不清楚',
                patientName: '刘女士',
                gender: 0,
                age: 65,
                phone: '136****3456',
                dischargeDept: '骨科',
                dischargeWard: '外科二病区',
                fillTime: '2024-01-12 14:40:30',
                processStatus: 0,
                questionnaireId: 1004
              },
              {
                id: 5,
                responsibilityDept: '妇产科',
                unsatisfactoryDetail: '产前检查排队时间过长,等待期间没有休息座位',
                patientName: '陈女士',
                gender: 0,
                age: 28,
                phone: '135****7890',
                dischargeDept: '妇产科',
                dischargeWard: '妇产科病区',
                fillTime: '2024-01-11 11:25:15',
                processStatus: 2,
                questionnaireId: 1005
              },
              {
                id: 6,
                responsibilityDept: '儿科',
                unsatisfactoryDetail: '儿童用药剂量交代不清晰,用药注意事项没有说明',
                patientName: '赵宝宝',
                gender: 1,
                age: 5,
                phone: '134****1234',
                dischargeDept: '儿科',
                dischargeWard: '儿科病区',
                fillTime: '2024-01-10 15:50:20',
                processStatus: 0,
                questionnaireId: 1006
              },
              {
                id: 7,
                responsibilityDept: '急诊科',
                unsatisfactoryDetail: '急诊等待时间过长,病情没有得到及时评估',
                patientName: '孙先生',
                gender: 1,
                age: 40,
                phone: '133****5678',
                dischargeDept: '急诊科',
                dischargeWard: '急诊病区',
                fillTime: '2024-01-09 10:15:40',
                processStatus: 0,
                questionnaireId: 1007
              },
              {
                id: 8,
                responsibilityDept: '呼吸内科',
                unsatisfactoryDetail: '医生开药较多,费用较高,没有说明必要性',
                patientName: '周女士',
                gender: 0,
                age: 55,
                phone: '132****9012',
                dischargeDept: '呼吸内科',
                dischargeWard: '内科一病区',
                fillTime: '2024-01-08 13:30:55',
                processStatus: 1,
                questionnaireId: 1008
              }
            ];
            this.total = this.exceptionList.length;
            resolve();
          }, 500);
        const date = new Date(dateTime);
        if (isNaN(date.getTime())) {
          return dateTime;
        }
        return (
          date.toLocaleDateString().replace(/\//g, "-") +
          " " +
          date.toTimeString().split(" ")[0]
        );
      } catch (error) {
        console.error("日期格式化错误:", error);
        return dateTime;
      }
    },
    /** 查询科室列表 */
    getDeptOptions() {
      deptTreeSelect()
        .then((res) => {
          if (res.code == 200) {
            this.deptList = this.flattenArray(res.data) || [];
          }
        })
        .catch((error) => {
          console.error("获取科室列表失败:", error);
          this.$message.error("获取科室列表失败");
        });
      } finally {
        this.loading = false;
    },
    /** 查询用户列表(流转负责人候选) */
    getUserOptions() {
      listUser({ pageNum: 1, pageSize: 999 })
        .then((res) => {
          if (res.code == 200) {
            this.userList = res.rows || [];
          }
        })
        .catch((error) => {
          console.error("获取用户列表失败:", error);
          this.$message.error("获取用户列表失败");
        });
    },
    flattenArray(multiArray) {
      let result = [];
      function flatten(element) {
        if (element.children && element.children.length > 0) {
          element.children.forEach((child) => flatten(child));
        } else {
          let item = JSON.parse(JSON.stringify(element));
          result.push(item);
        }
      }
      multiArray.forEach((element) => flatten(element));
      return result;
    },
    // 解析患者描述信息
    parsePatDesc(patdesc) {
      if (!patdesc) return [];
      try {
        const parts = patdesc.split("|");
        const items = [];
        if (parts[0]) items.push({ label: "姓名", value: parts[0] });
        if (parts[1]) items.push({ label: "电话", value: parts[1] });
        if (parts[2]) items.push({ label: "科室", value: parts[2] });
        return items;
      } catch (error) {
        console.error("解析患者信息失败:", error);
        return [];
      }
    },
    // 检查质管权限
    checkQualityPermission() {
      // 这里可以根据实际权限系统实现
      const userRoles = this.$store.getters.roles || [];
      return (
        userRoles.includes("quality_manager") || userRoles.includes("admin")
      );
    },
    // 获取状态标签类型
    getStatusTagType(status) {
      switch (status) {
        case 0: return 'warning'; // 待处理
        case 1: return 'primary'; // 处理中
        case 2: return 'success'; // 已处理
        default: return 'info';
    getStatusTagType(handleFlag) {
      switch (handleFlag) {
        case "0":
          return "warning"; // 未处理
        case "1":
          return "success"; // 已处理
        default:
          return "info";
      }
    },
    // 获取状态文本
    getStatusText(status) {
      switch (status) {
        case 0: return '待处理';
        case 1: return '处理中';
        case 2: return '已处理';
        default: return '未知';
    getStatusText(handleFlag) {
      switch (handleFlag) {
        case "0":
          return "未处理";
        case "1":
          return "已处理";
        default:
          return "未知";
      }
    },
    // 播放录音
    handlePlayAudio(url) {
      this.audioUrl = url;
      this.$nextTick(() => {
        const audioPlayer = this.$refs.audioPlayer;
        if (audioPlayer) {
          audioPlayer.play().catch((error) => {
            console.error("播放失败:", error);
            this.$message.error("音频播放失败");
          });
        }
      });
    },
    // 构建查询参数
    buildQueryParams() {
      const params = {
        pageNum: this.filterParams.pageNum,
        pageSize: this.filterParams.pageSize,
      };
      if (this.filterParams.todeptcode) {
        params.todeptcode = this.filterParams.todeptcode;
      }
      if (this.filterParams.handleFlag !== "") {
        params.handleFlag = this.filterParams.handleFlag;
      }
      if (this.filterParams.templateType) {
        params.templateType = this.filterParams.templateType;
      }
      // if (this.filterParams.scriptid) {
      //   params.scriptid = this.filterParams.scriptid;
      // }
      if (this.filterParams.scriptids) {
        params.scriptids = this.filterParams.scriptids.split(",");
      }
      return params;
    },
    // 加载异常列表
    async loadExceptionList() {
      this.loading = true;
      try {
        const params = this.buildQueryParams();
        const response = await tracelist(params);
        if (response && response.code === 200) {
          this.exceptionList = response.rows || [];
          this.total = response.total || 0;
        } else {
          this.exceptionList = [];
          this.total = 0;
          this.$message.error(response?.msg || "加载异常列表失败");
        }
      } catch (error) {
        console.error("加载异常列表失败:", error);
        this.$message.error("加载异常列表失败,请稍后重试");
        this.exceptionList = [];
        this.total = 0;
      } finally {
        this.loading = false;
      }
    },
@@ -621,69 +995,337 @@
    // 重置筛选
    handleResetFilter() {
      this.filterParams = {
        deptId: '',
        status: '',
        todeptcode: "",
        handleFlag: "",
        scriptids:
          this.$route.query.questionId || this.$route.query.questionIds || null,
        templateType: Number(this.$route.query.type) || null,
        pageNum: 1,
        pageSize: 10
        pageSize: 10,
      };
      this.selectedExceptionIds = [];
      this.loadExceptionList();
    },
    // 处理选择变化
    handleSelectionChange(selection) {
      this.selectedExceptionIds = selection.map(item => item.id);
      this.selectedExceptionIds = selection.map((item) => item.id);
    },
    // 处理批量提交
    handleBatchSubmit() {
      if (this.selectedExceptionIds.length === 0) {
        this.$message.warning('请先选择要处理的异常反馈');
        this.$message.warning("请先选择要处理的异常反馈");
        return;
      }
      // 重置批量处理表单
      this.batchProcessForm = {
        handleFlag: "",
        ccdepts: [],
        handleresult: "",
        handledesc: "",
      };
      this.batchDialogVisible = true;
    },
    // 返回异常列表
    handleGoBack() {
      this.$router.push('/satisfaction/exception/list');
      // this.$router.push("/satisfaction/exception/list");
      this.$router.push("/Intelligentcenter/dispose");
    },
    // 查看详情
    handleViewDetail(row) {
      this.$router.push({
        path: '/satisfaction/exception/detail',
        query: {
          id: row.questionnaireId
      this.selectedRecordId = row.id;
      this.selectedRecordData = row;
      // 生成弹框标题
      let title = "异常反馈详情";
      if (row.patdesc) {
        const patientName = row.patdescJson.sendname;
        if (patientName) {
          title = `${patientName} - ${title}`;
        }
      });
      }
      this.detailDialogTitle = title;
      this.detailDialogVisible = true;
    },
    // 处理详情弹框关闭
    handleDetailDialogClose() {
      this.detailDialogVisible = false;
      this.selectedRecordId = null;
      this.selectedRecordData = null;
    },
    // 处理完成后的回调
    handleProcessed() {
      this.loadExceptionList();
    },
    // 处理单个异常
    handleProcess(row) {
      this.currentExceptionId = row.id;
      const nickName = this.$store.state.user.nickName || "";
      const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
      // 是否流转(后端 circulationStatus:0 不流转 / 1 流转)
      const isFlow = String(row.circulationStatus) === "1" ? "1" : "0";
      // 报备科室(兼容数组或逗号分隔字符串)
      const ccdepts = Array.isArray(row.ccdepts)
        ? row.ccdepts
        : row.ccdepts
        ? row.ccdepts.split(",")
        : [];
      // 流转科室 code / 名称
      const flowDeptCodes = row.circulationDeptCode
        ? row.circulationDeptCode.split(",")
        : [];
      const flowDeptNames = row.circulationDeptName
        ? row.circulationDeptName.split(",")
        : [];
      // 推送负责人:后端存工号(userName),下拉 value 用 userId,需回映
      const pushUserNos = row.circulationDeptPersonCode
        ? row.circulationDeptPersonCode.split(",")
        : [];
      const pushUserNames = row.circulationDeptPersonName
        ? row.circulationDeptPersonName.split(",")
        : [];
      const pushUsers = pushUserNos.map((no) => {
        const u = this.userList.find((item) => item.userName === no);
        return u ? u.userId : no;
      });
      // 科室反馈:从 handledesc JSON 中还原
      let flowFeedbacks = [];
      try {
        const parsed =
          typeof row.handledesc === "string" &&
          row.handledesc.trim().startsWith("{")
            ? JSON.parse(row.handledesc)
            : null;
        if (parsed && parsed.flow && Array.isArray(parsed.flow.feedbacks)) {
          flowFeedbacks = parsed.flow.feedbacks;
        }
      } catch (e) {
        // handledesc 非 JSON,忽略
      }
      // 流转时间:后端 Date 字段,统一转成 yyyy-MM-dd HH:mm:ss 供日期选择器回显
      let flowTime = now;
      if (row.circulationTime) {
        const d = new Date(
          typeof row.circulationTime === "number"
            ? row.circulationTime
            : String(row.circulationTime).replace(" ", "T")
        );
        if (!isNaN(d.getTime())) {
          const pad = (n) => String(n).padStart(2, "0");
          flowTime =
            d.getFullYear() +
            "-" +
            pad(d.getMonth() + 1) +
            "-" +
            pad(d.getDate()) +
            " " +
            pad(d.getHours()) +
            ":" +
            pad(d.getMinutes()) +
            ":" +
            pad(d.getSeconds());
        }
      }
      // 初始化表单数据
      this.processForm = {
        status: row.processStatus === 0 ? 1 : row.processStatus,
        reportDepts: [],
        remark: ''
        handleFlag: "1",
        ccdepts,
        handleresult: row.handleresult || "",
        handledesc: this.formatHandledesc(row.handledesc),
        finaloption: row.finaloption || "",
        // 流转相关
        isFlow,
        flowPerson: row.circulationPersonName || nickName,
        flowPersonCode:
          row.circulationPersonCode || this.$store.state.user.userName || "",
        flowTime,
        flowDesc: row.circulationExplain || "",
        flowDepts: [...flowDeptCodes],
        flowDeptNames: [...flowDeptNames],
        flowDeptCodes: [...flowDeptCodes],
        pushUsers,
        pushUserNames: [...pushUserNames],
        pushUserNos: [...pushUserNos],
        flowFeedbacks,
        handleBy: nickName,
        handleTime: now,
      };
      this.processDialogVisible = true;
    },
    // 流转科室变化:同步科室名称、科室code,并生成反馈表格
    onFlowDeptChange(codes) {
      this.processForm.flowDeptCodes = [...codes];
      this.processForm.flowDeptNames = codes.map((code) => {
        const dept = this.deptList.find((item) => item.deptCode === code);
        return dept ? dept.label : code;
      });
      // 生成/维护第二步反馈表格(保留已填写的反馈)
      this.processForm.flowFeedbacks = codes.map((code) => {
        const existing = this.processForm.flowFeedbacks.find(
          (item) => item.deptCode === code
        );
        if (existing) return existing;
        const dept = this.deptList.find((item) => item.deptCode === code);
        return {
          deptCode: code,
          deptName: dept ? dept.label : code,
          agree: "",
          desc: "",
        };
      });
    },
    // 推送负责人变化:同步负责人昵称、工号
    onPushUserChange(ids) {
      this.processForm.pushUserNames = ids.map((id) => {
        const user = this.userList.find((u) => String(u.userId) === String(id));
        return user ? user.nickName || user.userName : "";
      });
      this.processForm.pushUserNos = ids.map((id) => {
        const user = this.userList.find((u) => String(u.userId) === String(id));
        return user ? user.userName || "" : "";
      });
    },
    // 组装 handledesc:流转时以 JSON 形式保存原处理说明与流转说明、科室反馈
    buildHandledesc() {
      if (this.processForm.isFlow !== "1") {
        return this.processForm.handledesc;
      }
      const flow = {
        feedbacks: this.processForm.flowFeedbacks.map((f) => ({
          deptCode: f.deptCode,
          deptName: f.deptName,
          agree: f.agree,
          desc: f.desc,
        })),
      };
      return JSON.stringify({
        desc: this.processForm.handledesc,
        flow,
      });
    },
    // 解析 handledesc:若是流转 JSON 则取其中的处理说明,否则原样返回
    formatHandledesc(val) {
      if (!val) return "";
      if (typeof val !== "string") return val;
      const trimmed = val.trim();
      if (trimmed.startsWith("{")) {
        try {
          const obj = JSON.parse(trimmed);
          if (obj && obj.desc != null) return obj.desc;
        } catch (e) {
          // 不是合法 JSON,按原文本返回
        }
      }
      return val;
    },
    // 流转时间转为带时区的 ISO 格式,供后端 Date 类型字段反序列化
    toISODateTime(str) {
      if (!str) return null;
      const d = new Date(String(str).replace(" ", "T"));
      if (isNaN(d.getTime())) return null;
      const pad = (n) => String(n).padStart(2, "0");
      const offset = -d.getTimezoneOffset();
      const sign = offset >= 0 ? "+" : "-";
      const abs = Math.abs(offset);
      const tz = sign + pad(Math.floor(abs / 60)) + ":" + pad(abs % 60);
      return (
        d.getFullYear() +
        "-" + pad(d.getMonth() + 1) +
        "-" + pad(d.getDate()) +
        "T" + pad(d.getHours()) +
        ":" + pad(d.getMinutes()) +
        ":" + pad(d.getSeconds()) +
        "." + String(d.getMilliseconds()).padStart(3, "0") +
        tz
      );
    },
    // 提交处理
    async submitProcess() {
      this.$refs.processForm.validate(async (valid) => {
        if (valid) {
          this.processing = true;
          try {
            // Mock API调用
            await new Promise(resolve => setTimeout(resolve, 1000));
        if (!valid) {
          return;
        }
            this.$message.success('处理提交成功');
            this.processDialogVisible = false;
            this.loadExceptionList();
          } finally {
            this.processing = false;
          }
        // 流转时校验必须选择流转科室
        if (
          this.processForm.isFlow === "1" &&
          (!this.processForm.flowDepts || this.processForm.flowDepts.length === 0)
        ) {
          this.$message.warning("请先选择流转科室");
          return;
        }
        this.processing = true;
        try {
          // 准备提交数据
          const submitData = {
            id: this.currentExceptionId,
            handleFlag: this.processForm.handleFlag,
            handleresult: this.processForm.handleresult,
            handledesc: this.buildHandledesc(),
            finaloption: this.processForm.finaloption,
            handleBy:
              this.processForm.handleBy || this.$store.state.user.nickName,
            handleTime:
              this.processForm.handleTime ||
              dayjs().format("YYYY-MM-DD HH:mm:ss"),
            // 将数组转换为逗号分隔的字符串
            ccdepts: Array.isArray(this.processForm.ccdepts)
              ? this.processForm.ccdepts.join(",")
              : this.processForm.ccdepts,
            // 流转相关主表字段(后端已定稿)
            circulationPersonName: this.processForm.flowPerson,
            circulationPersonCode:
              this.processForm.flowPersonCode ||
              this.$store.state.user.userName ||
              "",
            circulationStatus: this.processForm.isFlow,
            circulationDeptName: this.processForm.flowDeptNames.join(","),
            circulationDeptCode: this.processForm.flowDeptCodes.join(","),
            circulationDeptPersonName: this.processForm.pushUserNames.join(","),
            circulationDeptPersonCode: this.processForm.pushUserNos.join(","),
            circulationExplain: this.processForm.flowDesc,
            circulationTime: this.toISODateTime(this.processForm.flowTime),
          };
          // TODO: 这里需要调用实际的处理接口
          await traceedit(submitData);
          // await new Promise((resolve) => setTimeout(resolve, 1000));
          this.$message.success("处理提交成功");
          this.processDialogVisible = false;
          this.loadExceptionList();
        } catch (error) {
          console.error("处理提交失败:", error);
          this.$message.error("处理提交失败,请稍后重试");
        } finally {
          this.processing = false;
        }
      });
    },
@@ -691,19 +1333,111 @@
    // 提交批量处理
    async submitBatchProcess() {
      this.$refs.batchProcessForm.validate(async (valid) => {
        if (valid) {
          this.batchProcessing = true;
          try {
            // Mock API调用
            await new Promise(resolve => setTimeout(resolve, 1500));
        if (!valid) {
          return;
        }
            this.$message.success(`已批量处理 ${this.selectedExceptionIds.length} 条异常反馈`);
            this.batchDialogVisible = false;
            this.selectedExceptionIds = [];
            this.loadExceptionList();
          } finally {
            this.batchProcessing = false;
        this.batchProcessing = true;
        // 显示进度条
        this.batchProgress = {
          visible: true,
          percentage: 0,
          processed: 0,
          total: this.selectedExceptionIds.length,
        };
        try {
          // 准备批量提交数据
          const processData = {
            handleFlag: this.batchProcessForm.handleFlag,
            handleresult: this.batchProcessForm.handleresult,
            handledesc: this.batchProcessForm.handledesc,
            ccdepts: Array.isArray(this.batchProcessForm.ccdepts)
              ? this.batchProcessForm.ccdepts.join(",")
              : this.batchProcessForm.ccdepts,
          };
          // 控制并发数
          const CONCURRENT_LIMIT = 10; // 同时最多3个请求
          const totalCount = this.selectedExceptionIds.length;
          const results = [];
          let successCount = 0;
          let failCount = 0;
          this.$message.info(`开始批量处理 ${totalCount} 条记录...`);
          // 分组处理
          for (
            let i = 0;
            i < this.selectedExceptionIds.length;
            i += CONCURRENT_LIMIT
          ) {
            const batchIds = this.selectedExceptionIds.slice(
              i,
              i + CONCURRENT_LIMIT
            );
            // 并发处理当前批次
            const batchPromises = batchIds.map((id) =>
              traceedit({
                id: id,
                ...processData,
              })
                .then((result) => ({
                  id,
                  success: result && result.code === 200,
                  error: result?.msg,
                }))
                .catch((error) => ({
                  id,
                  success: false,
                  error: error.message,
                }))
            );
            const batchResults = await Promise.all(batchPromises);
            results.push(...batchResults);
            // 更新统计
            batchResults.forEach((result) => {
              if (result.success) {
                successCount++;
              } else {
                failCount++;
                console.error(`处理记录 ${result.id} 失败:`, result.error);
              }
            });
            // 更新进度
            this.batchProgress.processed = i + 1;
            this.batchProgress.percentage = Math.round(
              ((i + 1) / totalCount) * 100
            );
            // 显示进度
            console.log(
              `进度: ${Math.min(
                i + CONCURRENT_LIMIT,
                totalCount
              )}/${totalCount}`
            );
          }
          // 处理结果提示
          if (successCount === totalCount) {
            this.$message.success(`已成功处理全部 ${totalCount} 条异常反馈`);
          } else {
            this.$message.warning(
              `已处理 ${successCount} 条,失败 ${failCount} 条异常反馈`
            );
          }
          this.batchDialogVisible = false;
          this.selectedExceptionIds = [];
          this.loadExceptionList();
        } catch (error) {
          console.error("批量处理失败:", error);
          this.$message.error("批量处理失败,请稍后重试");
        } finally {
          this.batchProcessing = false;
          this.batchProgress.visible = false;
        }
      });
    },
@@ -720,24 +1454,7 @@
      this.filterParams.pageNum = page;
      this.loadExceptionList();
    },
    // 文件上传相关方法
    handlePreview(file) {
      console.log('预览文件:', file);
    },
    handleRemove(file, fileList) {
      console.log('移除文件:', file, fileList);
    },
    beforeRemove(file) {
      return this.$confirm(`确定移除 ${file.name}?`);
    },
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
    }
  }
  },
};
</script>
@@ -750,7 +1467,7 @@
  .page-header {
    margin-bottom: 20px;
    padding: 20px;
    background: linear-gradient(135deg, #5788FE 0%, #66b1ff 100%);
    background: linear-gradient(135deg, #5788fe 0%, #66b1ff 100%);
    border-radius: 8px;
    color: white;
@@ -804,63 +1521,108 @@
      }
      .detail-content {
        font-size: 13px;
        color: #606266;
        line-height: 1.5;
        text-align: left;
        font-size: 12px;
        line-height: 1.5;
        .question-text {
          color: #303133;
          margin-bottom: 5px;
          font-weight: 500;
        }
        .answer-text {
          color: #f56c6c;
          margin-bottom: 5px;
        }
        .matched-text {
          color: #e6a23c;
          font-style: italic;
        }
        strong {
          color: #606266;
          font-weight: 600;
        }
      }
      .patient-info {
        .patient-item {
        .patient-row {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-bottom: 5px;
          padding: 2px 0;
          margin-bottom: 8px;
          .label {
            font-size: 12px;
            color: #606266;
            min-width: 40px;
          &:last-child {
            margin-bottom: 0;
          }
          .value {
            font-size: 13px;
            color: #333;
            font-weight: 500;
            text-align: right;
          .patient-item {
            flex: 1;
            display: flex;
            justify-content: flex-start;
            align-items: center;
            padding: 0 5px;
            &.full-width {
              flex: 1 0 100%;
              margin-left: 0;
              margin-right: 0;
            }
            .label {
              font-size: 12px;
              color: #606266;
              margin-right: 5px;
              white-space: nowrap;
            }
            .value {
              font-size: 12px;
              color: #333;
              font-weight: 500;
              text-align: right;
              word-break: break-all;
            }
          }
        }
      }
      .discharge-info {
      .fill-info,
      .handle-info {
        font-size: 12px;
        .info-item {
          display: flex;
          justify-content: space-between;
          justify-content: flex-start;
          align-items: center;
          margin-bottom: 5px;
          padding: 2px 0;
          .label {
            font-size: 12px;
            color: #606266;
            min-width: 50px;
          }
          .value {
            font-size: 13px;
            color: #333;
            font-weight: 500;
            text-align: right;
            // text-align: right;
            flex: 1;
            &.time {
              font-size: 12px;
              color: #909399;
              font-size: 11px;
            }
          }
        }
      }
      .no-data {
        color: #909399;
        font-style: italic;
        font-size: 12px;
      }
    }
@@ -872,6 +1634,47 @@
  }
}
// 处理弹框左右布局
.flow-dialog-body {
  display: flex;
  align-items: stretch;
  .flow-left {
    flex: 1;
    min-width: 320px;
    padding-right: 24px;
    border-right: 1px solid #ebeef5;
  }
  .flow-right {
    flex: 1;
    min-width: 320px;
    padding-left: 24px;
    max-height: 60vh;
    overflow-y: auto;
    .flow-step-title {
      font-weight: 600;
      color: #303133;
      margin-bottom: 12px;
      font-size: 14px;
    }
    .flow-step-form {
      ::v-deep .el-form-item {
        margin-bottom: 12px;
      }
    }
    .flow-empty-tip {
      padding: 20px;
      text-align: center;
      color: #909399;
      font-size: 13px;
    }
  }
}
@media (max-width: 768px) {
  .batch-process {
    padding: 10px;