<template>
  <div class="app-container">
    <!-- 筛选条件 -->
    <el-card v-show="showSearch" class="query-card" shadow="never">
      <div class="card-head">
        <span class="card-head__title">筛选条件</span>
        <span v-if="activeFilterCount" class="card-head__extra">已选 {{ activeFilterCount }} 项</span>
      </div>
      <el-form ref="queryForm" :model="queryParams" class="query-form" label-position="top" @submit.native.prevent>
        <el-row :gutter="16">
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item label="任务名称" prop="batchName">
              <el-input
                v-model="queryParams.batchName"
                placeholder="请输入任务名称"
                clearable
                size="small"
                class="full-width"
                @keyup.enter.native="handleQuery"
              />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item label="TTS厂商" prop="voiceSource">
              <el-select v-model="queryParams.voiceSource" placeholder="请选择 TTS 厂商" filterable clearable size="small" class="full-width">
                <el-option
                  v-for="item in ttsProviderList"
                  :key="item.voiceSource"
                  :label="item.provider"
                  :value="item.voiceSource"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item label="ASR厂商" prop="asrProvider">
              <el-select v-model="queryParams.asrProvider" placeholder="请选择 ASR 厂商" filterable clearable size="small" class="full-width">
                <el-option
                  v-for="item in asrProviderList"
                  :key="item.asrProvider"
                  :label="item.provider"
                  :value="item.asrProvider"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6">
            <el-form-item label="外呼线路" prop="gatewayId">
              <el-select v-model="queryParams.gatewayId" placeholder="请选择外呼线路" filterable clearable size="small" class="full-width">
                <el-option
                  v-for="item in gatewayList"
                  :key="item.id"
                  :label="item.gwName"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="24" :md="16" :lg="10">
            <el-form-item label="创建时间">
              <el-date-picker
                v-model="createTimeRange"
                type="datetimerange"
                size="small"
                class="full-width"
                value-format="yyyy-MM-dd HH:mm:ss"
                format="yyyy-MM-dd HH:mm"
                range-separator="至"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
                :default-time="['00:00:00', '23:59:59']"
                clearable
              />
            </el-form-item>
          </el-col>
        </el-row>
        <div class="query-form__actions">
          <el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery">搜索</el-button>
          <el-button icon="el-icon-refresh" size="small" @click="resetQuery">重置</el-button>
        </div>
      </el-form>
    </el-card>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['his:aiSipCall:task:add']"
        >新增</el-button>
      </el-col>
