Selaa lähdekoodia

Merge branch 'refs/heads/dev' into test/exam

zhangchong 5 päivää sitten
vanhempi
commit
6d647a9e25

+ 2 - 2
.env.development

@@ -3,9 +3,9 @@ VITE_MODE_NAME=development
 # 防止部署多套系统到同一域名不同目录时,变量共用的问题 设置不同的前缀
 VITE_STORAGE_NAME=dev
 # 业务系统基础请求地址
-VITE_API_URL=http://110.188.24.28:50300
+VITE_API_URL=http://110.188.24.28:50100
 # 业务系统socket请求地址
-VITE_API_SOCKET_URL=http://110.188.24.28:50300/hubs/hotline
+VITE_API_SOCKET_URL=http://110.188.24.28:50100/hubs/hotline
 # 业务系统文件上传上传请求地址
 VITE_API_UPLOAD_URL=http://110.188.24.28:50120
 # 数据共享平台请求地址

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

@@ -0,0 +1,232 @@
+<template>
+	<el-dialog v-model="state.dialogVisible" width="60%" draggable title="语音回访" @close="close" append-to-body destroy-on-close>
+		<vxe-grid v-bind="gridOptions" ref="gridRef" v-on="gridEvents">
+			<template #form>
+				<el-form :model="state.queryParams" ref="queryFormRef" @submit.native.prevent inline label-width="100px" :disabled="gridOptions.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="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="resetQuery(queryFormRef)" class="default-button" :loading="state.loading">
+							<SvgIcon name="ele-Refresh" class="mr5" />重置
+						</el-button>
+					</el-form-item>
+				</el-form>
+			</template>
+			<template #order_detail="{ row }">
+				<order-detail :order="row.order" @updateList="queryList">{{ row.order?.title }}</order-detail>
+			</template>
+			<template #pager>
+				<pagination
+					@pagination="queryList"
+					:total="state.total"
+					v-model:current-page="state.queryParams.PageIndex"
+					v-model:page-size="state.queryParams.PageSize"
+					:disabled="state.loading"
+				/>
+			</template>
+		</vxe-grid>
+		<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 { ElMessage, FormInstance } from 'element-plus';
+import { reactive, ref, defineAsyncComponent, computed } from 'vue';
+import { visitList } from '@/api/todo/visit';
+
+const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+
+const emit = defineEmits(['updateList']);
+const state = reactive<any>({
+	queryParams: {
+		Keyword: null,
+		No: null,
+		AcceptType: null,
+		Hotspot: null,
+		PageIndex: 1,
+		PageSize: 20,
+		IsProvince: false, // 是否省工单
+		QuerySelf: false, // 默认查所有
+		VisitStateQuery: 2, // 回访状态  2待回访
+		IsCountersign: false, // 是否会签
+	},
+	total: 0, // 总数
+	dialogVisible: false, // 弹窗
+});
+
+const gridOptions = reactive<any>({
+	loading: false,
+	border: true,
+	showOverflow: true,
+	columnConfig: {
+		resizable: true,
+	},
+	scrollY: {
+		enabled: true,
+		gt: 100,
+	},
+	toolbarConfig: {
+		custom: true,
+		refresh: {
+			queryMethod: () => {
+				handleQuery();
+			},
+		},
+	},
+	customConfig: {
+		storage: true,
+	},
+	checkboxConfig: {
+		reserve: true,
+	},
+	id: 'businessVisitTodo',
+	rowConfig: { isHover: true, height: 30, isCurrent: true, useKey: true, keyField: 'id' },
+	maxHeight: 500,
+	columns: [
+		{ type: 'checkbox', width: 50, align: 'center', fixed: 'left' },
+		{ field: 'order.no', title: '工单编码', width: 140 },
+		{
+			field: 'order.title',
+			title: '工单标题',
+			minWidth: 200,
+			slots: { default: 'order_detail' },
+		},
+		{ field: 'order.sourceChannel', title: '来源渠道', width: 110 },
+		{ field: 'visitStateText', title: '回访状态', width: 100 },
+		{ field: 'order.acceptType', title: '受理类型', width: 110 },
+		{ field: 'order.hotspotName', title: '热点分类', width: 150 },
+		{ field: 'order.fromPhone', title: '来电号码', width: 150 },
+		{ field: 'order.orgLevelOneName', title: '一级部门', width: 150 },
+		{ field: 'order.actualHandleOrgName', title: '接办部门', width: 140 },
+		{
+			field: 'order.creationTime',
+			title: '受理时间',
+			width: 160,
+			formatter: 'formatDate',
+			sortable: true,
+		},
+		{
+			field: 'order.filedTime',
+			title: '办结时间',
+			width: 160,
+			formatter: 'formatDate',
+			sortable: true,
+		},
+		{
+			field: 'publishTime',
+			title: '发布时间',
+			width: 160,
+			formatter: 'formatDate',
+			sortable: true,
+		},
+		{ field: 'employeeName', title: '回访人', width: 120 },
+	],
+	data: [],
+	sortConfig: {
+		remote: true,
+	},
+});
+// 打开弹窗
+const openDialog = () => {
+	state.dialogVisible = true;
+	queryList();
+};
+const close = () => {
+	ruleFormRef.value?.clearValidate();
+	ruleFormRef.value?.resetFields();
+};
+// 获取所有工单列表
+const queryList = async () => {
+	state.loading = true;
+	gridOptions.loading = true;
+	try {
+		const { result } = await visitList(state.queryParams);
+		state.tableData = result;
+		gridOptions.data = result.items ?? [];
+		state.total = result.total ?? 0;
+		state.loading = false;
+		gridOptions.loading = false;
+	} catch (e) {
+		console.log(e);
+		state.loading = false;
+		gridOptions.loading = false;
+	}
+};
+const gridEvents = {
+	sortChange(val: any) {
+		state.queryParams.SortField = val.order ? val.field : null;
+		// 0 升序 1 降序
+		state.queryParams.SortRule = val.order ? (val.order == 'desc' ? 1 : 0) : null;
+		handleQuery();
+	},
+};
+// 手动查询,将页码设置为1
+const handleQuery = () => {
+	if (state.queryParams.VisitStateQuery !== 2) {
+		state.queryParams.IsAiVisit = null;
+	}
+	state.queryParams.PageIndex = 1;
+	queryList();
+};
+// 重置所有工单列表
+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;
+		gridOptions.loading = true;
+		const $grid = gridRef.value;
+		const selectRecords = $grid.getCheckboxRecords();
+		const selectReserveRecords = $grid.getCheckboxReserveRecords();
+		if (selectRecords.length === 0 && selectReserveRecords.length === 0) {
+			ElMessage({
+				message: '请至少选择一条数据',
+				type: 'warning',
+			});
+			return;
+		}
+		const selectAllRecords = [...selectRecords, ...selectReserveRecords];
+		console.log(selectAllRecords);
+		/*	smartVisitAdd(request)
+			.then(() => {
+				state.loading = false;
+				state.dialogVisible = false;
+				ElMessage.success('操作成功');
+				emit('updateList');
+				gridOptions.loading = false;
+			})
+			.catch(() => {
+				state.loading = false;
+				gridOptions.loading = false;
+			});*/
+	});
+};
+const gridRef = ref<RefType>();
+const isChecked = computed(() => {
+	if (!gridRef.value) return true;
+	const selectRecords = gridRef.value.getCheckboxRecords();
+	const selectReserveRecords = gridRef.value.getCheckboxReserveRecords();
+	return !Boolean(selectRecords.length + selectReserveRecords.length);
+});
+defineExpose({
+	openDialog,
+});
+</script>

