Ver Fonte

reactor:317 【回访功能】优化;

zhangchong há 7 meses atrás
pai
commit
daff4dacc7

+ 33 - 0
src/api/business/visit.ts

@@ -103,4 +103,37 @@ export const visitTurnSatisfaction = (data: object) => {
         method: 'post',
         data
     });
+};
+/**
+ * @description 发送回访短信
+ * @param {object} data
+ */
+export const visitSendSms = (data: object) => {
+    return request({
+        url: `/api/v1/Order/visit/sms`,
+        method: 'post',
+        data
+    });
+};
+/**
+ * @description 批量回访保存基础信息
+ * @param {object} params
+ */
+export const visitAddBaseData = (params?: object) => {
+    return request({
+        url: `/api/v1/Order/visit/batch-basedata`,
+        method: 'get',
+        params
+    });
+};
+/**
+ * @description 批量回访保存
+ * @param {object} data
+ */
+export const visitAddBatch = (data: object) => {
+    return request({
+        url: `/api/v1/Order/visit/batch`,
+        method: 'post',
+        data
+    });
 };

+ 7 - 7
src/components/OrderDetail/index.vue

@@ -70,12 +70,12 @@
 							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
 								<el-form-item label="来电主体"> {{ state.ruleForm.identityTypeText }} </el-form-item>
 							</el-col>
-              <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.licenceType">
-                <el-form-item label="证件类型"> {{ state.ruleForm.licenceType }} </el-form-item>
-              </el-col>
-              <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.licenceNo">
-                <el-form-item label="证件号码"> {{ state.ruleForm.licenceNo }} </el-form-item>
-              </el-col>
+							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.licenceType">
+								<el-form-item label="证件类型"> {{ state.ruleForm.licenceType }} </el-form-item>
+							</el-col>
+							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" v-if="state.ruleForm.licenceNo">
+								<el-form-item label="证件号码"> {{ state.ruleForm.licenceNo }} </el-form-item>
+							</el-col>
 							<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
 								<el-form-item label="受理短信"> {{ state.ruleForm.smsSendedText }} </el-form-item>
 							</el-col>
@@ -265,7 +265,7 @@
 							</el-col>
 							<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.orderRemarks?.length">
 								<el-form-item label="备注信息">
-									<el-row v-for="(item,index) in state.ruleForm.orderRemarks" class="w100 mb10" :key="index">
+									<el-row v-for="(item, index) in state.ruleForm.orderRemarks" class="w100 mb10" :key="index">
 										<el-col class="formatted-text">备注信息:{{ item.remark }} </el-col>
 										<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">备注人:{{ item.remarkUser }} </el-col>
 										<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">备注日期:{{ formatDate(item.remarkTime, 'YYYY-mm-dd HH:MM:SS') }}</el-col>

+ 1 - 8
src/views/business/order/copy-index.vue

@@ -464,16 +464,9 @@ const changeCheckList = () => {
 	handleQuery();
 };
 const proTableRef = ref<RefType>(); // 表格ref