<!--      <el-col :span="1.5">-->
<!--      <el-button-->
<!--        type="primary"-->
<!--        plain-->
<!--        icon="el-icon-plus"-->
<!--        size="mini"-->
<!--        @click="downloadCallTemplate"-->
<!--        v-hasPermi="['his:aiSipCall:task:download:template']"-->
<!--      >下载外呼模板</el-button>-->
<!--    </el-col>-->
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="el-icon-edit"
          size="mini"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['his:aiSipCall:task:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="el-icon-delete"
          size="mini"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['his:aiSipCall:task:remove']"
        >删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="el-icon-download"
          size="mini"
          :loading="exportLoading"
          @click="handleExport"
          v-hasPermi="['his:aiSipCall:task:export']"
        >导出</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table border v-loading="loading" :data="aiSipCallList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="任务名称" align="center" prop="batchName" />
      <el-table-column label="线路名称" align="center" prop="gatewayId">
        <template slot-scope="scope">
          <span v-for="item in gatewayList" v-if="scope.row.gatewayId === item.id">{{ item.gwName }}</span>
        </template>
      </el-table-column>
      <el-table-column label="并发量" align="center" prop="threadNum" />
      <el-table-column label="TTS厂商" align="center" prop="voiceSource" min-width="100">
        <template slot-scope="scope">
          {{ getTtsProviderLabel(scope.row.voiceSource) }}
        </template>
      </el-table-column>
      <el-table-column label="音色" align="center" prop="voiceCode">
        <template slot-scope="scope">
        <span v-for="(item, index) in queryVoiceList" v-if="scope.row.voiceCode === item.voiceCode" :key="'table-' + item.voiceCode + '-' + index">{{ item.voiceName }}</span>
      </template>
      </el-table-column>
      <el-table-column label="ASR厂商" align="center" prop="asrProvider" min-width="100">
        <template slot-scope="scope">
          {{ getAsrProviderLabel(scope.row.asrProvider) }}
        </template>
      </el-table-column>
      <el-table-column label="总名单量" align="center" prop="phoneCount" />
      <el-table-column label="未拨打" align="center" prop="noCallCount" />
      <el-table-column label="已拨打" align="center" prop="callCount" />
      <el-table-column label="接通量" align="center" prop="connectCount" />
      <el-table-column label="未接量" align="center" prop="noConnectCount" />
      <el-table-column label="接通率" align="center">
        <template slot-scope="scope">
          {{ formatConnectRate(scope.row.realConnectRate) }}
        </template>
      </el-table-column>
<!--      <el-table-column label="创建人" align="center" prop="createBy" />-->
<!--      <el-table-column label="创建时间" align="center" prop="createTime" />-->
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['his:aiSipCall:task:edit']"
          >修改</el-button>
<!--          <el-button-->
<!--            size="mini"-->
<!--            type="text"-->
<!--            icon="el-icon-video-play"-->
<!--            @click="startTask(scope.row.batchId)"-->
<!--            v-hasPermi="['his:aiSipCall:task:startTask']"-->
<!--          >启动外呼</el-button>-->
<!--          <el-button-->
<!--            size="mini"-->
<!--            type="text"-->
<!--            icon="el-icon-video-pause"-->
<!--            @click="stopTask(scope.row.batchId)"-->
<!--            v-hasPermi="['his:aiSipCall:task:stopTask']"-->
<!--          >停止外呼</el-button>-->
<!--          <el-button-->
<!--            size="mini"-->
<!--            type="text"-->
<!--            icon="el-icon-upload"-->
<!--            @click="handleImportData(scope.row.batchId)"-->
<!--            v-hasPermi="['his:aiSipCall:task:commonImportExcel']"-->
<!--          >导入外呼模板</el-button>-->
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['his:aiSipCall:task:remove']"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改aiSIP外呼任务对话框 -->
    <el-dialog
      :title="title"
      :visible.sync="open"
      width="860px"
      append-to-body
      :close-on-click-modal="false"
      custom-class="task-dialog"
    >
      <el-form ref="form" :model="form" :rules="rules" label-width="120px" class="dialog-form">
        <div class="form-block">
          <div class="form-block__title">基本信息</div>
          <el-row :gutter="16">
            <el-col :span="24">
              <el-form-item label="任务名称" prop="batchName">
                <el-input v-model="form.batchName" placeholder="请输入任务名称" clearable />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="16">
            <el-col :span="12">
              <el-form-item label="任务类型" prop="taskType">
                <el-select v-model="form.taskType" placeholder="请选择任务类型" filterable clearable class="full-width">
                  <el-option label="AI外呼" value="1" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="最大并发" prop="threadNum">
                <el-input-number
                  v-model="form.threadNum"
                  :min="1"
                  :precision="0"
                  :step="1"
                  controls-position="right"
                  placeholder="请输入最大并发"
                  class="full-width"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="16">
            <el-col :span="12">
              <el-form-item label="外呼线路" prop="gatewayId">
                <el-select
                  v-model="form.gatewayId"
                  placeholder="请选择外呼线路"
                  filterable
                  clearable
                  class="full-width"
                  :disabled="!!form.batchId"
                >
                  <el-option
                    v-for="item in gatewayList"
                    :key="item.id"
                    :label="item.gwName"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="自动停止" prop="autoStop">
                <el-select v-model="form.autoStop" placeholder="请选择自动停止" filterable clearable class="full-width">
                  <el-option label="名单拨打完后任务自动停止" value="1" />
                  <el-option label="任务不自动停止" value="0" />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
        </div>

        <div class="form-block" v-show="form.taskType === '0'">
          <div class="form-block__title">预测外呼参数</div>
          <el-row :gutter="16">
            <el-col :span="12">
              <el-form-item label="预估接通率" prop="conntectRate">
                <el-input v-model="form.conntectRate" placeholder="请输入预估接通率（%）" clearable>
                  <template slot="append">%</template>
                </el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="平均振铃时长" prop="avgRingTimeLen">
                <el-input v-model="form.avgRingTimeLen" placeholder="请输入平均振铃时长" clearable>
                  <template slot="append">秒</template>
                </el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="平均通话时长" prop="avgCallTalkTimeLen">
                <el-input v-model="form.avgCallTalkTimeLen" placeholder="请输入平均通话时长" clearable>
                  <template slot="append">秒</template>
                </el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="事后处理时长" prop="avgCallEndProcessTimeLen">
                <el-input v-model="form.avgCallEndProcessTimeLen" placeholder="请输入平均事后处理时长" clearable>
                  <template slot="append">秒</template>
                </el-input>
              </el-form-item>
            </el-col>
          </el-row>
        </div>

        <div class="form-block" v-show="form.taskType === '1'">
          <div class="form-block__title">大模型配置</div>
          <el-form-item label="大模型底座" prop="llmAccountId">
            <el-select v-model="form.llmAccountId" placeholder="请选择大模型底座" filterable clearable class="full-width">
              <el-option
                v-for="item in llmAgentAccountList"
                :key="item.id"
                :label="item.name"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
        </div>

        <div class="form-block" v-show="form.taskType === '1' || form.taskType === '2'">
          <div class="form-block__title">语音合成 (TTS)</div>
          <el-row :gutter="16">
            <el-col :span="12">
              <el-form-item label="TTS厂商" prop="voiceSource">
                <el-select
                  v-model="form.voiceSource"
                  placeholder="请选择 TTS 厂商"
                  filterable
                  clearable
                  class="full-width"
                  @change="handleVoiceSourceChange"
                >
                  <el-option
                    v-for="item in ttsProviderList"
                    :key="item.voiceSource"
                    :label="item.provider"
                    :value="item.voiceSource"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12" v-show="form.voiceSource && formTtsLanguageList.length">
              <el-form-item label="TTS语言" prop="ttsLanguageCode">
                <el-select v-model="form.ttsLanguageCode" placeholder="请选择 TTS 语言" filterable clearable class="full-width" @change="handleTtsLanguageChange">
                  <el-option
                    v-for="item in formTtsLanguageList"
                    :key="item.ttsLanguageCode"
                    :label="item.languageName"
                    :value="item.ttsLanguageCode"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12" v-show="form.voiceSource && form.ttsLanguageCode">
              <el-form-item label="TTS模型" prop="ttsModels">
                <el-select v-model="form.ttsModels" placeholder="请选择 TTS 模型" filterable clearable class="full-width" @change="handleTtsModelsChange">
                  <el-option
                    v-for="item in formTtsModelList"
                    :key="item.ttsModels"
                    :label="item.modelName"
                    :value="item.ttsModels"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12" v-show="form.ttsModels">
              <el-form-item label="音色" prop="voiceCode">
                <el-select v-model="form.voiceCode" placeholder="请选择音色" filterable clearable class="full-width">
                  <el-option
                    v-for="(item, index) in formVoiceList"
                    :key="'form-' + item.voiceCode + '-' + index"
                    :label="item.voiceName"
                    :value="item.voiceCode"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
        </div>

        <div class="form-block" v-show="form.taskType === '1' || form.taskType === '2'">
          <div class="form-block__title">语音识别 (ASR)</div>
          <el-row :gutter="16">
            <el-col :span="12">
              <el-form-item label="ASR厂商" prop="asrProvider">
                <el-select v-model="form.asrProvider" placeholder="请选择 ASR 厂商" filterable clearable class="full-width" @change="handleAsrProviderChange">
                  <el-option
                    v-for="item in asrProviderList"
                    :key="item.asrProvider"
                    :label="item.provider"
                    :value="item.asrProvider"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12" v-show="form.asrProvider && formAsrLanguageList.length">
              <el-form-item label="ASR语言" prop="asrLanguageCode">
                <el-select v-model="form.asrLanguageCode" placeholder="请选择 ASR 语言" filterable clearable class="full-width" @change="handleAsrLanguageChange">
                  <el-option
                    v-for="item in formAsrLanguageList"
                    :key="item.asrLanguageCode"
                    :label="item.languageName"
                    :value="item.asrLanguageCode"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12" v-show="form.asrProvider">
              <el-form-item label="ASR模型" prop="asrModels">
                <el-select v-model="form.asrModels" placeholder="请选择 ASR 模型" filterable clearable class="full-width">
                  <el-option
                    v-for="item in formAsrModelList"
                    :key="item.asrModels"
                    :label="item.modelName"
                    :value="item.asrModels"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
        </div>

        <div class="form-block" v-show="form.taskType === '2'">
          <div class="form-block__title">语音通知</div>
          <el-form-item label="播放次数" prop="playTimes">
            <el-input v-model="form.playTimes" placeholder="请输入播放次数" clearable style="max-width: 240px;" />
          </el-form-item>
        </div>

        <div class="form-block" v-show="form.taskType === '1'">
          <div class="form-block__title">转人工配置</div>
          <el-row :gutter="16">
            <el-col :span="12">
              <el-form-item label="转人工方式" prop="aiTransferType">
                <el-select v-model="form.aiTransferType" placeholder="请选择转人工方式" filterable clearable class="full-width" @change="handleAiTransferTypeChange">
                  <el-option label="电话排队" value="acd" />
                  <el-option label="转分机" value="extension" />
                  <el-option label="转外部网关" value="gateway" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12" v-show="form.aiTransferType !== 'extension' && form.aiTransferType !== 'gateway'">
              <el-form-item label="业务组" prop="aiTransferGroupId">
                <el-select v-model="form.aiTransferGroupId" placeholder="请选择业务组" filterable clearable class="full-width">
                  <el-option
                    v-for="item in bizGroupList"
                    :key="item.groupId"
                    :label="item.bizGroupName"
                    :value="item.groupId"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="24" v-show="form.aiTransferType === 'extension'">
              <el-form-item label="转接分机" prop="aiTransferExtNumber">
                <el-input v-model="form.aiTransferExtNumber" placeholder="多个分机用空格分隔" clearable />
              </el-form-item>
            </el-col>
            <el-col :span="12" v-show="form.aiTransferType === 'gateway'">
              <el-form-item label="网关" prop="aiTransferGatewayId">
                <el-select v-model="form.aiTransferGatewayId" placeholder="请选择外呼线路" filterable clearable class="full-width">
                  <el-option
                    v-for="item in gatewayList"
                    :key="item.id"
                    :label="item.gwName"
                    :value="item.id"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12" v-show="form.aiTransferType === 'gateway'">
              <el-form-item label="转接号码" prop="aiTransferGatewayDestNumber">
                <el-input v-model="form.aiTransferGatewayDestNumber" placeholder="请输入转接号码" clearable />
              </el-form-item>
            </el-col>
          </el-row>
          <div v-if="form.aiTransferType === 'acd'" class="form-hint">电话排队方式需要配合电话工具条使用</div>
        </div>
      </el-form>
      <div slot="footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="submitForm">确 定</el-button>
      </div>
    </el-dialog>

    <!-- 导入数据对话框 -->
    <el-dialog :title="uploadTitle" :visible.sync="uploadOpen" width="500px" append-to-body>
      <el-form ref="uploadForm" :model="uploadForm">
        <el-form-item label="选择文件">
          <input type="file" ref="fileInput" @change="handleFileChange" accept=".xlsx,.xls,.csv" style="width: 100%;">
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="uploadOpen = false">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { downloadTemplateByType,listAiSipCallTask, getAiSipCallTask, delAiSipCallTask, addAiSipCallTask, updateAiSipCallTask, exportAiSipCallTask, startTask, stopTask,commonImportExcel } from "@/api/aiSipCall/aiSipCallTask";
import {remoteGatewayList} from "../../api/aiSipCall/aiSipCallGateway";
import { remoteList, allTtsProvider, allAsrProvider, getTtsLanguages, getTtsModels, getAsrLanguages, getAsrModels } from '@/api/aiSipCall/aiSipCallVoiceTtsAliyun'
import {listAiSipCallLlmAgentAccount } from "@/api/aiSipCall/aiSipCallLlmAgentAccount";
import { listAiSipCallBizGroup } from "@/api/aiSipCall/aiSipCallBizGroup";
export default {
  name: "aiSipCallTask",
  data() {
    return {
      // 遮罩层
      loading: true,
      // 导出遮罩层
      exportLoading: false,
      //新增和修改使用
      gatewayList: [],
      ttsProviderList: [],
      formTtsLanguageList: [],
      asrProviderList: [],
      formAsrLanguageList: [],
      formAsrModelList: [],
      formVoiceList: [],
      formVoiceRawList: [],
      formTtsModelList: [],
      queryVoiceList: [],
      llmAgentAccountList: [],
      bizGroupList: [],
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // aiSIP 外呼任务表格数据
      aiSipCallList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 上传对话框标题
      uploadTitle: "导入数据",
      // 是否显示上传对话框
      uploadOpen: false,
      // 上传表单
      uploadForm: {
        batchId: null,
        file: null
      },
      // 当前选中的任务行
      currentRow: null,
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        createTimeStart: null,
        createTimeEnd: null,
        groupId: null,
        batchName: null,
        ifcall: null,
        rate: null,
        threadNum: null,
        createTime: null,
        executing: null,
        stopTime: null,
        userid: null,
        taskType: null,
        gatewayId: null,
        voiceCode: null,
        voiceSource: null,
        avgRingTimeLen: null,
        avgCallTalkTimeLen: null,
        avgCallEndProcessTimeLen: null,
        callNodeNo: null,
        llmAccountId: null,
        playTimes: null,
        asrProvider: null,
        asrLanguageCode: null,
        asrModels: null,
        aiTransferType: null,
        aiTransferData: null,
        autoStop: null,
        ivrId: null,
        remoteBatchId: null,
        status: 0
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        batchName: [
          { required: true, message: "任务名称不能为空", trigger: "blur" }
        ],
        taskType: [
          { required: true, message: "任务类型不能为空", trigger: "change" }
        ],
        threadNum: [
          { required: true, message: "最大并发不能为空", trigger: "blur" },
          { type: 'number', min: 1, message: "最大并发必须为正整数", trigger: "blur" }
        ],
        gatewayId: [
          { required: true, message: "外呼线路不能为空", trigger: "change" }
        ],
        autoStop: [
          { required: true, message: "自动停止不能为空", trigger: "change" }
        ],
        llmAccountId: [
          { required: true, message: "大模型底座不能为空", trigger: "change" }
        ],
        voiceSource: [
          { required: true, message: "TTS 厂商不能为空", trigger: "change" }
        ],
        ttsLanguageCode: [
          { validator: (rule, value, callback) => {
              if (this.formTtsLanguageList.length > 0 && !value) {
                callback(new Error('TTS 语言不能为空'));
              } else {
                callback();
              }
            }, trigger: "change" }
        ],
        ttsModels: [
          { required: true, message: "TTS 模型不能为空", trigger: "change" }
        ],
        voiceCode: [
          { required: true, message: "音色不能为空", trigger: "change" }
        ],
        asrProvider: [
          { required: true, message: "ASR 厂商不能为空", trigger: "change" }
        ],
        asrLanguageCode: [
          { validator: (rule, value, callback) => {
              if (this.formAsrLanguageList.length > 0 && !value) {
                callback(new Error('ASR 语言不能为空'));
              } else {
                callback();
              }
            }, trigger: "change" }
        ],
        asrModels: [
          { required: true, message: "ASR 模型不能为空", trigger: "change" }
        ],
        aiTransferType: [
          { required: true, message: "转人工方式不能为空", trigger: "change" }
        ],
        aiTransferGroupId: [
          { validator: (rule, value, callback) => {
              // 任务类型为 AI 外呼(1)且转人工方式为电话排队(acd)时必填
              if (this.form.taskType === '1' && this.form.aiTransferType !== 'extension' && this.form.aiTransferType !== 'gateway' && !value) {
                callback(new Error('业务组不能为空'));
              } else {
                callback();
              }
            }, trigger: "change" }
        ],
        groupId: [
          { validator: (rule, value, callback) => {
              // 任务类型为 AI 外呼（1）且转人工方式为电话排队（acd）时必填
              if (this.form.taskType === '1' && this.form.aiTransferType === 'acd' && !value) {
                callback(new Error('业务组不能为空'));
              } else {
                callback();
              }
            }, trigger: "change" }
        ],
        aiTransferExtNumber: [
          { validator: (rule, value, callback) => {
              if (this.form.aiTransferType === 'extension' && !value) {
                callback(new Error('转接分机不能为空'));
              } else {
                callback();
              }
            }, trigger: "blur" }
        ],
        aiTransferGatewayId: [
          { validator: (rule, value, callback) => {
              if (this.form.aiTransferType === 'gateway' && !value) {
                callback(new Error('外呼线路不能为空'));
              } else {
                callback();
              }
            }, trigger: "change" }
        ],
        aiTransferGatewayDestNumber: [
          { validator: (rule, value, callback) => {
             if (this.form.aiTransferType === 'gateway' && !value) {
                callback(new Error('转接号码不能为空'));
              } else {
                callback();
              }
            }, trigger: "blur" }
        ],
        conntectRate: [
          { validator: (rule, value, callback) => {
            if (this.form.taskType === '0' && !value) {
                callback(new Error('预估接通率不能为空'));
              } else {
                callback();
              }
            }, trigger: "blur" }
        ],
        avgRingTimeLen: [
          { validator: (rule, value, callback) => {
            if (this.form.taskType === '0' && !value) {
                callback(new Error('平均振铃时长不能为空'));
              } else {
                callback();
              }
            }, trigger: "blur" }
        ],
        avgCallTalkTimeLen: [
          { validator: (rule, value, callback) => {
            if (this.form.taskType === '0' && !value) {
                callback(new Error('平均通话时长不能为空'));
              } else {
                callback();
              }
            }, trigger: "blur" }
        ],
        avgCallEndProcessTimeLen: [
          { validator: (rule, value, callback) => {
            if (this.form.taskType === '0' && !value) {
                callback(new Error('平均事后处理时长不能为空'));
              } else {
                callback();
              }
            }, trigger: "blur" }
        ],
        playTimes: [
          { validator: (rule, value, callback) => {
            if (this.form.taskType === '2' && !value) {
                callback(new Error('播放次数不能为空'));
              } else {
                callback();
              }
            }, trigger: "blur" }
        ]
      }
    };
  },
  computed: {
    activeFilterCount() {
      const { batchName, voiceSource, asrProvider, gatewayId, createTimeStart, createTimeEnd } = this.queryParams
      let count = 0
      if (batchName) count++
      if (voiceSource) count++
      if (asrProvider) count++
      if (gatewayId) count++
      if (createTimeStart || createTimeEnd) count++
      return count
    },
    createTimeRange: {
      get() {
        const { createTimeStart, createTimeEnd } = this.queryParams
        if (createTimeStart && createTimeEnd) {
          return [createTimeStart, createTimeEnd]
        }
        return null
      },
      set(val) {
        if (val && val.length === 2) {
          this.queryParams.createTimeStart = val[0]
          this.queryParams.createTimeEnd = val[1]
        } else {
          this.queryParams.createTimeStart = null
          this.queryParams.createTimeEnd = null
        }
      }
    }
  },
  created() {
    remoteGatewayList({ pageNum:1, pageSize: 50,isAICall:true,params:{purposes: [2, 3]} }).then(response => {
      this.gatewayList = response.rows || [];
    });
    this.loadTtsProviders()
    this.loadAsrProviders()
    this.loadQueryVoiceList()
    //获取所有大模型底座
    listAiSipCallLlmAgentAccount().then(response => {
     this.llmAgentAccountList = response.rows;
    })
    // 获取所有业务组
    listAiSipCallBizGroup().then(response => {
     this.bizGroupList = response.rows;
    })


   this.getList();
  },
  methods: {
    downloadCallTemplate(){
      downloadTemplateByType(1).then(response => {
        // 创建 blob 对象
        const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });

        // 创建下载链接
        const link = document.createElement('a');
        link.href = window.URL.createObjectURL(blob);
        link.download = 'AICallList.xlsx';

        // 触发下载
        document.body.appendChild(link);
        link.click();

        // 清理
        document.body.removeChild(link);
        window.URL.revokeObjectURL(link.href);
      })
    },
    startTask(batchId){
      startTask(batchId).then(response => {
        if(response.code === 200){
          this.msgSuccess("启动外呼成功")
        }else{
          this.msgError("启动外呼失败");
        }
        this.getList();
      })
    },
    stopTask(batchId){
      stopTask(batchId).then(response => {
        if(response.code === 200){
          this.msgSuccess("停止外呼成功")
        }else{
          this.msgError("停止外呼失败");
        }
        this.getList();
      })
    },
    /** 查询aiSIP外呼任务列表 */
    getList() {
      this.loading = true;
      listAiSipCallTask(this.queryParams).then(response => {
        this.aiSipCallList = response.rows;
        this.total = response.total;
        this.loading = false;
      });
    },
    // 取消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // 表单重置
    reset() {
     this.form = {
        batchId: null,
        groupId: null,
       createTimeStart: null,
       createTimeEnd: null,
        batchName: null,
        ifcall: null,
        rate: null,
        threadNum: 10,
        createtime: null,
        executing: null,
        stopTime: null,
        userid: null,
        taskType: null,
        gatewayId: null,
        voiceCode: null,
        voiceSource: null,
        ttsLanguageCode: null,
        ttsModels: null,
        avgRingTimeLen: null,
        avgCallTalkTimeLen: null,
        avgCallEndProcessTimeLen: null,
        callNodeNo: null,
        llmAccountId: null,
        playTimes: null,
        asrProvider: null,
        asrLanguageCode: null,
        asrModels: null,
        aiTransferType: null,
        aiTransferData: null,
        autoStop: null,
        ivrId: null,
        remoteBatchId: null,
        aiTransferExtNumber: null,
        status: 0
      };
     this.resetForm("form");
     this.formVoiceList = [];
     this.formVoiceRawList = [];
     this.formTtsModelList = [];
     this.formTtsLanguageList = [];
     this.formAsrLanguageList = [];
     this.formAsrModelList = [];
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.batchId)
      this.single = selection.length!==1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset();
      // 默认选中 AI 外呼
      this.form.taskType = "1";
      // 默认自动停止
      this.form.autoStop = "1";
      // 默认选中第一个外呼线路
      if (this.gatewayList && this.gatewayList.length > 0) {
        this.form.gatewayId = this.gatewayList[0].id;
      }
      // 默认选中第一个大模型底座
      if (this.llmAgentAccountList && this.llmAgentAccountList.length > 0) {
        this.form.llmAccountId = this.llmAgentAccountList[0].id;
      }
      // 默认选中第一个 TTS 厂商及对应音色
      this.applyDefaultVoiceSelection(true)
      if (this.asrProviderList.length > 0) {
        this.form.asrProvider = this.asrProviderList[0].asrProvider
        this.loadAsrLanguages(this.form.asrProvider)
      }
      // 默认选中第一个转人工方式
      this.form.aiTransferType = "acd";
      // 根据转人工方式设置默认业务组
      if (this.bizGroupList && this.bizGroupList.length > 0) {
        this.form.aiTransferGroupId = this.bizGroupList[0].groupId;
      }
      this.open = true;
      this.title = "添加 aiSIP 外呼任务";
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset();
      const batchId = row.batchId || this.ids
      getAiSipCallTask(batchId).then(response => {
        const data = response.data;

        // 确保 taskType 为字符串类型，与 el-option 的 value 类型一致
        if (data.taskType !== null && data.taskType !== undefined) {
          this.form.taskType = String(data.taskType);
        }

        // 确保 autoStop 为字符串类型
        if (data.autoStop !== null && data.autoStop !== undefined) {
          this.form.autoStop = String(data.autoStop);
        }

        // 确保 aiTransferType 为字符串类型
        if (data.aiTransferType !== null && data.aiTransferType !== undefined) {
          this.form.aiTransferType = String(data.aiTransferType);
        }

        // 确保 voiceSource 为字符串类型
        if (data.voiceSource !== null && data.voiceSource !== undefined) {
          this.form.voiceSource = String(data.voiceSource);
        }

        // 确保 asrProvider 为字符串类型
        if (data.asrProvider !== null && data.asrProvider !== undefined) {
          this.form.asrProvider = String(data.asrProvider);
        }
        this.form.asrLanguageCode = data.asrLanguageCode;
        this.form.asrModels = data.asrModels;
        if (this.form.asrProvider) {
          this.loadAsrLanguages(this.form.asrProvider, { keepLanguageCode: true, keepAsrModels: true })
        }

        // 复制其他字段
        this.form.batchId = data.batchId;
        this.form.groupId = data.groupId;
        this.form.aiTransferGroupId = data.aiTransferGroupId;

        // 如果业务组没有值且需要显示业务组,则默认选中第一个
        if (!this.form.aiTransferGroupId &&
          this.form.taskType === '1' &&
          this.form.aiTransferType !== 'extension' &&
          this.form.aiTransferType !== 'gateway' &&
          this.bizGroupList && this.bizGroupList.length > 0) {
          this.form.aiTransferGroupId = this.bizGroupList[0].groupId;
        }

        this.form.batchName = data.batchName;
        this.form.ifcall = data.ifcall;
        this.form.rate = data.rate;
        this.form.threadNum = data.threadNum != null && data.threadNum !== '' ? Number(data.threadNum) : 10;
        this.form.gatewayId = data.gatewayId;
        this.form.voiceCode = data.voiceCode;
        this.form.ttsModels = data.ttsModels;
        this.form.ttsLanguageCode = data.ttsLanguageCode;
        if (this.form.voiceSource) {
          this.loadTtsLanguages(this.form.voiceSource, { keepLanguageCode: true, keepTtsModels: true, keepVoiceCode: true })
        }
        this.form.avgRingTimeLen = data.avgRingTimeLen;
        this.form.avgCallTalkTimeLen = data.avgCallTalkTimeLen;
        this.form.avgCallEndProcessTimeLen = data.avgCallEndProcessTimeLen;
        this.form.callNodeNo = data.callNodeNo;
        this.form.llmAccountId = data.llmAccountId;
        this.form.playTimes = data.playTimes;
        this.form.aiTransferData = data.aiTransferData;
        this.form.ivrId = data.ivrId;
        this.form.remoteBatchId = data.remoteBatchId;
        this.form.aiTransferExtNumber = data.aiTransferExtNumber;
        this.form.aiTransferGatewayId = data.aiTransferGatewayId;
        this.form.aiTransferGatewayDestNumber = data.aiTransferGatewayDestNumber;
        this.form.conntectRate = data.conntectRate;
        this.form.status = data.status !== undefined ? data.status : 0;

        // 如果是纯人工预测外呼，设置默认的并发相关字段
        if (this.form.taskType === '0') {
          if (!this.form.conntectRate) {
            this.form.conntectRate = '80';
          }
          if (!this.form.avgRingTimeLen) {
            this.form.avgRingTimeLen = '30';
          }
          if (!this.form.avgCallTalkTimeLen) {
            this.form.avgCallTalkTimeLen = '60';
          }
          if (!this.form.avgCallEndProcessTimeLen) {
            this.form.avgCallEndProcessTimeLen = '30';
          }
        }

        // 如果是语音通知，设置默认播放次数
        if (this.form.taskType === '2') {
          if (!this.form.playTimes) {
            this.form.playTimes = '1';
          }
        }

        this.open = true;
        this.title = "修改 aiSIP 外呼任务";
      });
    },
    /** 提交按钮 */
    submitForm() {
      this.applyDefaultLanguageCodes()
      this.$refs["form"].validate(valid => {
        if (valid) {
          // 如果 threadNum 为空，默认设置为 10
          if (!this.form.threadNum) {
            this.form.threadNum = 10;
          }

          if (this.form.batchId != null) {
            updateAiSipCallTask(this.form).then(() => {
              this.msgSuccess("修改成功");
              this.open = false;
              this.getList();
            });
          } else {
            addAiSipCallTask(this.form).then(() => {
              this.msgSuccess("新增成功");
              this.open = false;
              this.getList();
            });
          }
        }
      });
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const batchIds = row.batchId || this.ids;
      this.$confirm('是否确认删除aiSIP外呼任务编号为"' + batchIds + '"的数据项?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(function() {
          return delAiSipCallTask(batchIds);
        }).then(() => {
          this.getList();
          this.msgSuccess("删除成功");
        }).catch(() => {});
    },
    /** 导出按钮操作 */
    handleExport() {
      const queryParams = this.queryParams;
      this.$confirm('是否确认导出所有 aiSIP 外呼任务数据项？', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(() => {
          this.exportLoading = true;
          return exportAiSipCallTask(queryParams);
        }).then(response => {
          this.download(response.msg);
          this.exportLoading = false;
        }).catch(() => {});
    },
    /** 导入数据按钮操作 */
    handleImportData(batchId) {
      // 创建隐藏的文件输入框
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = '.xlsx,.xls,.csv';
      input.style.display = 'none';

      input.onchange = (event) => {
        const files = event.target.files;
       if (!files || files.length === 0) {
          return;
        }

        const file = files[0];

        // 验证文件类型
        const isExcelOrCSV = file.type === 'application/vnd.ms-excel' ||
                            file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
                            file.type === 'text/csv' ||
                            file.name.endsWith('.xlsx') ||
                            file.name.endsWith('.xls') ||
                            file.name.endsWith('.csv');
        const isLt100M = file.size / 1024 / 1024 < 100;

       if (!isExcelOrCSV) {
         this.msgError('只能上传 xlsx/xls/csv 文件!');
          return;
        }
       if (!isLt100M) {
         this.msgError('上传文件大小不能超过 100MB!');
          return;
        }

        // 创建 FormData 对象并调用接口
        const formData = new FormData();
        formData.append('batchId', batchId);
        formData.append('file', file);

        commonImportExcel(formData).then(response => {
         if (response.code === 200) {
           this.msgSuccess('导入成功');
           this.getList();
          } else {
           this.msgError(response.msg || '导入失败');
          }
        }).catch(error => {
         this.msgError('导入失败：' + error.message);
        });
      };

      document.body.appendChild(input);
      input.click();
      document.body.removeChild(input);
    },
    /** 将接口返回的 { key: label } 转为下拉选项 */
    parseProviderMap(data, valueKey) {
      if (!data || typeof data !== 'object' || Array.isArray(data)) return []
      return Object.keys(data).map(key => ({
        [valueKey]: key,
        provider: data[key]
      }))
    },
    /** 加载 TTS 厂商列表 */
    loadTtsProviders() {
      return allTtsProvider().then(response => {
        this.ttsProviderList = this.parseProviderMap(response.data, 'voiceSource')
        if (this.open && (this.form.taskType === '1' || this.form.taskType === '2')) {
          this.$nextTick(() => this.applyDefaultVoiceSelection())
        }
      })
    },
    /** 无语言配置时默认使用 zh-CN */
    applyDefaultLanguageCodes() {
      if (!(this.form.taskType === '1' || this.form.taskType === '2')) {
        return
      }
      if (this.form.voiceSource && !this.formTtsLanguageList.length) {
        this.form.ttsLanguageCode = 'zh-CN'
      }
      if (this.form.asrProvider && !this.formAsrLanguageList.length) {
        this.form.asrLanguageCode = 'zh-CN'
      }
    },
    /** 同步 TTS 语言默认值 */
    syncTtsLanguageCode(keepLanguageCode = false) {
      if (!this.formTtsLanguageList.length) {
        this.form.ttsLanguageCode = 'zh-CN'
        return
      }
      if (!keepLanguageCode) {
        this.form.ttsLanguageCode = this.formTtsLanguageList[0].ttsLanguageCode
      } else if (this.form.ttsLanguageCode && !this.formTtsLanguageList.some(item => item.ttsLanguageCode === this.form.ttsLanguageCode)) {
        this.form.ttsLanguageCode = this.formTtsLanguageList[0].ttsLanguageCode
      }
    },
    /** 同步 ASR 语言默认值 */
    syncAsrLanguageCode(keepLanguageCode = false) {
      if (!this.formAsrLanguageList.length) {
        this.form.asrLanguageCode = 'zh-CN'
        return
      }
      if (!keepLanguageCode) {
        this.form.asrLanguageCode = this.formAsrLanguageList[0].asrLanguageCode
      } else if (this.form.asrLanguageCode && !this.formAsrLanguageList.some(item => item.asrLanguageCode === this.form.asrLanguageCode)) {
        this.form.asrLanguageCode = this.formAsrLanguageList[0].asrLanguageCode
      }
    },
    parseTtsLanguageOptions(data) {
      if (!data) return []
      if (Array.isArray(data)) {
        return data.map(item => {
          if (typeof item === 'string') {
            return { ttsLanguageCode: item, languageName: item }
          }
          return {
            ttsLanguageCode: item.ttsLanguageCode || item.languageCode || item.code || item.key,
            languageName: item.languageName || item.name || item.label || item.value || item.provider
          }
        }).filter(item => item.ttsLanguageCode)
      }
      return this.parseProviderMap(data, 'ttsLanguageCode').map(item => ({
        ttsLanguageCode: item.ttsLanguageCode,
        languageName: item.provider
      }))
    },
    /** 按 TTS 厂商加载语言列表 */
    loadTtsLanguages(voiceSource, options = {}) {
      const { keepLanguageCode = false, keepTtsModels = false, keepVoiceCode = false } = options
      if (!voiceSource) {
        this.formTtsLanguageList = []
        this.formTtsModelList = []
        this.formVoiceList = []
        this.formVoiceRawList = []
        return Promise.resolve([])
      }
      return getTtsLanguages({ voiceSource }).then(response => {
        const data = response.data != null ? response.data : response.rows
        this.formTtsLanguageList = this.parseTtsLanguageOptions(data)
        this.syncTtsLanguageCode(keepLanguageCode)
        return this.loadTtsModels({ keepTtsModels, keepVoiceCode })
      })
    },
    /** 解析 TTS 模型列表 */
    parseTtsModelOptions(data) {
      if (!data) return []
      if (Array.isArray(data)) {
        return data.map(item => {
          if (typeof item === 'string') {
            return { ttsModels: item, modelName: item }
          }
          const ttsModels = item.ttsModels || item.modelCode || item.code || item.key || item.value
          const modelName = item.modelName || item.name || item.label || item.value || ttsModels
          return { ttsModels, modelName }
        }).filter(item => item.ttsModels)
      }
      return this.parseProviderMap(data, 'ttsModels').map(item => ({
        ttsModels: item.ttsModels,
        modelName: item.provider
      }))
    },
    /** 按 TTS 厂商和语言加载模型列表 */
    loadTtsModels(options = {}) {
      const { keepTtsModels = false, keepVoiceCode = false } = options
      const { voiceSource, ttsLanguageCode } = this.form
      if (!voiceSource || !ttsLanguageCode) {
        this.formTtsModelList = []
        this.formVoiceList = []
        this.formVoiceRawList = []
        if (!keepTtsModels) {
          this.form.ttsModels = null
        }
        return Promise.resolve([])
      }
      return getTtsModels({ voiceSource, ttsLanguageCode: ttsLanguageCode }).then(response => {
        const data = response.data != null ? response.data : response.rows
        this.formTtsModelList = this.parseTtsModelOptions(data)
        if (!keepTtsModels) {
          this.form.ttsModels = this.formTtsModelList.length ? this.formTtsModelList[0].ttsModels : null
        } else if (this.form.ttsModels && !this.formTtsModelList.some(item => item.ttsModels === this.form.ttsModels)) {
          this.form.ttsModels = this.formTtsModelList.length ? this.formTtsModelList[0].ttsModels : null
        }
        return this.loadFormVoiceList({ keepVoiceCode })
      })
    },
    /** 加载 ASR 厂商列表 */
    loadAsrProviders() {
      return allAsrProvider().then(response => {
        this.asrProviderList = this.parseProviderMap(response.data, 'asrProvider')
      })
    },
    /** 解析 ASR 语言列表 */
    parseAsrLanguageOptions(data) {
      if (!data) return []
      if (Array.isArray(data)) {
        return data.map(item => {
          if (typeof item === 'string') {
            return { asrLanguageCode: item, languageName: item }
          }
          return {
            asrLanguageCode: item.asrLanguageCode || item.languageCode || item.code || item.key,
            languageName: item.languageName || item.name || item.label || item.value || item.provider
          }
        }).filter(item => item.asrLanguageCode)
      }
      return this.parseProviderMap(data, 'asrLanguageCode').map(item => ({
        asrLanguageCode: item.asrLanguageCode,
        languageName: item.provider
      }))
    },
    /** 按 ASR 厂商加载语言列表 */
    loadAsrLanguages(asrProvider, options = {}) {
      const { keepLanguageCode = false, keepAsrModels = false } = options
      if (!asrProvider) {
        this.formAsrLanguageList = []
        this.formAsrModelList = []
        return Promise.resolve([])
      }
      return getAsrLanguages({ asrProvider }).then(response => {
        const data = response.data != null ? response.data : response.rows
        this.formAsrLanguageList = this.parseAsrLanguageOptions(data)
        this.syncAsrLanguageCode(keepLanguageCode)
        return this.loadAsrModels({ keepAsrModels })
      })
    },
    /** 解析 ASR 模型列表 */
    parseAsrModelOptions(data) {
      if (!data) return []
      if (Array.isArray(data)) {
        return data.map(item => {
          if (typeof item === 'string') {
            return { asrModels: item, modelName: item }
          }
          const asrModels = item.asrModels || item.modelCode || item.code || item.value
          const modelName = item.modelName || item.name || item.label || asrModels
          return { asrModels, modelName }
        }).filter(item => item.asrModels)
      }
      return this.parseProviderMap(data, 'asrModels').map(item => ({
        asrModels: item.asrModels,
        modelName: item.provider
      }))
    },
    /** 按 ASR 厂商和语言加载模型列表 */
    loadAsrModels(options = {}) {
      const { keepAsrModels = false } = options
      const { asrProvider, asrLanguageCode } = this.form
      if (!asrProvider || !asrLanguageCode) {
        this.formAsrModelList = []
        if (!keepAsrModels) {
          this.form.asrModels = null
        }
        return Promise.resolve([])
      }
      return getAsrModels({ asrProvider, asrLanguageCode: asrLanguageCode }).then(response => {
        const data = response.data != null ? response.data : response.rows
        this.formAsrModelList = this.parseAsrModelOptions(data)
        if (!keepAsrModels) {
          this.form.asrModels = this.formAsrModelList.length ? this.formAsrModelList[0].asrModels : null
        } else if (this.form.asrModels && !this.formAsrModelList.some(item => item.asrModels === this.form.asrModels)) {
          this.form.asrModels = this.formAsrModelList.length ? this.formAsrModelList[0].asrModels : null
        }
        return this.formAsrModelList
      })
    },
    // 处理 ASR 厂商变化
    handleAsrProviderChange() {
      this.form.asrLanguageCode = null
      this.form.asrModels = null
      this.formAsrModelList = []
      this.loadAsrLanguages(this.form.asrProvider)
    },
    // 处理 ASR 语言变化
    handleAsrLanguageChange() {
      this.form.asrModels = null
      this.loadAsrModels()
    },
    /** 加载筛选/列表展示用音色（全量） */
    loadQueryVoiceList() {
      return remoteList({ voiceEnabled: 1, pageNum: 1, pageSize: 500 }).then(response => {
        this.queryVoiceList = response.rows || response.data || []
      })
    },
    /** 按 TTS 模型加载音色列表 */
    loadFormVoiceList(options = {}) {
      const { keepVoiceCode = false } = options
      const { voiceSource, ttsModels, ttsLanguageCode } = this.form
      if (!voiceSource || !ttsModels) {
        this.formVoiceRawList = []
        this.formVoiceList = []
        if (!keepVoiceCode) {
          this.form.voiceCode = null
        }
        return Promise.resolve([])
      }
      const params = { voiceSource, voiceEnabled: 1, pageNum: 1, pageSize: 500, ttsModels }
      return remoteList(params).then(response => {
        let list = response.rows || response.data || []
        list = Array.isArray(list) ? list : []
        if (ttsLanguageCode) {
          list = list.filter(v => !v.languageCode || v.languageCode === ttsLanguageCode)
        }
        list = list.filter(v => v.ttsModels === ttsModels)
        this.formVoiceRawList = list
        this.formVoiceList = [...list]
        if (!keepVoiceCode) {
          this.form.voiceCode = list.length ? list[0].voiceCode : null
        } else if (this.form.voiceCode && !list.some(v => v.voiceCode === this.form.voiceCode)) {
          this.form.voiceCode = list.length ? list[0].voiceCode : null
        }
        return this.formVoiceList
      })
    },
    /** 默认选中第一个 TTS 厂商、语言、模型及音色 */
    applyDefaultVoiceSelection(force = false) {
      if (!(this.form.taskType === '1' || this.form.taskType === '2')) return Promise.resolve()
      if (!this.ttsProviderList.length) return Promise.resolve()
      if (!force && this.form.voiceSource) {
        return this.loadTtsLanguages(this.form.voiceSource, { keepLanguageCode: true, keepTtsModels: true, keepVoiceCode: true })
      }
      const first = this.ttsProviderList[0]
      this.form.voiceSource = first.voiceSource
      return this.loadTtsLanguages(first.voiceSource)
    },
    // 处理 TTS 厂商变化：重置并加载语言 → 模型 → 音色
    handleVoiceSourceChange() {
      this.form.ttsLanguageCode = null
      this.form.ttsModels = null
      this.form.voiceCode = null
      this.formTtsLanguageList = []
      this.formTtsModelList = []
      this.formVoiceList = []
      this.formVoiceRawList = []
      if (!this.form.voiceSource) return
      this.loadTtsLanguages(this.form.voiceSource)
    },
    // 处理 TTS 语言变化：重置并加载模型 → 音色
    handleTtsLanguageChange() {
      this.form.ttsModels = null
      this.form.voiceCode = null
      this.formTtsModelList = []
      this.formVoiceList = []
      this.formVoiceRawList = []
      this.loadTtsModels()
    },
    // 处理 TTS 模型变化：仅重置并加载音色
    handleTtsModelsChange() {
      this.form.voiceCode = null
      this.loadFormVoiceList()
    },
    // 处理转人工方式变化
    handleAiTransferTypeChange() {
     if (this.form.aiTransferType === 'extension') {
       // 选中转分机时，清空业务组
       this.form.aiTransferGroupId = null;
      } else if (this.form.aiTransferType === 'acd' || this.form.aiTransferType === 'gateway') {
        // 选中电话排队或转外部网关时，清空转接分机
       this.form.aiTransferExtNumber = null;
      }
    },
    // 处理文件变化
    handleFileChange(event) {
      const files = event.target.files;
     if (!files || files.length === 0) {
       return;
      }

      const file = files[0];

      // 验证文件类型
      const isExcelOrCSV = file.type === 'application/vnd.ms-excel' ||
                          file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
                          file.type === 'text/csv' ||
                          file.name.endsWith('.xlsx') ||
                          file.name.endsWith('.xls') ||
                          file.name.endsWith('.csv');
      const isLt100M = file.size / 1024 / 1024 < 100;

     if (!isExcelOrCSV) {
       this.msgError('只能上传 xlsx/xls/csv 文件!');
       return;
      }
     if (!isLt100M) {
       this.msgError('上传文件大小不能超过 100MB!');
       return;
      }

      // 创建 FormData 对象并调用接口
      const formData = new FormData();
      formData.append('batchId', this.uploadForm.batchId);
      formData.append('file', file);

      // 调用 importExcel 接口
      commonImportExcel(formData).then(response => {
       if (response.code === 200) {
         this.msgSuccess('导入成功');
         this.uploadOpen = false;
         this.getList();
        } else {
         this.msgError(response.msg || '导入失败');
        }
      }).catch(error => {
       this.msgError('导入失败：' + error.message);
      });
    },
    // 格式化接通率显示
    formatConnectRate(rate) {
      // 如果为空或为 0，返回 0.00%
      if (!rate || rate === 0 || rate === '0') {
        return '0.00%';
      }
      // 否则保留两位小数并添加%
      return parseFloat(rate).toFixed(2) + '%';
    },
    getTtsProviderLabel(voiceSource) {
      if (!voiceSource) return '-'
      const item = this.ttsProviderList.find(p => p.voiceSource === voiceSource)
      return item ? item.provider : voiceSource
    },
    getAsrProviderLabel(asrProvider) {
      if (!asrProvider) return '-'
      const item = this.asrProviderList.find(p => p.asrProvider === asrProvider)
      return item ? item.provider : asrProvider
    },

  }
};
</script>

