瀏覽代碼

reactor:知识库类型管理新增适用部门字段;

zhangchong 10 月之前
父節點
當前提交
967ff1093e

+ 31 - 34
src/layout/navBars/breadcrumb/telControl.vue

@@ -504,7 +504,7 @@
 					class="w100"
 					allow-create
 					default-first-option
-          :props="{
+					:props="{
 						label: 'dicDataName',
 						value: 'dicDataValue',
 					}"
@@ -521,7 +521,7 @@
 </template>
 
 <script setup lang="ts" name="telControl">
-import { reactive, ref, computed, defineAsyncComponent, onMounted, onBeforeUnmount } from 'vue';
+import { reactive, ref, computed, defineAsyncComponent, onMounted, onBeforeUnmount, watch } from 'vue';
 import { ElMessageBox, ElNotification, ElMessage, FormInstance } from 'element-plus';
 import { storeToRefs } from 'pinia';
 import { useTelStatus, TelStates, RestStates } from '@/stores/telStatus';
@@ -557,7 +557,7 @@ import mittBus from '@/utils/mitt';
 import { voiceAssistant } from '@/api/todo/voiceAssistant';
 import { submitLog } from '@/api/public/log';
 import { B } from '@vueuse/motion/dist/shared/motion.5ee44005';
-import { getDataByCode } from "@/api/system/dict";
+import { getDataByCode } from '@/api/system/dict';
 // 引入组件
 const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
 const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue'));