-const selectable = (row: any) => {
-	if (state.queryParams.IsProvinceOrder) {
-		return row?.isProvince && row?.source > 1 && row?.status <= 1;
-	} else {
-		return true;
-	}
-};
 // 表格配置项
 const columns = ref<any[]>([
-	{ type: 'selection', fixed: 'left', minWidth: 40, selectable: selectable, align: 'center' },
+	{ type: 'selection', fixed: 'left', minWidth: 40, align: 'center' },
 	{ prop: 'expiredStatusText', label: '超期状态', align: 'center', minWidth: 80 },
 	{ prop: 'no', label: '工单编码', minWidth: 140 },
 	{ prop: 'isProvinceText', label: '省/市工单', minWidth: 90 },

+ 2 - 10
src/views/business/order/index.vue

@@ -268,7 +268,6 @@ import { defineAsyncComponent, onMounted, reactive, ref, onActivated, onBeforeUn
 import type { FormInstance } from 'element-plus';
 import { ElMessage, ElMessageBox, ElNotification } from 'element-plus';
 import { defaultDateThree, defaultTimeStartEnd, shortcuts } from '@/utils/constants';
-import { useRouter } from 'vue-router';
 import { formatDate } from '@/utils/formatTime';
 import { exportJbOrder, exportOrder, listBaseData, orderList, provinceReturn } from '@/api/business/order';
 import { addObserve } from '@/api/query/observe';
@@ -358,18 +357,11 @@ const changeCheckList = () => {
 	else state.queryParams.IsSensitiveWord = null;
 	handleQuery();
 };
-const router = useRouter(); // 路由
 const proTableRef = ref<RefType>(); // 表格ref
-const selectable = (row: any) => {
-	if (state.queryParams.IsProvinceOrder) {
-		return row?.isProvince && row?.source > 1 && row?.status <= 1;
-	} else {
-		return true;
-	}
-};
+
 // 表格配置项
 const columns = ref<any[]>([
-	{ type: 'selection', minWidth: 40, selectable: selectable, align: 'center' },
+	{ type: 'selection', minWidth: 40, align: 'center' },
 	{ prop: 'expiredStatusText', label: '超期状态', align: 'center', minWidth: 80 },
 	{ prop: 'no', label: '工单编码', minWidth: 140 },
 	{ prop: 'isProvinceText', label: '省/市工单', minWidth: 90 },

+ 1 - 1
src/views/business/publish/component/Order-publish.vue

@@ -294,7 +294,7 @@ const orderPublishRedoRef = ref<RefType>();
 const onRedo = () => {
 	orderPublishRedoRef.value.openDialog(state.orderDetail);
 };
-// 重办成功
+// 重办和退回成功
 const updateList = () => {
 	closeDialog();
 	emit('updateList');

+ 1 - 5
src/views/business/publish/todo.vue

@@ -106,13 +106,9 @@ const state = reactive({
 	total: 0, // 总数
 });
 const proTableRef = ref<RefType>(); // 表格ref
-const selectable = (row: any) => {
-	//设置省工单和会签工单不可选(不可批量发布)
-	return !row.isProvince && row.counterSignType === null;
-};
 // 表格配置项
 const columns = ref<any[]>([
-	{ type: 'selection', selectable: selectable, fixed: 'left', minWidth: 40, align: 'center' },
+	{ type: 'selection', fixed: 'left', minWidth: 40, align: 'center' },
 	{ prop: 'no', label: '工单编码', minWidth: 140 },
 	{ prop: 'isProvinceText', label: '省/市工单', minWidth: 90 },
 	{ prop: 'statusText', label: '工单状态', minWidth: 100 },

+ 1 - 6
src/views/business/secondHandle/audit.vue

@@ -84,7 +84,6 @@
 import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
 import { FormInstance } from 'element-plus';
 import { formatDate } from '@/utils/formatTime';
-import { useRouter } from 'vue-router';
 import { secondHandleAuditExport, secondHandleAuditList, secondHandleBase } from '@/api/business/secondHandle';
 import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
 import other from '@/utils/other';
@@ -96,14 +95,10 @@ const SecondHandleAuditMultiple = defineAsyncComponent(() => import('@/views/bus
 const SecondHandleDetail = defineAsyncComponent(() => import('@/views/business/secondHandle/components/Second-handle-detail.vue')); // 办理明细
 // 定义变量内容
 const ruleFormRef = ref<RefType>(); // 表单ref
-const router = useRouter(); // 路由
 const proTableRef = ref<RefType>(); // 表格ref
 // 表格配置项
-const selectable = (row: any) => {
-	return row.state === 1;
-};
 const columns = ref<any[]>([
-	{ type: 'selection', fixed: 'left', width: 40, align: 'center',selectable: selectable },
+	{ type: 'selection', fixed: 'left', width: 40, align: 'center' },
 	{ prop: 'order.expiredStatusText', label: '超期状态', align: 'center', width: 80 },
 	{ prop: 'order.no', label: '工单编码', minWidth: 140 },
 	{ prop: 'stateText', label: '办理状态', minWidth: 100 },

+ 1 - 4
src/views/business/special/audit.vue

@@ -66,12 +66,9 @@ const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/
 // 定义变量内容
 const ruleFormRef = ref<RefType>(); // 表单ref
 const proTableRef = ref<RefType>(); // 表格ref
-const selectable = (row: any) => {
-	return [0].includes(row.state);
-};
 // 表格配置项
 const columns = ref<any[]>([
-	{ type: 'selection', selectable: selectable, minWidth: 40, align: 'center' },
+	{ type: 'selection', minWidth: 40, align: 'center' },
 	{ prop: 'order.no', label: '工单编码', minWidth: 140 },
 	{ prop: 'order.isProvinceText', label: '省/市工单', minWidth: 90 },
 	{ prop: 'order.title', label: '工单标题', minWidth: 200 },

+ 253 - 0
src/views/business/visit/component/Visit-batch.vue

@@ -0,0 +1,253 @@
+<template>
+	<el-dialog
+		v-model="state.dialogVisible"
+		draggable
+		title="批量回访"
+		append-to-body
+		destroy-on-close
+		@close="close"
+		ref="dialogRef"
+		@mouseup="mouseup"
+		:style="'transform: ' + state.transform + ';'"
+	>
+		<div class="collapse-container" v-loading="state.loading">
+			<el-form label-width="120px" ref="ruleFormRef" :model="state.ruleForm">
+				<el-row :gutter="35">
+					<el-col>
+						<el-form-item label="回访人">
+							{{ userInfos.name }}
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item label="话务员评价" prop="seatEvaluate" :rules="[{ required: true, message: '请选择话务员评价', trigger: 'change' }]">
+							<el-radio-group v-model="state.ruleForm.seatEvaluate">
+								<el-radio v-for="items in seatEvaluate" :key="items.key" :label="items.value" :value="items.key">{{ items.value }}</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item
+							label="话务员回访内容"
+							prop="seatVisitContent"
+							:rules="[{ required: true, message: '请填写话务员回访内容', trigger: 'blur' }]"
+						>
+							<common-advice
+								@chooseAdvice="chooseAdviceSeats"
+								v-model="state.ruleForm.seatVisitContent"
+								placeholder="请填写话务员回访内容"
+								:loading="state.loading"
+								:commonEnum="commonEnum.ReturnVisit"
+								:minRows="5"
+								:maxRows="10"
+								drawerWidth="40%"
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
+						<el-form-item
+							label="部门办件结果"
+							prop="orgProcessingResults"
+							:rules="[{ required: true, message: '请选择部门办件结果', trigger: 'change' }]"
+						>
+							<el-select
+								v-model="state.ruleForm.orgProcessingResults"
+								placeholder="请选择部门办件结果"
+								value-key="dicDataValue"
+								clearable
+								@change="
+									(val) => {
+										state.ruleForm.orgProcessingResults.value = val?.dicDataName;
+										state.ruleForm.orgProcessingResults.key = val?.dicDataValue;
+									}
+								"
+							>
+								<el-option v-for="items in visitSatisfaction" :key="items.dicDataValue" :label="items.dicDataName" :value="items" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<!-- 不满意才会选择不满意原因 -->
+					<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-if="['1', '2'].includes(state.ruleForm.orgProcessingResults?.key)">
+						<el-form-item
+							label="不满意原因"
+							prop="orgNoSatisfiedReason"
+							:rules="[{ required: true, message: '请选择不满意原因', trigger: 'change' }]"
+						>
+							<el-select
+								v-model="state.ruleForm.orgNoSatisfiedReason"
+								placeholder="请选择不满意原因"
+								value-key="dicDataValue"
+								multiple
+								collapse-tags
+								clearable
+								collapse-tags-tooltip
+								@change="
+									(val) => {
+										state.ruleForm.orgNoSatisfiedReason.value = val?.dicDataName;
+										state.ruleForm.orgNoSatisfiedReason.key = val?.dicDataValue;
+									}
+								"
+							>
+								<el-option v-for="items in dissatisfiedReason" :key="items.dicDataValue" :label="items.dicDataName" :value="items" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-if="['ZiGong'].includes(themeConfig.appScope)">
+						<el-form-item
+							label="部门办件态度"
+							prop="orgHandledAttitude"
+							:rules="[{ required: true, message: '请选择部门办件态度', trigger: 'change' }]"
+						>
+							<el-select
+								v-model="state.ruleForm.orgHandledAttitude"
+								placeholder="请选择部门办件态度"
+								value-key="dicDataValue"
+								clearable
+								@change="
+									(val) => {
+										state.ruleForm.orgHandledAttitude.value = val.dicDataName;
+										state.ruleForm.orgHandledAttitude.key = val.dicDataValue;
+									}
+								"
+							>
+								<el-option v-for="items in visitManner" :key="items.dicDataValue" :label="items.dicDataName" :value="items" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item label="部门回访内容" prop="orgVisitContent" :rules="[{ required: true, message: '请填写部门回访内容', trigger: 'blur' }]">
+							<common-advice
+								@chooseAdvice="chooseAdviceContent"
+								v-model="state.ruleForm.orgVisitContent"
+								d
+								placeholder="请填写部门回访内容"
+								:loading="state.loading"
+								:commonEnum="commonEnum.ReturnVisit"
+								:minRows="5"
+								:maxRows="10"
+								drawerWidth="40%"
+							/>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+		</div>
+		<template #footer>
+			<span class="dialog-footer">
+				<el-button @click="closeDialog" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onAudit(ruleFormRef)" :loading="state.loading">确 定</el-button>
+			</span>
+		</template>
+	</el-dialog>
+</template>
+<script setup lang="ts">
+import { defineAsyncComponent, reactive, ref } from 'vue';
+import { ElNotification, FormInstance } from 'element-plus';
+import { visitAddBaseData, visitAddBatch, visitTurnSatisfaction } from '@/api/business/visit';
+import { useUserInfo } from '@/stores/userInfo';
+import { storeToRefs } from 'pinia';
+import { commonEnum } from '@/utils/constants';
+import { useThemeConfig } from '@/stores/themeConfig';
+
+// 定义子组件向父组件传值/事件
+const emit = defineEmits(['updateList']);
+
+const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
+// 定义变量内容
+const state = reactive<any>({
+	dialogVisible: false, // 是否显示弹窗
+	loading: false, // 是否显示加载
+	ruleForm: {
+		seatEvaluate: null,
+		orgProcessingResults: null,
+		orgHandledAttitude: null,
+		orgNoSatisfiedReason: null,
+		seatVisitContent: null,
+		orgVisitContent: null,
+		visit: [],
+	},
+	transform: 'translate(0px, 0px)', // 附件弹窗位置
+});
+const ruleFormRef = ref<RefType>();
+const ids = ref<any>([]);
+const storesUserInfo = useUserInfo();
+const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
+const storesThemeConfig = useThemeConfig();
+const { themeConfig } = storeToRefs(storesThemeConfig);
+const seatEvaluate = ref<EmptyArrayType>(); // 话务员评价
+const dissatisfiedReason = ref<EmptyArrayType>(); // 不满意原因
+const visitManner = ref<EmptyArrayType>(); // 部门办件态度
+const visitSatisfaction = ref<EmptyArrayType>(); // 部门办件结果
+// 获取基础信息
+const getBaseData = async () => {
+	state.loading = true;
+	try {
+		const { result } = await visitAddBaseData();
+		seatEvaluate.value = result?.seatEvaluate ?? [];
+		dissatisfiedReason.value = result?.dissatisfiedReason ?? [];
+		visitManner.value = result?.visitManner ?? [];
+		visitSatisfaction.value = result?.visitSatisfaction ?? [];
+		state.loading = false;
+	} catch (error) {
+		console.log(error);
+		state.loading = false;
+	}
+};
+// 打开弹窗
+const openDialog = async (val: any) => {
+	state.dialogVisible = true;
+	state.ruleForm.visit = val;
+	await getBaseData();
+};
+// 关闭弹窗
+const closeDialog = () => {
+	state.dialogVisible = false;
+};
+const close = () => {
+	ruleFormRef.value?.clearValidate();
+	ruleFormRef.value?.resetFields();
+	state.loading = false;
+};
+// 设置抽屉
+const dialogRef = ref<RefType>(); // 弹窗ref
+const mouseup = () => {
+	state.transform = dialogRef.value.dialogContentRef.$el.style.transform;
+};
+// 保存
+const onAudit = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.loading = true;
+		visitAddBatch(state.ruleForm)
+			.then((res: any) => {
+				state.loading = false;
+				closeDialog();
+				emit('updateList');
+				ElNotification({
+					type: 'info',
+					title: '批量回访完成',
+					message: `成功评判${res.result?.completeCount}条,失败${res.result?.errorCount}条`,
+				});
+			})
+			.catch(() => {
+				state.loading = false;
+			});
+	});
+};
+// 选中常用意见
+const chooseAdviceSeats = (item: any) => {
+	state.ruleForm.seatVisitContent += item.content;
+};
+const chooseAdviceContent = (item: any) => {
+	state.ruleForm.orgVisitContent += item.content;
+};
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>
+<style lang="scss" scoped>
+.el-radio {
+	margin-right: 15px;
+}
+</style>

+ 59 - 43
src/views/business/visit/component/Visit-detail.vue

@@ -4,7 +4,6 @@
 		draggable
 		:title="dialogTitle"
 		ref="dialogRef"
-		width="50%"
 		append-to-body
 		@mouseup="mouseup"
 		:style="'transform: ' + state.transform + ';'"
@@ -183,11 +182,11 @@
 													{{ item.orgNoSatisfiedReason.map((item) => item.dicDataName).join(',') }}
 												</el-form-item>
 											</el-col>
-											<!--										<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
+												<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-if="['ZiGong'].includes(themeConfig.appScope)">
                         <el-form-item label="部门办件态度">
                           {{ item.orgHandledAttitude?.dicDataName }}
                         </el-form-item>
-                      </el-col>-->
+                      </el-col>
 											<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 												<el-form-item label="部门回访内容">
 													{{ item.visitContent }}
@@ -213,19 +212,22 @@
 									</el-form-item>
 								</el-col>
 								<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="['ZiGong'].includes(themeConfig.appScope)">
-									<el-form-item label="历史回访记录">
-										<ProTable
-											ref="proTableRef"
-											:columns="columns"
-											:data="state.tableData"
-											@updateTable="queryList"
-											:loading="state.loading"
-											:pagination="false"
-											border
-											:toolButton="false"
-										>
-											<template #empty> 暂无数据 </template>
-										</ProTable>
+									<el-form-item label="历史回访记录" class="w100">
+										<div class="w100">
+											<ProTable
+												ref="proTableRef"
+												:columns="columns"
+												:data="state.histories"
+												@updateTable="queryList"
+												:loading="state.loading"
+												:pagination="false"
+												border
+												:toolButton="false"
+												class="w100"
+											>
+												<template #empty> 暂无数据 </template>
+											</ProTable>
+										</div>
 									</el-form-item>
 								</el-col>
 							</el-row>
@@ -270,21 +272,23 @@
 													:rules="[{ required: true, message: '请选择语音评价', trigger: 'change' }]"
 												>
 													<el-radio-group v-model="item.viceEvaluate">
-														<el-radio v-for="items in seatEvaluate" :key="items.key" :label="items.value" :value="items.key">{{
+														<el-radio v-for="items in viceEvaluate" :key="items.key" :label="items.value" :value="items.key">{{
 															items.value
 														}}</el-radio>
 													</el-radio-group>
 												</el-form-item>
 											</el-col>
-											<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
+											<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 												<el-form-item
 													label="话务员评价"
 													:prop="`visitDetails.${index}.seatEvaluate`"
 													:rules="[{ required: true, message: '请选择话务员评价', trigger: 'change' }]"
 												>
-													<el-select v-model="item.seatEvaluate" placeholder="请选择话务员评价" class="w100">
-														<el-option v-for="items in seatEvaluate" :key="items.key" :label="items.value" :value="items.key" />
-													</el-select>
+													<el-radio-group v-model="item.seatEvaluate">
+														<el-radio v-for="items in seatEvaluate" :key="items.key" :label="items.value" :value="items.key">{{
+																items.value
+															}}</el-radio>
+													</el-radio-group>
 												</el-form-item>
 											</el-col>
 											<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
@@ -398,7 +402,7 @@
 													</el-select>
 												</el-form-item>
 											</el-col>
-											<!--											<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
+											<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-if="['ZiGong'].includes(themeConfig.appScope)">
 													<el-form-item
 														label="部门办件态度"
 														:prop="`visitDetails.${index}.orgHandledAttitude`"
@@ -419,7 +423,7 @@
 															<el-option v-for="items in visitManner" :key="items.dicDataValue" :label="items.dicDataName" :value="items" />
 														</el-select>
 													</el-form-item>
-												</el-col>-->
+												</el-col>
 											<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 												<el-form-item
 													label="部门回访内容"
@@ -450,18 +454,21 @@
 								</el-col>
 								<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="['ZiGong'].includes(themeConfig.appScope)">
 									<el-form-item label="历史回访记录">
-										<ProTable
-											ref="proTableRef"
-											:columns="columns"
-											:data="state.tableData"
-											@updateTable="queryList"
-											:loading="state.loading"
-											:pagination="false"
-											border
-											:toolButton="false"
-										>
-											<template #empty> 暂无数据 </template>
-										</ProTable>
+										<div class="w100">
+											<ProTable
+												ref="proTableRef"
+												:columns="columns"
+												:data="state.histories"
+												@updateTable="queryList"
+												:loading="state.loading"
+												:pagination="false"
+												border
+												:toolButton="false"
+												class="w100"
+											>
+												<template #empty> 暂无数据 </template>
+											</ProTable>
+										</div>
 									</el-form-item>
 								</el-col>
 							</el-row>
@@ -486,7 +493,7 @@
 	<!-- 播放录音 -->
 	<play-record ref="playRecordRef" />
 	<!-- 回访重办 -->
-	<visit-redo ref="visitRedoRef" />
+	<visit-redo ref="visitRedoRef" @updateList="onRedoSuccess" />
 </template>
 <script setup lang="tsx" name="orderFollowUpDetail">
 import { computed, defineAsyncComponent, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue';
@@ -523,7 +530,7 @@ const state = reactive<any>({
 	orderDetail: {}, // 工单详情
 	orderVisitModel: {}, // 回访详情
 	recordingAbsolutePath: '', // 录音文件
-	tableData: [], //回访记录列表
+	histories: [], //回访记录列表
 });
 const ruleFormRef = ref<RefType>();
 const storesUserInfo = useUserInfo();
@@ -555,6 +562,7 @@ const getBaseData = async (id: string) => {
 		state.recordingAbsolutePath = result?.recordingAbsolutePath ?? '';
 		state.smartRecord = result?.orderVisitModel.recordUrl ?? '';
 		aiVisitVoiceBaseUrl.value = result.aiVisitVoiceBaseUrl;
+		state.histories = result?.histories ?? []; // 回访记录列表
 		if (result?.orderVisitModel?.isPutThrough !== null) {
 			state.ruleForm.isPutThrough = !result?.orderVisitModel?.isPutThrough ?? false;
 		} else {
@@ -696,15 +704,20 @@ const visitRedoRef = ref<RefType>();
 const onRedo = () => {
 	visitRedoRef.value.openDialog(state.orderDetail);
 };
+// 重办成功
+const onRedoSuccess = () => {
+	closeDialog();
+	emit('updateList');
+};
 const queryList = () => {};
 // 表格配置项
 const columns = ref<any[]>([
-	{ prop: 'order.no', label: '语音评价' },
-	{ prop: 'order.isProvinceText', label: '话务员评价' },
-	{ prop: 'order.title', label: '部门名称' },
-	{ prop: 'order.sourceChannel', label: '部门办件结果' },
-	{ prop: 'visitStateText', label: '部门办件态度' },
-	{ prop: 'visitTypeText', label: '部门评价内容' },
+	{ prop: 'voiceEvaluateTxt', label: '语音评价', minWidth: 110 },
+	{ prop: 'seatEvaluateTxt', label: '话务员评价', minWidth: 110 },
+	{ prop: 'visitOrgName', label: '部门名称', minWidth: 110 },
+	{ prop: 'orgProcessingResultsValue', label: '部门办件结果', minWidth: 110 },
+	{ prop: 'orgHandledAttitudeValue', label: '部门办件态度', minWidth: 110 },
+	{ prop: 'visitContent', label: '部门评价内容', minWidth: 110 },
 	{
 		prop: 'visitTime',
 		label: '回访时间',
@@ -732,6 +745,9 @@ defineExpose({
 
 <style lang="scss" scoped>
 .collapse-box {
+	.el-radio {
+		margin-right: 10px;
+	}
 	:deep(.el-collapse-item__header) {
 		background-color: var(--hotline-bg-main-color);
 		height: 40px;

+ 20 - 2
src/views/business/visit/index.vue

@@ -61,6 +61,16 @@
 				<!-- 表格操作 -->
 				<template #operation="{ row }">
 					<el-button link type="primary" @click="visitDetail(row)" title="查看回访详情"> 回访详情 </el-button>
+					<el-button
+						link
+						type="primary"
+						@click="updateVisitResult(row)"
+						title="修改回访结果"
+						v-auth="'business:visit:visitEdit'"
+						v-if="['ZiGong'].includes(themeConfig.appScope) && row.visitState === 30"
+					>
+						修改回访结果
+					</el-button>
 				</template>
 			</ProTable>
 		</div>
@@ -130,6 +140,8 @@ import { formatDate } from '@/utils/formatTime';
 import { visitList, visitSearchBaseData } from '@/api/business/visit';
 import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
 import Other from '@/utils/other';
+import { useThemeConfig } from '@/stores/themeConfig';
+import { storeToRefs } from 'pinia';
 
 // 引入组件
 const VisitDetailCom = defineAsyncComponent(() => import('@/views/business/visit/component/Visit-detail.vue')); // 回访
@@ -211,7 +223,7 @@ const columns = ref<any[]>([
 	{ prop: 'order.counterSignTypeText', label: '是否会签', minWidth: 90 },
 	// { prop: 'voicePj', label: '语音评价', width: 150 },
 	{ prop: 'hwyPj', label: '话务员满意度', minWidth: 120 },
-	{ prop: 'operation', label: '操作', fixed: 'right', width: 90, align: 'center' },
+	{ prop: 'operation', label: '操作', fixed: 'right', width: 190, align: 'center' },
 ]);
 const state = reactive<any>({
 	queryParams: {
@@ -246,6 +258,8 @@ const state = reactive<any>({
 	], // 回访状态
 	visitTypeOptions: [],
 });
+const storesThemeConfig = useThemeConfig();
+const { themeConfig } = storeToRefs(storesThemeConfig);
 // 获取基础数据
 const getBaseData = () => {
 	visitSearchBaseData().then((res: any) => {
@@ -293,8 +307,12 @@ const visitDetailRef = ref<RefType>();
 const visitDetail = (row: any) => {
 	visitDetailRef.value.openDialog(row, '回访详情');
 };
+// 修改回访结果
+const updateVisitResult = (row: any) => {
+	visitDetailRef.value.openDialog(row);
+};
 onMounted(() => {
 	getBaseData();
 	queryList();
 });
-</script>
+</script>

+ 1 - 4
src/views/business/visit/reverse.vue

@@ -185,12 +185,9 @@ const ReverseAudit = defineAsyncComponent(() => import('@/views/business/visit/c
 const VisitDetailCom = defineAsyncComponent(() => import('@/views/business/visit/component/Visit-detail.vue')); // 回访
 // 定义变量内容
 const proTableRef = ref<RefType>(); // 表格ref
-const selectable = (row: any) => {
-	return row.judgeState === 0;
-};
 // 表格配置项
 const columns = ref<any[]>([
-	{ type: 'selection', fixed: 'left', width: 40, align: 'center', selectable: selectable },
+	{ type: 'selection', fixed: 'left', width: 40, align: 'center' },
 	{ prop: 'order.expiredStatusText', label: '超期状态', align: 'center', width: 80 },
 	{ prop: 'order.statusText', label: '工单状态', minWidth: 100 },
 	{ prop: 'order.sourceChannel', label: '来源渠道', minWidth: 100 },

+ 53 - 22
src/views/business/visit/todo.vue

@@ -43,33 +43,33 @@
 								@change="fastSearchChange"
 							/>
 						</el-form-item>
-<!--						<el-form-item label="回访状态" prop="QuerySelf" v-if="['ZiGong'].includes(themeConfig.appScope)">
+						<el-form-item label="回访状态" prop="VisitState" v-if="['ZiGong'].includes(themeConfig.appScope)">
 							<el-segmented
 								:options="[
-									{ label: '待回访', value: '1' },
-									{ label: '短信回访中', value: '2' },
-									{ label: '短信不满意待回访', value: '3' },
+									{ label: '待回访', value: '2' },
+									{ label: '短信回访中', value: '21' },
+									{ label: '短信不满意待回访', value: '41' },
 								]"
-								v-model="state.queryParams.QuerySelf"
+								v-model="state.queryParams.VisitState"
 								@change="handleQuery"
 							/>
-						</el-form-item>-->
+						</el-form-item>
 						<el-form-item label="工单标题" prop="Keyword">
 							<el-input v-model="state.queryParams.Keyword" placeholder="工单标题" clearable @keyup.enter="handleQuery" class="keyword-input" />
 						</el-form-item>
-						<el-form-item label="工单编码" prop="No">
-							<el-input v-model="state.queryParams.No" placeholder="工单编码" clearable @keyup.enter="handleQuery" class="keyword-input" />
-						</el-form-item>
-						<el-form-item label="">
+						<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>
 				</template>
 				<template #tableHeader="scope">
-<!--					<el-button type="primary" @click="messageVisit" :disabled="!scope.isSelected" v-auth="'business:visit:todo:message'" v-if="['ZiGong'].includes(themeConfig.appScope)">
+					<el-button type="primary" @click="messageVisit" :disabled="!scope.isSelected" v-auth="'business:visit:todo:message'" v-if="['ZiGong'].includes(themeConfig.appScope)">
 						<SvgIcon name="ele-Message" class="mr5" />短信回访</el-button
-					>-->
+					>
+					<el-button type="primary" @click="batchVisit" :disabled="!scope.isSelected" v-auth="'business:visit:todo:batch'" v-if="['ZiGong'].includes(themeConfig.appScope)">
+						<SvgIcon name="ele-DocumentCopy" class="mr5" />批量回访</el-button
+					>
 					<el-button type="primary" @click="multiplePeople" :disabled="!scope.isSelected" v-auth="'business:visit:todo:multiplePeople'">
 						<SvgIcon name="ele-User" class="mr5" />分配回访人</el-button
 					>
@@ -89,15 +89,18 @@
 				</template>
 			</ProTable>
 		</div>
-		<!-- 回访 -->
-		<visit-detail ref="visitDetailRef" @updateList="queryList" />
-		<!--  分配回访人  -->
-		<assign-return-visitors ref="assignReturnVisitorsRef" @updateList="queryList" />
-		<!-- 工单平移 -->
-		<order-migration ref="orderMigrationRef" @updateList="queryList" />
 		<!--	更多查询	-->
 		<el-drawer v-model="drawer" title="更多查询" size="500px">
 			<el-form :model="state.queryParams" ref="drawerRuleFormRef" @submit.native.prevent label-width="100px">
+				<el-form-item label="工单编码" prop="No">
+					<el-input v-model="state.queryParams.No" placeholder="工单编码" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="来电号码" prop="FromPhone">
+					<el-input v-model="state.queryParams.FromPhone" placeholder="来电号码" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
+				<el-form-item label="联系电话" prop="Contact">
+					<el-input v-model="state.queryParams.Contact" placeholder="联系电话" clearable @keyup.enter="handleQuery" />
+				</el-form-item>
 				<el-form-item label="回访人" prop="EmployeeName">
 					<el-input v-model="state.queryParams.EmployeeName" placeholder="回访人" clearable @keyup.enter="handleQuery" />
 				</el-form-item>
@@ -124,15 +127,23 @@
 				<el-button @click="resetQuery(drawerRuleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
 			</template>
 		</el-drawer>
+		<!-- 回访 -->
+		<visit-detail ref="visitDetailRef" @updateList="queryList" />
+		<!--  分配回访人  -->
+		<assign-return-visitors ref="assignReturnVisitorsRef" @updateList="queryList" />
+		<!-- 工单平移 -->
+		<order-migration ref="orderMigrationRef" @updateList="queryList" />
+		<!-- 批量回访 -->
+		<visit-batch ref="visitBatchRef" @updateList="queryList" />
 	</div>
 </template>
 
 <script setup lang="tsx" name="businessVisitTodo">
 import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
-import { ElMessageBox, FormInstance } from 'element-plus';
+import { ElMessageBox, FormInstance,ElMessage } from 'element-plus';
 import { formatDate } from '@/utils/formatTime';
 import { visitList } from '@/api/todo/visit';
-import { visitSearchBaseData } from '@/api/business/visit';
+import { visitSearchBaseData, visitSendSms } from '@/api/business/visit';
 import { useThemeConfig } from '@/stores/themeConfig';
 import { storeToRefs } from 'pinia';
 // 引入组件
@@ -140,6 +151,7 @@ const VisitDetail = defineAsyncComponent(() => import('/src/views/business/visit
 const AssignReturnVisitors = defineAsyncComponent(() => import('@/views/business/visit/component/Assign-return-visitors.vue')); // 分配回访人
 const OrderDetail = defineAsyncComponent(() => import('@/components/OrderDetail/index.vue')); // 工单详情
 const OrderMigration = defineAsyncComponent(() => import('@/views/todo/center/Order-migration.vue')); // 工单平移
+const VisitBatch = defineAsyncComponent(() => import('@/views/business/visit/component/Visit-batch.vue')); // 批量回访
 
 // 定义变量内容
 const proTableRef = ref<RefType>(); // 表格ref
@@ -173,7 +185,6 @@ const columns = ref<any[]>([
 	{ prop: 'order.acceptorName', label: '受理人', minWidth: 120 },
 	{ prop: 'order.orgLevelOneName', label: '一级部门', minWidth: 140 },
 	{ prop: 'order.currentHandleOrgName', label: '接办部门', minWidth: 140 },
-	{ prop: 'order.currentHandleOrgName', label: '接办部门', minWidth: 140 },
 	{
 		prop: 'order.startTime',
 		label: '受理时间',
@@ -228,6 +239,8 @@ const state = reactive<any>({
 		QuerySelf: 'true', // 是否只查询自己的待回访工单
 		EmployeeName: null, // 回访人
 		IsProvince: null, // 是否省工单
+		FromPhone:null, //来电号码
+		Contact:null, //联系电话
 	},
 	tableData: [], //表单
 	loading: false, // 加载
@@ -294,6 +307,7 @@ const onMigration = () => {
 // 短信回访
 const messageVisit = () => {
 	const ids = proTableRef.value.selectedList.map((item: any) => item.id);
+	console.log(ids,proTableRef.value.selectedList)
 	ElMessageBox.confirm(`您确定要选择的【${proTableRef.value.selectedList.length}】个工单进行短信回访?`, '提示', {
 		confirmButtonText: '确定',
 		cancelButtonText: '取消',
@@ -302,10 +316,27 @@ const messageVisit = () => {
 		autofocus: false,
 	})
 		.then(() => {
-			console.log(ids);
+			visitSendSms({ids}).then((res:any)=>{
+				ElMessage.success(res.message)
+				queryList();
+			}).catch((e)=>{
+				console.log(e)
+			})
 		})
 		.catch(() => {});
 };
+// 批量回访
+const visitBatchRef = ref<RefType>();
+const batchVisit = () => {
+	const visit =  proTableRef.value.selectedList.map((item: any) => {
+		return {
+			orderId:item.order?.id,
+			visitId:item.id,
+			no:item.order?.no
+		}
+	});
+	visitBatchRef.value.openDialog(visit);
+};
 onMounted(() => {
 	getBaseData();
 	queryList();