<style scoped>
.query-card {
  margin-bottom: 12px;
  border: 1px solid #ebeef5;
}

.query-card >>> .el-card__body {
  padding: 16px 20px 12px;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.card-head__title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
}

.card-head__extra {
  font-size: 12px;
  color: #909399;
}

.query-form >>> .el-form-item {
  margin-bottom: 8px;
}

.query-form >>> .el-form-item__label {
  padding-bottom: 4px;
  line-height: 1.2;
  font-size: 13px;
  color: #606266;
}

.query-form__actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-top: 8px;
  margin-top: 4px;
  border-top: 1px solid #f0f2f5;
}

.full-width {
  width: 100%;
}

.query-form >>> .el-date-editor--datetimerange.full-width {
  width: 100%;
}

.dialog-form {
  max-height: 65vh;
  overflow-y: auto;
  padding-right: 6px;
}

.dialog-form >>> .el-form-item {
  margin-bottom: 18px;
}

.dialog-form >>> .el-form-item__label {
  color: #606266;
  font-weight: 500;
}

.form-block {
  margin-bottom: 20px;
  padding: 16px 16px 4px;
  background: #fafbfc;
  border: 1px solid #ebeef5;
  border-radius: 6px;
}

.form-block:last-child {
  margin-bottom: 0;
}

.form-block__title {
  margin: -4px 0 14px;
  padding-left: 10px;
  font-size: 13px;
  font-weight: 600;
  color: #303133;
  line-height: 1.4;
  border-left: 3px solid #409eff;
}

.form-hint {
  margin: -6px 0 4px;
  padding-left: 120px;
  font-size: 12px;
  color: #909399;
  line-height: 1.5;
}

.dialog-form >>> .el-input-number.full-width .el-input__inner {
  text-align: left;
}
</style>
