| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937 |
- <template>
- <div class="app-container">
- <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
- <el-form-item label="任务名称" prop="batchName">
- <el-input
- v-model="queryParams.batchName"
- placeholder="请输入任务名称"
- clearable
- size="small"
- @keyup.enter.native="handleQuery"
- />
- </el-form-item>
- <el-form-item label="任务类型" prop="taskType">
- <el-select v-model="queryParams.taskType" placeholder="请选择任务类型" clearable size="small">
- <el-option label="全部" value="" />
- <el-option label="纯人工预测外呼" value="0" />
- <el-option label="AI外呼" value="1" />
- <el-option label="语音通知" value="2" />
- </el-select>
- </el-form-item>
- <el-form-item label="任务状态" prop="ifcall">
- <el-select v-model="queryParams.ifcall" placeholder="请选择任务状态" clearable size="small">
- <el-option label="全部" value="" />
- <el-option label="外呼中" value="1" />
- <el-option label="停止外呼" value="0" />
- </el-select>
- </el-form-item>
- <el-form-item label="创建时间">
- <el-date-picker v-model="queryParams.createTimeStart" size="small" style="width: 180px"
- value-format="yyyy-MM-dd HH:mm:ss" type="datetime" placeholder="开始时间"/>
- <span style="margin: 0 8px">-</span>
- <el-date-picker v-model="queryParams.createTimeEnd" size="small" style="width: 180px"
- value-format="yyyy-MM-dd HH:mm:ss" type="datetime" placeholder="结束时间"/>
- </el-form-item>
- <el-form-item label="外呼线路" prop="gatewayId">
- <el-select v-model="queryParams.gatewayId" placeholder="请选择外呼线路" clearable size="small">
- <el-option label="全部" value="" />
- <el-option
- v-for="item in gatewayList"
- :key="item.id"
- :label="item.gwName"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="音色" prop="voiceSource">
- <el-select v-model="queryParams.voiceSource" placeholder="请选择音色" clearable size="small">
- <el-option label="全部" value="" />
- <el-option
- v-for="(item, index) in voiceSourceList"
- :key="'query-' + item.voiceCode + '-' + index"
- :label="item.voiceName"
- :value="item.voiceCode"
- />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
- <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
- </el-form-item>
- </el-form>
- <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="['company: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="['company: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="['company: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="['company: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="['company: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="任务ID" align="center" prop="batchId" />
- <el-table-column label="任务名称" align="center" prop="batchName" />
- <el-table-column label="任务类型" align="center" prop="taskType">
- <template slot-scope="scope">
- <span v-if="scope.row.taskType === '0'">纯人工预测外呼</span>
- <span v-else-if="scope.row.taskType === 1">AI外呼</span>
- <span v-else-if="scope.row.taskType === 2">语音通知</span>
- <span v-else>{{ scope.row.taskType }}</span>
- </template>
- </el-table-column>
- <el-table-column label="外呼状态" align="center" prop="ifcall" >
- <template slot-scope="scope">
- <span v-if="scope.row.ifcall === 0">停止外呼</span>
- <span v-else-if="scope.row.ifcall === 1">外呼中</span>
- <span v-else>{{ scope.row.ifcall }}</span>
- </template>
- </el-table-column>
- <el-table-column label="最大并发" align="center" prop="threadNum" />
- <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="voiceCode">
- <template slot-scope="scope">
- <span v-for="(item, index) in voiceSourceList" v-if="scope.row.voiceCode === item.voiceCode" :key="'table-' + item.voiceCode + '-' + index">{{ item.voiceName }}</span>
- </template>
- </el-table-column>
- <el-table-column label="创建时间" align="center" prop="createTime" />
- <!-- <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="realConnectRate" />-->
- <el-table-column label="远程任务ID" align="center" prop="remoteBatchId" />
- <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="['company:aiSipCall:task:edit']"-->
- <!-- >修改</el-button>-->
- <el-button
- size="mini"
- type="text"
- icon="el-icon-video-play"
- @click="startTask(scope.row.batchId)"
- v-hasPermi="['company:aiSipCall:task:startTask']"
- >启动外呼</el-button>
- <el-button
- size="mini"
- type="text"
- icon="el-icon-video-pause"
- @click="stopTask(scope.row.batchId)"
- v-hasPermi="['company:aiSipCall:task:stopTask']"
- >停止外呼</el-button>
- <el-button
- size="mini"
- type="text"
- icon="el-icon-upload"
- @click="handleImportData(scope.row.batchId)"
- v-hasPermi="['company:aiSipCall:task:commonImportExcel']"
- >导入外呼模板</el-button>
- <!-- <el-button-->
- <!-- size="mini"-->
- <!-- type="text"-->
- <!-- icon="el-icon-delete"-->
- <!-- @click="handleDelete(scope.row)"-->
- <!-- v-hasPermi="['company: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="800px" append-to-body>
- <el-form ref="form" :model="form" :rules="rules" label-width="80px">
- <el-form-item label="任务名称" prop="batchName">
- <el-input v-model="form.batchName" placeholder="请输入外呼任务的业务组 " />
- </el-form-item>
- <el-form-item label="任务类型" prop="taskType">
- <el-select v-model="form.taskType" placeholder="请选择任务类型" clearable>
- <!-- <el-option label="纯人工预测外呼" value="0" />-->
- <el-option label="AI外呼" value="1" />
- <!-- <el-option label="语音通知" value="2" />-->
- <!-- <el-option label="IVR外呼" value="3" />-->
- </el-select>
- </el-form-item>
- <!-- 纯人工预测外呼显示项 -->
- <el-form-item label="预估接通率(%)" prop="conntectRate" v-show="form.taskType === '0'">
- <el-input v-model="form.conntectRate" placeholder="请输入预估接通率" />
- </el-form-item>
- <el-form-item label="平均振铃时长(秒)" prop="avgRingTimeLen" v-show="form.taskType === '0'">
- <el-input v-model="form.avgRingTimeLen" placeholder="请输入平均振铃时长" />
- </el-form-item>
- <el-form-item label="平均通话时长(秒)" prop="avgCallTalkTimeLen" v-show="form.taskType === '0'">
- <el-input v-model="form.avgCallTalkTimeLen" placeholder="请输入平均通话时长" />
- </el-form-item>
- <el-form-item label="平均事后处理时长(秒)" prop="avgCallEndProcessTimeLen" v-show="form.taskType === '0'">
- <el-input v-model="form.avgCallEndProcessTimeLen" placeholder="请输入平均事后处理时长" />
- </el-form-item>
- <el-form-item label="最大并发" prop="threadNum">
- <el-input v-model="form.threadNum" placeholder="请输入最大并发" />
- </el-form-item>
- <el-form-item label="外呼线路" prop="gatewayId">
- <el-select v-model="form.gatewayId" placeholder="请选择外呼线路" clearable>
- <el-option
- v-for="item in gatewayList"
- :key="item.id"
- :label="item.gwName"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="自动停止" prop="autoStop">
- <el-select v-model="form.autoStop" placeholder="请选择自动停止" clearable>
- <el-option label="名单拨打完后任务自动停止" value="1" />
- <el-option label="任务不自动停止" value="0" />
- </el-select>
- </el-form-item>
- <el-form-item label="大模型底座" prop="llmAccountId" v-show="form.taskType === '1'">
- <el-select v-model="form.llmAccountId" placeholder="请选择大模型底座" clearable>
- <el-option
- v-for="item in llmAgentAccountList"
- :key="item.id"
- :label="item.name"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="TTS厂商" prop="voiceSource" v-show="form.taskType === '1' || form.taskType === '2'">
- <el-select v-model="form.voiceSource" placeholder="请选择TTS厂商" clearable @change="handleVoiceSourceChange">
- <el-option label="电信" value="chinatelecom_tts" />
- <el-option label="豆包" value="doubao_vcl_tts" />
- <el-option label="阿里云" value="aliyun_tts" />
- </el-select>
- </el-form-item>
- <el-form-item label="音色" prop="voiceCode" v-show="form.voiceSource">
- <el-select v-model="form.voiceCode" placeholder="请选择音色" clearable>
- <el-option
- v-for="(item, index) in getCurrentVoiceCodeList()"
- :key="'form-' + item.voiceCode + '-' + index"
- :label="item.voiceName"
- :value="item.voiceCode"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="ASR厂商" prop="asrProvider" v-show="form.taskType === '1' || form.taskType === '2'">
- <el-select v-model="form.asrProvider" placeholder="请选择 ASR 厂商" clearable>
- <el-option label="电信" value="chinatelecom" />
- <el-option label="FunASR" value="funasr" />
- <el-option label="阿里云" value="aliyun" />
- </el-select>
- </el-form-item>
- <el-form-item label="播放次数" prop="playTimes" v-show="form.taskType === '2'">
- <el-input v-model="form.playTimes" placeholder="请输入播放次数" />
- </el-form-item>
- <el-form-item label="转人工方式" prop="aiTransferType" v-show="form.taskType === '1'">
- <el-select v-model="form.aiTransferType" placeholder="请选择转人工方式" clearable @change="handleAiTransferTypeChange">
- <el-option label="电话排队(需要电话工具条)" value="acd" />
- <el-option label="转分机(无需电话工具条)" value="extension" />
- <el-option label="转外部网关" value="gateway" />
- </el-select>
- </el-form-item>
- <el-form-item label="业务组" prop="aiTransferGroupId" v-show="form.taskType === '1' && form.aiTransferType !== 'extension' && form.aiTransferType !== 'gateway'">
- <el-select v-model="form.aiTransferGroupId" placeholder="请选择业务组" clearable size="small">
- <el-option label="请选择业务组" value="" />
- <el-option
- v-for="item in bizGroupList"
- :key="item.groupId"
- :label="item.bizGroupName"
- :value="item.groupId"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="转接分机(多个用空格分割)" prop="aiTransferExtNumber" v-show="form.aiTransferType === 'extension'">
- <el-input v-model="form.aiTransferExtNumber" placeholder="请输入转接分机" />
- </el-form-item>
- <el-form-item label="网关" prop="aiTransferGatewayId" v-show="form.aiTransferType === 'gateway'">
- <el-select v-model="form.aiTransferGatewayId" placeholder="请选择外呼线路" clearable>
- <el-option
- v-for="item in gatewayList"
- :key="item.id"
- :label="item.gwName"
- :value="item.id"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="转接号码" prop="aiTransferGatewayDestNumber" v-show="form.aiTransferType === 'gateway'">
- <el-input v-model="form.aiTransferGatewayDestNumber" placeholder="请输入转接号码" />
- </el-form-item>
- </el-form>
- <div slot="footer" class="dialog-footer">
- <el-button type="primary" @click="submitForm">确 定</el-button>
- <el-button @click="cancel">取 消</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 {listAiSipCallGateway} from "../../api/aiSipCall/aiSipCallGateway";
- import {listAiSipCallVoiceTtsAliyun} 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: [],
- voiceSourceList: [],
- // 按厂商分类的音色列表
- voiceCodeLists: {
- chinatelecom_tts: [],
- doubao_vcl_tts: [],
- aliyun_tts: []
- },
- 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,
- aiTransferType: null,
- aiTransferData: null,
- autoStop: null,
- ivrId: null,
- remoteBatchId: null
- },
- // 表单参数
- form: {},
- // 表单校验
- rules: {
- batchName: [
- { required: true, message: "任务名称不能为空", trigger: "blur" }
- ],
- taskType: [
- { required: true, message: "任务类型不能为空", trigger: "change" }
- ],
- threadNum: [
- { required: true, message: "最大并发不能为空", trigger: "blur" },
- { pattern: /^[1-9]\d*$/, 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" }
- ],
- voiceCode: [
- { required: true, message: "音色不能为空", trigger: "change" }
- ],
- asrProvider: [
- { required: true, message: "ASR 厂商不能为空", trigger: "change" }
- ],
- aiTransferType: [
- { required: true, message: "转人工方式不能为空", 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" }
- ]
- }
- };
- },
- created() {
- //获取所有网关
- listAiSipCallGateway().then(response => {
- this.gatewayList = response.rows;
- })
- //获取所有音色并按厂商分类
- listAiSipCallVoiceTtsAliyun({voiceEnabled: 1}).then(response => {
- const allVoices = response.rows || [];
- // voiceSourceList 使用所有音色
- this.voiceSourceList = allVoices;
- // 按 voiceSource 分类
- this.voiceCodeLists.chinatelecom_tts = allVoices.filter(item => item.voiceSource === 'chinatelecom_tts');
- this.voiceCodeLists.doubao_vcl_tts = allVoices.filter(item => item.voiceSource === 'doubao_vcl_tts');
- this.voiceCodeLists.aliyun_tts = allVoices.filter(item => item.voiceSource === 'aliyun_tts');
- })
- //获取所有大模型底座
- 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: 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,
- aiTransferType: null,
- aiTransferData: null,
- autoStop: null,
- ivrId: null,
- remoteBatchId: null,
- aiTransferExtNumber: null
- };
- this.resetForm("form");
- },
- /** 搜索按钮操作 */
- 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();
- this.open = true;
- this.title = "添加 aiSIP 外呼任务";
- // 默认选中 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.form.voiceSource = "chinatelecom_tts";
- // 根据选中的 TTS 厂商设置默认音色
- this.$nextTick(() => {
- if (this.voiceCodeLists.chinatelecom_tts && this.voiceCodeLists.chinatelecom_tts.length > 0) {
- this.form.voiceCode = this.voiceCodeLists.chinatelecom_tts[0].voiceCode;
- }
- });
- // 默认选中第一个 ASR 厂商
- this.form.asrProvider = "chinatelecom";
- // 默认选中第一个转人工方式
- this.form.aiTransferType = "acd";
- // 根据转人工方式设置默认业务组
- this.$nextTick(() => {
- if (this.bizGroupList && this.bizGroupList.length > 0) {
- this.form.groupId = this.bizGroupList[0].groupId;
- }
- });
- },
- /** 修改按钮操作 */
- handleUpdate(row) {
- this.reset();
- const batchId = row.batchId || this.ids
- getAiSipCallTask(batchId).then(response => {
- this.form = response.data;
- // 如果有 voiceSource,设置对应的音色列表
- if (this.form.voiceSource) {
- // 不需要重新请求,直接使用已加载的数据
- }
- this.open = true;
- this.title = "修改 aiSIP 外呼任务";
- // 如果是纯人工预测外呼,设置默认的并发相关字段
- 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';
- }
- }
- });
- },
- /** 提交按钮 */
- submitForm() {
- this.$refs["form"].validate(valid => {
- if (valid) {
- 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);
- },
- // 获取当前选中厂商的音色列表
- getCurrentVoiceCodeList() {
- if (!this.form.voiceSource) {
- return [];
- }
- return this.voiceCodeLists[this.form.voiceSource] || [];
- },
- // 处理 TTS 厂商变化
- handleVoiceSourceChange() {
- // 清空已选音色
- this.form.voiceCode = null;
- // 默认选中当前厂商的第一个音色
- this.$nextTick(() => {
- const currentList = this.voiceCodeLists[this.form.voiceSource];
- if (currentList && currentList.length > 0) {
- this.form.voiceCode = currentList[0].voiceCode;
- }
- });
- },
- // 处理转人工方式变化
- handleAiTransferTypeChange() {
- if (this.form.aiTransferType === 'extension') {
- // 选中转分机时,清空业务组
- this.form.groupId = 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);
- });
- },
- }
- };
- </script>
|