Parcourir la source

reactor:自贡新增语音回访

zhangchong il y a 1 semaine
Parent
commit
04ac68ce3a

+ 2 - 2
src/views/business/visit/components/Smart-visit-Detail.vue

@@ -1,5 +1,5 @@
 <template>
-	<el-dialog v-model="state.dialogVisible" width="60%" draggable title="回访明细" append-to-body destroy-on-close @close="close" @opened="opened">
+	<el-dialog v-model="state.dialogVisible" width="60%" draggable title="只能回访明细" append-to-body destroy-on-close @close="close" @opened="opened">
 		<el-form :model="state.queryParams" ref="queryParamsRef" inline @submit.native.prevent>
 			<el-form-item label="关键词" prop="Keyword">
 				<el-input v-model="state.queryParams.Keyword" placeholder="工单标题/工单编码" clearable @keyup.enter="handleQuery" />
@@ -108,7 +108,7 @@ const state = reactive({
 	dialogVisible: false, // 弹窗
 });
 // 页面基础数据
-const aiOrderVisitState = ref([]);
+const aiOrderVisitState = ref<EmptyArrayType>([]);
 const getBaseData = async () => {
 	try {
 		const { result } = await getSmartVisitBaseData();

+ 172 - 0
src/views/business/visit/components/Voice-visit-Detail.vue

@@ -0,0 +1,172 @@
+<template>
+	<el-dialog v-model="state.dialogVisible" width="60%" draggable title="语音回访明细" append-to-body destroy-on-close @close="close" @opened="opened">
+		<el-form :model="state.queryParams" ref="queryParamsRef" inline @submit.native.prevent>
+			<el-form-item label="关键词" prop="Keyword">
+				<el-input v-model="state.queryParams.Keyword" placeholder="工单标题/工单编码" clearable @keyup.enter="handleQuery" />
+			</el-form-item>
+			<el-form-item label="任务状态" prop="AiOrderVisitState">
+				<el-select v-model="state.queryParams.AiOrderVisitState" placeholder="请选择任务状态" @change="handleQuery" clearable>
+					<el-option v-for="item in aiOrderVisitState" :value="item.key" :key="item.key" :label="item.value" />
+				</el-select>
+			</el-form-item>
+			<el-form-item>
+				<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+				<el-button @click="resetQuery(queryParamsRef)" :loading="state.loading" class="default-button">
+					<SvgIcon name="ele-Refresh" class="mr5" />重置
+				</el-button>
+			</el-form-item>
+		</el-form>
+		<vxe-toolbar
+			ref="toolbarRef"
+			:loading="state.loading"
+			custom
+			:refresh="{
+				queryMethod: handleQuery,
+			}"
+			:tools="[{ toolRender: { name: 'exportCurrent' } }, { toolRender: { name: 'exportAll' } }]"
+		>
+		</vxe-toolbar>
+		<vxe-table
+			border
+			:loading="state.loading"
+			:data="state.tableData"
+			:column-config="{ resizable: true }"
+			:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
+			ref="tableRef"
+			show-overflow
+			:scrollY="{ enabled: true, gt: 100 }"
+			id="smartVisitDetail"
+			:custom-config="{ storage: true }"
+			:params="{ exportMethod: getSmartVisitDetailExport, exportParams: requestParams }"
+			showHeaderOverflow
+			max-height="300px"
+		>
+			<vxe-column field="no" title="工单编码" width="140"></vxe-column>
+			<vxe-column field="title" title="工单标题" width="200">
+				<template #default="{ row }">
+					<order-detail :order="row.order" @updateList="queryList">{{ row.order?.title }}</order-detail>
+				</template>
+			</vxe-column>
+
+			<vxe-column field="aiOrderVisitStateText" title="外呼状态" width="120"></vxe-column>
+			<vxe-column field="isSuccessText" title="是否成功" width="120"></vxe-column>
+			<vxe-column field="outerNo" title="外呼电话" width="120"></vxe-column>
+			<vxe-column field="fromName" title="姓名" width="120"></vxe-column>
+			<vxe-column field="fromGenderText" title="性别" width="120"></vxe-column>
+			<vxe-column field="callTimes" title="重拨次数" width="120"></vxe-column>
+			<vxe-column field="callTime" title="外呼时间" width="160">
+				<template #default="{ row }">
+					{{ formatDate(row.callTime, 'YYYY-mm-dd HH:MM:SS') }}
+				</template>
+			</vxe-column>
+			<vxe-column field="creationTime" title="受理时间" width="160">
+				<template #default="{ row }">
+					{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+				</template>
+			</vxe-column>
+			<vxe-column field="filedTime" title="办结时间" width="160">
+				<template #default="{ row }">
+					{{ formatDate(row.filedTime, 'YYYY-mm-dd HH:MM:SS') }}
+				</template>
+			</vxe-column>
+
+			<vxe-column field="seatEvaluateText" title="话务员评价" width="110"></vxe-column>
+			<vxe-column field="orgProcessingResults" title="部门办件结果" width="140"></vxe-column>
+			<vxe-column field="isContact" title="部门是否联系" width="120"></vxe-column>
+			<vxe-column field="volved" title="处理结果" width="120"></vxe-column>
+		</vxe-table>
+		<pagination
+			@pagination="queryList"
+			:total="state.total"
+			v-model:current-page="state.queryParams.PageIndex"
+			v-model:page-size="state.queryParams.PageSize"
+			:disabled="state.loading"
+		/>
+	</el-dialog>
+</template>
+<script setup lang="tsx">
+import { formatDate } from '@/utils/formatTime';
+import { FormInstance } from 'element-plus';
+import { defineAsyncComponent, reactive, ref } from 'vue';
+import { getSmartVisitBaseData, getSmartVisitDetail, getSmartVisitDetailExport } from '@/api/smartVisit';
+import { exportOrder } from '@/api/business/order';
+
+const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+const state = reactive({
+	queryParams: {
+		// 查询条件
+		PageIndex: 1,
+		PageSize: 10,
+		Keyword: null, // 关键字
+		id: '',
+		AiOrderVisitState: null,
+	},
+	tableData: [], //表格
+	loading: false, // 加载
+	total: 0, // 总数
+	dialogVisible: false, // 弹窗
+});
+// 页面基础数据
+const aiOrderVisitState = ref<EmptyArrayType>([]);
+const getBaseData = async () => {
+	try {
+		const { result } = await getSmartVisitBaseData();
+		aiOrderVisitState.value = result.aiOrderVisitState;
+	} catch (e) {
+		console.log(e);
+	}
+};
+// 打开弹窗
+const openDialog = (row?: any) => {
+	if (row) {
+		state.dialogVisible = true;
+		getBaseData();
+		state.queryParams.id = row.id;
+		queryList();
+	}
+};
+// 手动查询,将页码设置为1
+const handleQuery = () => {
+	state.queryParams.PageIndex = 1;
+	queryList();
+};
+// 查询智能回访明细表
+const requestParams = ref({});
+const queryList = async () => {
+	state.loading = true;
+	try {
+		state.tableData = [];
+		requestParams.value = state.queryParams;
+		const res = await getSmartVisitDetail(state.queryParams);
+		state.tableData = res.result.items ?? [];
+		state.total = res.result.total ?? 0;
+		state.loading = false;
+	} catch (e) {
+		console.log(e);
+		state.loading = false;
+		state.tableData = [];
+	}
+};
+const close = () => {
+	queryParamsRef.value?.resetFields();
+	queryParamsRef.value?.resetFields();
+};
+// 重置所有工单列表
+const queryParamsRef = ref<RefType>();
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	queryList();
+};
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
+const opened = () => {
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+};
+defineExpose({
+	openDialog,
+});
+</script>

+ 250 - 0
src/views/business/visit/components/Voice-visit-add.vue

@@ -0,0 +1,250 @@
+<template>
+	<el-dialog
+		v-model="state.dialogVisible"
+		width="60%"
+		draggable
+		title="新增语音回访任务"
+		@close="close"
+		append-to-body
+		destroy-on-close
+		@opened="opened"
+	>
+		<el-divider content-position="left" class="mb30">
+			<el-text tag="b" size="large"> 回访任务内容 </el-text>
+		</el-divider>
+		<el-form :model="state.ruleForm" label-width="90px" ref="ruleFormRef" v-loading="state.loading">
+			<el-row :gutter="10">
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+					<el-form-item label="任务名称" prop="name" :rules="[{ required: true, message: '请填写任务名称', trigger: 'blur' }]">
+						<el-input v-model="state.ruleForm.name" placeholder="请填写任务名称" clearable></el-input>
+					</el-form-item>
+				</el-col>
+			</el-row>
+		</el-form>
+		<el-divider content-position="left" class="mb30">
+			<el-text tag="b" size="large"> 回访任务名单 </el-text>
+		</el-divider>
+		<el-form :model="state.queryParams" ref="queryFormRef" @submit.native.prevent>
+			<el-row :gutter="20">
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8">
+					<el-form-item label="工单标题" prop="Title">
+						<el-input v-model="state.queryParams.Title" placeholder="工单标题" clearable @keyup.enter="queryList" />
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8">
+					<el-form-item label="工单编码" prop="No">
+						<el-input v-model="state.queryParams.No" placeholder="工单编码" clearable @keyup.enter="queryList" />
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8">
+					<el-form-item label="受理类型" prop="AcceptType">
+						<el-select v-model="state.queryParams.AcceptType" placeholder="请选择受理类型" clearable class="w100" @change="queryList">
+							<el-option v-for="item in state.acceptTypeOptions" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
+						</el-select>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8">
+					<el-form-item label="热点分类" prop="Hotspot">
+						<el-input v-model="state.queryParams.Hotspot" placeholder="热点分类名称" clearable @keyup.enter="queryList" />
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="8">
+					<el-form-item>
+						<el-button type="primary" @click="queryList" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+						<el-button @click="resetQuery(queryFormRef)" class="default-button" :loading="state.loading">
+							<SvgIcon name="ele-Refresh" class="mr5" />重置
+						</el-button>
+					</el-form-item>
+				</el-col>
+			</el-row>
+		</el-form>
+		<vxe-toolbar
+			ref="toolbarRef"
+			:loading="state.loading"
+			custom
+			:refresh="{
+				queryMethod: queryList,
+			}"
+		>
+		</vxe-toolbar>
+		<vxe-table
+			border
+			:loading="state.loading"
+			:data="state.tableData"
+			:column-config="{ resizable: true }"
+			:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
+			ref="tableRef"
+			@checkbox-all="selectAllChangeEvent"
+			@checkbox-change="selectChangeEvent"
+			show-overflow
+			:scrollY="{ enabled: true, gt: 100 }"
+			id="smartVisitAdd"
+			:custom-config="{ storage: true }"
+			max-height="300px"
+		>
+			<vxe-column type="checkbox" width="50" align="center"></vxe-column>
+			<vxe-column field="order.no" title="工单编码" width="140"></vxe-column>
+			<vxe-column field="order.title" title="工单标题" width="200">
+				<template #default="{ row }">
+					<order-detail :order="row.order" @updateList="queryList">{{ row.order?.title }}</order-detail>
+				</template>
+			</vxe-column>
+			<vxe-column field="order.sourceChannel" title="来源渠道" width="110"></vxe-column>
+			<vxe-column field="visitStateText" title="回访状态" width="110"></vxe-column>
+			<vxe-column field="order.acceptType" title="受理类型" width="110"></vxe-column>
+			<vxe-column field="order.hotspotName" title="热点分类" width="150"></vxe-column>
+			<vxe-column field="order.currentStepName" title="当前节点" width="110"></vxe-column>
+			<vxe-column field="order.acceptorName" title="受理人" width="120"></vxe-column>
+			<vxe-column field="order.orgLevelOneName" title="一级部门" width="140"></vxe-column>
+			<vxe-column field="order.actualHandleOrgName" title="接办部门" width="140"></vxe-column>
+			<vxe-column field="order.creationTime" title="受理时间" width="160">
+				<template #default="{ row }">
+					{{ formatDate(row.order?.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+				</template>
+			</vxe-column>
+			<vxe-column field="order.filedTime" title="办结时间" width="160">
+				<template #default="{ row }">
+					{{ formatDate(row.order?.filedTime, 'YYYY-mm-dd HH:MM:SS') }}
+				</template>
+			</vxe-column>
+			<vxe-column field="publishTime" title="发布时间" width="160">
+				<template #default="{ row }">
+					{{ formatDate(row.publishTime, 'YYYY-mm-dd HH:MM:SS') }}
+				</template>
+			</vxe-column>
+			<vxe-column field="employeeName" title="回访人" width="120"></vxe-column>
+		</vxe-table>
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="state.dialogVisible = false" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading" :disabled="!isChecked">确 定</el-button>
+			</span>
+		</template>
+	</el-dialog>
+</template>
+<script setup lang="tsx">
+import { formatDate } from '@/utils/formatTime';
+import { ElMessage, FormInstance } from 'element-plus';
+import { reactive, ref, defineAsyncComponent, computed } from 'vue';
+import { getSmartVisitRecord } from '@/api/smartVisit';
+import { defaultTimeStartEnd } from '@/utils/constants';
+import { smartVisitAdd, smartVisitBaseData } from '@/api/smartVisit';
+
+const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
+const emit = defineEmits(['updateList']);
+const state = reactive({
+	queryParams: {
+		Title: null,
+		No: null,
+		AcceptType: null,
+		Hotspot: null,
+	},
+	tableData: [], //表格
+	loading: false, // 加载
+	dialogVisible: false, // 弹窗
+	ruleForm: {
+		name: '',
+		crTime: [],
+		festivalBan: 1,
+	}, // 表单数据
+	acceptTypeOptions: [],
+});
+const isChecked = computed(() => {
+	return Boolean(checkTable.value.length);
+});
+const disabledDate = (time) => {
+	return time.getTime() < new Date().setHours(0, 0, 0, 0); // 禁用今天之前的日期
+};
+// 基础信息
+const getBaseData = async () => {
+	const acceptTypeOptions = await smartVisitBaseData();
+	state.acceptTypeOptions = acceptTypeOptions.result?.acceptTypeOptions;
+};
+// 打开弹窗
+const openDialog = () => {
+	state.dialogVisible = true;
+	getBaseData();
+	queryList();
+};
+const close = () => {
+	ruleFormRef.value?.clearValidate();
+	ruleFormRef.value?.resetFields();
+};
+// 获取所有工单列表
+const queryList = async () => {
+	state.loading = true;
+	try {
+		const { result } = await getSmartVisitRecord(state.queryParams);
+		state.tableData = result;
+		state.loading = false;
+	} catch (e) {
+		console.log(e);
+		state.loading = false;
+	}
+};
+// 重置所有工单列表
+const queryFormRef = ref<RefType>();
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	queryList();
+};
+// 保存
+const ruleFormRef = ref<RefType>();
+const onSubmit = async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.loading = true;
+		const request = {
+			name: state.ruleForm.name,
+			beginTime: state.ruleForm.crTime[0],
+			endTime: state.ruleForm.crTime[1],
+			festivalBan: state.ruleForm.festivalBan,
+			aiOrderVisitDetails: checkTable.value.map((item: any) => {
+				return {
+					orderId: item.order?.id,
+					orderVisitId: item.id,
+					outerNo: item.order?.contact,
+				};
+			}),
+		};
+		smartVisitAdd(request)
+			.then(() => {
+				state.loading = false;
+				state.dialogVisible = false;
+				ElMessage.success('操作成功');
+				emit('updateList');
+			})
+			.catch(() => {
+				state.loading = false;
+			});
+	});
+};
+const tableRef = ref<RefType>();
+const checkTable = ref<EmptyArrayType>([]);
+const selectAllChangeEvent = ({ checked }) => {
+	if (tableRef.value) {
+		const records = tableRef.value.getCheckboxRecords();
+		checkTable.value = records;
+		console.log(checked ? '所有勾选事件' : '所有取消事件', records);
+	}
+};
+
+const selectChangeEvent = ({ checked }) => {
+	if (tableRef.value) {
+		const records = tableRef.value.getCheckboxRecords();
+		checkTable.value = records;
+		console.log(checked ? '勾选事件' : '取消事件', records);
+	}
+};
+const toolbarRef = ref<RefType>();
+const opened = () => {
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+};
+defineExpose({
+	openDialog,
+});
+</script>