+ 12 - 0
src/views/business/visit/todo.vue

@@ -79,6 +79,9 @@
 					<el-button type="primary" @click="onMigration" v-auth="'business:visit:todo:migration'" :disabled="isChecked">
 						<SvgIcon name="ele-Rank" class="mr5" />平级移动<span v-if="checkTable.length">({{ checkTable.length }})</span>
 					</el-button>
+					<el-button type="primary" @click="onVoiceVisit" v-auth="'business:visit:todo:voice'" v-if="['ZiGong'].includes(themeConfig.appScope)">
+						<SvgIcon name="iconfont icon-dutyOff" class="mr5" />语音回访
+					</el-button>
 				</template>
 				<template #order_detail="{ row }">
 					<order-detail :order="row.order" @updateList="refreshList">{{ row.order?.title }}</order-detail>
@@ -215,6 +218,8 @@
 		<order-migration ref="orderMigrationRef" @updateList="refreshList" />
 		<!-- 批量回访 -->
 		<visit-batch ref="visitBatchRef" @updateList="refreshList" />
+		<!-- 语音回访 -->
+		<voice-visit-add ref="voiceVisitAddRef" @updateList="refreshList" />
 	</div>
 </template>
 
@@ -234,6 +239,7 @@ const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/
 const OrderMigration = defineAsyncComponent(() => import('@/views/todo/center/Order-migration.vue')); // 工单平移
 const VisitBatch = defineAsyncComponent(() => import('@/views/business/visit/components/Visit-batch.vue')); // 批量回访
 const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
+const VoiceVisitAdd = defineAsyncComponent(() => import('@/views/business/visit/components/Voice-visit-add-voice.vue')); // 语音回访
 
 // 定义变量内容
 const fastSearch = ref('all'); // tab位置
@@ -426,6 +432,7 @@ if (themeConfig.value.appScope === 'YiBin') {
 		{ label: '短信回访中', value: 21 },
 		{ label: '短信不满意待回访', value: 41 },
 		{ label: '未接通', value: 51 },
+		{ label: '语音回访', value: 61 },
 	];
 } else {
 	visitStateOptions.value = [
@@ -567,6 +574,11 @@ const batchVisit = () => {
 	});
 	visitBatchRef.value.openDialog(visit);
 };
+// 语音回访
+const voiceVisitAddRef = ref<RefType>();
+const onVoiceVisit = () => {
+	voiceVisitAddRef.value.openDialog();
+};
 const checkTable = ref<EmptyArrayType>([]);
 const gridRef = ref<RefType>();
 const selectAllChangeEvent = ({ checked }) => {