@@ -571,7 +571,7 @@ const state = reactive<any>({
 		telNo: null, //分机号
 	},
 	telsList: <EmptyArrayType>[], // 分机列表
-  threeWayAndTransfer: <EmptyArrayType>[], // 三方通话和转接
+	threeWayAndTransfer: <EmptyArrayType>[], // 三方通话和转接
 	loading: false,
 	showHangupList: false, //是否展示挂断列表
 	restDialogVisible: false, //小休弹窗
@@ -738,7 +738,7 @@ const RestApplyPassFn = (data: any) => {
 const getTelsLists = async () => {
 	state.loading = true;
 	try {
-		const {result} = await getTelList();
+		const { result } = await getTelList();
 		state.telsList = result ?? [];
 		state.loading = false;
 		return state.telsList;
@@ -750,12 +750,12 @@ const getTelsLists = async () => {
 // 查询三方会议和转接的号码
 const getThreeWayAndTransfer = async () => {
 	try {
-		const {result} = await getDataByCode('TransferNumber');
-    state.threeWayAndTransfer = result ?? [];
+		const { result } = await getDataByCode('TransferNumber');
+		state.threeWayAndTransfer = result ?? [];
 	} catch (err) {
-    console.log(err);
-  }
-}
+		console.log(err);
+	}
+};
 // 鼠标移入移出改变图标
 const onHover = (val: string, path: string) => {
 	state[val] = getImageUrl(path);
@@ -856,7 +856,6 @@ const onConnect = () => {
 		// 普通模式才链接语音助手
 		connectVoiceAssistant(currentTel.value.telNo); // 坐席助手开启
 	}
-	// isReconnect.value = true;
 };
 // 业务系统发送消息
 const sendMsg = (msg: any) => {
@@ -1262,31 +1261,22 @@ const onClose = async (event: any) => {
 	await submitLogFn(event);
 };
 // 重新链接呼叫中心
-let reconnectAttempts = 0; // 重连次数
-let maxReconnectAttempts = 99; // 最大重连次数
-let reconnectInterval = 2; // 重连间隔
 const reconnectTimeout = ref(); // 重连定时器
+// 避免重复连接
+let lockReconnect = false;
 const reConnect = async () => {
-	/*	ElNotification({
-		title: '重连提示',
-		message: `检测到与呼叫中心链接断开,${reconnectInterval}秒后将重新链接`,
-		type: 'warning',
-		duration: reconnectInterval * 1000,
-	});*/
-	console.log('开始重连', `已重连${reconnectAttempts}次,最大重连次数${maxReconnectAttempts}次,重连间隔${reconnectInterval}秒`);
-	if (reconnectAttempts < maxReconnectAttempts) {
-		reconnectTimeout.value = setTimeout(() => {
-			reconnectAttempts++;
-			websocket_connect();
-		}, reconnectInterval * 1000);
-	} else {
-		ElNotification({
-			title: '呼叫中心重连失败',
-			message: '已到达重连次数最高,请手动刷新重连',
-			type: 'warning',
-		});
-		console.error('已到达重连次数最高,请手动刷新重连');
+	console.log(`是否锁定重连: ${lockReconnect}`);
+	if (lockReconnect) {
+		return;
 	}
+	lockReconnect = true;
+	//没连接上会一直重连,设置延迟避免请求过多
+	reconnectTimeout.value && clearTimeout(reconnectTimeout.value);
+	console.log('开始重连');
+	reconnectTimeout.value = setTimeout(() => {
+		websocket_connect();
+		lockReconnect = false;
+	}, 2 * 1000);
 };
 // 链接成功 停止重连
 const stopReconnect = () => {
@@ -2013,11 +2003,18 @@ onMounted(async () => {
 	await signalRStart(); //开启消息监听
 	await resetState(); // 先重置状态
 	await getTelsLists(); // 查询所有分机
-  await getThreeWayAndTransfer(); // 查询转接和三方
+	await getThreeWayAndTransfer(); // 查询转接和三方
 	await callCenterConnect(); // 呼叫中心链接
 	// 加入分组
 	await signalR.joinGroup('CallCenter');
 });
+watch(
+	() => isReconnect.value,
+	(val: boolean) => {
+		console.log(`是否需要重连:${isReconnect.value}`);
+	},
+	{ immediate: true }
+);
 onBeforeUnmount(() => {
 	mittBus.off('RestApplyPass');
 	if (ola.ws) ola.close();

+ 51 - 22
src/views/knowledge/config/type/component/Knowledge-type-add.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="knowledge-type-add-container">
-		<el-dialog title="新增类型" v-model="state.dialogVisible" draggable>
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px">
+		<el-dialog title="新增类型" v-model="state.dialogVisible" draggable append-to-body destroy-on-close @close="close">
+			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px" v-loading="state.loading">
 				<el-row :gutter="10">
 					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
 						<el-form-item label="类型名称" prop="name" :rules="[{ required: true, message: '请填写类型名称', trigger: 'blur' }]">
@@ -24,22 +24,22 @@
 							</el-cascader>
 						</el-form-item>
 					</el-col>
-          <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
-            <el-form-item label="适用部门" prop="parentId" :rules="[{ required: true, message: '请选择适用部门', trigger: 'change' }]">
-              <el-cascader
-                :options="state.treeData"
-                filterable
-                :props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
-                placeholder="请选择适用部门"
-                clearable
-                class="w100"
-                v-model="state.ruleForm.parentId"
-                ref="cascadeRef"
-                @change="getKnowledgeList"
-              >
-              </el-cascader>
-            </el-form-item>
-          </el-col>
+					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+						<el-form-item label="适用部门" prop="orgArray" :rules="[{ required: true, message: '请选择适用部门', trigger: 'change' }]">
+							<el-cascader
+								:options="orgData"
+								filterable
+								:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, multiple: true }"
+								placeholder="请选择适用部门"
+								clearable
+								class="w100"
+								v-model="state.ruleForm.orgArray"
+								ref="orgRef"
+								@change="changeOrgData"
+							>
+							</el-cascader>
+						</el-form-item>
+					</el-col>
 					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
 						<el-form-item label="排序" prop="sort" :rules="[{ required: false, message: '请填写排序', trigger: 'blur' }]">
 							<el-input-number v-model="state.ruleForm.sort" :min="0" :precision="0" class="w100" placeholder="请填写排序" />
@@ -50,7 +50,7 @@
 			<template #footer>
 				<span class="dialog-footer">
 					<el-button @click="closeDialog" class="default-button">取 消</el-button>
-					<el-button type="primary" @click="onSubmit(ruleFormRef)" v-waves="'light'" :loading="state.loading">确 定 </el-button>
+					<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确 定 </el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -61,6 +61,7 @@
 import { reactive, ref } from 'vue';
 import { ElMessage, FormInstance } from 'element-plus';
 import { addType } from '@/api/knowledge/type';
+import { getCanUseOrg } from '@/api/system/user';
 
 // 定义子组件向父组件传值/事件
 const emit = defineEmits(['updateList']);
@@ -70,19 +71,36 @@ const state = reactive<any>({
 	dialogVisible: false, // 弹窗
 	ruleForm: {
 		name: '', // 类型名称
-		sort: 0,  // 排序
+		sort: 0, // 排序
 		parentId: '', // 上级类型
+    orgArray:[]
 	},
 	treeData: [], // 上级
 	loading: false, // 加载
 });
+// 获取机构数据
+const orgData = ref<any[]>([]);
+const getOrgData = async () => {
+	state.loading = true;
+	getCanUseOrg()
+		.then((res: any) => {
+			orgData.value = res?.result ?? [];
+			state.loading = false;
+		})
+		.catch(() => {
+			state.loading = false;
+		});
+};
 // 打开弹窗
 const ruleFormRef = ref<any>(); // 表单ref
-const openDialog = (treeData: any) => {
+const openDialog = (treeData: any[], orgData: any[]) => {
 	state.treeData = treeData ?? [];
+	getOrgData();
+	state.dialogVisible = true;
+};
+const close = () => {
 	ruleFormRef.value?.clearValidate();
 	ruleFormRef.value?.resetFields();
-	state.dialogVisible = true;
 };
 // 关闭弹窗
 const closeDialog = () => {
@@ -94,6 +112,17 @@ const getKnowledgeList = () => {
 	let currentNode = cascadeRef.value.getCheckedNodes();
 	state.ruleForm.parentName = currentNode[0]?.label ?? '';
 };
+// 选择适用部门
+const orgRef = ref<RefType>();
+const changeOrgData = () => {
+	let currentNode = orgRef.value.getCheckedNodes();
+  state.ruleForm.typeOrgDtos = currentNode.map((item: any) => {
+    return {
+      orgId: item.value,
+      orgName: item.label
+    }
+  });
+};
 // 新增
 const onSubmit = async (formEl: FormInstance | undefined) => {
 	if (!formEl) return;

+ 58 - 23
src/views/knowledge/config/type/component/Knowledge-type-edit.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="knowledge-type-edit-container">
-		<el-dialog title="修改类型" v-model="state.dialogVisible" draggable>
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px">
+		<el-dialog title="修改类型" v-model="state.dialogVisible" draggable append-to-body destroy-on-close @close="close">
+			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="80px" v-loading="state.loading">
 				<el-row :gutter="10">
 					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
 						<el-form-item label="类型名称" prop="name" :rules="[{ required: true, message: '请填写类型名称', trigger: 'blur' }]">
@@ -24,22 +24,25 @@
 							</el-cascader>
 						</el-form-item>
 					</el-col>
-          <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
-            <el-form-item label="适用部门" prop="parentId" :rules="[{ required: true, message: '请选择适用部门', trigger: 'change' }]">
-              <el-cascader
-                :options="state.treeData"
-                filterable
-                :props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
-                placeholder="请选择适用部门"
-                clearable
-                class="w100"
-                v-model="state.ruleForm.parentId"
-                ref="cascadeRef"
-                @change="getKnowledgeList"
-              >
-              </el-cascader>
-            </el-form-item>
-          </el-col>
+					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
+						<el-form-item label="适用部门" prop="orgArray" :rules="[{ required: true, message: '请选择适用部门', trigger: 'change' }]">
+							<el-cascader
+								:options="orgData"
+								filterable
+								:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, multiple: true }"
+								placeholder="请选择适用部门"
+								clearable
+								class="w100"
+								v-model="state.ruleForm.orgArray"
+								ref="orgRef"
+								@change="changeOrgData"
+								collapse-tags
+								collapse-tags-tooltip
+								:max-collapse-tags="3"
+							>
+							</el-cascader>
+						</el-form-item>
+					</el-col>
 					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
 						<el-form-item label="排序" prop="sort" :rules="[{ required: false, message: '请填写排序', trigger: 'blur' }]">
 							<el-input-number v-model="state.ruleForm.sort" :min="0" :precision="0" class="w100" placeholder="请填写排序" />
@@ -50,7 +53,7 @@
 			<template #footer>
 				<span class="dialog-footer">
 					<el-button @click="closeDialog" class="default-button">取 消</el-button>
-					<el-button type="primary" @click="onSubmit(ruleFormRef)" v-waves="'light'" :loading="state.loading">确 定 </el-button>
+					<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确 定 </el-button>
 				</span>
 			</template>
 		</el-dialog>
@@ -63,6 +66,7 @@ import { ElMessage, FormInstance } from 'element-plus';
 import { excludeSelfById } from '@/utils/tools';
 import other from '@/utils/other';
 import { updateType, typeDetail } from '@/api/knowledge/type';
+import { getCanUseOrg } from '@/api/system/user';
 
 // 定义子组件向父组件传值/事件
 const emit = defineEmits(['updateList']);
@@ -72,26 +76,46 @@ const state = reactive<any>({
 	dialogVisible: false, // 弹窗
 	ruleForm: {
 		name: '', // 类型名称
-		sort: 0,  // 排序
+		sort: 0, // 排序
 		parentId: '', // 上级类型
+		orgArray: [],
 	},
 	treeData: [], // 上级
 	loading: false, // 加载
 });
+// 获取机构数据
+const orgData = ref<any[]>([]);
+const getOrgData = async () => {
+	state.loading = true;
+	getCanUseOrg()
+		.then((res: any) => {
+			orgData.value = res?.result ?? [];
+			state.loading = false;
+		})
+		.catch(() => {
+			state.loading = false;
+		});
+};
 // 打开弹窗
 const ruleFormRef = ref<any>(); // 表单ref
 const openDialog = async (row: any, treeData: any) => {
 	try {
-		const res: any = await typeDetail(row.id);
-		state.ruleForm = res.result;
+		await getOrgData();
+		const { result } = await typeDetail(row.id);
+		state.ruleForm = result;
 		state.treeData = other.deepClone(treeData);
 		state.treeData = excludeSelfById(state.treeData, row.id);
+		state.ruleForm.orgArray = result.knowledgeTypeOrgs.map((item: any) => item.orgId);
 		state.dialogVisible = true;
 	} catch (error) {
 		// 打印错误信息
 		console.error(error);
 	}
 };
+const close = () => {
+	ruleFormRef.value?.clearValidate();
+	ruleFormRef.value?.resetFields();
+};
 // 关闭弹窗
 const closeDialog = () => {
 	state.dialogVisible = false;
@@ -102,7 +126,18 @@ const getKnowledgeList = () => {
 	let currentNode = cascadeRef.value.getCheckedNodes();
 	state.ruleForm.parentName = currentNode[0]?.label ?? '';
 };
-// 新增
+// 选择适用部门
+const orgRef = ref<RefType>();
+const changeOrgData = () => {
+	let currentNode = orgRef.value.getCheckedNodes();
+	state.ruleForm.typeOrgDtos = currentNode.map((item: any) => {
+		return {
+			orgId: item.value,
+			orgName: item.label,
+		};
+	});
+};
+// 保存
 const onSubmit = async (formEl: FormInstance | undefined) => {
 	if (!formEl) return;
 	await formEl.validate((valid: boolean) => {

+ 10 - 0
src/views/knowledge/config/type/index.vue

@@ -62,6 +62,7 @@ import { formatDate } from '@/utils/formatTime';
 import { delType, treeList } from '@/api/knowledge/type';
 import { throttle } from '@/utils/tools';
 import other from '@/utils/other';
+import { getCanUseOrg } from "@/api/system/user";
 // 引入组件
 const KnowledgeTypeAdd = defineAsyncComponent(() => import('@/views/knowledge/config/type/component/Knowledge-type-add.vue')); // 新增组件
 const KnowledgeTypeEdit = defineAsyncComponent(() => import('@/views/knowledge/config/type/component/Knowledge-type-edit.vue')); // 修改组件
@@ -89,6 +90,15 @@ const state = reactive<any>({
         return <TextTooltip content={data.rowData.name} effect="dark" placement="top"></TextTooltip>;
       },
 		},
+    {
+      key: 'name',
+      dataKey: 'name',
+      title: '所属部门',
+      width: 300,
+      cellRenderer: (data: any) => {
+        return <TextTooltip content={data.rowData.name} effect="dark" placement="top"></TextTooltip>;
+      },
+    },
 		{
 			key: 'sort',
 			dataKey: 'sort',