+ 379 - 0
src/views/business/visit/voice.vue

@@ -0,0 +1,379 @@
+<template>
+	<div class="business-visit-voice-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent :disabled="state.loading">
+				<el-form-item label="任务名称" prop="Keyword">
+					<el-input v-model.trim="state.queryParams.Keyword" placeholder="回访任务名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="任务状态" prop="AiOrderVisitTaskState">
+					<el-select v-model="state.queryParams.AiOrderVisitTaskState" placeholder="请选择任务状态" @change="handleQuery" clearable>
+						<el-option v-for="item in aiOrderVisitTaskState" :value="item.key" :key="item.key" :label="item.value" />
+					</el-select>
+				</el-form-item>
+				<el-form-item label="工单编码" prop="No">
+					<el-input v-model.trim="state.queryParams.No" placeholder="工单编码" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="drawer = true" class="default-button"> <SvgIcon name="ele-Search" class="mr5" />更多查询</el-button>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.loading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+				:tools="[{ toolRender: { name: 'exportCurrent' } }, { toolRender: { name: 'exportAll' } }]"
+			>
+				<template #buttons>
+					<el-button type="primary" @click="onAddVisit" v-auth="'business:visit:voice:add'" :loading="state.loading">
+						<SvgIcon name="ele-Plus" class="mr5" /> 创建任务
+					</el-button>
+				</template>
+			</vxe-toolbar>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-table
+					border
+					:loading="state.loading"
+					:data="state.tableData"
+					:column-config="{ resizable: true }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					:scrollY="{ enabled: true, gt: 100 }"
+					id="businessVisitVoice"
+					:custom-config="{
+						storage: true,
+					}"
+					:params="{ exportMethod: getSmartVisitExport, exportParams: requestParams }"
+					showHeaderOverflow
+				>
+					<vxe-column field="name" title="回访任务名称" min-width="200"></vxe-column>
+					<vxe-column field="beginTime" title="开始时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.beginTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="endTime" title="结束时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.endTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="hasVisitCount" title="回访任务总数量" width="140"></vxe-column>
+					<vxe-column field="visitedCount" title="回访任务成功数量" width="140"></vxe-column>
+					<vxe-column field="visitedFailCount" title="回访任务失败数量" width="140"></vxe-column>
+					<vxe-column field="taskStateText" title="任务完成状态" width="130"></vxe-column>
+					<vxe-column field="creatorName" title="创建人" width="130"></vxe-column>
+					<vxe-column field="creationTime" title="创建时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column title="操作" fixed="right" width="220" align="center">
+						<template #default="{ row }">
+							<el-button link type="primary" @click="onDetail(row)" title="回访明细"> 回访明细 </el-button>
+							<el-button
+								link
+								type="primary"
+								v-show="[5].includes(row.taskState)"
+								@click="onTermination(row)"
+								title="终止回访任务"
+								v-auth="'business:visit:voice:termination'"
+							>
+								终止任务
+							</el-button>
+							<el-button
+								link
+								type="primary"
+								v-show="[5].includes(row.taskState)"
+								@click="onStart(row)"
+								title="启动任务"
+								v-auth="'business:visit:voice:start'"
+							>
+								启动
+							</el-button>
+							<el-button
+								link
+								type="primary"
+								v-show="[1, 2].includes(row.taskState)"
+								@click="onPause(row)"
+								title="暂停任务"
+								v-auth="'business:visit:voice:pause'"
+							>
+								暂停
+							</el-button>
+						</template>
+					</vxe-column>
+				</vxe-table>
+			</div>
+			<pagination
+				@pagination="queryList"
+				:total="state.total"
+				v-model:current-page="state.queryParams.PageIndex"
+				v-model:page-size="state.queryParams.PageSize"
+				:disabled="state.loading"
+			/>
+		</div>
+		<el-drawer v-model="drawer" title="更多查询" size="500px">
+			<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="90px" :disabled="state.loading">
+				<el-form-item label="创建时间" prop="crTime">
+					<el-date-picker
+						v-model="state.queryParams.crTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>
+				<el-form-item label="开始时间" prop="startTime">
+					<el-date-picker
+						v-model="state.queryParams.startTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>
+				<el-form-item label="结束时间" prop="endTime">
+					<el-date-picker
+						v-model="state.queryParams.endTime"
+						type="datetimerange"
+						unlink-panels
+						range-separator="至"
+						start-placeholder="开始时间"
+						end-placeholder="结束时间"
+						:shortcuts="shortcuts"
+						@change="handleQuery"
+						value-format="YYYY-MM-DD[T]HH:mm:ss"
+						:default-time="defaultTimeStartEnd"
+					/>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+				<el-button @click="resetQuery(drawerRuleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+			</template>
+		</el-drawer>
+		<!--  选择需要语音回访的工单  -->
+		<voice-visit-add ref="voiceVisitAddRef" @updateList="refreshList" />
+		<!--  回访明细  -->
+		<voice-visit-detail ref="voiceVisitDetailRef" @updateList="refreshList" />
+	</div>
+</template>
+
+<script lang="tsx" setup name="businessVisitVoice">
+import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
+import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
+import { formatDate } from '@/utils/formatTime';
+import { getSmartVisitBaseData, getSmartVisitExport, getSmartVisitList } from '@/api/smartVisit';
+import { smartCallOutTaskPause, smartCallOutTaskStart, smartCallOutTaskStop } from '@/api/auxiliary/smartCallOut';
+import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
+import Other from '@/utils/other';
+
+// 引入组件
+const VoiceVisitAdd = defineAsyncComponent(() => import('@/views/business/visit/components/Voice-visit-add.vue')); // 选择需要语音回访的工单
+const VoiceVisitDetail = defineAsyncComponent(() => import('@/views/business/visit/components/Voice-visit-Detail.vue')); // 回访明细
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+
+// 定义变量内容
+const state = reactive<any>({
+	loading: false, // 加载状态
+	queryParams: {
+		// 查询参数
+		PageIndex: 1,
+		PageSize: 20,
+		Keyword: null,
+		AiOrderVisitTaskState: null,
+		crTime: [],
+		StartTime: null,
+		EndTime: null,
+		startTime: [],
+		AiVisitTimeBeginStart: null,
+		AiVisitTimeBeginEnd: null,
+		endTime: [],
+		AiVisitTimeEndStart: null,
+		AiVisitTimeEndEnd: null,
+		No: null, // 工单编码
+	},
+	total: 0, // 总条数
+	tableData: [], // 表格数据
+});
+// 手动查询,将页码设置为1
+const handleQuery = () => {
+	state.queryParams.PageIndex = 1;
+	queryList();
+};
+// 刷新列表
+const refreshList = () => {
+	queryList();
+};
+const requestParams = ref<EmptyObjectType>({});
+// 获取参数列表
+const queryList = () => {
+	return new Promise((resolve, reject) => {
+		state.loading = true;
+		requestParams.value = Other.deepClone(state.queryParams);
+		requestParams.value.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
+		requestParams.value.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
+		Reflect.deleteProperty(requestParams.value, 'crTime');
+		requestParams.value.AiVisitTimeBeginStart = state.queryParams.startTime === null ? null : state.queryParams.startTime[0];
+		requestParams.value.AiVisitTimeBeginEnd = state.queryParams.startTime === null ? null : state.queryParams.startTime[1];
+		Reflect.deleteProperty(requestParams.value, 'startTime');
+		requestParams.value.AiVisitTimeEndStart = state.queryParams.endTime === null ? null : state.queryParams.endTime[0];
+		requestParams.value.AiVisitTimeEndEnd = state.queryParams.endTime === null ? null : state.queryParams.endTime[1];
+		Reflect.deleteProperty(requestParams.value, 'endTime');
+		getSmartVisitList(requestParams.value)
+			.then((res) => {
+				state.tableData = res.result.items ?? [];
+				state.total = res.result.total ?? 0;
+				state.loading = false;
+				resolve(res);
+			})
+			.catch(() => {
+				state.loading = false;
+				reject();
+			});
+	});
+};
+// 页面基础数据
+const aiOrderVisitTaskState = ref<EmptyArrayType>([]);
+const getBaseData = async () => {
+	try {
+		const { result } = await getSmartVisitBaseData();
+		aiOrderVisitTaskState.value = result.aiOrderVisitTaskState;
+	} catch (e) {
+		console.log(e);
+	}
+};
+// 重置表单
+const drawerRuleFormRef = ref();
+const ruleFormRef = ref<RefType>(null); // 表单ref
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	ruleFormRef.value?.resetFields();
+	queryList();
+};
+// 新增回访任务
+const voiceVisitAddRef = ref<RefType>();
+const onAddVisit = () => {
+	voiceVisitAddRef.value.openDialog();
+};
+// 回访明细
+const voiceVisitDetailRef = ref<RefType>();
+const onDetail = (row: any) => {
+	voiceVisitDetailRef.value.openDialog(row);
+};
+// 终止智能回访任务
+const onTermination = (row: any) => {
+	ElMessageBox.confirm(`您确定要终止回访任务【${row.name}】吗?`, '提示', {
+		confirmButtonText: '确定',
+		cancelButtonText: '取消',
+		type: 'warning',
+		draggable: true,
+		cancelButtonClass: 'default-button',
+		autofocus: false,
+	})
+		.then(() => {
+			state.loading = true;
+			// 1 :智能回访 2:批量外呼
+			smartCallOutTaskStop({ id: row.id, typeId: 1 })
+				.then(() => {
+					ElMessage({
+						type: 'success',
+						message: '终止任务成功',
+					});
+					queryList();
+					state.loading = false;
+				})
+				.catch(() => {
+					state.loading = false;
+				});
+		})
+		.catch(() => {
+			// 取消
+		});
+};
+// 启动任务
+const onStart = (row: any) => {
+	ElMessageBox.confirm(`您确定要启动回访任务【${row.name}】吗?`, '提示', {
+		confirmButtonText: '确定',
+		cancelButtonText: '取消',
+		type: 'warning',
+		draggable: true,
+		cancelButtonClass: 'default-button',
+		autofocus: false,
+	})
+		.then(() => {
+			smartCallOutTaskStart({ id: row.id, typeId: 1 })
+				.then(() => {
+					ElMessage({
+						type: 'success',
+						message: '启动任务成功',
+					});
+					queryList();
+					state.loading = false;
+				})
+				.catch(() => {
+					state.loading = false;
+				});
+		})
+		.catch(() => {
+			// 取消
+		});
+};
+// 暂停任务
+const onPause = (row: any) => {
+	ElMessageBox.confirm(`您确定要暂停回访任务【${row.name}】吗?`, '提示', {
+		confirmButtonText: '确定',
+		cancelButtonText: '取消',
+		type: 'warning',
+		draggable: true,
+		cancelButtonClass: 'default-button',
+		autofocus: false,
+	})
+		.then(() => {
+			smartCallOutTaskPause({ id: row.id, typeId: 1 })
+				.then(() => {
+					ElMessage({
+						type: 'success',
+						message: '暂停任务成功',
+					});
+					queryList();
+					state.loading = false;
+				})
+				.catch(() => {
+					state.loading = false;
+				});
+		})
+		.catch(() => {
+			// 取消
+		});
+};
+const drawer = ref(false);
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
+// 页面加载时
+onMounted(() => {
+	queryList().then(() => {
+		getBaseData();
+	});
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+});
+</script>