浏览代码

reactor:知识库调整对接;

zhangchong 1 年之前
父节点
当前提交
5b0a42c445
共有 57 个文件被更改,包括 3151 次插入4312 次删除
  1. 1 1
      .env.development
  2. 1 1
      .env.production
  3. 1 1
      .env.test
  4. 0 124
      src/api/knowledge/apply.ts
  5. 76 0
      src/api/knowledge/error.ts
  6. 15 71
      src/api/knowledge/index.ts
  7. 76 0
      src/api/knowledge/question.ts
  8. 20 0
      src/api/public/system.ts
  9. 47 19
      src/api/public/wex.ts
  10. 52 0
      src/components/ProcessAudit/index.vue
  11. 4 0
      src/layout/navBars/breadcrumb/index.vue
  12. 427 258
      src/layout/navBars/breadcrumb/telControl.vue
  13. 22 17
      src/layout/navBars/breadcrumb/user.vue
  14. 10 23
      src/router/backEnd.ts
  15. 4 6
      src/stores/appConfig.ts
  16. 5 3
      src/types/pinia.d.ts
  17. 13 3
      src/utils/ola_api.ts
  18. 199 193
      src/views/auxiliary/area/index.vue
  19. 0 1
      src/views/auxiliary/notice/component/Notice-edit.vue
  20. 2 2
      src/views/business/followUp/component/Follow-up-detail.vue
  21. 2 2
      src/views/business/order/components/Order-detail.vue
  22. 0 131
      src/views/knowledge/apply/component/Knowledge-apply-detail.vue
  23. 0 208
      src/views/knowledge/apply/component/Knowledge-apply-handle.vue
  24. 0 244
      src/views/knowledge/apply/index.vue
  25. 0 167
      src/views/knowledge/apply/my/component/Knowledge-my-apply-add.vue
  26. 0 131
      src/views/knowledge/apply/my/component/Knowledge-my-apply-detail.vue
  27. 0 167
      src/views/knowledge/apply/my/component/Knowledge-my-apply-edit.vue
  28. 0 286
      src/views/knowledge/apply/my/index.vue
  29. 11 18
      src/views/knowledge/component/Knowledge-standard-info.vue
  30. 2 7
      src/views/knowledge/config/standard/index.vue
  31. 22 17
      src/views/knowledge/config/type/index.vue
  32. 169 0
      src/views/knowledge/error/components/Error-add.vue
  33. 174 0
      src/views/knowledge/error/index.vue
  34. 388 0
      src/views/knowledge/index/edit.vue
  35. 502 0
      src/views/knowledge/index/index.vue
  36. 105 0
      src/views/knowledge/index/preview.vue
  37. 0 121
      src/views/knowledge/knowledge/component/Knowledge-update.vue
  38. 0 348
      src/views/knowledge/knowledge/component/knowledge-edit.vue
  39. 0 231
      src/views/knowledge/knowledge/delApply/index.vue
  40. 0 181
      src/views/knowledge/knowledge/draft/index.vue
  41. 0 631
      src/views/knowledge/knowledge/index.vue
  42. 0 213
      src/views/knowledge/process/index.vue
  43. 168 0
      src/views/knowledge/question/components/Question-add.vue
  44. 152 0
      src/views/knowledge/question/index.vue
  45. 346 84
      src/views/knowledge/retrieval/index.vue
  46. 2 4
      src/views/quality/index/components/Order-detail.vue
  47. 8 7
      src/views/system/config/dict/index.vue
  48. 1 1
      src/views/system/config/workflow/component/Workflow-config.vue
  49. 26 24
      src/views/system/menu/index.vue
  50. 25 23
      src/views/system/organize/index.vue
  51. 2 2
      src/views/system/parameter/component/Parameter-edit.vue
  52. 7 6
      src/views/system/user/component/User-add.vue
  53. 7 6
      src/views/system/user/component/User-edit.vue
  54. 18 37
      src/views/tels/blacklist/component/Blacklist-add.vue
  55. 39 53
      src/views/tels/blacklist/index.vue
  56. 0 93
      src/views/tels/whitelist/component/Whitelist-add.vue
  57. 0 146
      src/views/tels/whitelist/index.vue

+ 1 - 1
.env.development

@@ -26,5 +26,5 @@ VITE_AMAP_SECURITYJSCODE=dd12ddafb11921dbcdc5b9c4484bb4e2
 VITE_AMAP_KEY=83f51df235e4008e4eaf515cff63785c
 
 # # 呼叫中心socket地址
-VITE_CALLCENTER_SOCKET_URL=ws://192.168.169.105:29003/ola_socket
+VITE_CALLCENTER_SOCKET_URL=ws://222.213.23.229:29003/ola_socket
 

+ 1 - 1
.env.production

@@ -26,4 +26,4 @@ VITE_AMAP_SECURITYJSCODE=dd12ddafb11921dbcdc5b9c4484bb4e2
 VITE_AMAP_KEY=83f51df235e4008e4eaf515cff63785c
 
 # # 呼叫中心socket地址
-VITE_CALLCENTER_SOCKET_URL=internal.ttf-cti.com:8080/ola_socket
+VITE_CALLCENTER_SOCKET_URL=ws://222.213.23.229:29003/ola_socket

+ 1 - 1
.env.test

@@ -25,4 +25,4 @@ VITE_AMAP_SECURITYJSCODE=dd12ddafb11921dbcdc5b9c4484bb4e2
 VITE_AMAP_KEY=83f51df235e4008e4eaf515cff63785c
 
 # # 呼叫中心socket地址
-VITE_CALLCENTER_SOCKET_URL=internal.ttf-cti.com:8080
+VITE_CALLCENTER_SOCKET_URL=ws://222.213.23.229:29003/ola_socket

+ 0 - 124
src/api/knowledge/apply.ts

@@ -1,124 +0,0 @@
-/*
- * @Author: zc
- * @description 知识管理 申请管理
- * @version:
- * @Date: 2022-08-09 16:19:55
- * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-11-15 10:21:44
- */
-import request from '/@/utils/request';
-/**
- * @description 知识申请列表 基础数据
- * @return {*}
- */
-export const baseData = () => {
-	return request({
-		url: '/api/v1/KnowledgeApply/apply-base-data',
-		method: 'get'
-	});
-};
-/**
- * @description 知识申请处理列表
- * @param {object} params
- * @return {*}
- */
-export const handleList = (params:object) => {
-	return request({
-		url: '/api/v1/KnowledgeApply/handlelist',
-		method: 'get',
-        params
-	});
-};
-/**
- * @description 我的知识申请列表
- * @param {object} params
- * @return {*}
- */
-export const KnowledgeApply = (params:object) => {
-	return request({
-		url: '/api/v1/KnowledgeApply',
-		method: 'get',
-        params
-	});
-};
-/**
- * @description 发起申请
- * @param {object} data
- * @return {*}
- */
-export const KnowledgeApplyAdd = (data:object) => {
-	return request({
-		url: '/api/v1/KnowledgeApply/add',
-		method: 'post',
-        data
-	});
-};
-/**
- * @description 修改申请
- * @param {object} data
- * @return {*}
- */
-export const KnowledgeApplyUpdate = (data:object) => {
-	return request({
-		url: '/api/v1/KnowledgeApply/update',
-		method: 'put',
-        data
-	});
-};
-/**
- * @description 查询申请详情
- * @param {string} Id
- * @return {*}
- */
-export const KnowledgeApplyDetail = (Id:string) => {
-	return request({
-		url: `/api/v1/KnowledgeApply/info/${Id}`,
-		method: 'get',
-	});
-};
-/**
- * @description 知识申请-信息办理
- * @param {object} data
- * @return {*}
- */
-export const KnowledgeHandle = (data:object) => {
-	return request({
-		url: `/api/v1/KnowledgeApply/handle`,
-		method: 'put',
-		data
-	});
-};
-/**
- * @description 我的知识申请- 撤销操作 撤销申请
- * @param {string} Id
- * @return {*}
- */
-export const KnowledgeCancel= (Id:string) => {
-	return request({
-		url: `/api/v1/KnowledgeApply/apply-handle/${Id}`,
-		method: 'put'
-	});
-};
-/**
- * @description 知识申请- 退回操作
- * @return {*}
- * @param data
- */
-export const KnowledgeReturn= (data:object) => {
-	return request({
-		url: `/api/v1/KnowledgeApply/return`,
-		method: 'put',
-		data
-	});
-};
-/**
- * @description 删除申请
- * @return {*}
- * @param {string} id
- */
-export const KnowledgeRemove= (id:string) => {
-	return request({
-		url: `/api/v1/KnowledgeApply/remove?Id=${id}`,
-		method: 'Delete'
-	});
-};

+ 76 - 0
src/api/knowledge/error.ts

@@ -0,0 +1,76 @@
+/*
+ * @Author: zc
+ * @description 知识库-知识纠错
+ */
+import request from '/@/utils/request';
+/**
+ * @description 纠错列表
+ * @param {object} params
+ * @return {*}
+ */
+export const correctionList = (params: object) => {
+	return request({
+		url: '/api/v1/Knowledge/knowledge_correction/list',
+		method: 'get',
+		params,
+	});
+};
+/**
+ * @description 纠错新增
+ * @param {object} data
+ * @return {*}
+ */
+export const correctionAdd = (data: object) => {
+	return request({
+		url: '/api/v1/Knowledge/knowledge_correction',
+		method: 'post',
+		data,
+	});
+};
+/**
+ * @description 纠错修改
+ * @param {object} data
+ * @return {*}
+ */
+export const correctionUpdate = (data: object) => {
+	return request({
+		url: '/api/v1/Knowledge/knowledge_correction',
+		method: 'put',
+		data,
+	});
+};
+/**
+ * @description 纠错删除
+ * @param {object} data
+ * @return {*}
+ */
+export const correctionDelete = (data: object) => {
+	return request({
+		url: '/api/v1/Knowledge/knowledge_correction',
+		method: 'delete',
+		data,
+	});
+};
+/**
+ * @description 纠错回复
+ * @param {object} data
+ * @return {*}
+ */
+export const correctionReply = (data: object) => {
+	return request({
+		url: '/api/v1/Knowledge/knowledge_correction/Reply',
+		method: 'put',
+		data,
+	});
+};
+/**
+ * @description 纠错详情
+ * @param {object} id
+ * @return {*}
+ */
+export const correctionDetail = (id: string | string[]) => {
+	return request({
+		url: `/api/v1/Knowledge/knowledge_correction/${id}`,
+		method: 'get',
+	});
+};

+ 15 - 71
src/api/knowledge/index.ts

@@ -51,18 +51,6 @@ export const KnowledgePaged = (params: object) => {
 		params
 	});
 };
-/**
- * @description 我的草稿箱
-  @param {object} params
- * @return {*}
- */
-  export const myDraftsList = (params: object) => {
-	return request({
-		url: '/api/v1/Knowledge/mydraftslist',
-		method: 'get',
-        params
-	});
-};
 /**
  * @description 知识库新增
  * @param {object} data
@@ -88,25 +76,15 @@ export const KnowledgeUpdate = (data: object) => {
 	});
 };
 /**
- * @description 知识库删除(草稿状态删除)
- * @param {string} id
+ * @description 知识库删除
+ * @param {object} data
  * @return {*}
  */
-export const KnowledgeDel = (id: string) => {
+export const KnowledgeDel = (data: object) => {
 	return request({
-		url: `/api/v1/Knowledge/${id}`,
+		url: `/api/v1/Knowledge`,
 		method: 'delete',
-	});
-};
-/**
- * @description 知识库详情
- * @param {string} Id
- * @return {*}
- */
-export const KnowledgeDetail = (Id: string | string[]) => {
-	return request({
-		url: `/api/v1/Knowledge/updateinfo/${Id}`,
-		method: 'get',
+		data
 	});
 };
 /**
@@ -156,50 +134,6 @@ export const KnowledgeGetKnowledge = (params?: object) => {
 		params
 	});
 };
-/**
- * @description  我的知识删除列表 基础数据
- * @return {*}
- */
-export const deleteBase = () => {
-	return request({
-		url: `/api/v1/Knowledge/delete-status-data`,
-		method: 'get'
-	});
-};
-/**
- * @description  我的知识删除列表
- * @param {object} params
- * @return {*}
- */
-export const KnowledgeDeleteList = (params: object) => {
-	return request({
-		url: `/api/v1/Knowledge/deletelist`,
-		method: 'get',
-		params
-	});
-};
-/**
- * @description  审核管理列表 基础数据
- * @return {*}
- */
-export const approvedBaseData = () => {
-	return request({
-		url: `/api/v1/Knowledge/approval-base-data`,
-		method: 'get'
-	});
-};
-/**
- * @description  审核管理列表
- * @param {object} params
- * @return {*}
- */
-export const KnowledgeApprovedList = (params: object) => {
-	return request({
-		url: `/api/v1/Knowledge/approvedlist`,
-		method: 'get',
-		params
-	});
-};
 /**
  * @description  新增-开始流程
  * @param {string} id
@@ -236,6 +170,16 @@ export const KnowledgeAddStartFlowParams = () => {
 		method: 'get'
 	});
 };
+/**
+ * @description  查询知识库办理流程开启参数-更新
+ * @return {*}
+ */
+export const KnowledgeUpdateStartFlowParams = () => {
+	return request({
+		url: `/api/v1/Knowledge/update-flow-start`,
+		method: 'get'
+	});
+};
 /**
  * @description  查询知识库办理流程开启参数-删除
  * @return {*}

+ 76 - 0
src/api/knowledge/question.ts

@@ -0,0 +1,76 @@
+/*
+ * @Author: zc
+ * @description 知识库-知识提问
+ */
+import request from '/@/utils/request';
+/**
+ * @description 提问列表
+ * @param {object} params
+ * @return {*}
+ */
+export const questionList = (params: object) => {
+    return request({
+        url: '/api/v1/Knowledge/knowledge_questions/list',
+        method: 'get',
+        params,
+    });
+};
+/**
+ * @description 提问新增
+ * @param {object} data
+ * @return {*}
+ */
+export const questionAdd = (data: object) => {
+    return request({
+        url: '/api/v1/Knowledge/knowledge_questions',
+        method: 'post',
+        data,
+    });
+};
+/**
+ * @description 提问修改
+ * @param {object} data
+ * @return {*}
+ */
+export const questionUpdate = (data: object) => {
+    return request({
+        url: '/api/v1/Knowledge/knowledge_questions',
+        method: 'put',
+        data,
+    });
+};
+/**
+ * @description 提问删除
+ * @param {object} data
+ * @return {*}
+ */
+export const questionDelete = (data: object) => {
+    return request({
+        url: '/api/v1/Knowledge/knowledge_questions',
+        method: 'delete',
+        data,
+    });
+};
+/**
+ * @description 提问回复
+ * @param {object} data
+ * @return {*}
+ */
+export const questionReply = (data: object) => {
+    return request({
+        url: '/api/v1/Knowledge/knowledge_questions/Reply',
+        method: 'put',
+        data,
+    });
+};
+/**
+ * @description 提问详情
+ * @param {object} id
+ * @return {*}
+ */
+export const questionDetail = (id: string | string[]) => {
+    return request({
+        url: `/api/v1/Knowledge/knowledge_questions/${id}`,
+        method: 'get',
+    });
+};

+ 20 - 0
src/api/public/system.ts

@@ -0,0 +1,20 @@
+/*
+ * @Author: zc
+ * @description 系统配置
+ * @version:
+ * @Date: 2022-08-09 16:19:55
+ * @LastEditors: Please set LastEditors
+ * @LastEditTime: 2022-11-16 14:49:01
+ */
+import request from '/@/utils/request';
+/**
+ * @description 查询系统配置
+ * @param {object}  params
+ */
+export const appConfigInfo = (params?: object) => {
+    return request({
+        url: `/api/v1/Home/home-page-info`,
+        method: 'get',
+        params,
+    });
+};

+ 47 - 19
src/api/public/wex.ts

@@ -9,7 +9,7 @@
 import request from '/@/utils/request';
 import qs from "qs";
 /**
- * @description  分机小休原
+ * @description  分机小休原
  */
 export const telRestBaseData = () => {
     return request({
@@ -79,41 +79,69 @@ export const telUnrestWex = () => {
 };
 /*------------------------------呼叫中心--------------------------------------------- */
 /**
- * @description 呼叫中心登录
- * @param data
+ * @description 查询呼叫中心分机列表
+ * @param params
  */
-export const callCenterLogin = (data:object) => {
+export const getTelList = (params?:object) => {
     return request({
-        url: `/login/token`,
-        method: 'post',
-        baseURL:import.meta.env.VITE_CALLCENTER_API_URL,
-        data
+        url: `/api/v1/IPPbx/query-tels`,
+        method: 'get',
+        params,
     });
 }
 /**
- * @description 查询呼叫中心分机列表
+ * @description 查询呼叫中心黑白名单列表
  * @param params
  */
-export const getTelList = (params?:object) => {
+export const queryBlacklist = (params?:object) => {
     return request({
-        url: `/api/ola/dicts/detail`,
+        url: `/api/v1/IPPbx/query-blacklist`,
         method: 'get',
-        baseURL:import.meta.env.VITE_CALLCENTER_API_URL,
         params,
-        headers:{
-            'content-type': 'application/x-www-form-urlencoded'
-        },
     });
 }
+
 /**
- * @description 查询威而信通话记录分页
+ * @description 新增呼叫中心黑白名单
  * @param {object} data
  */
-export const callLogPaged = (data:object) => {
+export const addBlacklist = (data:object) => {
     return request({
-        url: `/api/record/list_page`,
+        url: `/api/v1/IPPbx/add-blacklist`,
+        method: 'post',
+        data
+    });
+}
+/**
+ * @description 删除呼叫中心黑白名单
+ * @param {object} data
+ */
+export const removeBlacklist = (data:object) => {
+    return request({
+        url: `/api/v1/IPPbx/remove-blacklist`,
+        method: 'post',
+        data
+    });
+}
+/**
+ * @description 呼叫中心签入
+ * @param {object} data
+ */
+export const dutyOn = (data?:object) => {
+    return request({
+        url: `/api/v1/IPPbx/on-duty`,
+        method: 'post',
+        data
+    });
+}
+/**
+ * @description 呼叫中心签出
+ * @param {object} data
+ */
+export const dutyOff = (data?:object) => {
+    return request({
+        url: `/api/v1/IPPbx/off-duty`,
         method: 'post',
-        baseURL:import.meta.env.VITE_WEX_API_URL,
         data
     });
 }

+ 52 - 0
src/components/ProcessAudit/index.vue

@@ -528,6 +528,7 @@ import {discernApply, screenBaseData, workflowDiscernParams} from '/@/api/busine
 import {debounce} from '/@/utils/tools';
 import {bulletinAdd, bulletinAddBaseData, circularAdd, circularAddBaseData, getAllUsers, workflowBulletinParams, workflowCircularParams} from '/@/api/auxiliary/notice';
 import {getCanUseOrg} from '/@/api/system/user';
+import {KnowledgeAdd, KnowledgeAddStartFlowParams, KnowledgeDeleteStartFlowParams, KnowledgeDel, KnowledgeUpdate, KnowledgeUpdateStartFlowParams} from "/@/api/knowledge";
 
 // 引入组件
 const CommonAdvice = defineAsyncComponent(() => import('/@/components/CommonAdvice/index.vue')); // 常用意见
@@ -715,6 +716,18 @@ const openDialog = async (val: any) => {
 			orgsOptions.value = responseAnnounce.result?.orgsOptions ?? [];
 			handleResult(workflowBulletinResponse);
 			break;
+    case '新增知识':
+      const [KnowledgeAddStartFlowResponse] = await Promise.all([KnowledgeAddStartFlowParams()]); // 知识库新增参数
+      handleResult(KnowledgeAddStartFlowResponse);
+      break;
+    case '更新知识':
+      const [KnowledgeUpdateResponse] = await Promise.all([KnowledgeUpdateStartFlowParams()]); // 知识库更新参数
+      handleResult(KnowledgeUpdateResponse);
+      break;
+    case '删除知识':
+      const [KnowledgeDeleteResponse] = await Promise.all([KnowledgeDeleteStartFlowParams()]); // 知识库删除参数
+      handleResult(KnowledgeDeleteResponse);
+      break;
 		default: // 默认下一流程 工单办理
 		// 获取下一节点和下一节点参数
 			const [nextResponse] = await Promise.all([workflowNextSteps(state.workflowId)]);
@@ -1083,6 +1096,45 @@ const onSubmit = (formEl: FormInstance | undefined) => {
 								afterSubmit('orderProcessFailed');
 							});
 						break;
+          case '新增知识':
+            const KnowledgeAddRequest = {
+              data: { ...state.orderDetail },
+              workflow: submitObj,
+            };
+            KnowledgeAdd(KnowledgeAddRequest)
+                .then(() => {
+                  afterSubmit('orderProcessSuccess', true);
+                })
+                .catch(() => {
+                  afterSubmit('orderProcessFailed');
+                });
+            break;
+          case '更新知识':
+            const KnowledgeUpdateRequest = {
+              data: { ...state.orderDetail },
+              workflow: submitObj,
+            };
+            KnowledgeUpdate(KnowledgeUpdateRequest)
+                .then(() => {
+                  afterSubmit('orderProcessSuccess', true);
+                })
+                .catch(() => {
+                  afterSubmit('orderProcessFailed');
+                });
+            break;
+          case '删除知识':
+            const KnowledgeRemoveRequest = {
+              data: { ...state.orderDetail },
+              workflow: submitObj,
+            };
+            KnowledgeDel(KnowledgeRemoveRequest)
+                .then(() => {
+                  afterSubmit('orderProcessSuccess', true);
+                })
+                .catch(() => {
+                  afterSubmit('orderProcessFailed');
+                });
+            break;
 					default: // 默认工单办理
 						workflowNext(submitObj)
 							.then(() => {

+ 4 - 0
src/layout/navBars/breadcrumb/index.vue

@@ -108,6 +108,10 @@ onMounted(() => {
 	});
   // 加入分组
   signalR.joinGroup('CallCenter');
+  signalR.SR.on('Send', (data: any) => {
+    // 加入分组成功
+    console.log(data, '加入分组成功');
+  });
 });
 // 页面卸载时
 onUnmounted(() => {

+ 427 - 258
src/layout/navBars/breadcrumb/telControl.vue

@@ -10,7 +10,7 @@
 			</div>
 		</div>
 		<div class="btn">
-			<!-- 签 -->
+			<!-- 签 -->
 			<template v-if="telStatusInfo.isDutyOn">
 				<!-- 签出可用 -->
 				<div
@@ -127,24 +127,24 @@
 				</div>
 			</template>
 
-			<!-- 事后处理和取消事后处理 可用-->
+			<!-- 话后整理和取消话后整理中 可用-->
 			<template v-if="telStatusInfo.isDutyOn && activeArr.includes('TalkingDeal')">
 				<div
 					class="item active"
 					@click="onControlClick(telStatusInfo.isTalkingDeal ? 'unTalkingDeal' : 'TalkingDeal')"
 					@mouseenter="onHover('talkingDealSrc', 'phoneControls/talkingDeal_white.png')"
-					:title="telStatusInfo.isTalkingDeal ? '取消事后处理' : '事后处理'"
+					:title="telStatusInfo.isTalkingDeal ? '取消话后整理' : '话后整理'"
 					@mouseleave="onHover('talkingDealSrc', 'phoneControls/talkingDeal_blue.png')"
 				>
 					<img :src="state.talkingDealSrc" alt="" />
-					<span>{{ telStatusInfo.isTalkingDeal ? '取消事后处理' : '事后处理' }}</span>
+					<span>{{ telStatusInfo.isTalkingDeal ? '取消话后整理' : '话后整理' }}</span>
 				</div>
 			</template>
-			<!-- 事后处理不可用 -->
+			<!-- 话后整理中不可用 -->
 			<template v-else>
-				<div class="item disabled" title="事后处理">
+				<div class="item disabled" title="话后整理">
 					<img :src="getImageUrl('phoneControls/talkingDeal_grey.png')" alt="" />
-					<span>事后处理</span>
+					<span>话后整理</span>
 				</div>
 			</template>
 
@@ -169,7 +169,7 @@
 				</div>
 			</template>
 
-			<!-- 三方会议 可用(两个通话 一个取消保持 一个保持 才能使用三方通话) -->
+			<!-- 三方会议 可用(当前处于通话中)-->
 			<template v-if="telStatusInfo.isDutyOn && activeArr.includes('conference')">
 				<div
 					class="item active"
@@ -182,6 +182,34 @@
 					<span>三方会议</span>
 				</div>
 			</template>
+      <!-- 三方会议并且处于三方会议中  -->
+      <template v-else-if="telStatusInfo.isDutyOn && activeArr.includes('conference') && onCallArr.length === 2">
+        <el-popover
+            :width="130 * onCallArr.length"
+            :offset="0"
+            v-model:visible="threeWayVisible"
+            trigger="hover"
+            popper-class="hangup-popover"
+        >
+          <template #reference>
+            <div
+                class="item active"
+                @mouseenter="onHover('conferenceSrc', 'phoneControls/conference_white.png')"
+                title="三方会议"
+                @mouseleave="onHover('conferenceSrc', 'phoneControls/conference_blue.png')"
+            >
+              <img :src="state.holdSrc" alt="" />
+              <span>三方会议({{ onCallArr.length }})</span>
+            </div>
+          </template>
+          <div class="hangup-container">
+            <div class="hangup-item" v-for="(item, index) in onCallArr" :key="index">
+              <p class="hangup-item-phoneNumber">{{ item.number }}</p>
+              <el-button size="small" @click="kickOut(item)" class="default-button">踢出</el-button>
+            </div>
+          </div>
+        </el-popover>
+      </template>
 			<!-- 三方会议 不可用 -->
 			<template v-else>
 				<div class="item disabled" title="三方会议">
@@ -218,9 +246,13 @@
 	<!-- 签入弹窗 -->
 	<el-dialog v-model="state.dutyDialogVisible" draggable title="签入" width="500px" :show-close="false">
 		<el-form :model="state.dutyForm" label-width="80px" ref="dutyFormRef">
-			<el-form-item label="分机" prop="telNo" :rules="[{ required: true, message: '请选择需要签入的分机', trigger: 'change' }]">
+			<el-form-item label="分机" prop="telNo" :rules="[{ required: true, message: '请选择需要签入的分机', trigger: 'change' }]" v-if="AppConfigInfo.isNeedTelNo">
 				<el-select-v2 v-model="state.dutyForm.telNo" :options="state.telsList" placeholder="选择要签入的分机" filterable class="w100" />
 			</el-form-item>
+      <!-- 是否需要输入分机密码 -->
+      <el-form-item label="分机密码" prop="password" :rules="[{ required: true, message: '请输入分机密码', trigger: 'blur' }]" v-if="AppConfigInfo.isTelNeedVerify">
+        <el-input v-model="state.dutyForm.password" placeholder="请输入分机密码"/>
+      </el-form-item>
 		</el-form>
 		<template #footer>
 			<span class="dialog-footer">
@@ -236,13 +268,13 @@
 		ref="dialogRestRef"
 		draggable
 		title="小休申请"
-		:width="AppConfigInfo.IsRestApproval ? '60%' : '500px'"
+		:width="AppConfigInfo.isRestApproval ? '60%' : '500px'"
 		@mouseup="mouseup"
 		:style="'transform: ' + state.transform + ';'"
 		@opend="restFormOpened"
 	>
 		<!-- 需要审核 -->
-		<template v-if="AppConfigInfo.IsRestApproval">
+		<template v-if="AppConfigInfo.isRestApproval">
 			<el-form :model="state.restForm" label-width="100px" ref="restFormRef">
 				<el-row :gutter="10">
 					<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
@@ -390,7 +422,27 @@
 	</el-dialog>
 
   <!-- 三方通话弹窗 -->
-
+  <el-dialog v-model="state.threeWayDialogVisible" draggable title="三方会议" width="450px">
+    <el-form :model="state.threeWayForm" label-width="120px" ref="threeWayFormRef">
+      <el-form-item label="三方通话号码" prop="telNo" :rules="[{ required: true, message: '请选择或输入三方通话号码', trigger: 'blur' }]">
+        <el-select-v2
+            v-model="state.threeWayForm.telNo"
+            :options="state.telsList"
+            placeholder="请选择或输入三方通话号码"
+            filterable
+            class="w100"
+            allow-create
+            default-first-option
+        />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+			<span class="dialog-footer">
+				<el-button @click="state.threeWayDialogVisible = false" class="default-button" :loading="state.loading">取 消</el-button>
+				<el-button type="primary" @click="clickOnThreeWay(threeWayFormRef)" :loading="state.loading">确 定</el-button>
+			</span>
+    </template>
+  </el-dialog>
 </template>
 
 <script setup lang="ts" name="telControl">
@@ -405,13 +457,11 @@ import { formatDuration } from '/@/utils/formatTime';
 import { commonEnum } from '/@/utils/constants';
 import other from '/@/utils/other';
 import { workflowStepOptions } from '/@/api/system/workflow';
-import { restFlowStart, restFlowDel, restFlowStartWex, getTelList, telRestProcess, telRestAdd, telRestBaseData } from '/@/api/public/wex';
+import {restFlowStart, restFlowDel, restFlowStartWex, getTelList, telRestProcess, telRestAdd, telRestBaseData, dutyOff, dutyOn} from '/@/api/public/wex';
 import { auth } from '/@/utils/authFunction';
-import { VoiceInterfaceObject } from '/@/utils/PhoneScript';
 import signalR from '/@/utils/signalR';
 import { Local } from '/@/utils/storage';
 import { ola } from '/@/utils/ola_api';
-
 // 引入组件
 const CommonAdvice = defineAsyncComponent(() => import('/@/components/CommonAdvice/index.vue')); // 常用意见
 const AnnexList = defineAsyncComponent(() => import('/@/components/AnnexList/index.vue'));
@@ -466,13 +516,11 @@ const state = reactive<any>({
 	handleId: '', // 流程处理ID
 	transform: 'translate(0px, 0px)',
 	fileList: [], // 文件上传列表
-	metingDialogVisible: false, // 三方会议弹窗
-	metingForm: {
+  threeWayDialogVisible: false, // 三方会议弹窗
+  threeWayForm: {
 		// 三方会议表单
-		metingId: '', // 三方会议ID
-		phoneNo: '', // 三方会议号码
+    telNo: null, // 三方会议号码
 	},
-	groupName: '', //坐席组名称
 });
 
 const useTelStatusStore = useTelStatus();
@@ -509,10 +557,6 @@ const removeTimer = () => {
 };
 // 监听消息
 const signalRStart = () => {
-	signalR.SR.on('Send', (data: any) => {
-		// 加入分组成功
-		console.log(data, '加入分组成功');
-	});
 	signalR.SR.on('RestApplyPass', (data: any) => {
 		// 小休审批通过消息
 		console.log(data, '小休审批通过消息');
@@ -529,7 +573,7 @@ const activeArr = computed(() => {
 		ring: ['hangup'], //振铃中
 		onCall: ['hangup', 'hold', 'transfer', 'evaluate','conference'], // 单个通话中
 		onHold: ['hangup', 'hold', 'transfer', 'evaluate'], // 保持中
-		onTalkingDeal: ['dutyOff', 'rest', 'outbound', 'callForwarding', 'TalkingDeal'], // 事后处理中
+		onTalkingDeal: ['dutyOff', 'rest', 'outbound', 'callForwarding', 'TalkingDeal'], // 话后整理中
 		onTransferSuccess: ['hangup', 'conference'], // 转接成功
 		onConference: ['hangup'], // 三方会议中 只能挂断
 	};
@@ -548,7 +592,7 @@ const currentStatusText = computed(() => {
 		ring: '振铃中',
 		onHold: '保持中',
 		onCall: '通话中',
-		onTalkingDeal: '事后处理',
+		onTalkingDeal: '整理中',
 		onConference: '会议中',
 		onTransferSuccess: '转接成功',
 	};
@@ -561,21 +605,23 @@ const RestApplyPassFn = (data: any) => {
 		message: '小休审批通过,开始小休',
 		type: 'success',
 	});
-	VoiceInterfaceObject.SetBusy(data); //设置忙碌
+  //不需要审核直接开始小休
+  ola.go_break(state.restForm.reason); //设置忙碌
 };
 // 查询所有分机
-const getTelsLists = async (object?: object) => {
+const getTelsLists = async () => {
 	state.loading = true;
 	try {
-		const res: any = await getTelList(object);
-		state.telsList = res?.data ?? [];
+		const res: any = await getTelList();
+		state.telsList = res?.result ?? [];
 		state.telsList = state.telsList.map((item: any) => ({
-			value: item.device,
-			label: item.device,
+			value: item.telNo,
+			label: item.telNo,
+      queue: item.description === '默认' ? '10010' : item.description,
 			...item,
 		}));
 		state.loading = false;
-		return Promise.resolve(state.telsList);
+    return state.telsList;
 	} catch (err) {
 		console.log(err);
 		state.loading = false;
@@ -616,12 +662,12 @@ const onControlClick = (val: string) => {
 			if (!auth('public:seat:unHold')) ElMessage.error('抱歉,您没有取消保持权限!');
 			else onUnHold();
 			break;
-		case 'TalkingDeal': //事后处
-			if (!auth('public:seat:TalkingDeal')) ElMessage.error('抱歉,您没有事后处理权限!');
+		case 'TalkingDeal': //话后整
+			if (!auth('public:seat:TalkingDeal')) ElMessage.error('抱歉,您没有话后整理权限!');
 			else onTalkingDeal();
 			break;
-		case 'unTalkingDeal': // 取消事后处
-			if (!auth('public:seat:unTalkingDeal')) ElMessage.error('抱歉,您没有取消事后处理权限!');
+		case 'unTalkingDeal': // 取消话后整
+			if (!auth('public:seat:unTalkingDeal')) ElMessage.error('抱歉,您没有取消话后整理权限!');
 			else unTalkingDeal();
 			break;
 		case 'transfer': //转接
@@ -641,77 +687,168 @@ const onControlClick = (val: string) => {
 	}
 };
 
-// 当前分机对象
-const ola_object = {
-	ola_extn: '1001', //分机hao
-	ola_password: '!@#123Qw', //分机密码
-	queues: '10010', //队列
+//签入
+const dutyFormRef = ref<RefType>();
+const onDutyFn = async () => {
+  if(AppConfigInfo.value.isNeedTelNo || AppConfigInfo.value.isTelNeedVerify){ // 需要选择分机号或者输入密码 打开弹窗选择分机号
+    dutyFormRef.value?.resetFields();
+    state.dutyDialogVisible = true;
+  }else{
+    ElMessageBox.confirm(`确定要签入,是否继续?`, '提示', {
+      confirmButtonText: '确认',
+      cancelButtonText: '取消',
+      type: 'warning',
+      draggable: true,
+      cancelButtonClass: 'default-button',
+      autofocus: false,
+    })
+        .then(() => {
+          state.loading = true;
+          dutyOn({}).then((res:any)=>{
+            currentTel.value.password = res.result.telPwd;
+            currentTel.value.telNo = res.result.telNo;
+            currentTel.value.queue = res.result.description === '默认' ? '10010' : res.result.description;
+            // 不需要选择分机号和密码 直接签入
+            currentTel.value = state.telsList.find((item: any) => item.value === userInfos.value.defaultTelNo);
+            websocket_connect(); //开启消息监听
+            state.loading = false;
+
+          }).catch(()=>{
+          }).finally(()=>{
+            state.loading = false;
+          })
+        })
+        .catch(() => {
+          state.loading = false;
+        });
+  }
+};
+// 确认签入
+const currentTel = ref<any>({});
+const clickOnDuty = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.loading = true;
+    if(AppConfigInfo.value.isNeedTelNo && AppConfigInfo.value.isTelNeedVerify){ // 需要分机和密码
+      currentTel.value = state.telsList.find((item: any) => item.value === state.dutyForm.telNo);
+      currentTel.value.password = state.dutyForm.password;
+      const request = {
+        telId:currentTel.value.id,
+        telNo:state.dutyForm.telNo,
+        telPwd:state.dutyForm.password,
+        queue: currentTel.value.description,
+      }
+      dutyOn(request).then(()=>{
+        currentTel.value.password = state.dutyForm.password;
+        currentTel.value.telNo = state.dutyForm.telNo;
+        currentTel.value.queue = currentTel.value.description === '默认' ? '10010' : currentTel.value.description;
+        websocket_connect(); //开启消息监听
+        state.loading = false;
+        state.dutyDialogVisible = false;
+      }).catch(()=>{
+      }).finally(()=>{
+        state.loading = false;
+        state.dutyDialogVisible = false;
+      })
+    }else if(AppConfigInfo.value.isNeedTelNo){ //需要分机
+      currentTel.value = state.telsList.find((item: any) => item.value === state.dutyForm.telNo);
+      currentTel.value.description = currentTel.value.description === '默认' ? '10010' : currentTel.value.description;
+      const request = {
+        telId:currentTel.value.id,
+        telNo:currentTel.value.telNo,
+        telPwd: currentTel.value.password,
+        queue: currentTel.value.description,
+      }
+      dutyOn(request).then(()=>{
+        websocket_connect(); //开启消息监听
+        state.loading = false;
+        state.dutyDialogVisible = false;
+      }).catch(()=>{
+      }).finally(()=>{
+        state.loading = false;
+        state.dutyDialogVisible = false;
+      })
+    }else if(AppConfigInfo.value.isTelNeedVerify){// 需要密码
+      dutyOn({telPwd:state.dutyForm.password}).then((res:any)=>{
+        currentTel.value.password = state.dutyForm.password;
+        currentTel.value.telNo = res.result.telNo;
+        currentTel.value.queue = res.result.description === '默认' ? '10010' : res.result.description;
+        websocket_connect(); //开启消息监听
+        state.loading = false;
+        state.dutyDialogVisible = false;
+      }).catch(()=>{
+      }).finally(()=>{
+        state.loading = false;
+        state.dutyDialogVisible = false;
+      })
+    }
+	});
 };
+
 // 链接呼叫中心
 const websocket_connect = () => {
-	ola.onConnect = onConnect;
-	ola.onClose = onClose;
-	ola.onMessage = onMessage;
-	ola.connect(import.meta.env.VITE_CALLCENTER_SOCKET_URL, ola_object.ola_extn, ola_object.ola_password);
+  if(ola.ws) { // 如果已经连接 则先关闭
+    ola.close();
+  }
+  ola.onConnect = onConnect;
+  ola.onClose = onClose;
+  ola.onMessage = onMessage;
+  ola.connect(import.meta.env.VITE_CALLCENTER_SOCKET_URL, currentTel.value.telNo, currentTel.value.password);
 };
 // 呼叫中心链接
 const onConnect = () => {
-	ola.subscribe('ola.agent.' + ola_object.ola_extn);
-	ola.subscribe('ola.caller.' + ola_object.ola_extn);
-	ola.get_agent_state(ola_object.ola_extn);
+  ola.subscribe('ola.agent.' + currentTel.value.telNo);
+  ola.subscribe('ola.caller.' + currentTel.value.telNo);
+  ola.get_agent_state(currentTel.value.telNo);
 
-	callCenterLogin();
-};
-// 呼叫中心登录
-const callCenterLogin = () => {
-	ola.logout(ola_object.ola_extn); //连接之后,先登出一次,防止其他地方已经登陆
-	let array_ola_queue: EmptyArrayType = []; // 队列
-	if (ola_object.queues) {
-		let array = ola_object.queues.split(',');
-		for (let i = 0; i < array.length; i++) {
-			array_ola_queue[i] = array[i];
-		}
-		ola.login(array_ola_queue, ola_object.ola_extn, { type: 'onhook' });
-	}
+  ola.logout(currentTel.value.telNo); //连接之后,先登出一次,防止其他地方已经登陆
+  let array_ola_queue: EmptyArrayType = []; // 队列
+  if (currentTel.value.queue) {
+    let array = currentTel.value.queue.split(',');
+    for (let i = 0; i < array.length; i++) {
+      array_ola_queue[i] = array[i];
+    }
+    ola.login(array_ola_queue, currentTel.value.telNo, { type: 'onhook' });
+  }
 };
 // 呼叫中心消息
 const onMessage = (event: any) => {
-	const data = JSON.parse(event.data);
-	console.log('onMessage', data);
-	if (data.event_type == 'agent_state') {
-		// 坐席状态
-		if (data.state == 'login') {
-			// 签入
-			// 设置分机号和坐席组
-			useTelStatusStore.setCallInfo({ telsNo: ola_object.ola_extn });
-			// 设置签入状态
-			useTelStatusStore.setDutyState(true);
-			// 设置电话状态
-			useTelStatusStore.setPhoneControlState(TelStates.dutyOn);
-			setTimeout(() => {
-				// 设置示闲状态
-				ola.go_ready();
-			}, 1000);
-			console.log('已签入');
-		} else if (data.state == 'logout') {
-			// 签出
-			state.loading = true;
-			// 重置所有状态
-			useTelStatusStore.resetState();
-			state.loading = false;
-			console.log('已签出');
-		} else if (data.state == 'ready') {
-			// 示闲中
-			// 设置休息状态 设置未正常状态
-			useTelStatusStore.setRest(RestStates.unRest);
-			// 设置话机状态 结束休息改为签入状态
-			useTelStatusStore.setPhoneControlState(TelStates.dutyOn);
-			console.log('示闲中');
-		} else if (data.state == 'unready') {
-			// 示忙中
-			useTelStatusStore.setPhoneControlState(TelStates.rest);
-			useTelStatusStore.setRest(RestStates.resting);
-			/*if (AppConfigInfo.value.IsRestApproval) {
+  const data = JSON.parse(event.data);
+  console.log('onMessage', data);
+  if (data.event_type == 'agent_state') {
+    // 坐席状态
+    if (data.state == 'login') {
+      // 签入
+      // 设置分机号和坐席组
+      useTelStatusStore.setCallInfo({ telsNo: currentTel.value.telNo });
+      state.loading = true;
+      setTimeout(() => {
+        // 设置示闲状态
+        ola.go_ready();
+      }, 1000);
+      console.log('已签入');
+    } else if (data.state == 'logout') {
+      // 签出
+      // 重置所有状态
+      useTelStatusStore.resetState();
+      console.log('已签出');
+    } else if (data.state == 'ready') {
+      // 设置签入状态
+      useTelStatusStore.setDutyState(true);
+      // 示闲中
+      // 设置休息状态 设置未正常状态
+      useTelStatusStore.setRest(RestStates.unRest);
+      // 设置话机状态 结束休息改为签入状态
+      useTelStatusStore.setPhoneControlState(TelStates.dutyOn);
+      state.loading = false;
+      ElMessage.success('签入成功!');
+      console.log('示闲中');
+    } else if (data.state == 'unready') {
+      // 示忙中
+      useTelStatusStore.setPhoneControlState(TelStates.rest);
+      useTelStatusStore.setRest(RestStates.resting);
+      /*if (AppConfigInfo.value.isRestApproval) {
         // 如果小休需要审核
         telRestProcess()
             .then((res: any) => {
@@ -744,124 +881,123 @@ const onMessage = (event: any) => {
 
             });
       }*/
-			break_reason(data.private_data);
-			console.log('示忙中');
-		} else if (data.state == 'acw') {
-			// 话后整理中
-			const time: number = AppConfigInfo.value.TalkingDealTime * 1000; // 事后处理时间
-			ElNotification({
-				title: '自动开启事后处理成功',
-				message: `${AppConfigInfo.value.TalkingDealTime}秒后自动结束事后处理,或者手动结束事后处理`,
-				type: 'success',
-				duration: time,
-			});
-			// 设置事后处
-			useTelStatusStore.setTalkingDeal(true);
-			// 设置话机状态 设置为事后处理中
-			useTelStatusStore.setPhoneControlState(TelStates.onTalkingDeal);
-			setTimeout(() => {
-				// 设置事后处
-				useTelStatusStore.setTalkingDeal(false);
-				// 设置话机状态 取消事后处理修改为空闲状态
-				useTelStatusStore.setPhoneControlState(TelStates.dutyOn);
-				ola.go_ready(); // 示闲
-			}, time);
-			console.log('话后整理中');
-		} else if (data.state == 'busy') {
+      break_reason(data.private_data);
+      console.log('示忙中');
+    } else if (data.state == 'acw') {
+      // 话后整理中
+      const time: number = AppConfigInfo.value.talkingDealTime * 1000; // 话后整理时间
+      ElNotification({
+        title: '自动开启话后整理成功',
+        message: `${time/1000}秒后自动结束话后整理,或者手动结束话后整理`,
+        type: 'success',
+        duration: time,
+      });
+      // 设置话后整
+      useTelStatusStore.setTalkingDeal(true);
+      // 设置话机状态 设置为话后整理中
+      useTelStatusStore.setPhoneControlState(TelStates.onTalkingDeal);
+      setTimeout(() => {
+        // 设置话后整
+        useTelStatusStore.setTalkingDeal(false);
+        // 设置话机状态 取消话后整理修改为空闲状态
+        useTelStatusStore.setPhoneControlState(TelStates.dutyOn);
+        ola.go_ready(); // 示闲
+      }, time);
+      console.log('话后整理中');
+    } else if (data.state == 'busy') {
 
-		} else {
-			console.log(data.state, '其他状态');
-		}
+    } else {
+      console.log(data.state, '其他状态');
+    }
 
-		if (data.state == 'busy') {
+    if (data.state == 'busy') {
       holdStatus(data.private_data); //处理保持
-			if (data.call_direction == 'outbound') {
-				// 呼出
-				if (data.private_data == 'calling') {
-					// 拨号中
-					// 设置电话状态 振铃中
-					useTelStatusStore.setPhoneControlState(TelStates.ring);
-					console.log('呼出拨号中');
-				} else if (data.private_data == 'answered') {
-					//振铃中
-					if (data.other_answered == false) {
-						// 设置电话状态 振铃中
-						useTelStatusStore.setPhoneControlState(TelStates.ring);
-						console.log('呼出振铃中');
-					} else if (data.other_answered == true) {
-						// 通话中
+      if (data.call_direction == 'outbound') {
+        // 呼出
+        if (data.private_data == 'calling') {
+          // 拨号中
+          // 设置电话状态 振铃中
+          useTelStatusStore.setPhoneControlState(TelStates.ring);
+          console.log('呼出拨号中');
+        } else if (data.private_data == 'answered') {
+          //振铃中
+          if (data.other_answered == false) {
+            // 设置电话状态 振铃中
+            useTelStatusStore.setPhoneControlState(TelStates.ring);
+            console.log('呼出振铃中');
+          } else if (data.other_answered == true) {
+            // 通话中
             // 开始计时
             startTime();
-						// 设置电话状态 通话中
-						useTelStatusStore.setPhoneControlState(TelStates.onCall);
-						console.log('呼出通话中');
-					}
-				}
-			} else {
-				// 呼入
-				if (data.private_data == 'ring') {
-					// 设置电话状态 振铃中
-					useTelStatusStore.setPhoneControlState(TelStates.ring);
-					console.log('呼入振铃中');
-				} else if (data.private_data == 'answered') {
+            // 设置电话状态 通话中
+            useTelStatusStore.setPhoneControlState(TelStates.onCall);
+            console.log('呼出通话中');
+          }
+        }
+      } else {
+        // 呼入
+        if (data.private_data == 'ring') {
+          // 设置电话状态 振铃中
+          useTelStatusStore.setPhoneControlState(TelStates.ring);
+          console.log('呼入振铃中');
+        } else if (data.private_data == 'answered') {
           // 开始计时
           startTime();
-					// 设置电话状态 通话中
-					useTelStatusStore.setPhoneControlState(TelStates.onCall);
-					console.log('呼入通话中');
-				}
-			}
-		} else if (data.old_state == 'busy') {
-			//挂机后系统可以返回两种状态:acw 话后整理状态 ready 示闲状态,如果不需要acw,可以联系我们后台修改配置,如果需要保留,如果需要再次
-			//拨打电话的话,需要手动点击示闲按钮
+          // 设置电话状态 通话中
+          useTelStatusStore.setPhoneControlState(TelStates.onCall);
+          console.log('呼入通话中');
+        }
+      }
+    } else if (data.old_state == 'busy') {
+      //挂机后系统可以返回两种状态:acw 话后整理状态 ready 示闲状态,如果不需要acw,可以联系我们后台修改配置,如果需要保留,如果需要再次
+      //拨打电话的话,需要手动点击示闲按钮
 
-			// 设置电话状态
-			useTelStatusStore.setPhoneControlState(TelStates.dutyOn);
-			// 结束计时
-			removeTimer();
-			console.log('已挂机');
-		}
-	} else if (data.event_type == 'agent_caller_state') {
-		//通话状态
-		// special feature, never mind
-		if (data.action == 'in') {
-			console.log('呼入', data.caller.cid_number, data.caller.uuid);
-			// ola.take_call(data.caller.uuid);
-		} else {
-			console.log('呼出', data.caller.uuid);
-		}
-	} else if (data.event_type == 'command/reply') {
-		// 其他消息
-		// console.log('command/reply', data);
-	}
+      // 结束计时
+      removeTimer();
+      console.log('已挂机');
+    }
+  } else if (data.event_type == 'agent_caller_state') {
+    //通话状态
+    // special feature, never mind
+    if (data.action == 'in') {
+      console.log('呼入', data.caller.cid_number, data.caller.uuid);
+      // ola.take_call(data.caller.uuid);
+    } else {
+      console.log('呼出', data.caller.uuid);
+    }
+  } else if (data.event_type == 'command/reply') {
+    // 其他消息
+    // console.log('command/reply', data);
+  }
 };
 // 呼叫中心链接关闭
 const onClose = () => {
-	ElMessage.error('呼叫中心断开链接');
+  console.log('呼叫中心断开链接')
+  // ElMessage.error('呼叫中心断开链接');
 };
 // 小休原因
 const restReason = ref(''); // 小休原因
 const break_reason = (reason: string) => {
-	switch (reason) {
-		case 'away':
-			restReason.value = '外出中';
-			break;
-		case 'rest':
-			restReason.value = '休息中';
-			break;
-		case 'conference':
-			restReason.value = '会议中';
-			break;
-		case 'train':
-			restReason.value = '培训中';
-			break;
-		case 'eat':
-			restReason.value = '用餐中';
-			break;
-		default:
-			restReason.value = '休息中';
-			break;
-	}
+  switch (reason) {
+    case 'away':
+      restReason.value = '外出中';
+      break;
+    case 'rest':
+      restReason.value = '休息中';
+      break;
+    case 'conference':
+      restReason.value = '会议中';
+      break;
+    case 'train':
+      restReason.value = '培训中';
+      break;
+    case 'eat':
+      restReason.value = '用餐中';
+      break;
+    default:
+      restReason.value = '休息中';
+      break;
+  }
 };
 // 保持状态处理
 const holdStatus = (holdStatus:string)=>{
@@ -883,30 +1019,6 @@ const holdStatus = (holdStatus:string)=>{
       break;
   }
 }
-//签入
-const dutyFormRef = ref<RefType>();
-const onDutyFn = async () => {
-	websocket_connect();
-	/*dutyFormRef.value?.resetFields();
-	// 获取所有分机列表(未签入的)
-	const list = await getTelsLists({ sigin: 0 });
-	const isDefaultTelNo = list.some((item: any) => item.value === userInfos.value.defaultTelNo);
-	if (isDefaultTelNo) {
-		// 如果默认分机号是空闲的,就默认选中
-		state.dutyForm.telNo = userInfos.value.defaultTelNo;
-	}
-	state.dutyDialogVisible = true;*/
-};
-// 确认签入
-const clickOnDuty = (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.loading = true;
-		// {telNo:state.dutyForm.telNo}
-		websocket_connect(); //开启消息监听
-	});
-};
 // 签出
 const offDutyFn = () => {
 	ElMessageBox.confirm(`确定要签出,是否继续?`, '提示', {
@@ -919,11 +1031,18 @@ const offDutyFn = () => {
 	})
 		.then(() => {
 			state.loading = true;
-			ola.logout(ola_object.ola_extn); //签出
-			// 重置所有状态
-			useTelStatusStore.resetState();
-			state.loading = false;
-			state.dutyOnSrc = getImageUrl('phoneControls/dutyOn_blue.png'); //签入图片
+      dutyOff().then(()=>{
+        ola.logout(currentTel.value.telNo); //签出
+        ola.close();
+        // 重置所有状态
+        useTelStatusStore.resetState();
+        state.loading = false;
+        state.dutyOnSrc = getImageUrl('phoneControls/dutyOn_blue.png'); //签入图片
+        state.loading = false;
+      }).catch(()=>{
+      }).finally(()=>{
+        state.loading = false;
+      })
 		})
 		.catch(() => {
 			state.loading = false;
@@ -949,7 +1068,7 @@ const onHangup = () => {
 // 小休
 const restFormRef = ref<RefType>(); //小休表单
 const onRest = async () => {
-	if (AppConfigInfo.value.IsRestApproval) {
+	if (AppConfigInfo.value.isRestApproval) {
 		// 如果小休需要审核
 		// 查询流程节点参数
 		const res: any = await restFlowStart();
@@ -996,7 +1115,7 @@ const clickOnRest = (formEl: FormInstance | undefined) => {
 	formEl.validate((valid: boolean) => {
 		if (!valid) return;
 		state.loading = true;
-		if (AppConfigInfo.value.IsRestApproval) {
+		if (AppConfigInfo.value.isRestApproval) {
 			//如果需要审核
 			state.restForm.additions = state.fileList;
 			let submitObj = other.deepClone(state.restForm);
@@ -1097,11 +1216,11 @@ const onUnHold = () => {
 		})
 		.catch(() => {});
 };
-// 事后处理(系统默认进入)
+// 话后整理(系统默认进入)
 const onTalkingDeal = () => {};
-// 取消事后处
+// 取消话后整
 const unTalkingDeal = () => {
-	ElMessageBox.confirm(`确定要取消事后处理,是否继续?`, '提示', {
+	ElMessageBox.confirm(`确定要取消话后整理,是否继续?`, '提示', {
 		confirmButtonText: '确认',
 		cancelButtonText: '取消',
 		type: 'warning',
@@ -1111,9 +1230,9 @@ const unTalkingDeal = () => {
 	})
 		.then(() => {
 			state.loading = true;
-			// 设置事后处
+			// 设置话后整
 			useTelStatusStore.setTalkingDeal(false);
-			// 设置话机状态 取消事后处理修改为空闲状态
+			// 设置话机状态 取消话后整理修改为空闲状态
 			useTelStatusStore.setPhoneControlState(TelStates.dutyOn);
 			ola.go_ready(); // 示闲
 			state.loading = false;
@@ -1126,9 +1245,7 @@ const onTransfer = () => {
 	//  重置表单
 	transferFormRef.value?.resetFields();
 	// 获取所有分机列表
-	getTelsLists().then(() => {
-		state.transferDialogVisible = true;
-	});
+  state.transferDialogVisible = true;
 };
 // 确认转接
 const clickOnTransfer = (formEl: FormInstance | undefined) => {
@@ -1141,28 +1258,51 @@ const clickOnTransfer = (formEl: FormInstance | undefined) => {
 };
 // 三方会议开始
 const onConference = () => {
-	ElMessageBox.confirm(`确定确定要开启三方会议,是否继续?`, '提示', {
-		confirmButtonText: '确认',
-		cancelButtonText: '取消',
-		type: 'warning',
-		draggable: true,
-		cancelButtonClass: 'default-button',
-		autofocus: false,
-	})
-		.then(() => {
-			VoiceInterfaceObject.Dtmf('0'); // 开启dtmf 三方通话
-		})
-		.catch(() => {});
+  //  重置表单
+  transferFormRef.value?.resetFields();
+  // 获取所有分机列表
+  state.threeWayDialogVisible = true;
+};
+// 三方会议确定
+const onCallArr = ref<EmptyArrayType>([
+  {
+    number:"2121"
+  },
+  {
+    number:"1001"
+  },
+]); // 三方会议选中的分机
+const threeWayVisible = ref(false); // 三方会议弹窗
+const threeWayFormRef = ref<RefType>(); // 三方会议表单
+const clickOnThreeWay = (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  formEl.validate((valid: boolean) => {
+    if (!valid) return;
+    // ola.conference(state.conferenceForm.telNo); //三方会议
+    state.threeWayDialogVisible = false;
+  });
 };
+const kickOut = (item:any)=>{
+  ElMessageBox.confirm(`确定确定要踢出${item.number},并恢复通话,是否继续?`, '提示', {
+  	confirmButtonText: '确认',
+  	cancelButtonText: '取消',
+  	type: 'warning',
+  	draggable: true,
+  	cancelButtonClass: 'default-button',
+  	autofocus: false,
+  })
+  	.then(() => {
+      // state.threeWayDialogVisible = true;
+  	})
+  	.catch(() => {});
+}
 // 外呼
 const outboundFormRef = ref<RefType>(); //外呼
 const onOutbound = () => {
 	//  重置表单
 	outboundFormRef.value?.resetFields();
 	// 获取所有分机列表
-	getTelsLists().then(() => {
-		state.outboundDialogVisible = true;
-	});
+  state.outboundDialogVisible = true;
 };
 // 外呼保存
 const clickOnOutbound = (formEl: FormInstance | undefined) => {
@@ -1177,11 +1317,20 @@ const clickOnOutbound = (formEl: FormInstance | undefined) => {
 		}, 300);
 	});
 };
-onMounted(() => {
+onMounted(async () => {
 	signalRStart(); //开启消息监听
+  const telList =   await getTelsLists(); // 查询所有分机
 	if (telStatusInfo.value.telsNo) {
-		// 有分机号
-		websocket_connect(); // 链接呼叫中心
+    dutyOn({}).then(()=>{
+      // 有分机号
+      currentTel.value = telList.find((item: any) => item.value === telStatusInfo.value.telsNo);
+      websocket_connect(); //开启消息监听
+      state.loading = false;
+    }).catch(()=>{
+    }).finally(()=>{
+      state.loading = false;
+    })
+
 	}
 });
 </script>
@@ -1262,3 +1411,23 @@ onMounted(() => {
 	}
 }
 </style>
+<style lang="scss">
+.el-popover.hangup-popover {
+  .hangup-container {
+    display: flex;
+    flex-wrap: nowrap;
+    .hangup-item {
+      text-align: center;
+      width: 120px;
+      border-right: 1px solid var(--el-border-color-darker);
+      &:last-child {
+        border-right: 0;
+      }
+      &-phoneNumber {
+        padding-top: 4px;
+        margin-bottom: 10px;
+      }
+    }
+  }
+}
+</style>

+ 22 - 17
src/layout/navBars/breadcrumb/user.vue

@@ -155,10 +155,11 @@ import { useTelStatus } from '/@/stores/telStatus';
 import { useThemeConfig } from '/@/stores/themeConfig';
 import { Session, Local, Cookie } from '/@/utils/storage';
 import mittBus from '/@/utils/mitt';
-import { VoiceInterfaceObject } from '/@/utils/PhoneScript';
 import { changePwd } from '/@/api/login/user';
-import { megcount, muquery } from '/@/api/auxiliary/notice';
+import { megcount } from '/@/api/auxiliary/notice';
 import signalR from '/@/utils/signalR';
+import { ola } from '/@/utils/ola_api';
+import {dutyOff} from "/@/api/public/wex";
 
 // 引入组件
 const UserNews = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/userNews.vue'));
@@ -330,8 +331,12 @@ const onLogOut = () => {
 				}
 			},
 		})
-			.then(async () => {
-				VoiceInterfaceObject.LogOut();
+			.then(() => {
+				ola.logout();
+				ola.close();
+        dutyOff();
+				signalR.leaveGroup('CallCenter');
+				signalR.stop();
 				// offDuty().then(() => {
 				// 断开链接
 				// signalR.stop();
@@ -343,6 +348,7 @@ const onLogOut = () => {
 				Cookie.clear();
 				// 使用 reload 时,不需要调用 resetRoute() 重置路由
 				window.location.reload();
+
 				// });
 			})
 			.catch(() => {});
@@ -471,11 +477,11 @@ onMounted(() => {
 		initComponentSize();
 	}
 	getNumAndList();
-  signalR.SR.on('CircularRecord', (data: any) => {
-    // 小红点数量消息通知
-    console.log(data, '小红点数量消息通知');
-    getNumAndList();
-  });
+	signalR.SR.on('CircularRecord', (data: any) => {
+		// 小红点数量消息通知
+		console.log(data, '小红点数量消息通知');
+		getNumAndList();
+	});
 });
 </script>
 
@@ -514,13 +520,13 @@ onMounted(() => {
 		&:hover {
 		}
 	}
-  .arrow {
-    transition: transform var(--el-transition-duration);
-    cursor: pointer;
-  }
-  .arrow.is-reverse {
-    transform: rotateZ(-180deg);
-  }
+	.arrow {
+		transition: transform var(--el-transition-duration);
+		cursor: pointer;
+	}
+	.arrow.is-reverse {
+		transform: rotateZ(-180deg);
+	}
 	:deep(.el-dropdown) {
 		color: var(--hotline-color-text-main);
 		flex: 1;
@@ -583,5 +589,4 @@ onMounted(() => {
 		}
 	}
 }
-
 </style>

+ 10 - 23
src/router/backEnd.ts

@@ -13,7 +13,7 @@ import { getMenu } from '/@/api/login/user';
 import { removeNullAndDuplicates } from '/@/utils/arrayOperation';
 import other from '/@/utils/other';
 import { pwdCheck } from '/@/api/login';
-import { getSettingByCode } from '/@/api/system/parameter';
+import { appConfigInfo } from '/@/api/public/system';
 const layoutModules: any = import.meta.glob('../layout/routerView/*.{vue,tsx}');
 const viewsModules: any = import.meta.glob('../views/**/*.{vue,tsx}');
 // 后端控制路由
@@ -47,32 +47,19 @@ const formatRouter = (arr: Array<any>): Array<any> => {
 		return v;
 	});
 };
-// 获取系统配置
-const getSettingValue = async (code: string, isNumber: boolean = false) => {
-	try {
-		const setting = await getSettingByCode(code);
-		const value = setting.result?.settingValue.join('|') ?? (isNumber ? '0' : 'false');
-		return isNumber ? Number(value) : value === 'true';
-	} catch (e) {
-		console.log(e);
-		return isNumber ? 0 : false;
-	}
-};
+// 获取系统配置 存入pinia
 const getAppConfigFn = async () => {
 	try {
-		const [IsRestApprovalValueBoolean, IsAutoTalkingDealValueBoolean, TalkingDealTimeValueNumber] = await Promise.all([
-			getSettingValue('IsRestApproval'),
-			getSettingValue('IsAutoTalkingDeal'),
-			getSettingValue('TalkingDealTime', true),
-		]);
-		console.log(
-			`是否开启小休审批${IsRestApprovalValueBoolean},是否自动事后处理${IsAutoTalkingDealValueBoolean},自动事后处理时间${TalkingDealTimeValueNumber}秒`
-		);
+		const { result } = await appConfigInfo();
 		useAppConfig().setAppConfigInfo({
-			IsRestApproval: IsRestApprovalValueBoolean,
-			IsAutoTalkingDeal: IsAutoTalkingDealValueBoolean,
-			TalkingDealTime: TalkingDealTimeValueNumber,
+			isRestApproval: result.isRestApproval ?? false, //是否开启小休审批
+			isNeedTelNo: result.isNeedTelNo ?? false, //分机签入是否需要选择号码
+			talkingDealTime: result.talkingDealTime ?? 0, // 自动话后整理时间
+			isTelNeedVerify: result.isTelNeedVerify ?? false, //分机签入是否需要输入密码
 		});
+		console.log(
+			`是否开启小休审批${result.isRestApproval},自动话后整理时间${result.talkingDealTime}秒,分机签入是否需要选择号码${result.isNeedTelNo},分机签入是否需要输入密码${result.isTelNeedVerify}`
+		);
 	} catch (e) {
 		console.log(e);
 	}

+ 4 - 6
src/stores/appConfig.ts

@@ -7,15 +7,13 @@ import { defineStore } from 'pinia';
 export const useAppConfig = defineStore('AppConfig', {
 	state: (): AppConfigState => ({
 		AppConfigInfo: {
-			IsRestApproval: false, // 电话控件小休是否要进行审批
-			IsAutoTalkingDeal: false, // 呼叫中心是否自动事后处理
-			TalkingDealTime: 0, // 呼叫中心自动事后处理时间
+			isRestApproval: false, // 电话控件小休是否要进行审批
+			talkingDealTime: 0, // 呼叫中心自动事后处理时间
+			isNeedTelNo: false, // 分机签入是否需要选择号码
+			isTelNeedVerify: false, // 分机签入是否需要输入密码
 		},
 	}),
 	actions: {
-		getAppInfo() {
-			return this.AppConfigInfo;
-		},
 		// 设置系统信息
 		setAppConfigInfo(data: object): void {
 			this.AppConfigInfo = {

+ 5 - 3
src/types/pinia.d.ts

@@ -98,9 +98,10 @@ declare interface ThemeConfigStates {
 }
 declare interface AppConfigState {
 	AppConfigInfo: {
-		IsRestApproval: boolean; // 电话控件小休是否要进行审批
-		IsAutoTalkingDeal: boolean; // 呼叫中心是否自动事后处理
-		TalkingDealTime: number; // 呼叫中心事后处理时间
+		isRestApproval: boolean; // 电话控件小休是否要进行审批
+		talkingDealTime: number; // 呼叫中心事后处理时间
+		isNeedTelNo: boolean; // 分机签入是否需要选择号码
+		isTelNeedVerify: boolean; // 分机签入是否需要输入密码
 		[x: string]: any
 	}
 }
@@ -138,5 +139,6 @@ declare interface TelsStateInfos {
 		telType: string | number; //来电 外呼 转接
 		fromTel: string | number; // 来电号码
 		callTime?: number; // 通话时长
+		[x: string]: any
 	}
 }

+ 13 - 3
src/utils/ola_api.ts

@@ -1,3 +1,4 @@
+import {dutyOff} from '/@/api/public/wex';
 /**
  * @description 呼叫中心对接接口
  */
@@ -53,6 +54,10 @@ export const ola: any = {
 
 	_onMessage: function (evt: any) { //获取消息
 		const msg = JSON.parse(evt.data);
+		if(msg.event_type == 'command/reply' && msg.code !== 200){ //授权失败 调用签出接口
+			ElMessage.error(msg.text)
+			dutyOff()
+		}
 		if (msg.event_name == 'command/reply' && msg.code == 200) {
 			ola.ws.onmessage = this.onMessage;
 		}
@@ -79,8 +84,9 @@ export const ola: any = {
 		return ola.send({ action: 'api', cmd: 'login', args: args });
 	},
 
-	logout: function (extn:string) {
-		return this.send({ action: 'api', cmd: 'logout', args: { extn } });
+	logout: function (extn?:string) {
+		const extns = extn || this._extn;
+		return this.send({ action: 'api', cmd: 'logout', args: { extn:extns } });
 	},
 
 	collect_dtmf: function (extn: any, soundfile: any) {
@@ -130,7 +136,7 @@ export const ola: any = {
 		return this.send({ action: 'api', cmd: 'hangup_other', args: { extn: this._extn } });
 	},
 
-	dial: function (dst: any, otherStr: any, gateway?: any) {
+	dial: function (dst: any, otherStr?: any, gateway?: any) {
 		return this.send({ action: 'api', cmd: 'dial', args: { extn: this._extn, dest: dst, gateway: gateway, otherStr: otherStr } });
 	},
 
@@ -317,6 +323,10 @@ export const ola: any = {
 	},
 
 	send: function (msg: any) { //发送消息
+		if(!ola.ws) {
+			ElMessage.error("请先签入")
+			return;
+		}
 		msg.uuid = ola.next_uuid();
 		ola.ws.send(JSON.stringify(msg));
 		return msg.uuid;

+ 199 - 193
src/views/auxiliary/area/index.vue

@@ -1,212 +1,216 @@
 <template>
-  <div class="auxiliary-area-container layout-padding">
-    <div class="layout-padding-auto layout-padding-view pd20">
-      <div class="flex-center-between mb20">
-        <el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
-          <el-form-item label="关键字" prop="keyword" class="mb0">
-            <el-input v-model="state.queryParams.keyword" placeholder="区域名称" clearable @keyup.enter="handleQuery" style="width: 250px" />
-          </el-form-item>
-          <el-form-item class="mb0">
-            <el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-            <el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-          </el-form-item>
-        </el-form>
-        <div>
-          <el-button type="primary" @click="expand"
-          ><SvgIcon
-              name="ele-ArrowDownBold"
-              style="transition: transform var(--el-transition-duration)"
-              :style="state.isExpand ? 'transform: none' : 'transform: rotateZ(180deg)'"
-              class="mr5"
-          />
-            {{ state.isExpand ? '收起' : '展开' }}</el-button
-          >
-          <el-button type="primary" @click="onOpenAddArea('')" v-auth="'auxiliary:area:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
-        </div>
-      </div>
-      <!-- 表格 -->
-      <el-auto-resizer class="table" v-loading="state.loading">
-        <template #default="{ height, width }">
-          <el-table-v2
-              v-model:expanded-row-keys="state.expandedRowKeys"
-              :columns="state.columns"
-              :data="state.orgTableData"
-              expand-column-key="areaName"
-              fixed
-              :width="width"
-              :height="height"
-          >
-            <template #empty>
-              <Empty />
-            </template>
-          </el-table-v2>
-        </template>
-      </el-auto-resizer>
-    </div>
-    <area-add ref="areaAddRef" @updateList="queryList" />
-    <area-edit ref="areaEditRef" @updateList="queryList" />
-  </div>
+	<div class="auxiliary-area-container layout-padding">
+		<div class="layout-padding-auto layout-padding-view pd20">
+			<el-row class="mb20" :gutter="10">
+				<el-col :xs="24" :sm="12" :md="18" :lg="18" :xl="18">
+					<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
+						<el-form-item label="关键字" prop="keyword" class="mb0">
+							<el-input v-model="state.queryParams.keyword" placeholder="区域名称" clearable @keyup.enter="handleQuery" style="width: 250px" />
+						</el-form-item>
+						<el-form-item class="mb0">
+							<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+							<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading">
+								<SvgIcon name="ele-Refresh" class="mr5" />重置
+							</el-button>
+						</el-form-item>
+					</el-form>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6" style="text-align: right">
+					<el-button type="primary" @click="expand"
+						><SvgIcon
+							name="ele-ArrowDownBold"
+							style="transition: transform var(--el-transition-duration)"
+							:style="state.isExpand ? 'transform: none' : 'transform: rotateZ(180deg)'"
+							class="mr5"
+						/>
+						{{ state.isExpand ? '收起' : '展开' }}</el-button
+					>
+					<el-button type="primary" @click="onOpenAddArea('')" v-auth="'auxiliary:area:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
+				</el-col>
+			</el-row>
+			<!-- 表格 -->
+			<el-auto-resizer class="table" v-loading="state.loading">
+				<template #default="{ height, width }">
+					<el-table-v2
+						v-model:expanded-row-keys="state.expandedRowKeys"
+						:columns="state.columns"
+						:data="state.orgTableData"
+						expand-column-key="areaName"
+						fixed
+						:width="width"
+						:height="height"
+					>
+						<template #empty>
+							<Empty />
+						</template>
+					</el-table-v2>
+				</template>
+			</el-auto-resizer>
+		</div>
+		<area-add ref="areaAddRef" @updateList="queryList" />
+		<area-edit ref="areaEditRef" @updateList="queryList" />
+	</div>
 </template>
 <script lang="ts" setup name="auxiliaryArea">
 import { defineAsyncComponent, ref, h, reactive, onMounted, watch } from 'vue';
-import {ElButton, ElMessage, ElMessageBox} from 'element-plus';
+import { ElButton, ElMessage, ElMessageBox } from 'element-plus';
 import type { FormInstance } from 'element-plus';
 import { formatDate } from '/@/utils/formatTime';
 import { auth } from '/@/utils/authFunction';
 import { throttle } from '/@/utils/tools';
 import other from '/@/utils/other';
-import {treeArea,treeAreaDelete} from '/@/api/auxiliary/area';
+import { treeArea, treeAreaDelete } from '/@/api/auxiliary/area';
 // 引入组件
-const AreaAdd = defineAsyncComponent(() => import('/@/views/auxiliary/area/component/Area-add.vue'));  // 新增区域
-const AreaEdit = defineAsyncComponent(() => import('/@/views/auxiliary/area/component/Area-edit.vue'));  // 编辑区域
+const AreaAdd = defineAsyncComponent(() => import('/@/views/auxiliary/area/component/Area-add.vue')); // 新增区域
+const AreaEdit = defineAsyncComponent(() => import('/@/views/auxiliary/area/component/Area-edit.vue')); // 编辑区域
 
 // 定义变量内容
 const state = reactive({
-  orgTableData: <EmptyArrayType>[], // 获取所有菜单
-  staticArr: <EmptyArrayType>[],  // 静态数据
-  loading: false, // 加载状态
-  queryParams: {
-    keyword: '',  // 关键字
-  },
-  expandedRowKeys: <EmptyArrayType>[],  // 展开行
-  columns: [
-    {
-      key: 'areaName',
-      dataKey: 'areaName',
-      title: '区域名称',
-      width: 600,
-    },
-    {
-      key: 'id',
-      dataKey: 'id',
-      title: '区域代码',
-      width: 400,
-    },
-    {
-      key: 'creationTime',
-      dataKey: 'creationTime',
-      title: '创建时间',
-      width: 200,
-      cellRenderer: (data: any) => h('span', {}, { default: () => formatDate(new Date(data.rowData.creationTime), 'YYYY-mm-dd HH:MM:SS') }),
-    },
-    {
-      key: 'handle',
-      title: '操作',
-      width: 100,
-      fixed: 'right',
-      align: 'center',
-      cellRenderer: ({ rowData }: any) => {
-        return h('span', { class: 'flex' }, [
-          (auth('auxiliary:area:edit') && rowData.isCanModify)
-              ? h(
-                  ElButton,
-                  {
-                    onClick: () => onOpenEditArea(rowData),
-                    type: 'primary',
-                    title: '修改',
-                    link: true,
-                  },
-                  { default: () => '修改' }
-              )
-              : '',
-          (auth('auxiliary:area:delete') && rowData.isCanModify)
-              ? h(
-                  ElButton,
-                  {
-                    onClick: () => onDelArea(rowData),
-                    type: 'danger',
-                    title: '删除',
-                    link: true,
-                  },
-                  { default: () => '删除' }
-              )
-              : '',
-        ]);
-      },
-    },
-  ],
-  isExpand: false, // 是否展开
+	orgTableData: <EmptyArrayType>[], // 获取所有菜单
+	staticArr: <EmptyArrayType>[], // 静态数据
+	loading: false, // 加载状态
+	queryParams: {
+		keyword: '', // 关键字
+	},
+	expandedRowKeys: <EmptyArrayType>[], // 展开行
+	columns: [
+		{
+			key: 'areaName',
+			dataKey: 'areaName',
+			title: '区域名称',
+			width: 600,
+		},
+		{
+			key: 'id',
+			dataKey: 'id',
+			title: '区域代码',
+			width: 400,
+		},
+		{
+			key: 'creationTime',
+			dataKey: 'creationTime',
+			title: '创建时间',
+			width: 200,
+			cellRenderer: (data: any) => h('span', {}, { default: () => formatDate(new Date(data.rowData.creationTime), 'YYYY-mm-dd HH:MM:SS') }),
+		},
+		{
+			key: 'handle',
+			title: '操作',
+			width: 100,
+			fixed: 'right',
+			align: 'center',
+			cellRenderer: ({ rowData }: any) => {
+				return h('span', { class: 'flex' }, [
+					auth('auxiliary:area:edit') && rowData.isCanModify
+						? h(
+								ElButton,
+								{
+									onClick: () => onOpenEditArea(rowData),
+									type: 'primary',
+									title: '修改',
+									link: true,
+								},
+								{ default: () => '修改' }
+						  )
+						: '',
+					auth('auxiliary:area:delete') && rowData.isCanModify
+						? h(
+								ElButton,
+								{
+									onClick: () => onDelArea(rowData),
+									type: 'danger',
+									title: '删除',
+									link: true,
+								},
+								{ default: () => '删除' }
+						  )
+						: '',
+				]);
+			},
+		},
+	],
+	isExpand: false, // 是否展开
 });
 const ruleFormRef = ref<RefType>(); // 搜索表单ref
 // 搜索
 const formatTable = (list: any[], keyword: string) => {
-  if (!list.length || !Array.isArray(list)) return [];
-  let emptyArr: any[] = [];
-  list.map((item) => {
-    if (item.areaName.includes(keyword)) {
-      if (item.children && Array.isArray(item.children) && item.children.length > 0) {
-        item.children = formatTable(item.children, keyword);
-      }
-      emptyArr.push(item);
-    } else if (item.children && Array.isArray(item.children) && item.children.length > 0) {
-      item.children = formatTable(item.children, keyword);
-      if (item.children.length) {
-        emptyArr.push(item);
-      }
-    }
-  });
-  return emptyArr;
+	if (!list.length || !Array.isArray(list)) return [];
+	let emptyArr: any[] = [];
+	list.map((item) => {
+		if (item.areaName.includes(keyword)) {
+			if (item.children && Array.isArray(item.children) && item.children.length > 0) {
+				item.children = formatTable(item.children, keyword);
+			}
+			emptyArr.push(item);
+		} else if (item.children && Array.isArray(item.children) && item.children.length > 0) {
+			item.children = formatTable(item.children, keyword);
+			if (item.children.length) {
+				emptyArr.push(item);
+			}
+		}
+	});
+	return emptyArr;
 };
 let emptyArr: any[] = [];
 const getExpand = (list: any[]) => {
-  if (!list.length || !Array.isArray(list)) return [];
-  list.map((item) => {
-    if (item.children && Array.isArray(item.children) && item.children.length > 0) {
-      getExpand(item.children);
-    }
-    emptyArr.push(item.id);
-  });
-  return emptyArr;
+	if (!list.length || !Array.isArray(list)) return [];
+	list.map((item) => {
+		if (item.children && Array.isArray(item.children) && item.children.length > 0) {
+			getExpand(item.children);
+		}
+		emptyArr.push(item.id);
+	});
+	return emptyArr;
 };
 /** 搜索按钮操作 节流操作 */
 const handleQuery = throttle(() => {
-  if (state.queryParams.keyword) {
-    state.loading = true;
-    state.expandedRowKeys = [];
-    emptyArr = [];
-    state.orgTableData = formatTable(other.deepClone(state.staticArr), state.queryParams.keyword);
-    state.expandedRowKeys = getExpand(state.orgTableData);
-    state.loading = false;
-  } else {
-    queryList();
-  }
+	if (state.queryParams.keyword) {
+		state.loading = true;
+		state.expandedRowKeys = [];
+		emptyArr = [];
+		state.orgTableData = formatTable(other.deepClone(state.staticArr), state.queryParams.keyword);
+		state.expandedRowKeys = getExpand(state.orgTableData);
+		state.loading = false;
+	} else {
+		queryList();
+	}
 }, 300);
 /** 重置按钮操作 */
 const resetQuery = throttle((formEl: FormInstance | undefined) => {
-  if (!formEl) return;
-  formEl.resetFields();
-  queryList();
-  state.expandedRowKeys = [];
-  emptyArr = [];
+	if (!formEl) return;
+	formEl.resetFields();
+	queryList();
+	state.expandedRowKeys = [];
+	emptyArr = [];
 }, 300);
 // 打开新增弹窗
 const areaAddRef = ref<RefType>(); // 新增组织机构ref
 const onOpenAddArea = (row?: any) => {
-  areaAddRef.value.openDialog(state.orgTableData, row);
+	areaAddRef.value.openDialog(state.orgTableData, row);
 };
 // 打开编辑弹窗
-const areaEditRef = ref<RefType>();  // 编辑组织机构ref
+const areaEditRef = ref<RefType>(); // 编辑组织机构ref
 const onOpenEditArea = (row: any) => {
-  areaEditRef.value.openDialog(row, state.orgTableData);
+	areaEditRef.value.openDialog(row, state.orgTableData);
 };
 const expand = () => {
-  state.isExpand = !state.isExpand;
+	state.isExpand = !state.isExpand;
 };
 watch(
-    () => state.isExpand,
-    (old: Boolean) => {
-      if (old) getAllIds(state.orgTableData);
-      else state.expandedRowKeys = [];
-    }
+	() => state.isExpand,
+	(old: Boolean) => {
+		if (old) getAllIds(state.orgTableData);
+		else state.expandedRowKeys = [];
+	}
 );
 const getAllIds = (arr: any) => {
-  if (!arr) return [];
-  arr.forEach((v: any) => {
-    if (v.children?.length) {
-      getAllIds(v.children);
-      state.expandedRowKeys.push(v.id);
-    }
-  });
+	if (!arr) return [];
+	arr.forEach((v: any) => {
+		if (v.children?.length) {
+			getAllIds(v.children);
+			state.expandedRowKeys.push(v.id);
+		}
+	});
 };
 // 删除当前行
 const onDelArea = (row: any) => {
@@ -214,38 +218,40 @@ const onDelArea = (row: any) => {
 		confirmButtonText: '确定',
 		cancelButtonText: '取消',
 		type: 'warning',
-	}).then(() => {
-    treeAreaDelete(row.id).then(() => {
-			ElMessage.success('删除成功');
-      queryList();
+	})
+		.then(() => {
+			treeAreaDelete(row.id).then(() => {
+				ElMessage.success('删除成功');
+				queryList();
+			});
 		})
-	}).catch(() => { });
+		.catch(() => {});
 };
 // 获取所有部门结构
 const queryList = async () => {
-  if (!auth('auxiliary:area:query')) ElMessage.error('抱歉,您没有权限获区域列表!');
-  else {
-    state.loading = true;
-    try {
-      const res: any = await Promise.all([treeArea()]);
-      state.orgTableData = res[0].result ?? [];
-      state.staticArr = res[0].result ?? [];
-      state.loading = false;
-    } catch (error) {
-      console.log(error)
-      state.loading = false;
-    }
-  }
+	if (!auth('auxiliary:area:query')) ElMessage.error('抱歉,您没有权限获区域列表!');
+	else {
+		state.loading = true;
+		try {
+			const res: any = await Promise.all([treeArea()]);
+			state.orgTableData = res[0].result ?? [];
+			state.staticArr = res[0].result ?? [];
+			state.loading = false;
+		} catch (error) {
+			console.log(error);
+			state.loading = false;
+		}
+	}
 };
 // 页面加载时
 onMounted(() => {
-  queryList();
+	queryList();
 });
 </script>
 <style lang="scss" scoped>
-.auxiliary-area-container{
-  .table {
-    flex: 1;
-  }
+.auxiliary-area-container {
+	.table {
+		flex: 1;
+	}
 }
 </style>

+ 0 - 1
src/views/auxiliary/notice/component/Notice-edit.vue

@@ -139,7 +139,6 @@ const ruleFormRef = ref<RefType>();
 const dialogTitle = ref<string>('编辑通知');
 
 const bulletinTypeOptions = ref<EmptyArrayType>([]); // 公告类型
-const circularTypeOptions = ref<EmptyArrayType>([]); // 通知类型
 const pushRangesOptions = ref<EmptyArrayType>([]); // 公告范围
 const orgsOptions = ref<EmptyArrayType>([]); // 来源单位
 const openDialog = async (row: any, type: string) => {

+ 2 - 2
src/views/business/followUp/component/Follow-up-detail.vue

@@ -287,13 +287,13 @@
 <script setup lang="ts" name="orderFollowUpDetail">
 import { computed, defineAsyncComponent, reactive, ref } from 'vue';
 import { ElMessage, FormInstance } from 'element-plus';
-import { VoiceInterfaceObject } from '/@/utils/PhoneScript';
 import { commonEnum } from '/@/utils/constants';
 import { visitDetailBaseData } from '/@/api/business/followUp';
 import { storeToRefs } from 'pinia';
 import { useUserInfo } from '/@/stores/userInfo';
 import { formatDate } from '/@/utils/formatTime';
 import { visitOrder } from '/@/api/business/followUp';
+import {ola} from "/@/utils/ola_api";
 
 const storesUserInfo = useUserInfo();
 const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
@@ -395,7 +395,7 @@ const closeDialog = () => {
 };
 // 呼叫
 const dialOut = (phoneNumber: string) => {
-	VoiceInterfaceObject.DialOut(phoneNumber);
+  ola.dial(phoneNumber)
 };
 const onCall = () => {
 	if (checkedCities.value && checkedCities.value.length > 0) {

+ 2 - 2
src/views/business/order/components/Order-detail.vue

@@ -417,7 +417,7 @@ import { commonEnum } from '/@/utils/constants';
 import { orderDetail } from '/@/api/business/order';
 import { formatDate } from '/@/utils/formatTime';
 import { ElMessage } from 'element-plus';
-import { VoiceInterfaceObject } from '/@/utils/PhoneScript';
+import {ola} from "/@/utils/ola_api";
 
 // 引入组件
 const OrderExpandDetail = defineAsyncComponent(() => import('/@/views/business/order/components/Order-expand-detail.vue')); // 扩展信息
@@ -615,7 +615,7 @@ const recordFile = (callId: string) => {
 };
 // 电话外呼
 const callPhone = (number: number | string) => {
-	VoiceInterfaceObject.DialOut(number); // 呼叫
+  ola.dial(number)
 };
 const orderRepeatRef = ref<RefType>();
 // 展示重复工单列表

+ 0 - 131
src/views/knowledge/apply/component/Knowledge-apply-detail.vue

@@ -1,131 +0,0 @@
-<template>
-	<div class="knowledge-apply-detail-container">
-		<el-dialog title="申请详情" v-model="state.dialogVisible" draggable width="769px">
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="100px">
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="申请类型" class="mb10">
-							{{ state.ruleForm.knowledgeApplyType === 0 ? '新增' : '更新' }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="诉求处理部门" class="mb10">
-							{{ state.ruleForm.department }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="申请人" class="mb10">
-							{{ state.ruleForm.creationName }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="申请部门" class="mb10">
-							{{ state.ruleForm.creationBMName }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.expiredTime">
-						<el-form-item label="截止时间" class="mb10">
-							{{ formatDate(state.ruleForm.expiredTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="诉求内容" class="mb10">
-							{{ state.ruleForm.content }}
-						</el-form-item>
-					</el-col>
-					<el-divider />
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.kbTitle">
-						<el-form-item label="关联知识" class="mb10">
-							<el-button link type="primary" @click="onPreview">{{ state.ruleForm.kbTitle }}</el-button>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="处理人" class="mb10">
-							{{ state.ruleForm.processor }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.handleTime">
-						<el-form-item label="处理完成时间" class="mb10">
-							{{ formatDate(state.ruleForm.handleTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.returnTime">
-						<el-form-item label="退回时间" class="mb10">
-							{{ formatDate(state.ruleForm.returnTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.opinion">
-						<el-form-item :label="state.ruleForm.returnTime ? '退回原因' : '备注'">
-							{{ state.ruleForm.opinion }}
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="closeDialog" class="default-button">关 闭</el-button>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-
-<script setup lang="ts" name="knowledgeApplyDetail">
-import { reactive, ref } from 'vue';
-import { useRouter } from 'vue-router';
-import { formatDate } from '/@/utils/formatTime';
-import { KnowledgeApplyDetail } from '/@/api/knowledge/apply';
-
-// 定义变量内容
-const ruleFormRef = ref<any>(); // 表单ref
-const router = useRouter(); // 路由
-const state = reactive<any>({
-	dialogVisible: false, // 弹窗
-	ruleForm: {
-    knowledgeApplyType: 1,  // 申请类型
-    department: '',  // 诉求处理部门
-    creationName: '',  // 申请人
-    creationBMName: '',  // 申请部门
-    expiredTime: '',  // 截止时间
-    content: '',  // 诉求内容
-		KnowledgeId: '',  // 关联知识
-    processor: '',  // 处理人
-    handleTime: '',  // 处理完成时间
-    returnTime: '',  // 退回时间
-    opinion: '',  // 退回原因
-	},
-	orgData: [], // 上级
-	loading: false, // 加载
-});
-// 打开弹窗
-const openDialog = async (row: any) => {
-	state.loading = true;
-	try {
-		const res: any = await KnowledgeApplyDetail(row.id);
-		state.ruleForm = res.result ?? {};
-		state.dialogVisible = true;
-		state.loading = false;
-	} catch (error) {
-		state.loading = false;
-	}
-};
-// 预览
-const onPreview = () => {
-	router.push({
-		name: 'knowledgePreview',
-		params: {
-			id: state.ruleForm.kbid,
-			tagsViewName: '知识预览',
-		},
-	});
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-};
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>

+ 0 - 208
src/views/knowledge/apply/component/Knowledge-apply-handle.vue

@@ -1,208 +0,0 @@
-<template>
-	<div class="knowledge-apply-handle-container">
-		<el-dialog title="知识申请处理" v-model="state.dialogVisible" draggable width="769px">
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="100px">
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
-						<span class="font16"><b>基本信息</b></span>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="诉求类型" class="mb10">
-							{{ state.ruleForm.knowledgeApplyType === 0 ? '新增' : '更新' }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="诉求处理部门" class="mb10">
-							{{ state.ruleForm.department }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="申请人" class="mb10"> {{ state.ruleForm.creationName }} </el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="申请部门" class="mb10"> {{ state.ruleForm.creationBMName }} </el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.expiredTime">
-						<el-form-item label="截止时间" class="mb10">
-							{{ formatDate(state.ruleForm.expiredTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.kbTitle">
-						<el-form-item label="关联知识" class="mb10">
-							<el-button link type="primary" @click="onPreview">{{ state.ruleForm.kbTitle }}</el-button>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="诉求内容" class="mb10">
-							{{ state.ruleForm.content }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
-						<span class="font16"><b>办理信息</b></span>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="关联知识" prop="knowledgeId" :rules="[{ required: true, message: '请选择关联知识', trigger: 'change' }]">
-							<template #label>
-								<div style="height: 34px; display: flex; align-items: center">
-									关联知识
-									<el-tooltip placement="top-start">
-										<SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
-										<template #content>
-											温馨提示:
-											<br />
-											1、新增诉求:已有对应知识时,请选择对应知识进行关联;没有对应知识时,请先新增知识,然后再进行关联 <br />
-											2、更新诉求:需先更新对应知识,方可进行关联;若知识库未按照要求更新,直接关联,将影响部门指标考核
-										</template>
-									</el-tooltip>
-								</div>
-							</template>
-							<el-select-v2
-								v-model="state.ruleForm.knowledgeId"
-								clearable
-								:options="state.knowledgeOptions"
-								placeholder="请选择关联知识"
-								style="width: calc(100% - 80px)"
-								@change="changeKonwledge"
-							/>
-							<el-button type="primary" link class="ml10" @click="createKnowledge">创建知识</el-button>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="备注" prop="opinion" :rules="[{ required: false, message: '请填写备注', trigger: 'blur' }]">
-							<el-input
-								v-model="state.ruleForm.opinion"
-								type="textarea"
-								:autosize="{ minRows: 6, maxRows: 8 }"
-								placeholder="请填写备注"
-								clearable
-								maxlength="2000"
-							>
-							</el-input>
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-			<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>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-
-<script setup lang="ts" name="knowledgeApplyHandle">
-import { reactive, ref, onMounted } from 'vue';
-import { ElMessage, FormInstance } from 'element-plus';
-import { useRouter } from 'vue-router';
-import { formatDate } from '/@/utils/formatTime';
-import { KnowledgeApplyDetail, KnowledgeHandle } from '/@/api/knowledge/apply';
-import { KnowledgeGetKnowledge } from '/@/api/knowledge';
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['updateList']);
-
-// 定义变量内容
-const ruleFormRef = ref<any>(); // 表单
-const state = reactive<any>({
-	dialogVisible: false, // 弹窗
-	ruleForm: {
-		knowledgeApplyType: 1,  // 诉求类型
-    department: '',  // 部门
-    creationName: '',  // 诉求人
-    creationBMName: '',  // 诉求人部门
-    expiredTime: '',  // 截至时间
-    kbTitle: '',  // 关联知识
-    content: '',  // 诉求内容
-    knowledgeId: '',  // 关联知识id
-    opinion: '',  // 备注
-	},
-	orgData: [], // 上级
-	loading: false, // 加载
-	knowledgeOptions: [], // 关联知识数据
-});
-const router = useRouter();
-// 打开弹窗
-const openDialog = async (row: any) => {
-	state.loading = true;
-	try {
-		const res: any = await KnowledgeApplyDetail(row.id);
-		state.ruleForm = res.result ?? {};
-		state.dialogVisible = true;
-		state.loading = false;
-	} catch (error) {
-		state.loading = false;
-	}
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-};
-// 选择关联知识
-const changeKonwledge = (val: any) => {
-	const item = state.knowledgeOptions.find((v: any) => v.id === val);
-	if (item) state.ruleForm.code = item.code;
-};
-// 预览
-const onPreview = () => {
-	router.push({
-		name: 'knowledgePreview',
-		params: {
-			id: state.ruleForm.kbid,
-			tagsViewName: '知识预览',
-		},
-	});
-};
-// 创建知识
-const createKnowledge = () => {
-	router.push({
-		name: 'knowledgeEdit',
-		params: {
-			tagsViewName: '创建知识',
-		},
-	});
-};
-// 保存
-const onSubmit = async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.loading = true;
-		const request = {
-			id: state.ruleForm.id,
-			knowledgeId: state.ruleForm.knowledgeId,
-			opinion: state.ruleForm.opinion,
-			code: state.ruleForm.code,
-		};
-		KnowledgeHandle(request)
-			.then(() => {
-				emit('updateList');
-				closeDialog(); // 关闭弹窗
-				state.loading = false;
-				ElMessage.success('操作成功');
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	});
-};
-onMounted(async () => {
-	try {
-		const res: any = await KnowledgeGetKnowledge();
-		state.knowledgeOptions = res.result ?? [];
-		state.knowledgeOptions = state.knowledgeOptions.map((v: any) => ({
-			label: v.title,
-			value: v.id,
-			...v,
-		}));
-	} catch (error) {
-		console.log(error);
-	}
-});
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>

+ 0 - 244
src/views/knowledge/apply/index.vue

@@ -1,244 +0,0 @@
-<template>
-	<div class="knowledge-apply-container layout-pd">
-		<el-card shadow="never">
-			<el-tabs v-model="state.queryParams.Status" @tab-change="handleClick">
-				<el-tab-pane label="全部" name=" "></el-tab-pane>
-				<el-tab-pane :label="v.value" :name="v.key" v-for="(v, i) in state.statusOptions" :key="i"></el-tab-pane>
-				<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="mt15">
-					<el-form-item label="申请类型" prop="ApplyType">
-						<el-select v-model="state.queryParams.ApplyType" placeholder="请选择申请类型" class="w100">
-							<el-option v-for="item in state.eKnowledgeApplyType" :key="item.key" :label="item.value" :value="item.key" />
-						</el-select>
-					</el-form-item>
-					<el-form-item label="关键字" prop="Keyword">
-						<el-input v-model="state.queryParams.Keyword" @keyup.enter="queryList" placeholder="申请人/申请部门" clearable> </el-input>
-					</el-form-item>
-					<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="timeChange"
-							value-format="YYYY-MM-DD[T]HH:mm:ss"
-						/>
-						<!-- value-format="YYYY-MM-DD" -->
-					</el-form-item>
-					<el-form-item label="是否超时" prop="IsOvertime">
-						<el-select v-model="state.queryParams.IsOvertime" placeholder="请选择是否超时" class="w100">
-							<el-option label="否" value="1" />
-							<el-option label="是" value="0" />
-						</el-select>
-					</el-form-item>
-					<el-form-item>
-						<el-button type="primary" @click="queryList" :loading="state.loading" v-waves> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-						<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading">
-							<SvgIcon name="ele-Refresh" class="mr5" />重置
-						</el-button>
-					</el-form-item>
-				</el-form>
-			</el-tabs>
-		</el-card>
-		<el-card shadow="never">
-			<!-- 表格 -->
-			<el-table :data="state.tableList" v-loading="state.loading" row-key="id">
-				<el-table-column prop="content" label="申请内容" show-overflow-tooltip width="170"></el-table-column>
-				<el-table-column prop="knowledgeApplyTypeName" label="申请类型" show-overflow-tooltip></el-table-column>
-				<el-table-column label="状态" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span class="color-primary" v-if="row.status === 0">{{ row.statusName }}</span>
-						<span class="color-success" v-if="row.status === 1">{{ row.statusName }}</span>
-						<span class="color-danger" v-if="row.status === 2">{{ row.statusName }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="processor" label="处理人" show-overflow-tooltip width="170"></el-table-column>
-				<el-table-column prop="creationName" label="申请人" show-overflow-tooltip width="170"></el-table-column>
-				<el-table-column prop="creationOrgName" label="部门名称" show-overflow-tooltip width="170"></el-table-column>
-				<el-table-column prop="toNo" label="创建时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="截止时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.expiredTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="处理完成时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.handleTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="退回时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.returnTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column label="是否超时" show-overflow-tooltip>
-					<template #default="{ row }">
-						{{ row.isOvertime ? '是' : '否' }}
-					</template>
-				</el-table-column>
-				<el-table-column label="操作" width="160" fixed="right" align="center">
-					<template #default="{ row }">
-						<el-button
-							link
-							type="primary"
-							@click="onDetail(row)"
-							title="查看详情"
-							v-if="[1, 2].includes(row.status)"
-							v-auth="'knowledge:apply:detail'"
-						>
-							查看详情
-						</el-button>
-						<el-button link type="primary" @click="onHandle(row)" title="处理" v-if="[0].includes(row.status)" v-auth="'knowledge:apply:handle'">
-							处理
-						</el-button>
-						<el-button link type="danger" @click="onReturn(row)" title="退回" v-if="[0].includes(row.status)" v-auth="'knowledge:apply:recall'">
-							退回
-						</el-button>
-					</template>
-				</el-table-column>
-				<template #empty>
-					<Empty />
-				</template>
-			</el-table>
-			<!-- 分页 -->
-			<pagination
-				:total="state.total"
-				v-model:page="state.queryParams.PageIndex"
-				v-model:limit="state.queryParams.PageSize"
-				@pagination="queryList"
-			/>
-		</el-card>
-		<knowledge-apply-detail ref="KnowledgeApplyDetailRef" />
-		<knowledge-apply-handle ref="KnowledgeApplyHandleRef" @updateList="queryList" />
-	</div>
-</template>
-
-<script lang="ts" setup name="knowledgeApply">
-import { ref, reactive, onMounted, defineAsyncComponent } from 'vue';
-import type { FormInstance } from 'element-plus';
-import { ElMessage, ElMessageBox } from 'element-plus';
-import { auth } from '/@/utils/authFunction';
-import other from '/@/utils/other';
-import { formatDate } from '/@/utils/formatTime';
-import { throttle } from '/@/utils/tools';
-import {shortcuts} from '/@/utils/constants';
-import { handleList, KnowledgeReturn, baseData } from '/@/api/knowledge/apply';
-
-// 引入组件
-const KnowledgeApplyDetail = defineAsyncComponent(() => import('/@/views/knowledge/apply/component/Knowledge-apply-detail.vue')); // 详情组件
-const KnowledgeApplyHandle = defineAsyncComponent(() => import('/@/views/knowledge/apply/component/Knowledge-apply-handle.vue')); // 处理组件
-
-// 定义变量内容
-const state = reactive(<any>{
-	queryParams: {
-    PageSize: 10, // 每页条数
-		PageIndex: 1, // 当前页码
-		Status: ' ',  // 状态
-		ApplyType: '',  // 申请类型
-		IsOvertime: '', // 是否超时
-		StartTime: '',  // 开始时间
-		EndTime: '',  // 结束时间
-	},
-	tableList: [],  // 表格数据
-	loading: false, // 加载状态
-	total: 0, // 总条数
-	eKnowledgeApplyType: [],  // 申请类型数据
-	statusOptions: [],  // 状态数据
-});
-const ruleFormRef = ref<FormInstance>();  // 表单ref
-// 创建时间
-const timeChange = (val: string[]) => {
-	state.queryParams.StartTime = val[0];
-	state.queryParams.EndTime = val[1];
-};
-/** 获取知识申请列表 */
-const queryList = throttle(() => {
-	if (!auth('knowledge:apply:query')) ElMessage.error('抱歉,您没有权限查看知识申请列表');
-	else {
-		state.loading = true;
-		let request = other.deepClone(state.queryParams);
-		Reflect.deleteProperty(request, 'crTime'); // 删除无用的参数
-		handleList(request)
-			.then((response: any) => {
-				state.tableList = response?.result.items ?? [];
-				state.total = response?.result.total;
-				state.loading = false;
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	}
-}, 500);
-/** 重置按钮操作 */
-const resetQuery = throttle((formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	state.queryParams.StartTime = '';
-	state.queryParams.EndTime = '';
-	state.queryParams.PageIndex = 1;
-	queryList();
-}, 500);
-// 切换tab 查询列表
-const handleClick = () => {
-	queryList();
-};
-// 查看详情
-const KnowledgeApplyDetailRef = ref<RefType>();
-const onDetail = (row: any) => {
-	KnowledgeApplyDetailRef.value.openDialog(row);
-};
-// 处理
-const KnowledgeApplyHandleRef = ref<RefType>();
-const onHandle = (row: any) => {
-	KnowledgeApplyHandleRef.value.openDialog(row);
-};
-// 退回
-const onReturn = (row: any) => {
-	ElMessageBox.prompt('退回原因', '提示', {
-		confirmButtonText: '确定',
-		cancelButtonText: '取消',
-		inputPlaceholder: '请输入退回原因,不超过50字符',
-		draggable: true,
-		inputErrorMessage: '请输入退回原因',
-		inputType: 'textarea',
-		inputValidator: (value) => {
-			if (value) return true;
-			else return '请输入退回原因';
-		},
-	})
-		.then(({ value }) => {
-			let req = {
-				id: row.id,
-				opinion: value,
-			};
-			KnowledgeReturn(req)
-				.then(() => {
-					ElMessage.success('操作成功');
-					queryList();
-				})
-				.catch(() => {});
-		})
-		.catch(() => {});
-};
-// 页面基础数据
-const getBaseData = async () => {
-	try {
-		const { result } = await baseData();
-		state.statusOptions = result.eKnowledgeApplyStatus;
-		state.eKnowledgeApplyType = result.eKnowledgeApplyType;
-	} catch (error) {
-		console.log(error);
-	}
-};
-onMounted(() => {
-	queryList();
-	getBaseData();
-});
-</script>
-<style lang="scss" scoped></style>

+ 0 - 167
src/views/knowledge/apply/my/component/Knowledge-my-apply-add.vue

@@ -1,167 +0,0 @@
-<template>
-	<div class="knowledge-my-apply-add-container">
-		<el-dialog title="发起申请" v-model="state.dialogVisible" draggable width="769px">
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="100px">
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="申请类型" prop="knowledgeApplyType" :rules="[{ required: true, message: '请选择申请类型', trigger: 'change' }]">
-							<el-radio-group v-model="state.ruleForm.knowledgeApplyType">
-								<el-radio :label="0">新增</el-radio>
-								<el-radio :label="1">更新</el-radio>
-							</el-radio-group>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.knowledgeApplyType === 1">
-						<el-form-item label="关联知识" prop="knowledgeId" :rules="[{ required: false, message: '请选择关联知识', trigger: 'change' }]">
-							<el-select-v2
-								v-model="state.ruleForm.knowledgeId"
-								filterable
-								clearable
-								:options="state.knowledgeOptions"
-								placeholder="请选择关联知识"
-								class="w100"
-								@change="changeKnowledge"
-							/>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="申请内容" prop="content" :rules="[{ required: true, message: '请填写申请内容', trigger: 'blur' }]">
-							<el-input
-								v-model="state.ruleForm.content"
-								type="textarea"
-								:autosize="{ minRows: 6, maxRows: 10 }"
-								placeholder="请填写申请内容"
-								clearable
-								maxlength="2000"
-							>
-							</el-input>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.knowledgeApplyType === 0">
-						<el-form-item label="处理部门" prop="departmentId" :rules="[{ required: true, message: '请选择处理部门', trigger: 'change' }]">
-							<el-cascader
-								:options="state.orgData"
-								filterable
-								:props="{ checkStrictly: true, value: 'id', label: 'orgName', emitPath: false }"
-								placeholder="请选择处理部门"
-								clearable
-								class="w100"
-								v-model="state.ruleForm.departmentId"
-								ref="cascadeRef"
-								@change="getKnowledgeList"
-							>
-							</el-cascader>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-else>
-						<el-form-item label="部门名称" prop="department">
-							{{ state.ruleForm.department }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="截止日期" prop="expiredTime" :rules="[{ required: false, message: '请选择截止日期', trigger: 'change' }]">
-							<template #label>
-								<div style="height: 34px; display: flex; align-items: center">
-									截止日期
-									<el-tooltip placement="top-start">
-										<SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
-										<template #content> 超过处理截止日期未反馈,将影响处理部门绩效考核,请谨慎设置 </template>
-									</el-tooltip>
-								</div>
-							</template>
-							<el-date-picker
-								v-model="state.ruleForm.expiredTime"
-								type="datetime"
-								placeholder="请选择截止日期"
-								class="w100"
-								value-format="YYYY-MM-DD[T]HH:mm:ss"
-							/>
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-			<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>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-
-<script setup lang="ts" name="knowledgeMyApplyAdd">
-import { reactive, ref } from 'vue';
-import { ElMessage, FormInstance } from 'element-plus';
-import { KnowledgeApplyAdd } from '/@/api/knowledge/apply';
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['updateList']);
-
-// 定义变量内容
-const ruleFormRef = ref<any>(); // 表单ref
-const state = reactive<any>({
-	dialogVisible: false, // 弹窗显示隐藏
-	ruleForm: {
-		knowledgeApplyType: 0,  // 申请类型
-    knowledgeId: null, // 关联知识id
-    content: '', // 申请内容
-    departmentId: '', // 处理部门id
-    department: '', // 处理部门
-    expiredTime: '', // 截止日期
-	},
-	orgData: [],  // 处理部门列表
-	loading: false, // 确定按钮loading
-	knowledgeOptions: [], //关联知识列表
-});
-// 打开弹窗
-const openDialog = (orgData: any, knowledgeOptions: any) => {
-	ruleFormRef.value?.clearValidate();
-	ruleFormRef.value?.resetFields();
-	state.orgData = orgData;
-	state.knowledgeOptions = knowledgeOptions;
-	state.dialogVisible = true;
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-};
-const cascadeRef = ref<RefType>();
-// 获取选择name值
-const getKnowledgeList = () => {
-	let currentNode = cascadeRef.value.getCheckedNodes();
-	state.ruleForm.department = currentNode[0]?.label ?? '';
-};
-// 选择关联知识
-const changeKnowledge = (val: any) => {
-	const item = state.knowledgeOptions.find((v: any) => v.id === val);
-	if (item) {
-		state.ruleForm.department = item.department;
-		state.ruleForm.departmentId = item.departmentId;
-		state.ruleForm.code = item.code;
-	}
-};
-// 新增
-const onSubmit = async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.loading = true;
-		KnowledgeApplyAdd(state.ruleForm)
-			.then(() => {
-				emit('updateList');
-				closeDialog(); // 关闭弹窗
-				state.loading = false;
-				ElMessage.success('新增成功');
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	});
-};
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>

+ 0 - 131
src/views/knowledge/apply/my/component/Knowledge-my-apply-detail.vue

@@ -1,131 +0,0 @@
-<template>
-	<div class="knowledge-my-apply-detail-container">
-		<el-dialog title="申请详情" v-model="state.dialogVisible" draggable  width="769px">
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="100px">
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="申请类型" class="mb10">
-							{{ state.ruleForm.knowledgeApplyType === 0 ? '新增' : '更新' }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="诉求处理部门" class="mb10">
-							{{ state.ruleForm.department }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="申请人" class="mb10">
-							{{ state.ruleForm.creationName }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
-						<el-form-item label="申请部门" class="mb10">
-							{{ state.ruleForm.creationBMName }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.expiredTime">
-						<el-form-item label="截止时间" class="mb10">
-							{{ formatDate(state.ruleForm.expiredTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="诉求内容" class="mb10">
-							{{ state.ruleForm.content }}
-						</el-form-item>
-					</el-col>
-					<el-divider />
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.kbTitle">
-						<el-form-item label="关联知识" class="mb10">
-							<el-button link type="primary" @click="onPreview">{{ state.ruleForm.kbTitle }}</el-button>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.processor">
-						<el-form-item label="处理人" class="mb10">
-							{{ state.ruleForm.processor }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.handleTime">
-						<el-form-item label="处理完成时间" class="mb10">
-							{{ formatDate(state.ruleForm.handleTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.returnTime">
-						<el-form-item label="退回时间" class="mb10">
-							{{ formatDate(state.ruleForm.returnTime, 'YYYY-mm-dd HH:MM:SS') }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="state.ruleForm.opinion">
-						<el-form-item label="备注" class="mb10">
-							{{ state.ruleForm.opinion }}
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="closeDialog" class="default-button">关 闭</el-button>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-
-<script setup lang="ts" name="knowledgeMyApplyDetail">
-import { reactive, ref } from 'vue';
-import { useRouter } from 'vue-router';
-import { formatDate } from '/@/utils/formatTime';
-import { KnowledgeApplyDetail } from '/@/api/knowledge/apply';
-
-// 定义变量内容
-const ruleFormRef = ref<any>(); // 表单ref
-const router = useRouter(); // 路由
-const state = reactive<any>({
-	dialogVisible: false,
-	ruleForm: {
-    knowledgeApplyType: 1,  // 申请类型
-    department: '', // 诉求处理部门
-    creationName: '', // 申请人
-    creationBMName: '', // 申请部门
-    expiredTime: '', // 截止时间
-    content: '', // 诉求内容
-    kbTitle: '', // 关联知识
-    processor: '', // 处理人
-    handleTime: '', // 处理完成时间
-    returnTime: '', // 退回时间
-    opinion: '', // 备注
-	},
-	orgData: [], // 机构数据
-	loading: false, // 加载状态
-});
-// 打开弹窗
-const openDialog = async (row: any) => {
-	state.loading = true;
-	try {
-		const res: any = await KnowledgeApplyDetail(row.id);
-		state.ruleForm = res.result ?? {};
-		state.dialogVisible = true;
-		state.loading = false;
-	} catch (error) {
-		state.loading = false;
-	}
-};
-// 预览
-const onPreview = () => {
-	router.push({
-		name: 'knowledgePreview',
-		params: {
-			id: state.ruleForm.kbid,
-			tagsViewName: '知识预览',
-		},
-	});
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-};
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>

+ 0 - 167
src/views/knowledge/apply/my/component/Knowledge-my-apply-edit.vue

@@ -1,167 +0,0 @@
-<template>
-	<div class="knowledge-my-apply-edit-container">
-		<el-dialog title="编辑申请" v-model="state.dialogVisible" draggable width="769px">
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="100px">
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="申请类型" prop="knowledgeApplyType" :rules="[{ required: true, message: '请选择申请类型', trigger: 'change' }]">
-							<el-radio-group v-model="state.ruleForm.knowledgeApplyType">
-								<el-radio :label="0">新增</el-radio>
-								<el-radio :label="1">更新</el-radio>
-							</el-radio-group>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.knowledgeApplyType === 1">
-						<el-form-item label="关联知识" prop="knowledgeId" :rules="[{ required: false, message: '请选择关联知识', trigger: 'change' }]">
-							<el-select-v2
-								v-model="state.ruleForm.knowledgeId"
-								filterable
-								clearable
-								:options="state.knowledgeOptions"
-								placeholder="请选择关联知识"
-								class="w100"
-								@change="changeKonwledge"
-							/>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="申请内容" prop="content" :rules="[{ required: true, message: '请填写申请内容', trigger: 'blur' }]">
-							<el-input
-								v-model="state.ruleForm.content"
-								type="textarea"
-								:autosize="{ minRows: 6, maxRows: 10 }"
-								placeholder="请填写申请内容"
-								clearable
-								maxlength="2000"
-							>
-							</el-input>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.knowledgeApplyType === 0">
-						<el-form-item label="处理部门" prop="departmentId" :rules="[{ required: true, message: '请选择处理部门', trigger: 'change' }]">
-							<el-cascader
-								:options="state.orgData"
-								filterable
-								:props="{ checkStrictly: true, value: 'id', label: 'orgName', emitPath: false }"
-								placeholder="请选择处理部门"
-								clearable
-								class="w100"
-								v-model="state.ruleForm.departmentId"
-								ref="cascaderRef"
-								@change="getselKnowledgeList"
-							>
-							</el-cascader>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-else>
-						<el-form-item label="部门名称" prop="department">
-							{{ state.ruleForm.department }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="截止日期" prop="expiredTime" :rules="[{ required: false, message: '请选择截止日期', trigger: 'change' }]">
-							<template #label>
-								<div style="height: 34px; display: flex; align-items: center">
-									截止日期
-									<el-tooltip placement="top-start">
-										<SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
-										<template #content> 超过处理截止日期未反馈,将影响处理部门绩效考核,请谨慎设置 </template>
-									</el-tooltip>
-								</div>
-							</template>
-							<el-date-picker
-								v-model="state.ruleForm.expiredTime"
-								type="datetime"
-								placeholder="请选择截止日期"
-								class="w100"
-								value-format="YYYY-MM-DD[T]HH:mm:ss"
-							/>
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-			<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>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-
-<script setup lang="ts" name="knowledgeMyApplyEdit">
-import { reactive, ref } from 'vue';
-import { ElMessage, FormInstance } from 'element-plus';
-import { KnowledgeApplyUpdate, KnowledgeApplyDetail } from '/@/api/knowledge/apply';
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['updateList']);
-
-// 定义变量内容
-const ruleFormRef = ref<any>(); // 表单ref
-const state = reactive<any>({
-	dialogVisible: false, // 弹窗显示隐藏
-	ruleForm: {
-    knowledgeApplyType: 1,  // 申请类型
-    knowledgeId: null, // 关联知识id
-    content: '', // 申请内容
-    departmentId: '', // 处理部门id
-    department: '', // 处理部门
-    expiredTime: '', // 截止日期
-	},
-	orgData: [], // 上级
-	loading: false,
-	knowledgeOptions: [], //关联知识列表
-});
-// 打开弹窗
-const openDialog = async (row: any, orgData: any, knowledgeOptions: any) => {
-	try {
-		const res: any = await KnowledgeApplyDetail(row.id);
-		state.ruleForm = res.result ?? {};
-		ruleFormRef.value?.clearValidate();
-		ruleFormRef.value?.resetFields();
-		state.orgData = orgData;
-		state.knowledgeOptions = knowledgeOptions;
-		state.dialogVisible = true;
-	} catch (error) {
-		state.loading = false;
-	}
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-};
-const cascaderRef = ref<RefType>();
-// 获取选择name值
-const getselKnowledgeList = () => {
-	let currentNode = cascaderRef.value.getCheckedNodes();
-	state.ruleForm.department = currentNode[0]?.label ?? '';
-};
-// 选择关联知识
-const changeKonwledge = (val: any) => {
-	const item = state.knowledgeOptions.find((v: any) => v.id === val);
-	if (item) {
-		state.ruleForm.department = item.department;
-		state.ruleForm.departmentId = item.departmentId;
-		state.ruleForm.code = item.code;
-	}
-};
-// 新增
-const onSubmit = async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		KnowledgeApplyUpdate(state.ruleForm).then(() => {
-			emit('updateList');
-			closeDialog(); // 关闭弹窗
-			ElMessage.success('新增成功');
-		});
-	});
-};
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>

+ 0 - 286
src/views/knowledge/apply/my/index.vue

@@ -1,286 +0,0 @@
-<template>
-	<div class="knowledge-apply-my-container layout-pd">
-		<el-card shadow="never">
-			<el-tabs v-model="state.queryParams.Status" @tab-change="handleClick">
-				<el-tab-pane label="全部" name=" "></el-tab-pane>
-				<el-tab-pane :label="v.value" :name="v.key" v-for="(v, i) in state.statusOptions" :key="i"></el-tab-pane>
-				<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="mt15">
-					<el-form-item label="申请类型" prop="ApplyType">
-						<el-select v-model="state.queryParams.ApplyType" placeholder="请选择申请类型" class="w100">
-							<el-option v-for="item in state.ApplyTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
-						</el-select>
-					</el-form-item>
-					<el-form-item label="是否超时" prop="IsOvertime">
-						<el-select v-model="state.queryParams.IsOvertime" placeholder="请选择是否超时" class="w100">
-							<el-option label="否" value="1" />
-							<el-option label="是" value="0" />
-						</el-select>
-					</el-form-item>
-					<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="timeChange"
-							value-format="YYYY-MM-DD[T]HH:mm:ss"
-						/>
-					</el-form-item>
-					<el-form-item>
-						<el-button type="primary" @click="queryList" :loading="state.loading" v-waves> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-						<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading">
-							<SvgIcon name="ele-Refresh" class="mr5" />重置
-						</el-button>
-					</el-form-item>
-				</el-form>
-			</el-tabs>
-		</el-card>
-		<el-card shadow="never">
-			<div class="mb20">
-				<el-button type="primary" @click="onApply" v-auth="'knowledge:myApply:add'">
-					<SvgIcon name="ele-Plus" class="mr5" />
-					发起申请
-				</el-button>
-			</div>
-			<!-- 表格 -->
-			<el-table :data="state.tableList" v-loading="state.loading" row-key="id">
-				<el-table-column prop="content" label="申请内容" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="knowledgeApplyTypeName" label="申请类型" show-overflow-tooltip></el-table-column>
-				<el-table-column label="状态" show-overflow-tooltip>
-					<template #default="{ row }">
-            <span v-if="row.status === 0" class="color-primary">{{ row.statusName }}</span>
-            <span v-if="row.status === 1" class="color-success">{{ row.statusName }}</span>
-            <span v-if="row.status === 2" class="color-danger">{{ row.statusName }}</span>
-            <span v-if="row.status === 3" class="color-info">{{ row.statusName }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="创建时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="处理完成时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.handleTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="撤回时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.revokeTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="退回时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.returnTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column label="是否超时" show-overflow-tooltip>
-					<template #default="{ row }">
-						{{ row.isOvertime ? '是' : '否' }}
-					</template>
-				</el-table-column>
-				<el-table-column label="操作" width="180" fixed="right" align="center">
-					<template #default="{ row }">
-						<el-button
-							link
-							type="primary"
-							@click="onDetail(row)"
-							title="查看详情"
-							v-if="[0, 1, 2].includes(row.status)"
-							v-auth="'knowledge:apply:detail'"
-						>
-							查看详情
-						</el-button>
-						<el-button link type="primary" @click="onEdit(row)" title="编辑" v-if="[2, 3].includes(row.status)" v-auth="'knowledge:myApply:edit'">
-							编辑
-						</el-button>
-						<el-button link type="danger" @click="onRecall(row)" title="撤回" v-if="[0].includes(row.status)" v-auth="'knowledge:myApply:recall'">
-							撤回
-						</el-button>
-						<el-button link type="danger" @click="onDelete(row)" title="删除" v-if="[2, 3].includes(row.status)" v-auth="'knowledge:myApply:delete'">
-							删除
-						</el-button>
-					</template>
-				</el-table-column>
-				<template #empty>
-					<Empty />
-				</template>
-			</el-table>
-			<!-- 分页 -->
-			<pagination
-				:total="state.total"
-				v-model:page="state.queryParams.PageIndex"
-				v-model:limit="state.queryParams.PageSize"
-				@pagination="queryList"
-			/>
-		</el-card>
-		<!-- 新增 -->
-		<knowledge-my-apply-add ref="KnowledgeMyApplyAddRef" @updateList="queryList" />
-		<!-- 修改 -->
-		<knowledge-my-apply-edit ref="KnowledgeMyApplyEditRef" @updateList="queryList" />
-		<!-- 详情 -->
-		<knowledge-my-apply-detail ref="KnowledgeMyApplyDetailRef" />
-	</div>
-</template>
-
-<script lang="ts" setup name="MyKnowledgeApply">
-import { ref, reactive, onMounted, defineAsyncComponent } from 'vue';
-import type { FormInstance } from 'element-plus';
-import { ElMessage, ElMessageBox } from 'element-plus';
-import { auth } from '/@/utils/authFunction';
-import { formatDate } from '/@/utils/formatTime';
-import other from '/@/utils/other';
-import { throttle } from '/@/utils/tools';
-import { shortcuts } from '/@/utils/constants';
-import { KnowledgeApply, KnowledgeRemove, KnowledgeCancel, baseData } from '/@/api/knowledge/apply';
-import { getOrgList } from '/@/api/system/organize';
-import { KnowledgeGetKnowledge } from '/@/api/knowledge';
-
-// 引入组件
-const KnowledgeMyApplyAdd = defineAsyncComponent(() => import('/@/views/knowledge/apply/my/component/Knowledge-my-apply-add.vue')); // 新增组件
-const KnowledgeMyApplyEdit = defineAsyncComponent(() => import('/@/views/knowledge/apply/my/component/Knowledge-my-apply-edit.vue')); // 修改组件
-const KnowledgeMyApplyDetail = defineAsyncComponent(() => import('/@/views/knowledge/apply/my/component/Knowledge-my-apply-detail.vue')); // 详情组件
-// 定义变量内容
-const state = reactive(<any>{
-	queryParams: {
-		PageIndex: 1, // 当前页码
-		PageSize: 10, // 每页条数
-		Status: ' ',  // 状态
-		ApplyType: '',  // 申请类型
-		IsOvertime: '', // 是否超时
-		StartTime: '',  // 开始时间
-		EndTime: '',  // 结束时间
-	},
-	tableList: [],  // 表格数据
-	loading: false,   // 加载状态
-	total: 0, // 总条数
-	ApplyTypeOptions: [ // 申请类型数据
-		{
-			label: '新增',
-			value: 0,
-		},
-		{
-			label: '修改',
-			value: 1,
-		},
-	],
-	orgData: [],  // 组织机构数据
-});
-const ruleFormRef = ref<FormInstance>();  // 表单实例
-// 创建时间
-const timeChange = (val: string[]) => {
-	if (val) {
-		state.queryParams.StartTime = val[0];
-		state.queryParams.EndTime = val[1];
-	}
-};
-/** 获取我的知识申请列表 */
-const queryList = throttle(() => {
-	if (!auth('knowledge:myApply:query')) ElMessage.error('抱歉,您没有权限查看知识申请列表');
-	else {
-		state.loading = true;
-		let request = other.deepClone(state.queryParams);
-		Reflect.deleteProperty(request, 'crTime'); // 删除无用的参数
-		KnowledgeApply(request)
-			.then((response: any) => {
-				state.tableList = response?.result.items ?? [];
-				state.total = response?.result.total;
-				state.loading = false;
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	}
-}, 500);
-/** 重置按钮操作 */
-const resetQuery = throttle((formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	state.queryParams.PageIndex = 1;
-	state.queryParams.StartTime = '';
-	state.queryParams.EndTime = '';
-	queryList();
-}, 500);
-// 切换tab 查询列表
-const handleClick = () => {
-	queryList();
-};
-// 查看详情
-const KnowledgeMyApplyDetailRef = ref<RefType>(); // 详情实例
-const onDetail = (row: any) => {
-	KnowledgeMyApplyDetailRef.value.openDialog(row);
-};
-// 发起申请
-const KnowledgeMyApplyAddRef = ref<RefType>();  // 新增实例
-const onApply = () => {
-	KnowledgeMyApplyAddRef.value.openDialog(state.orgData, state.knowledgeOptions);
-};
-// 修改申请
-const KnowledgeMyApplyEditRef = ref<RefType>(); // 修改实例
-const onEdit = (row: any) => {
-	KnowledgeMyApplyEditRef.value.openDialog(row, state.orgData, state.knowledgeOptions);
-};
-// 撤回
-const onRecall = (row: any) => {
-	ElMessageBox.confirm(`是否确定要撤回申请?撤回后请到【主动撤回】中进行查看和管理`, '提示', {
-		confirmButtonText: '确认',
-		cancelButtonText: '取消',
-		type: 'warning',
-		draggable: true,
-		cancelButtonClass: 'default-button',
-	})
-		.then(() => {
-			KnowledgeCancel(row.id).then(() => {
-				ElMessage.success('操作成功');
-				queryList();
-			});
-		})
-		.catch(() => {});
-};
-// 删除
-const onDelete = (row: any) => {
-	ElMessageBox.confirm(`是否确定删除该申请?`, '提示', {
-		confirmButtonText: '确认',
-		cancelButtonText: '取消',
-		type: 'warning',
-		draggable: true,
-		cancelButtonClass: 'default-button',
-	})
-		.then(() => {
-			KnowledgeRemove(row.id).then(() => {
-				ElMessage.success('操作成功');
-				queryList();
-			});
-		})
-		.catch(() => {});
-};
-// 页面基础数据
-const getBaseData = async () => {
-	try {
-		const { result } = await baseData();
-		state.statusOptions = result.eKnowledgeApplyStatus;
-		state.eKnowledgeApplyType = result.eKnowledgeApplyType;
-	} catch (error) {
-		console.log(error);
-	}
-};
-onMounted(async () => {
-	queryList();
-	await getBaseData();
-	try {
-		const res: any = await Promise.all([getOrgList(), KnowledgeGetKnowledge()]);
-		state.orgData = res[0].result ?? [];
-		state.knowledgeOptions = res[1].result ?? [];
-		state.knowledgeOptions = state.knowledgeOptions.map((v: any) => ({
-			label: v.title,
-			value: v.id,
-			...v,
-		}));
-	} catch (error) {
-		console.log(error);
-	}
-});
-</script>

+ 11 - 18
src/views/knowledge/knowledge/component/Knowledge-standard-info.vue → src/views/knowledge/component/Knowledge-standard-info.vue

@@ -1,17 +1,10 @@
 <template>
-	<div class="knowledge-Standard-container">
-		<el-dialog title="知识编写规范" v-model="state.dialogVisible" draggable width="70%">
-			<div>
-				<h3 class="font18">{{ state.info.title }}</h3>
-				<div v-html="state.info.content" class="mt20 lineHeight24"></div>
-			</div>
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="state.dialogVisible = false" class="default-button">关 闭</el-button>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
+	<el-drawer title="知识编写规范" v-model="state.drawerVisible" size="40%">
+		<div>
+			<h3 class="font18">{{ state.info.title }}</h3>
+			<div v-html="state.info.content" class="mt20 lineHeight24"></div>
+		</div>
+	</el-drawer>
 </template>
 
 <script setup lang="ts" name="knowledgeStandardInfo">
@@ -22,18 +15,18 @@ import { standardInfo } from '/@/api/knowledge/standard';
 const state = reactive<any>({
 	dialogVisible: false,
 	info: {
-    title: '', // 标题
-    content: '', // 内容
-  },
+		title: '', // 标题
+		content: '', // 内容
+	},
 });
 // 打开弹窗
 const openDialog = () => {
 	standardInfoFn();
-	state.dialogVisible = true;
+	state.drawerVisible = true;
 };
 // 关闭弹窗
 const closeDialog = () => {
-	state.dialogVisible = false;
+	state.drawerVisible = false;
 };
 // 查询规范详情
 const standardInfoFn = async () => {

+ 2 - 7
src/views/knowledge/config/standard/index.vue

@@ -14,17 +14,12 @@
 				</el-form-item>
 			</el-form>
 		</el-card>
-		<el-dialog title="知识编写规范预览" v-model="state.dialogVisible" draggable width="70%">
+		<el-drawer title="知识编写规范预览" v-model="state.dialogVisible" size="40%">
 			<div>
 				<h3 class="font18">{{ state.ruleForm.title }}</h3>
 				<div v-html="state.ruleForm.content" class="mt20 lineHeight24"></div>
 			</div>
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="state.dialogVisible = false" class="default-button">关 闭</el-button>
-				</span>
-			</template>
-		</el-dialog>
+		</el-drawer>
 	</div>
 </template>
 

+ 22 - 17
src/views/knowledge/config/type/index.vue

@@ -1,17 +1,21 @@
 <template>
 	<div class="knowledge-type-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-			<div class="flex-center-between mb20">
-				<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
-					<el-form-item label="关键字" prop="keyword" class="mb0">
-						<el-input v-model="state.queryParams.keyword" placeholder="类型名称" clearable @keyup.enter="handleQuery" style="width: 250px" />
-					</el-form-item>
-					<el-form-item class="mb0">
-						<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-						<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.loading"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-					</el-form-item>
-				</el-form>
-				<div>
+			<el-row class="mb20" :gutter="10">
+				<el-col :xs="24" :sm="12" :md="18" :lg="18" :xl="18">
+					<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
+						<el-form-item label="关键字" prop="keyword" class="mb0">
+							<el-input v-model="state.queryParams.keyword" placeholder="类型名称" clearable @keyup.enter="handleQuery" style="width: 250px" />
+						</el-form-item>
+						<el-form-item class="mb0">
+							<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+							<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.loading">
+								<SvgIcon name="ele-Refresh" class="mr5" />重置
+							</el-button>
+						</el-form-item>
+					</el-form>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6" style="text-align: right">
 					<el-button type="primary" @click="expand">
 						<SvgIcon
 							name="ele-ArrowDownBold"
@@ -22,8 +26,8 @@
 						{{ state.isExpand ? '收起' : '展开' }}</el-button
 					>
 					<el-button type="primary" @click="onOpenAdd" v-auth="'knowledge:type:add'"> <SvgIcon name="ele-Plus" class="mr5" /> 新增 </el-button>
-				</div>
-			</div>
+				</el-col>
+			</el-row>
 			<!-- 表格 -->
 			<el-auto-resizer class="table" v-loading="state.loading">
 				<template #default="{ height, width }">
@@ -66,11 +70,12 @@ const state = reactive({
 	tableData: <EmptyArrayType>[], // 获取所有菜单
 	staticArr: <EmptyArrayType>[], // 获取所有菜单
 	loading: false, // 加载状态
-	isExpand: false,  // 是否展开
-	queryParams: {  // 查询参数
+	isExpand: false, // 是否展开
+	queryParams: {
+		// 查询参数
 		keyword: '',
 	},
-	expandedRowKeys: <EmptyArrayType>[],  // 展开的行
+	expandedRowKeys: <EmptyArrayType>[], // 展开的行
 	columns: [
 		{
 			key: 'name',
@@ -255,7 +260,7 @@ const onOpenAdd = () => {
 	knowledgeTypeAddRef.value.openDialog(state.tableData);
 };
 // 打开编辑分类弹窗
-const knowledgeTypeEditRef = ref<RefType>();  // 修改ref
+const knowledgeTypeEditRef = ref<RefType>(); // 修改ref
 const onOpenEdit = (row: any) => {
 	knowledgeTypeEditRef.value.openDialog(row, state.tableData);
 };

+ 169 - 0
src/views/knowledge/error/components/Error-add.vue

@@ -0,0 +1,169 @@
+<template>
+	<el-drawer title="知识纠错" v-model="drawerVisible" size="40%" destroy-on-close @close="close">
+		<el-form :model="state.ruleForm" label-width="110px" ref="ruleFormRef">
+			<el-row>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="知识标题"> {{state.ruleForm.title}} </el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+					<el-form-item label="知识创建部门:"> {{state.ruleForm.creatorOrgName}}  </el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+					<el-form-item label="知识创建人:"> {{state.ruleForm.creatorName}}  </el-form-item>
+				</el-col>
+        <template v-if="isReply">
+          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+            <el-form-item label="纠错人部门:"> {{ state.ruleForm.orgName }} </el-form-item>
+          </el-col>
+          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+            <el-form-item label="纠错人:"> {{ state.ruleForm.name }} </el-form-item>
+          </el-col>
+        </template>
+        <template v-else>
+          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+            <el-form-item label="纠错人部门:"> {{ userInfos.orgName }} </el-form-item>
+          </el-col>
+          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+            <el-form-item label="纠错人:"> {{ userInfos.orgName }} </el-form-item>
+          </el-col>
+        </template>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="纠错内容" prop="opinion" :rules="[{ required: true, message: '请填写纠错内容', trigger: 'blur' }]">
+						<el-input
+							type="textarea"
+							v-model="state.ruleForm.opinion"
+							placeholder="请填写纠错内容"
+							:autosize="{ minRows: 6, maxRows: 8 }"
+              :disabled="isReply"
+						></el-input>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="附件" prop="additions" :rules="[{ required: false, message: '请填写诉求内容', trigger: 'change' }]">
+						<annex-list ref="annexListRef" classify="知识纠错上传" />
+					</el-form-item>
+				</el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="isReply">
+          <el-divider style="margin: 15px 0" />
+          <el-form-item label="答复内容" prop="replyContent" :rules="[{ required: true, message: '请填写答复内容', trigger: 'blur' }]">
+            <el-input
+                type="textarea"
+                v-model="state.ruleForm.replyContent"
+                placeholder="请填写答复内容"
+                :autosize="{ minRows: 6, maxRows: 8 }"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+			</el-row>
+		</el-form>
+    <template #footer v-if="isReply">
+			<span class="dialog-footer">
+				<el-button @click="drawerVisible = false" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onReply(ruleFormRef)" :loading="state.loading">答 复</el-button>
+			</span>
+    </template>
+    <template #footer v-else>
+			<span class="dialog-footer">
+				<el-button @click="drawerVisible = false" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">提 交</el-button>
+			</span>
+    </template>
+	</el-drawer>
+</template>
+<script setup lang="ts" name="knowledgeErrorAdd">
+import { ref, defineAsyncComponent, reactive } from 'vue';
+import {ElMessage, FormInstance} from 'element-plus';
+import { storeToRefs } from 'pinia';
+import { useUserInfo } from '/@/stores/userInfo';
+import { correctionAdd,correctionReply,correctionDetail } from '/@/api/knowledge/error';
+
+const emit = defineEmits(['submitSuccess'])
+
+const state = reactive<any>({
+	ruleForm: {
+		title: '', // 标题
+		content: '', // 内容
+		additions: [], // 附件
+	},
+	loading: false, // 加载状态
+});
+
+const AnnexList = defineAsyncComponent(() => import('/@/components/AnnexList/index.vue')); // 附件列表
+const drawerVisible = ref<boolean>(false);
+const storesUserInfo = useUserInfo();
+const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
+
+// 提交
+const ruleFormRef = ref<RefType>();
+const annexListRef = ref<RefType>(); // 附件列表
+const isReply = ref<boolean>(false); // 是否答复
+// 打开弹窗
+const openDialog = (row:any,reply = false) => {
+  isReply.value = reply;
+  if (reply) {
+    correctionDetail(row.id)
+        .then((res) => {
+          state.ruleForm = res.result;
+          state.ruleForm.opinion = state.ruleForm.content;
+          state.ruleForm.title = state.ruleForm.knowledge?.title;
+          state.ruleForm.creatorOrgName = state.ruleForm.knowledge?.creatorOrgName; //知识创建人
+          state.ruleForm.creatorName = state.ruleForm.knowledge?.creatorName; // 知识创建人
+          state.ruleForm.name = state.ruleForm.creatorName; // 提问人
+          state.ruleForm.orgName = state.ruleForm.creatorOrgName; // 提问人部门
+          drawerVisible.value = true;
+        })
+        .catch(() => {
+          ElMessage.error('获取详情失败');
+        });
+  } else {
+    state.ruleForm = row;
+    drawerVisible.value = true;
+  }
+};
+// 关闭弹窗
+const closeDialog = () => {
+  drawerVisible.value = false;
+};
+const close = () => {
+  ruleFormRef.value?.resetFields();
+  ruleFormRef.value?.clearValidate();
+};
+// 提交
+const onSubmit = async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+    const request = {
+      knowledgeId: state.ruleForm.id,
+      content: state.ruleForm.opinion,
+      files: annexListRef.value?.fileList,
+    };
+    correctionAdd(request).then(()=>{
+      ElMessage.success('操作成功');
+      closeDialog();
+      emit('submitSuccess')
+    })
+	});
+};
+// 答复
+const onReply = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate((valid: boolean) => {
+    if (!valid) return;
+    const request = {
+      id: state.ruleForm.id,
+      replyContent: state.ruleForm.replyContent,
+    };
+    correctionReply(request).then(() => {
+      ElMessage.success('操作成功');
+      closeDialog();
+      emit('submitSuccess');
+    });
+  });
+};
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>
+<style scoped lang="scss"></style>

+ 174 - 0
src/views/knowledge/error/index.vue

@@ -0,0 +1,174 @@
+<template>
+	<div class="knowledge-error-container layout-pd">
+		<el-card shadow="never">
+			<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
+				<el-form-item label="知识分类" prop="KnowledgeTypeId">
+					<el-cascader
+						:options="state.typeData"
+						filterable
+						:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
+						placeholder="请选择知识分类"
+						v-model="state.queryParams.KnowledgeTypeId"
+						ref="cascadeRef"
+					>
+					</el-cascader>
+				</el-form-item>
+				<el-form-item label="纠错人" prop="CreatorName">
+					<el-input v-model="state.queryParams.CreatorName" placeholder="请输入纠错人" clearable @keyup.enter="queryList" style="width: 250px" />
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="queryList" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+				</el-form-item>
+			</el-form>
+		</el-card>
+		<el-card shadow="never">
+			<!-- 表格 -->
+			<el-table :data="state.tableData" v-loading="state.loading">
+				<el-table-column prop="knowledge.title" label="知识标题" show-overflow-tooltip width="130"></el-table-column>
+				<el-table-column prop="knowledgeTypeText" label="知识分类" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="knowledge.statusText" label="知识状态" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="stateText" label="答复状态" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="creatorName" label="纠错人" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="creationTime" label="纠错时间" show-overflow-tooltip width="170">
+					<template #default="{ row }">
+						<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="content" label="纠错内容" show-overflow-tooltip></el-table-column>
+				<el-table-column prop="replyContent" label="答复内容" show-overflow-tooltip></el-table-column>
+				<el-table-column label="答复时间" show-overflow-tooltip width="170">
+					<template #default="{ row }">
+						<span>{{ formatDate(row.replyTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column label="操作" width="200" fixed="right" align="center">
+					<template #default="{ row }">
+						<el-button link type="primary" @click="onPreview(row)" v-auth="'knowledge:index:preview'" title="知识详情"> 知识详情 </el-button>
+						<el-button link type="primary" @click="onReply(row)" v-auth="'knowledge:error:reply'" title="答复" v-if="[0].includes(row.state)">
+							答复
+						</el-button>
+						<el-button
+							link
+							type="primary"
+							@click="onEdit(row)"
+							v-auth="'knowledge:error:edit'"
+							title="编辑"
+							v-if="![1, 3].includes(row.knowledge?.status)"
+						>
+							去修改
+						</el-button>
+					</template>
+				</el-table-column>
+				<template #empty>
+					<Empty />
+				</template>
+			</el-table>
+			<!-- 分页 -->
+			<pagination
+				:total="state.total"
+				v-model:page="state.queryParams.PageIndex"
+				v-model:limit="state.queryParams.PageSize"
+				@pagination="queryList"
+			/>
+		</el-card>
+		<!-- 知识纠错 -->
+		<error-add ref="errorAddRef" @submitSuccess="queryList" />
+	</div>
+</template>
+
+<script lang="ts" setup name="knowledgeError">
+import { reactive, ref, onMounted, defineAsyncComponent } from 'vue';
+import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
+import { formatDate } from '/@/utils/formatTime';
+import { auth } from '/@/utils/authFunction';
+import { correctionList } from '/@/api/knowledge/error';
+import { useRouter } from 'vue-router';
+import { treeList } from '/@/api/knowledge/type';
+
+// 引入组件
+const ErrorAdd = defineAsyncComponent(() => import('/@/views/knowledge/error/components/Error-add.vue')); // 知识纠错
+
+// 定义变量内容
+const state = reactive<any>({
+	loading: false, // 加载状态
+	queryParams: {
+		// 查询参数
+		PageIndex: 1,
+		PageSize: 10,
+		KnowledgeTypeId: null, // 知识分类
+		CreatorName: null, // 提问人
+	},
+	total: 0, // 总条数
+	tableData: [], // 表格数据
+	typeData: [], // 知识分类
+});
+const ruleFormRef = ref<RefType>(null); // 表单ref
+const getBaseData = async () => {
+	try {
+		const typeDataRes = await treeList({ IsEnable: true });
+		state.typeData = typeDataRes.result ?? [];
+	} catch (error) {
+		console.log(error);
+	}
+};
+// 获取参数列表
+const queryList = () => {
+	state.loading = true;
+	if (!auth('knowledge:error:query')) ElMessage.error('抱歉,您没有权限获取知识纠错列表!');
+	else {
+		correctionList(state.queryParams)
+			.then((res) => {
+				state.loading = false;
+				state.tableData = res.result.items ?? [];
+				state.total = res.result.total ?? 0;
+			})
+			.finally(() => {
+				state.loading = false;
+			});
+	}
+};
+// 重置表单
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	queryList();
+};
+
+// 知识详情
+const router = useRouter();
+const onPreview = (row: any) => {
+	router.push({
+		name: 'knowledgePreview',
+		params: {
+			id: row.knowledge.id,
+			tagsViewName: '知识详情',
+		},
+	});
+};
+// 答复
+const errorAddRef = ref<RefType>();
+const onReply = (row: any) => {
+	errorAddRef.value.openDialog(row, true);
+};
+// 编辑
+const onEdit = (row: any) => {
+	router.push({
+		name: 'knowledgeEdit',
+		params: {
+			id: row.knowledge.id,
+			tagsViewName: '编辑知识',
+		},
+	});
+};
+// 页面加载时
+onMounted(() => {
+	getBaseData();
+	queryList();
+});
+</script>
+
+<style lang="scss" scoped>
+.knowledge-error-container {
+}
+</style>

+ 388 - 0
src/views/knowledge/index/edit.vue

@@ -0,0 +1,388 @@
+<template>
+	<div class="knowledge-knowledge-edit-container layout-pd">
+		<el-card shadow="never" style="padding: 0 50px">
+			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="120px" scroll-to-error>
+				<el-row :gutter="35">
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item label="温馨提示">
+							<span class="color-danger">
+								发布知识前请仔细阅读 <el-link type="primary" @click="showStandard">【知识编写规范】</el-link>,以免知识无法通过审核,浪费您的时间!
+							</span>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
+						<el-form-item label="知识归属" prop="attribution" :rules="[{ required: true, message: '请选择知识归属', trigger: 'change' }]">
+							<el-select v-model="state.ruleForm.attribution" placeholder="请选择知识归属" class="w100">
+								<el-option label="中心知识库" value="中心知识库" />
+                <el-option label="部门知识库" value="部门知识库" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
+						<el-form-item label="知识分类" prop="knowledgeTypeId" :rules="[{ required: true, message: '请选择知识分类', trigger: 'change' }]">
+							<el-cascader
+								:options="state.typeData"
+								filterable
+								:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
+								placeholder="请选择知识分类"
+								clearable
+								class="w100"
+								v-model="state.ruleForm.knowledgeTypeId"
+								ref="cascadeRef"
+								@change="getKnowledgeList"
+							>
+							</el-cascader>
+						</el-form-item>
+					</el-col>
+          <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
+            <el-form-item label="失效时间" prop="expiredTime" :rules="[{ required: false, message: '请选择失效时间', trigger: 'change' }]">
+              <template #label>
+                <div style="height: 34px; display: flex; align-items: center">
+                  失效时间
+                  <el-tooltip placement="top-start">
+                    <SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
+                    <template #content> 不设置则代表永久有效;到达预设失效时间,知识将自动下架 </template>
+                  </el-tooltip>
+                </div>
+              </template>
+              <el-date-picker
+                  v-model="state.ruleForm.expiredTime"
+                  type="datetime"
+                  placeholder="请选择失效时间"
+                  class="w100"
+                  value-format="YYYY-MM-DD[T]HH:mm:ss"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
+            <el-form-item label="是否公开" prop="isPublic" :rules="[{ required: false, message: '请选择是否公开', trigger: 'change' }]">
+              <el-radio-group v-model="state.ruleForm.isPublic">
+                <el-radio :label="true">是</el-radio>
+                <el-radio :label="false">否</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
+            <el-form-item label="来源部门" prop="sourceOrganizeId" :rules="[{ required: true, message: '请选择来源部门', trigger: 'change' }]">
+              <el-cascader
+                  :options="orgsOptions"
+                  filterable
+                  :props="{ value: 'id', label: 'name', emitPath: false, checkStrictly: true }"
+                  placeholder="请选择来源部门"
+                  class="w100"
+                  v-model="state.ruleForm.sourceOrganizeId"
+                  ref="orgRef"
+                  @change="selectOrg"
+              >
+              </el-cascader>
+            </el-form-item>
+          </el-col>
+					<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="8">
+						<el-form-item label="热点分类" prop="hotspotId" :rules="[{ required: true, message: '请选择热点分类', trigger: 'change' }]">
+							<el-tree-select
+								class="w100"
+                  v-model="state.ruleForm.hotspotId"
+								filterable
+								placeholder="请选择热点分类"
+								:props="HotspotProps"
+								lazy
+								:load="load"
+								node-key="id"
+								check-strictly
+								:render-after-expand="false"
+								@node-click="hotSpotChange"
+								ref="hotspotRef"
+								:default-expanded-keys="state.hotspotExternal"
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item label="知识标题" prop="title" :rules="[{ required: true, message: '请输入知识标题', trigger: 'blur' }]">
+							<el-input v-model="state.ruleForm.title" placeholder="请输入知识标题" clearable></el-input>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item label="知识摘要" prop="summary" :rules="[{ required: false, message: '请输入知识摘要', trigger: 'blur' }]">
+							<el-input v-model="state.ruleForm.summary" placeholder="请输入知识摘要" clearable></el-input>
+						</el-form-item>
+					</el-col>
+          <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+            <el-form-item label="关联知识" prop="knowledges" :rules="[{ required: false, message: '请选择关联知识', trigger: 'change' }]">
+              <template #label>
+                <div style="height: 34px; display: flex; align-items: center">
+                  关联知识
+                  <el-tooltip placement="top-start">
+                    <SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
+                    <template #content> 关联其它相似或业务相关的知识,方便话务员可以查询其他相似的知识 </template>
+                  </el-tooltip>
+                </div>
+              </template>
+              <el-select-v2
+                  v-model="state.ruleForm.knowledges"
+                  filterable
+                  clearable
+                  :options="state.knowledgeOptions"
+                  placeholder="请选择关联知识"
+                  class="w100"
+                  multiple
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+            <el-form-item label="关键词" prop="keywords" :rules="[{ required: false, message: '请填写关键词要', trigger: 'blur' }]">
+              <el-input v-model="state.ruleForm.keywords" placeholder="请输入关键词,多个关键词用英文“,”分开" max-length="200" clearable></el-input>
+            </el-form-item>
+          </el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item label="知识内容" prop="content" :rules="[{ required: true, message: '请输入知识内容', trigger: 'blur' }]">
+							<editor v-model:get-html="state.ruleForm.content" :disable="state.disable" placeholder="请输入知识内容" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item label="附件" prop="additions" :rules="[{ required: false, message: '请选择附件', trigger: 'change' }]">
+							<annex-list name="知识附件" :businessId="state.knowledgeId" classify="知识上传" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+						<el-form-item>
+							<el-button type="primary" @click="onSubmitReview(ruleFormRef)" :loading="state.loading">提交审核</el-button>
+							<el-button class="default-button" @click="onPreview" :loading="state.loading">预览 </el-button>
+							<el-button @click="onSaveOnly(ruleFormRef)" class="default-button" :loading="state.loading">{{ saveText }}</el-button>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+		</el-card>
+		<!-- 编写规范 -->
+		<knowledge-standard ref="KnowledgeStandardRef" />
+    <!-- 流程审批 -->
+    <process-audit ref="processAuditRef" @orderProcessSuccess="knowledgeProcessSuccess" />
+	</div>
+</template>
+
+<script setup lang="ts" name="knowledgeEdit">
+import { reactive, ref, defineAsyncComponent, onMounted } from 'vue';
+import { ElMessage } from 'element-plus';
+import type { FormInstance } from 'element-plus';
+import mittBus from '/@/utils/mitt';
+import { useRoute, useRouter } from 'vue-router';
+import { storeToRefs } from 'pinia';
+import { useUserInfo } from '/@/stores/userInfo';
+import { Local } from '/@/utils/storage';
+import other from '/@/utils/other';
+import { throttle } from '/@/utils/tools';
+import { commonEnum } from '/@/utils/constants';
+import { treeList } from '/@/api/knowledge/type';
+import { KnowledgeInfo, KnowledgeAdd, KnowledgeGetKnowledge, KnowledgeUpdate } from '/@/api/knowledge';
+import { hotSpotType } from '/@/api/business/order';
+import {getCanUseOrg} from '/@/api/system/user';
+
+// 引入组件
+const Editor = defineAsyncComponent(() => import('/@/components/Editor/index.vue')); // 富文本编辑器
+const ProcessAudit = defineAsyncComponent(() => import('/@/components/ProcessAudit/index.vue')); // 流程审批
+const KnowledgeStandard = defineAsyncComponent(() => import('/@/views/knowledge/component/Knowledge-standard-info.vue')); // 编写规范
+const AnnexList = defineAsyncComponent(() => import('/@/components/AnnexList/index.vue')); // 附件组件
+
+// 定义变量内容
+const state = reactive<any>({
+	dialogVisible: false,
+	ruleForm: {
+    attribution: '', // 知识归属
+		isPublic: true, // 是否公开
+		keywords: '', // 关键字
+		knowledgeTypeId: '', // 知识分类
+		hotspotId: '', // 热点分类
+		knowledges: [], // 关联知识
+	},
+	typeData: [], // 知识分类
+	loading: false,
+	hotspotExternal: [],
+	knowledgeOptions: [], //关联知识
+	knowledgeId: '', // 当前id
+});
+const ruleFormRef = ref<any>(); // 表单ref
+// 热点分类远程搜索
+const HotspotProps = {
+	label: 'hotSpotFullName',
+	children: 'children',
+	isLeaf: 'isLeaf',
+};
+// 热点分类懒加载
+const load = async (node: any, resolve: any) => {
+	if (node.isLeaf) return resolve([]);
+	const res: any = await hotSpotType({ id: node.data.id ? node.data.id : '' });
+	resolve(res.result);
+};
+// 选择热点分类
+const hotSpotChange = (val: any, e: any) => {
+	state.hotspotExternal = [];
+	state.external = [];
+	state.hotspotExternal = getParentId(e, state.external);
+	state.ruleForm.hotspotSpliceName = val.hotSpotFullName;
+	state.ruleForm.hotspotName = val.hotSpotFullName;
+	state.ruleForm.hotspot = val.hotSpotName;
+};
+// 选择部门
+const orgRef = ref<RefType>();
+const selectOrg = () => {
+  state.ruleForm.sourceOrganizeName = orgRef.value.getCheckedNodes()[0]?.label ?? '';
+};
+// 递归查找父级Id
+const getParentId = (val: any, arr: string[]) => {
+	if (val.data.parentId) {
+		arr.push(val.data.parentId);
+		getParentId(val.parent, arr);
+	}
+	return arr;
+};
+// 展示编写规范
+const KnowledgeStandardRef = ref<RefType>();
+const showStandard = () => {
+	KnowledgeStandardRef.value.openDialog();
+};
+const cascadeRef = ref<RefType>();
+// 获取选择name值
+const getKnowledgeList = () => {
+	let currentNode = cascadeRef.value.getCheckedNodes();
+	state.ruleForm.parentName = currentNode[0]?.label ?? '';
+	state.ruleForm.knowledgeTypeName = currentNode[0]?.text ?? '';
+};
+// 提交审核
+const processAuditRef = ref<RefType>(); // 流程组件
+const route = useRoute(); // 获取路由
+const router = useRouter(); // 路由跳转
+const onSubmitReview = async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		state.ruleForm.hotspotExternal = state.hotspotExternal.join(',');
+		const submitObj = other.deepClone(state.ruleForm);
+    Reflect.deleteProperty(submitObj, 'creationTime');
+    if(submitObj.workflowId){ //如果已经有流程ID 说明是已经提交过的数据 提交更新流程
+      const params = {
+        id: submitObj.workflowId,
+        processType: '更新知识',
+        extra: {
+          dialogTitle: '更新知识',
+          inputPlaceholder: '办理意见',
+          annexName: '知识附件',
+        },
+        orderDetail:submitObj,
+      };
+      processAuditRef.value.openDialog(params);
+    }else{
+      const params = {
+        id: '',
+        processType: '新增知识',
+        extra: {
+          dialogTitle: '新增知识',
+          inputPlaceholder: '办理意见',
+          annexName: '知识附件',
+        },
+        orderDetail:submitObj,
+      };
+      processAuditRef.value.openDialog(params);
+    }
+	});
+};
+// 流程提交成功
+const knowledgeProcessSuccess = () => {
+	// 关闭当前 tagsView
+	mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
+  mittBus.emit('clearCache', 'knowledgeManage');
+	router.push({
+    path: '/knowledge/index',
+	});
+};
+// 预览
+const stores = useUserInfo(); // 用户信息
+const { userInfos } = storeToRefs(stores); // 用户信息
+const onPreview = () => {
+  if(route.params.id){
+
+  }else{
+    state.ruleForm.creatorName = userInfos.value?.name ?? '';
+    state.ruleForm.creationTime = new Date();
+    state.ruleForm.creatorOrgName = userInfos.value?.orgName ?? '';
+  }
+
+	Local.set('previewForm', state.ruleForm);
+	router.push({
+		name: 'knowledgePreview',
+		params: {
+			tagsViewName: '知识预览',
+		},
+	});
+};
+// 保存到草稿箱
+const onSaveOnly = throttle(async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+    state.loading = true;
+		state.ruleForm.hotspotExternal = state.hotspotExternal.join(',');
+		const submitObj = other.deepClone(state.ruleForm);
+    Reflect.deleteProperty(submitObj, 'creationTime');
+    if(submitObj.workflowId){// 如果是已经提交过的数据 直接新增草稿
+      KnowledgeAdd({data:submitObj}).then(handleSuccess).catch(() => {
+        state.loading = false;
+      });
+    }else{
+      if(route.params.id){ // 更新
+        KnowledgeUpdate({data:submitObj}).then(handleSuccess).catch(() => {
+          state.loading = false;
+        });
+      }else{ // 新增
+        KnowledgeAdd({data:submitObj}).then(handleSuccess).catch(() => {
+          state.loading = false;
+        });
+      }
+    }
+	});
+}, 300);
+const handleSuccess = () => {
+  state.loading = false;
+  ElMessage.success('操作成功');
+  // 关闭当前 tagsView
+  mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
+  mittBus.emit('clearCache', 'knowledgeManage');
+  router.push({
+    path: '/knowledge/index',
+  });
+};
+const orgsOptions = ref<EmptyArrayType>([]); // 来源单位
+// 知识分类
+const getKnowledgeType = async () => {
+	state.loading = true;
+	try {
+		const [typeDataRes,knowledgeOptionsRes,orgsOptionsRes] = await Promise.all([treeList({ IsEnable: true }), KnowledgeGetKnowledge(),getCanUseOrg()]);
+		state.typeData = typeDataRes.result ?? [];
+		state.knowledgeOptions = knowledgeOptionsRes.result ?? [];
+		state.knowledgeOptions = state.knowledgeOptions.map((v: any) => ({
+			label: v.title,
+			value: v.id,
+			...v,
+		}));
+    orgsOptions.value = orgsOptionsRes.result ?? [];
+		state.loading = false;
+	} catch (error) {
+		state.loading = false;
+	}
+};
+const saveText = ref('保存为草稿');
+onMounted(async () => {
+	await getKnowledgeType();
+	if (route.params.id) {
+		const res: any = await KnowledgeInfo(route.params.id); //知识详情
+		if (route.params.isDraft) {
+			saveText.value = '保存';
+		}
+		state.ruleForm = res.result ?? {};
+		if (res.result.hotspotExternal) {
+			//热点分类默认展开
+			state.hotspotExternal = state.ruleForm.hotspotExternal.split(',');
+		}
+		state.ruleForm.knowledges = state.ruleForm.knowledges ?? [];
+	}
+});
+</script>

+ 502 - 0
src/views/knowledge/index/index.vue

@@ -0,0 +1,502 @@
+<template>
+	<div class="knowledge-index-container layout-padding">
+		<el-card shadow="never" class="h100">
+			<el-row :gutter="20" class="h100">
+				<el-col :xs="6" :sm="6" :md="6" :lg="4" :xl="4" class="orgTree">
+					<div class="h100 pr10">
+						<el-tabs v-model="state.activeName" stretch>
+							<el-tab-pane label="部门" name="0">
+								<el-input v-model="filterOrg" placeholder="请输入部门名称" class="input-with-select mt10 mb10" clearable> </el-input>
+							</el-tab-pane>
+							<el-tab-pane label="知识分类" name="1">
+								<el-input v-model="filterType" placeholder="请输入知识分类名称" class="input-with-select mt10 mb10" clearable> </el-input>
+							</el-tab-pane>
+							<el-tab-pane label="热点" name="2">
+								<el-input v-model="filterHot" placeholder="请输入热点名称" class="input-with-select mt10 mb10" clearable> </el-input>
+							</el-tab-pane>
+						</el-tabs>
+						<div style="height: calc(100% - 100px);'">
+							<el-scrollbar>
+								<el-tree
+									v-show="state.activeName === '0'"
+									:data="state.orgData"
+									highlight-current
+									:expand-on-click-node="false"
+									:props="{ children: 'children', label: 'name' }"
+									@node-click="handleNodeClick"
+									ref="orgRef"
+									v-loading="state.loading"
+									:filter-node-method="filterNode"
+									node-key="id"
+									:style="state.activeName === '0' ? '' : 'display:none'"
+									:default-expanded-keys="state.defaultExpandedOrgKeys"
+								>
+								</el-tree>
+								<el-tree
+									:data="state.knowledgeOptions"
+									highlight-current
+									:expand-on-click-node="false"
+									:props="{ children: 'children', label: 'name' }"
+									@node-click="handleNodeClick"
+									ref="typeRef"
+									v-loading="state.loading"
+									:filter-node-method="filterNodeType"
+									node-key="id"
+									:style="state.activeName === '1' ? '' : 'display:none'"
+									:default-expanded-keys="state.defaultExpandedTypeKeys"
+								>
+								</el-tree>
+								<el-tree
+									filterable
+									highlight-current
+									placeholder="请选择热点分类"
+									:props="HotspotProps"
+									@node-click="handleNodeClick"
+									lazy
+									:load="load"
+									node-key="id"
+									ref="hotRef"
+									:filter-node-method="filterNodeHot"
+									:expand-on-click-node="false"
+									:style="state.activeName === '2' ? '' : 'display:none'"
+								>
+									<template #default="{ data }">
+										<span :title="data.hotSpotName">
+											{{ data.hotSpotName }}
+										</span>
+									</template>
+								</el-tree>
+							</el-scrollbar>
+						</div>
+					</div>
+				</el-col>
+				<el-col :xs="18" :sm="18" :md="18" :lg="20" :xl="20" class="rightContent">
+					<el-scrollbar class="pr10 scrollbar__view">
+						<el-tabs v-model="state.queryParams.Status" @tab-change="handleClick">
+							<el-tab-pane label="全部" name=" "></el-tab-pane>
+							<el-tab-pane :label="v.value" :name="v.key" v-for="(v, i) in state.statusOptions" :key="i"></el-tab-pane>
+						</el-tabs>
+						<!-- 搜索条件 -->
+						<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="pl15 pr15 pt15">
+							<el-form-item label="关键字" prop="Keyword">
+								<el-input
+									v-model="state.queryParams.Keyword"
+									placeholder="标题/创建人/创建部门/申请部门"
+									clearable
+									@keyup.enter="handleQuery"
+									style="width: 250px"
+								/>
+							</el-form-item>
+							<el-form-item label="标题" prop="Title">
+								<el-input v-model="state.queryParams.Title" placeholder="标题" clearable @keyup.enter="handleQuery" />
+							</el-form-item>
+							<el-form-item label="是否公开" prop="IsPublic">
+								<el-select v-model="state.queryParams.IsPublic" placeholder="请选择是否公开" class="w100">
+									<el-option label="公开" :value="true" />
+									<el-option label="不公开" :value="false" />
+								</el-select>
+							</el-form-item>
+							<el-form-item>
+								<el-button type="primary" @click="handleQuery" :loading="state.tableLoading">
+									<SvgIcon name="ele-Search" class="mr5" />查询
+								</el-button>
+								<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.tableLoading">
+									<SvgIcon name="ele-Refresh" class="mr5" />重置
+								</el-button>
+							</el-form-item>
+						</el-form>
+						<div class="mb20">
+							<el-button type="primary" @click="onOpenAddUser" v-auth="'knowledge:index:add'">
+								<SvgIcon name="ele-Plus" class="mr5" />新增知识
+							</el-button>
+						</div>
+						<!-- 表格 -->
+						<el-table :data="state.tableData" v-loading="state.tableLoading" row-key="id">
+							<el-table-column prop="title" label="标题" show-overflow-tooltip width="300">
+								<template #default="{ row }">
+									<el-link type="primary" :underline="false" @click="onPreview(row)">
+										{{ row.title }}
+									</el-link>
+								</template>
+							</el-table-column>
+							<el-table-column prop="knowledgeTypeName" label="知识分类" show-overflow-tooltip></el-table-column>
+							<el-table-column prop="statusName" label="知识状态" show-overflow-tooltip></el-table-column>
+							<el-table-column prop="hotspotName" label="热点" show-overflow-tooltip width="120"></el-table-column>
+							<el-table-column prop="hotspotName" label="是否公开" show-overflow-tooltip>
+								<template #default="{ row }">
+									<span>{{ row.isPublic ? '公开' : '不公开' }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column prop="pageView" label="阅读次数" show-overflow-tooltip></el-table-column>
+							<el-table-column prop="onShelfTime" label="上架时间" show-overflow-tooltip width="170">
+								<template #default="{ row }">
+									<span>{{ formatDate(row.onShelfTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column prop="offShelfTime" label="下架时间" show-overflow-tooltip width="170">
+								<template #default="{ row }">
+									<span>{{ formatDate(row.offShelfTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column prop="creatorName" label="创建人" show-overflow-tooltip width="120"></el-table-column>
+							<el-table-column prop="creatorOrgName" label="创建部门" show-overflow-tooltip width="150"></el-table-column>
+							<el-table-column prop="creationTime" label="创建时间" show-overflow-tooltip width="170">
+								<template #default="{ row }">
+									<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column prop="lastModificationTime" label="更新时间" show-overflow-tooltip width="170">
+								<template #default="{ row }">
+									<span>{{ formatDate(row.lastModificationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+								</template>
+							</el-table-column>
+							<el-table-column label="操作" width="200" fixed="right" align="center">
+								<template #default="{ row }">
+									<el-button link type="primary" @click="onEdit(row)" title="编辑" v-if="[0, 4].includes(row.status)" v-auth="'knowledge:index:edit'">
+										编辑
+									</el-button>
+									<el-button
+										link
+										type="danger"
+										@click="onRowDel(row)"
+										title="删除"
+										v-if="[2, 4].includes(row.status)"
+										v-auth="'knowledge:index:delete'"
+									>
+										删除
+									</el-button>
+									<el-button
+										link
+										type="primary"
+										@click="offShelfFn(row)"
+										title="下架"
+										v-if="[3].includes(row.status)"
+										v-auth="'knowledge:index:undercarriage'"
+									>
+										下架
+									</el-button>
+									<el-button
+										link
+										type="primary"
+										@click="groundingFn(row)"
+										title="上架"
+										v-if="[4].includes(row.status)"
+										v-auth="'knowledge:index:grounding'"
+									>
+										上架
+									</el-button>
+									<el-button
+										link
+										type="primary"
+										@click="onAudit(row)"
+										title="审批"
+										v-if="[1, 2].includes(row.status)"
+										v-auth="'business:order:handle'"
+									>
+										审批
+									</el-button>
+									<el-button
+										link
+										type="primary"
+										@click="onPreview(row)"
+										title="查看"
+										v-if="[1, 2, 3, 4].includes(row.status)"
+										v-auth="'knowledge:index:preview'"
+									>
+										查看
+									</el-button>
+								</template>
+							</el-table-column>
+							<template #empty>
+								<Empty />
+							</template>
+						</el-table>
+						<!-- 分页 -->
+						<pagination
+							:total="state.total"
+							v-model:page="state.queryParams.PageIndex"
+							v-model:limit="state.queryParams.PageSize"
+							@pagination="queryList"
+						/>
+						<el-backtop target=".scrollbar__view > div" />
+					</el-scrollbar>
+				</el-col>
+			</el-row>
+		</el-card>
+		<!-- 流程审批 -->
+		<process-audit ref="processAuditRef" @orderProcessSuccess="queryList" />
+	</div>
+</template>
+
+<script lang="ts" setup name="knowledgeManage">
+import { ref, reactive, onMounted, watch, defineAsyncComponent } from 'vue';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { useRouter } from 'vue-router';
+import type { FormInstance } from 'element-plus';
+import { formatDate } from '/@/utils/formatTime';
+import { throttle } from '/@/utils/tools';
+import { commonEnum } from '/@/utils/constants';
+import { auth } from '/@/utils/authFunction';
+import { KnowledgePaged, KnowledgeOffShelf, KnowledgeOnTheShelf, baseData } from '/@/api/knowledge';
+import { getOrgList } from '/@/api/system/organize';
+import { treeList } from '/@/api/knowledge/type';
+import { hotSpotType } from '/@/api/business/order';
+
+// 引入组件
+const ProcessAudit = defineAsyncComponent(() => import('/@/components/ProcessAudit/index.vue')); // 流程审批
+
+// 定义变量内容
+const state = reactive<any>({
+	queryParams: {
+		PageIndex: 1, //页码
+		PageSize: 10, //每页条数
+		Keyword: null, //关键字
+		Status: ' ', //状态
+		OrgId: null, //组织机构
+		HotSpotTypeId: null, //热点分类
+		KnowledgeTypeId: null, //知识类型
+		Title: null, //标题
+		Summary: null, //摘要
+	},
+	activeName: '0', //tab切换
+	tableData: [], //表格数据
+	total: 0, //总条数
+	loading: false, //表格loading
+	tableLoading: false, //表格loading
+	orgData: [], //组织机构数据
+	knowledgeOptions: [], //知识库类型数据
+	statusOptions: [], //状态数据
+	defaultExpandedOrgKeys: [], //默认展开的组织机构
+	defaultExpandedTypeKeys: [], //默认展开的知识库类型
+});
+const router = useRouter(); //路由
+const ruleFormRef = ref<FormInstance>(); //表单ref
+// 热点分类远程搜索
+const HotspotProps = {
+	label: 'hotSpotFullName',
+	children: 'children',
+	isLeaf: 'isLeaf',
+};
+// 热点分类懒加载
+const load = async (node: any, resolve: any) => {
+	if (node.isLeaf) return resolve([]);
+	const res: any = await hotSpotType({ id: node.data.id ? node.data.id : '' });
+	resolve(res.result);
+};
+// 三个类型的搜索
+const filterOrg = ref('');
+const orgRef = ref<RefType>();
+watch(filterOrg, (val) => {
+	orgRef.value!.filter(val);
+});
+const filterNode = (value: string, data: any) => {
+	if (!value) return true;
+	return data.name.includes(value);
+};
+const filterType = ref('');
+const typeRef = ref<RefType>();
+watch(filterType, (val) => {
+	typeRef.value!.filter(val);
+});
+const filterNodeType = (value: string, data: any) => {
+	if (!value) return true;
+	return data.name.includes(value);
+};
+const filterHot = ref('');
+const hotRef = ref<RefType>();
+watch(filterHot, (val) => {
+	hotRef.value!.filter(val);
+});
+const filterNodeHot = (value: string, data: any) => {
+	if (!value) return true;
+	return data.hotSpotName.includes(value);
+};
+
+// 切换tab 查询列表
+const handleClick = () => {
+	queryList();
+};
+/** 搜索按钮操作 节流操作 */
+const handleQuery = throttle(() => {
+	state.queryParams.PageIndex = 1;
+	queryList();
+}, 500);
+// 获取所有组织结构 和基础数据
+const getOrgListApi = async () => {
+	state.loading = true;
+	try {
+		const res: any = await Promise.all([getOrgList(), treeList({ IsEnable: true }), baseData()]);
+		state.orgData = res[0].result ?? []; //部门
+		state.knowledgeOptions = res[1].result ?? []; // 知识类型
+		state.statusOptions = res[2].result ?? []; // 列表状态
+		state.loading = false;
+	} catch (error) {
+		state.loading = false;
+	}
+};
+/** 获取知识列表 */
+const queryList = () => {
+	if (!auth('knowledge:index:query')) ElMessage.error('抱歉,您没有权限获取知识库列表');
+	else {
+		state.tableLoading = true;
+		KnowledgePaged(state.queryParams)
+			.then((response: any) => {
+				state.tableData = response?.result.items ?? [];
+				state.total = response?.result.total;
+				state.tableLoading = false;
+			})
+			.catch(() => {
+				state.tableLoading = false;
+			});
+	}
+};
+// 点击节点
+const handleNodeClick = (data: any) => {
+	switch (state.activeName) {
+		case '0':
+			state.queryParams.CreateOrgId = data.id;
+			break;
+		case '1':
+			state.queryParams.KnowledgeTypeId = data.id;
+			break;
+		case '2':
+			state.queryParams.HotspotId = data.id;
+			break;
+		default:
+			break;
+	}
+	console.log(state.queryParams);
+	queryList();
+};
+/** 重置按钮操作 */
+const resetQuery = throttle((formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	state.queryParams.CreateOrgId = null;
+	state.queryParams.KnowledgeTypeId = null;
+	state.queryParams.HotspotId = null;
+	filterOrg.value = '';
+	filterType.value = '';
+	filterHot.value = '';
+	typeRef.value?.setCurrentKey(null);
+	orgRef.value?.setCurrentKey(null);
+	hotRef.value?.setCurrentKey(null);
+	handleQuery();
+}, 500);
+// 新增知识
+const onOpenAddUser = () => {
+	router.push({
+		name: 'knowledgeEdit',
+		params: {
+			tagsViewName: '新增知识',
+		},
+	});
+};
+// 修改知识
+const onEdit = (row: any) => {
+	router.push({
+		name: 'knowledgeEdit',
+		params: {
+			id: row.id,
+			tagsViewName: '编辑知识',
+		},
+	});
+};
+// 预览
+const onPreview = (row: any) => {
+	router.push({
+		name: 'knowledgePreview',
+		params: {
+			id: row.id,
+			tagsViewName: '知识查看',
+		},
+	});
+};
+// 审批
+const processAuditRef = ref<RefType>(); //审核记录ref
+const onAudit = (row: any) => {
+	const params = {
+		id: row.workflowId,
+		commonEnum,
+		processType: '工单办理',
+		orderDetail: {},
+		extra: {
+			dialogTitle: '知识审批',
+			inputPlaceholder: '办理意见',
+			annexName: '知识附件',
+		},
+	};
+	processAuditRef.value.openDialog(params);
+};
+// 下架
+const offShelfFn = (row: any) => {
+	ElMessageBox.confirm(`是否确定要下架【${row.title}】?知识下架后,将不会被检索到!`, '提示', {
+		confirmButtonText: '确认',
+		cancelButtonText: '取消',
+		type: 'warning',
+		draggable: true,
+		cancelButtonClass: 'default-button',
+	})
+		.then(() => {
+			KnowledgeOffShelf(row.id).then(() => {
+				ElMessage.success('操作成功');
+				handleQuery();
+				getOrgListApi();
+			});
+		})
+		.catch(() => {});
+};
+// 上架
+const groundingFn = (row: any) => {
+	ElMessageBox.confirm(`是否确定要上架【${row.title}】?`, '提示', {
+		confirmButtonText: '确认',
+		cancelButtonText: '取消',
+		type: 'warning',
+		draggable: true,
+		cancelButtonClass: 'default-button',
+	})
+		.then(() => {
+			KnowledgeOnTheShelf(row.id).then(() => {
+				ElMessage.success('操作成功');
+				handleQuery();
+				getOrgListApi();
+			});
+		})
+		.catch(() => {});
+};
+// 删除知识
+const onRowDel = (row: any) => {
+  const params = {
+    id: row.workflowId,
+    processType: '删除知识',
+    extra: {
+      dialogTitle: '删除知识',
+      inputPlaceholder: '办理意见',
+      annexName: '知识附件',
+    },
+    orderDetail:row,
+  };
+  processAuditRef.value.openDialog(params);
+};
+onMounted(() => {
+	queryList();
+	getOrgListApi();
+});
+</script>
+<style lang="scss" scoped>
+.knowledge-index-container {
+	.orgTree {
+		border-right: 1px solid var(--el-border-color);
+		height: 100%;
+	}
+	.rightContent {
+		height: 100%;
+	}
+	:deep(.el-tree-node__content) {
+		height: 40px;
+	}
+	:deep(.el-card__body) {
+		height: 100%;
+	}
+}
+</style>

+ 105 - 0
src/views/knowledge/index/preview.vue

@@ -0,0 +1,105 @@
+<template>
+	<div class="knowledge-preview-container layout-pd">
+		<el-card shadow="never">
+			<el-row v-loading="loading">
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+					<h1 class="font18">{{ state.info.title }}</h1></el-col
+				>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="color-info flex-center-align">
+					<span class="mr10">创建时间:{{ formatDate(state.info.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+					<span class="mr10">创建人:{{ state.info.creatorName }}</span>
+					<span class="mr10">创建部门:{{ state.info.creatorOrgName }}</span>
+					<span class="mr10">更新时间:{{ formatDate(state.info.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+					<span class="mr10">知识分类:{{ state.info.knowledgeTypeName }}</span>
+					<span class="mr10">已阅:{{ state.info.pageView }}</span>
+					<el-button link class="flex-center-align" type="info" @click="onCollect"> <SvgIcon name="ele-Star" class="mr4" />点击收藏</el-button>
+					<el-button link class="flex-center-align" type="info" @click="onRate"> <el-rate v-model="state.info.score" allow-half /> 评分</el-button>
+					<el-button link class="flex-center-align" type="info" @click="onError"> <SvgIcon name="ele-EditPen" class="mr4" />知识纠错</el-button>
+					<el-button link class="flex-center-align" type="info" @click="onQuestion">
+						<SvgIcon name="ele-QuestionFilled" class="mr4" />知识提问</el-button
+					>
+				</el-col>
+				<el-divider style="margin: 15px 0" />
+				摘要
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mt5"> {{ state.info.summary }}</el-col>
+				<el-divider style="margin: 15px 0" />
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24"> <div v-html="state.info.content" class="lineHeight24"></div></el-col>
+			</el-row>
+		</el-card>
+		<!-- 知识纠错 -->
+		<error-add ref="errorAddRef" />
+		<!-- 知识提问 -->
+		<question-add ref="questionRef" />
+	</div>
+</template>
+
+<script setup lang="ts" name="knowledgePreview">
+import { reactive, onMounted, onBeforeUnmount, ref, defineAsyncComponent } from 'vue';
+import { useRoute } from 'vue-router';
+import { Local } from '/@/utils/storage';
+import { KnowledgeInfo } from '/@/api/knowledge';
+import { formatDate } from '/@/utils/formatTime';
+
+// 引入组件
+const ErrorAdd = defineAsyncComponent(() => import('/@/views/knowledge/error/components/Error-add.vue')); // 知识纠错
+const QuestionAdd = defineAsyncComponent(() => import('/@/views/knowledge/question/components/Question-add.vue')); // 知识提问
+
+// 定义变量内容
+const state = reactive<any>({
+	info: {
+		knowledgeTypeName: '', // 类别
+		hotspotName: '', // 热点
+		keywords: '', // 关键词
+		isPublic: false, // 是否公开
+		creatorName: '', // 创建人
+		creationTime: '', // 创建时间
+		summary: '', // 摘要
+		content: '', // 内容
+	},
+});
+const value1 = ref(3.5);
+const loading = ref<Boolean>(false); // 加载状态
+// 查询知识详情
+const route = useRoute(); //  获取路由参数
+// 收藏
+const onCollect = () => {};
+// 评分
+const onRate = () => {};
+// 知识纠错
+const errorAddRef = ref<RefType>();
+const onError = () => {
+	errorAddRef.value?.openDialog(state.info);
+};
+// 知识提问
+const questionRef = ref<RefType>();
+const onQuestion = () => {
+	questionRef.value?.openDialog(state.info);
+};
+onMounted(async () => {
+	loading.value = true;
+	if (route.params.id) {
+		try {
+			const { isAddPv } = route.params;
+			let IsAddPv = isAddPv ? 'true' : false;
+			const res: any = await KnowledgeInfo(route.params.id, { isAddPv: IsAddPv });
+			state.info = res.result ?? {};
+			loading.value = false;
+		} catch (error) {
+			loading.value = false;
+		}
+	} else {
+		state.info = Local.get('previewForm') ?? {};
+		loading.value = false;
+	}
+});
+onBeforeUnmount(() => {
+	Local.remove('previewForm'); // 删除本地缓存
+});
+</script>
+<style lang="scss" scoped>
+.knowledge-knowledge-Standard-container {
+	.el-card {
+		color: var(--el-text-color-regular) !important;
+	}
+}
+</style>

+ 0 - 121
src/views/knowledge/knowledge/component/Knowledge-update.vue

@@ -1,121 +0,0 @@
-<template>
-	<div class="knowledge-upDate-container">
-		<el-dialog title="发起更新申请" v-model="state.dialogVisible" draggable>
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="100px">
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="关联知识" prop="knowledgeName" :rules="[{ required: true, message: '请选择关联知识', trigger: 'change' }]">
-							{{ state.ruleForm.knowledgeName }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="申请内容" prop="content" :rules="[{ required: true, message: '请填写申请内容', trigger: 'blur' }]">
-							<el-input
-								v-model="state.ruleForm.content"
-								type="textarea"
-								:autosize="{ minRows: 6, maxRows: 10 }"
-								placeholder="请填写申请内容"
-								clearable
-								maxlength="2000"
-							>
-							</el-input>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="部门名称" prop="department">
-							{{ state.ruleForm.department }}
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="截止日期" prop="expiredTime" :rules="[{ required: false, message: '请选择截止日期', trigger: 'change' }]">
-							<template #label>
-								<div style="height: 34px; display: flex; align-items: center">
-									截止日期
-									<el-tooltip placement="top">
-										<SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
-										<template #content> 超过处理截止日期未反馈,将影响处理部门绩效考核,请谨慎设置 </template>
-									</el-tooltip>
-								</div>
-							</template>
-							<el-date-picker
-								v-model="state.ruleForm.expiredTime"
-								type="date"
-								placeholder="请选择截止日期"
-								class="w100"
-								value-format="YYYY-MM-DD[T]HH:mm:ss"
-							/>
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="closeDialog" class="default-button">取 消</el-button>
-					<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">确 定 </el-button>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-
-<script setup lang="ts" name="knowledgeUpdate">
-import { reactive, ref } from 'vue';
-import { ElMessage, FormInstance } from 'element-plus';
-import { KnowledgeApplyAdd } from '/@/api/knowledge/apply';
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['updateList']);
-
-// 定义变量内容
-const state = reactive<any>({
-	dialogVisible: false,
-	ruleForm: {
-    knowledgeName: '', //关联知识
-    department: '', //部门名称
-    departmentId: '', //部门id
-		knowledgeApplyType: 1, //申请类型 1更新 2删除
-		expiredTime: [], //截止日期
-	},
-	loading: false,
-	knowledgeOptions: [], //关联知识列表
-});
-const ruleFormRef = ref<any>(); //表单ref
-// 打开弹窗
-const openDialog = (row: any) => {
-	state.ruleForm.knowledgeApplyType = 1; //更新
-	state.ruleForm.department = row.creationBMName;
-	state.ruleForm.departmentId = row.creatorOrgId;
-	state.ruleForm.knowledgeId = row.id; //关联知识
-	state.ruleForm.knowledgeName = row.title; //关联知识
-	ruleFormRef.value?.clearValidate();
-	ruleFormRef.value?.resetFields();
-	state.dialogVisible = true;
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-};
-// 新增
-const onSubmit = async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.loading = true;
-		KnowledgeApplyAdd(state.ruleForm)
-			.then(() => {
-				emit('updateList');
-				closeDialog(); // 关闭弹窗
-				state.loading = false;
-				ElMessage.success('操作成功');
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	});
-};
-// 暴露变量
-defineExpose({
-	openDialog,
-	closeDialog,
-});
-</script>

+ 0 - 348
src/views/knowledge/knowledge/component/knowledge-edit.vue

@@ -1,348 +0,0 @@
-<template>
-	<div class="knowledge-knowledge-edit-container layout-pd">
-		<el-card shadow="never" style="padding: 0 50px">
-			<el-form :model="state.ruleForm" ref="ruleFormRef" label-width="120px" scroll-to-error>
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="温馨提示">
-							<span class="color-danger">
-								发布知识前请仔细阅读 <el-link type="primary" @click="showStandard">【知识编写规范】</el-link>,以免知识无法通过审核,浪费您的时间!
-							</span>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="知识分类" prop="knowledgeTypeId" :rules="[{ required: true, message: '请选择知识分类', trigger: 'change' }]">
-							<el-cascader
-								:options="state.typeData"
-								filterable
-								:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
-								placeholder="请选择上知识分类"
-								clearable
-								class="w100"
-								v-model="state.ruleForm.knowledgeTypeId"
-								ref="cascadeRef"
-								@change="getKnowledgeList"
-							>
-							</el-cascader>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="热点分类" prop="hotspotId" :rules="[{ required: true, message: '请选择热点分类', trigger: 'change' }]">
-							<el-tree-select
-								class="w100"
-								v-model="state.ruleForm.hotspotId"
-								filterable
-								placeholder="请选择热点分类"
-								:props="HotspotProps"
-								lazy
-								:load="load"
-								node-key="id"
-								check-strictly
-								:render-after-expand="false"
-								@node-click="hotSpotChange"
-								ref="hotspotRef"
-								:default-expanded-keys="state.hotspotExternal"
-							/>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请填写标题', trigger: 'blur' }]">
-							<el-input v-model="state.ruleForm.title" placeholder=" 输入标题,不超过30个字" max-length="30" clearable></el-input>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="摘要" prop="summary" :rules="[{ required: false, message: '请填写摘要', trigger: 'blur' }]">
-							<el-input v-model="state.ruleForm.summary" placeholder="输入摘要,不超过200个字" max-length="200" clearable></el-input>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="正文" prop="content" :rules="[{ required: true, message: '请输入正文内容', trigger: 'blur' }]">
-							<editor v-model:get-html="state.ruleForm.content" :disable="state.disable" placeholder="请输入正文内容" />
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="关键词" prop="keywords" :rules="[{ required: false, message: '请填写关键词要', trigger: 'blur' }]">
-							<el-input v-model="state.ruleForm.keywords" placeholder="请输入关键词,多个关键词用英文“,”分开" max-length="200" clearable></el-input>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="是否公开" prop="isPublic" :rules="[{ required: false, message: '请选择是否公开', trigger: 'change' }]">
-							<el-radio-group v-model="state.ruleForm.isPublic">
-								<el-radio :label="true">是</el-radio>
-								<el-radio :label="false">否</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="knowledges" :rules="[{ required: false, message: '请选择关联知识', trigger: 'change' }]">
-							<template #label>
-								<div style="height: 34px; display: flex; align-items: center">
-									关联知识
-									<el-tooltip placement="top-start">
-										<SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
-										<template #content> 关联其它相似或业务相关的知识,方便话务员可以查询其他相似的知识 </template>
-									</el-tooltip>
-								</div>
-							</template>
-							<el-select-v2
-								v-model="state.ruleForm.knowledges"
-								filterable
-								clearable
-								:options="state.knowledgeOptions"
-								placeholder="请选择关联知识"
-								class="w100"
-								multiple
-							/>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="失效时间" prop="expiredTime" :rules="[{ required: false, message: '请选择失效时间', trigger: 'change' }]">
-							<template #label>
-								<div style="height: 34px; display: flex; align-items: center">
-									失效时间
-									<el-tooltip placement="top-start">
-										<SvgIcon name="ele-QuestionFilled" size="18px" class="ml3" />
-										<template #content> 不设置则代表永久有效;到达预设失效时间,知识将自动下架 </template>
-									</el-tooltip>
-								</div>
-							</template>
-							<el-date-picker
-								v-model="state.ruleForm.expiredTime"
-								type="datetime"
-								placeholder="请选择失效时间"
-								class="w100"
-								value-format="YYYY-MM-DD[T]HH:mm:ss"
-							/>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="附件" prop="additions" :rules="[{ required: false, message: '请选择附件', trigger: 'change' }]">
-							<annex-list name="知识附件" :businessId="state.knowledgeId" classify="知识上传"/>
-						</el-form-item>
-					</el-col>
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item>
-							<el-button type="primary" @click="onSubmitReview(ruleFormRef)" :loading="state.loading">提交审核</el-button>
-							<el-button class="default-button" @click="onPreview" :loading="state.loading">预览 </el-button>
-							<el-button @click="onSaveOnly(ruleFormRef)" class="default-button" :loading="state.loading">{{ saveText }}</el-button>
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-		</el-card>
-		<!-- 编写规范 -->
-		<knowledge-standard ref="KnowledgeStandardRef" />
-		<!-- 流程组件 -->
-		<knowledge-process ref="KnowledgeProcessRef" @knowledgeProcessSuccess="knowledgeProcessSuccess" />
-	</div>
-</template>
-
-<script setup lang="ts" name="knowledgeEdit">
-import { reactive, ref, defineAsyncComponent, onMounted } from 'vue';
-import { ElMessage } from 'element-plus';
-import type { FormInstance } from 'element-plus';
-import mittBus from '/@/utils/mitt';
-import { useRoute, useRouter } from 'vue-router';
-import { storeToRefs } from 'pinia';
-import { useUserInfo } from '/@/stores/userInfo';
-import { Local } from '/@/utils/storage';
-import other from '/@/utils/other';
-import { throttle } from '/@/utils/tools';
-import {commonEnum} from '/@/utils/constants';
-import { treeList } from '/@/api/knowledge/type';
-import { KnowledgeDetail, KnowledgeAdd, KnowledgeGetKnowledge, KnowledgeUpdate } from '/@/api/knowledge';
-import { hotSpotType } from '/@/api/business/order';
-
-// 引入组件
-const Editor = defineAsyncComponent(() => import('/@/components/Editor/index.vue'));  // 富文本编辑器
-const KnowledgeProcess = defineAsyncComponent(() => import('/@/views/knowledge/component/Knowledge-process.vue'));  // 流程组件
-const KnowledgeStandard = defineAsyncComponent(() => import('/@/views/knowledge/knowledge/component/Knowledge-standard-info.vue')); // 编写规范
-const AnnexList = defineAsyncComponent(() => import('/@/components/AnnexList/index.vue'));  // 附件组件
-
-// 定义变量内容
-const state = reactive<any>({
-	dialogVisible: false,
-	ruleForm: {
-		isPublic: true, // 是否公开
-    keywords: '', // 关键字
-		knowledgeTypeId: '',// 知识分类
-		hotspotId: '', // 热点分类
-		knowledges: [], // 关联知识
-	},
-	typeData: [], // 知识分类
-	loading: false,
-	hotspotExternal: [],
-	knowledgeOptions: [], //关联知识
-	knowledgeId: '', // 当前id
-});
-const ruleFormRef = ref<any>(); // 表单ref
-// 热点分类远程搜索
-const HotspotProps = {
-	label: 'hotSpotFullName',
-	children: 'children',
-	isLeaf: 'isLeaf',
-};
-// 热点分类懒加载
-const load = async (node: any, resolve: any) => {
-	if (node.isLeaf) return resolve([]);
-	const res: any = await hotSpotType({ id: node.data.id ? node.data.id : '' });
-	resolve(res.result);
-};
-// 选择热点分类
-const hotSpotChange = (val: any, e: any) => {
-	state.hotspotExternal = [];
-	state.external = [];
-	state.hotspotExternal = getParentId(e, state.external);
-	state.ruleForm.hotspotSpliceName = val.hotSpotFullName;
-	state.ruleForm.hotspotName = val.hotSpotFullName;
-	state.ruleForm.hotspot = val.hotSpotName;
-};
-// 递归查找父级Id
-const getParentId = (val: any, arr: string[]) => {
-	if (val.data.parentId) {
-		arr.push(val.data.parentId);
-		getParentId(val.parent, arr);
-	}
-	return arr;
-};
-// 展示编写规范
-const KnowledgeStandardRef = ref<RefType>();
-const showStandard = () => {
-	KnowledgeStandardRef.value.openDialog();
-};
-const cascadeRef = ref<RefType>();
-// 获取选择name值
-const getKnowledgeList = () => {
-	let currentNode = cascadeRef.value.getCheckedNodes();
-	state.ruleForm.parentName = currentNode[0]?.label ?? '';
-	state.ruleForm.knowledgeTypeName = currentNode[0]?.text ?? '';
-};
-// 提交审核
-const KnowledgeProcessRef = ref<RefType>(); // 流程组件
-const handleOperation = async (submitObj: any, operation: Function) => {
-	await operation(submitObj).then((res: any) => {
-		const id = res.result || submitObj.id;
-		KnowledgeProcessRef.value.openDialog({ id, title: '创建知识', commonEnum: commonEnum.KnowledgeLocution, processType: 'addStart' });
-	});
-};
-const route = useRoute(); // 获取路由
-const router = useRouter(); // 路由跳转
-const onSubmitReview = async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.ruleForm.hotspotExternal = state.hotspotExternal.join(',');
-		const submitObj = other.deepClone(state.ruleForm);
-		if (route.params.id) {
-			// 更新
-			submitObj.id = route.params.id;
-			const operation = route.params.isDraft ? KnowledgeUpdate : KnowledgeAdd;
-			handleOperation(submitObj, operation);
-		} else {
-			if (state.knowledgeId) {
-				// 更新
-				submitObj.id = state.knowledgeId;
-				handleOperation(submitObj, KnowledgeUpdate);
-			} else {
-				//知识流程提交
-				handleOperation(submitObj, KnowledgeAdd);
-			}
-		}
-	});
-};
-// 流程提交成功
-const knowledgeProcessSuccess = () => {
-	// 关闭当前 tagsView
-	mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
-	mittBus.emit('clearCache', 'knowledge');
-	router.push({
-		path: '/knowledge',
-	});
-};
-// 预览
-const stores = useUserInfo(); // 用户信息
-const { userInfos } = storeToRefs(stores);  // 用户信息
-const onPreview = () => {
-	state.ruleForm.creatorName = userInfos.value?.name ?? '';
-	state.ruleForm.creationTime = new Date();
-	Local.set('previewForm', state.ruleForm);
-	router.push({
-		name: 'knowledgePreview',
-		params: {
-			tagsViewName: '知识预览',
-		},
-	});
-};
-// 保存到草稿箱
-const handleSuccess = () => {
-	ElMessage.success('操作成功');
-	// 关闭当前 tagsView
-	mittBus.emit('onCurrentContextmenuClick', Object.assign({}, { contextMenuClickId: 1, ...route }));
-	mittBus.emit('clearCache', 'knowledge');
-	mittBus.emit('clearCache', 'knowledgeDraft');
-	router.push({
-		path: '/knowledge/draft',
-	});
-};
-const onSaveOnly = throttle(async (formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	await formEl.validate((valid: boolean) => {
-		if (!valid) return;
-		state.ruleForm.hotspotExternal = state.hotspotExternal.join(',');
-		const submitObj = other.deepClone(state.ruleForm);
-		if (route.params.id) {
-			// 更新
-			submitObj.id = route.params.id;
-			if (route.params.isDraft) {
-				// 如果从草稿进来 // 更新
-				KnowledgeUpdate(submitObj).then(handleSuccess);
-			} else {
-				//如果是直接从知识库编辑 新增
-				KnowledgeAdd(submitObj).then(handleSuccess);
-			}
-		} else {
-			if (state.knowledgeId) {
-				// 更新
-				submitObj.id = state.knowledgeId;
-				KnowledgeUpdate(submitObj).then(handleSuccess);
-			} else {
-				// 新增
-				KnowledgeAdd(submitObj).then(handleSuccess);
-			}
-		}
-	});
-}, 300);
-// 知识分类
-const getKnowledgeType = async () => {
-	state.loading = true;
-	try {
-		const res: any = await Promise.all([treeList({ IsEnable: true }), KnowledgeGetKnowledge()]);
-		state.typeData = res[0].result ?? [];
-		state.knowledgeOptions = res[1].result ?? [];
-		state.knowledgeOptions = state.knowledgeOptions.map((v: any) => ({
-			label: v.title,
-			value: v.id,
-			...v,
-		}));
-		state.loading = false;
-	} catch (error) {
-		state.loading = false;
-	}
-};
-const saveText = ref('保存为草稿');
-onMounted(async () => {
-	await getKnowledgeType();
-	if (route.params.id) {
-		const res: any = await KnowledgeDetail(route.params.id); //知识详情
-		if (route.params.isDraft) {
-			saveText.value = '保存';
-		}
-		state.ruleForm = res.result ?? {};
-		if (res.result.hotspotExternal) {
-			//热点分类默认展开
-			state.hotspotExternal = state.ruleForm.hotspotExternal.split(',');
-		}
-		state.ruleForm.knowledges = state.ruleForm.knowledges ?? [];
-	}
-});
-</script>

+ 0 - 231
src/views/knowledge/knowledge/delApply/index.vue

@@ -1,231 +0,0 @@
-<template>
-	<div class="knowledge-delApply-container layout-pd">
-		<el-card shadow="never">
-			<el-tabs v-model="state.queryParams.EKnowledgeWorkFlowStatus" @tab-change="handleClick">
-				<el-tab-pane label="全部" name=" "></el-tab-pane>
-				<el-tab-pane :label="v.value" :name="v.key" v-for="(v, i) in state.statusOptions" :key="i"></el-tab-pane>
-				<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="mt15">
-					<el-form-item label="关键字" prop="Keyword">
-						<el-input
-							v-model="state.queryParams.Keyword"
-							placeholder="标题/创建人/创建部门/申请部门"
-							@keyup.enter="queryList"
-							clearable
-							style="width: 300px"
-						>
-						</el-input>
-					</el-form-item>
-					<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="timeChange"
-							value-format="YYYY-MM-DD[T]HH:mm:ss"
-						/>
-						<!-- value-format="YYYY-MM-DD" -->
-					</el-form-item>
-					<el-form-item>
-						<el-button type="primary" @click="queryList" :loading="state.loading" v-waves> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-						<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading">
-							<SvgIcon name="ele-Refresh" class="mr5" />重置
-						</el-button>
-					</el-form-item>
-				</el-form>
-			</el-tabs>
-		</el-card>
-		<el-card shadow="never">
-			<!-- 表格 -->
-			<el-table :data="state.tableList" v-loading="state.loading" row-key="id">
-				<el-table-column prop="title" label="标题" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="knowledgeTypeName" label="类型" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="hotspotName" label="热点" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="creationName" label="创建人" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="creationBMName" label="创建部门" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="pageView" label="阅读次数" show-overflow-tooltip></el-table-column>
-				<el-table-column label="状态" show-overflow-tooltip>
-					<template #default="{ row }">
-						<span v-if="row.workFlowApplyStatus === 1" class="color-primary">{{ row.workFlowApplyStatusName }}</span>
-						<span v-if="row.workFlowApplyStatus === 2" class="color-success">{{ row.workFlowApplyStatusName }}</span>
-						<span v-if="row.workFlowApplyStatus === 3" class="color-info">{{ row.workFlowApplyStatusName }}</span>
-						<span v-if="row.workFlowApplyStatus === 4" class="color-danger">{{ row.workFlowApplyStatusName }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="申请时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column label="操作" width="190" fixed="right" align="center">
-					<template #default="{ row }">
-						<el-button
-							link
-							type="primary"
-							@click="onRecord(row)"
-							v-auth="'system:workflow:record'"
-							title="查看审核记录"
-							v-if="[1, 2, 3, 4].includes(row.workFlowApplyStatus)"
-						>
-							查看审核记录
-						</el-button>
-						<el-button
-							link
-							type="danger"
-							@click="onRecall(row)"
-							title="撤回申请"
-							v-auth="'system:workflow:stop'"
-							v-if="[1].includes(row.workFlowApplyStatus)"
-						>
-							撤回申请
-						</el-button>
-					</template>
-				</el-table-column>
-				<template #empty>
-					<Empty />
-				</template>
-			</el-table>
-			<!-- 分页 -->
-			<pagination
-				:total="state.total"
-				v-model:page="state.queryParams.PageIndex"
-				v-model:limit="state.queryParams.PageSize"
-				@pagination="queryList"
-			/>
-		</el-card>
-		<!-- 审核记录 -->
-		<audit-record ref="auditRecordRef" />
-	</div>
-</template>
-
-<script lang="ts" setup name="knowledgeDelApply">
-import { ref, reactive, onMounted, defineAsyncComponent } from 'vue';
-import type { FormInstance } from 'element-plus';
-import { ElMessage, ElMessageBox } from 'element-plus';
-import { auth } from '/@/utils/authFunction';
-import other from '/@/utils/other';
-import { formatDate } from '/@/utils/formatTime';
-import { throttle } from '/@/utils/tools';
-import { shortcuts } from '/@/utils/constants';
-import { KnowledgeDeleteList, deleteBase } from '/@/api/knowledge';
-import { workflowTerminate } from '/@/api/system/workflow';
-
-// 引入组件
-const AuditRecord = defineAsyncComponent(() => import('/@/components/AuditRecord/index.vue'));  // 审核记录
-
-// 定义变量内容
-const state = reactive(<any>{
-	queryParams: {
-		PageIndex: 1, // 页码
-		PageSize: 10, // 每页条数
-		EKnowledgeWorkFlowStatus: ' ', // 状态
-		StartApplyTime: '', // 开始时间
-		EndApplyTime: '', // 结束时间
-	},
-	tableList: [], // 表格数据
-	loading: false, // 加载状态
-	total: 0, // 总条数
-	statusOptions: [], // 状态下拉
-});
-const ruleFormRef = ref<FormInstance>();  // 表单ref
-// 创建时间
-const timeChange = (val: string[]) => {
-	state.queryParams.StartApplyTime = val[0];
-	state.queryParams.EndApplyTime = val[1];
-};
-/** 获取知识库删除列表 */
-const queryList = throttle(() => {
-	if (!auth('knowledge:delApply:query')) ElMessage.error('抱歉,您没有权限获取删除申请列表');
-	else {
-		state.loading = true;
-		let request = other.deepClone(state.queryParams);
-		Reflect.deleteProperty(request, 'crTime'); // 删除无用的参数
-		KnowledgeDeleteList(request)
-			.then((response: any) => {
-				state.tableList = response?.result.items ?? [];
-				state.total = response?.result.total;
-				state.loading = false;
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	}
-}, 500);
-/** 重置按钮操作 */
-const resetQuery = throttle((formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	state.queryParams.StartApplyTime = '';
-	state.queryParams.EndApplyTime = '';
-	queryList();
-}, 500);
-// 切换tab 查询列表
-const handleClick = () => {
-	queryList();
-};
-// 查看申请记录
-const auditRecordRef = ref<RefType>();  // 审核记录ref
-const onRecord = (row: any) => {
-	const params = {
-		title: `审核记录 (${row.title})`,
-		...row,
-	};
-	auditRecordRef.value.openDialog(params);
-};
-// 撤回
-const onRecall = (row: any) => {
-	ElMessageBox.prompt('撤回原因', '提示', {
-		confirmButtonText: '确定',
-		cancelButtonText: '取消',
-		inputPlaceholder: '请输入撤回原因,不超过50字符',
-		draggable: true,
-		inputErrorMessage: '请输入撤回原因',
-		inputType: 'textarea',
-		inputValidator: (value) => {
-			if (value) return true;
-			else return '请输入撤回原因';
-		},
-	})
-		.then(({ value }) => {
-			let req = {
-				workflowId: row.workflowId,
-				opinion: value,
-			};
-			ElMessageBox.confirm(`是否确定要撤回申请?`, '提示', {
-				confirmButtonText: '确认',
-				cancelButtonText: '取消',
-				type: 'warning',
-				draggable: true,
-				cancelButtonClass: 'default-button',
-				autofocus: false,
-			})
-				.then(() => {
-					workflowTerminate(req)
-						.then(() => {
-							ElMessage.success('操作成功');
-							queryList();
-						})
-						.catch(() => {});
-				})
-				.catch(() => {});
-		})
-		.catch(() => {});
-};
-// 页面基础数据
-const getBaseData = async () => {
-	try {
-		const { result } = await deleteBase();
-		state.statusOptions = result;
-	} catch (error) {
-		console.log(error);
-	}
-};
-onMounted(() => {
-	queryList();
-	getBaseData();
-});
-</script>
-<style lang="scss" scoped></style>

+ 0 - 181
src/views/knowledge/knowledge/draft/index.vue

@@ -1,181 +0,0 @@
-<template>
-	<div class="knowledge-draft-container layout-pd">
-		<el-card shadow="never">
-			<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="mt15">
-				<el-form-item label="标题" prop="street">
-					<el-input v-model="state.queryParams.street" placeholder="请填写标题" @keyup.enter="queryList" clearable> </el-input>
-				</el-form-item>
-				<el-form-item label="类型" prop="KnowledgeTypeId">
-					<el-cascader
-						:options="state.typeData"
-						filterable
-						:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
-						placeholder="请选择类型"
-						clearable
-						class="w100"
-						v-model="state.queryParams.KnowledgeTypeId"
-					>
-					</el-cascader>
-				</el-form-item>
-				<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="timeChange"
-						value-format="YYYY-MM-DD[T]HH:mm:ss"
-					/>
-					<!-- value-format="YYYY-MM-DD" -->
-				</el-form-item>
-				<el-form-item>
-					<el-button type="primary" @click="queryList" :loading="state.loading" v-waves> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-					<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-				</el-form-item>
-			</el-form>
-		</el-card>
-		<el-card shadow="never">
-			<div class="mb20">
-				
-			</div>
-			<!-- 表格 -->
-			<el-table :data="state.tableList" v-loading="state.loading" row-key="id">
-				<el-table-column prop="title" label="标题" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="knowledgeTypeName" label="类型" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="creationTime" label="创建时间" show-overflow-tooltip width="170">
-					<template #default="{row}">
-						<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column label="操作" width="120" fixed="right" align="center">
-					<template #default="{row}">
-						<el-button link type="primary" @click="onEdit(row)" title="编辑" v-auth="'knowledge:draft:edit'"> 编辑 </el-button>
-						<el-button link type="danger" @click="onDel(row)" title="删除" v-auth="'knowledge:draft:delete'"> 删除 </el-button>
-					</template>
-				</el-table-column>
-				<template #empty>
-					<Empty />
-				</template>
-			</el-table>
-			<!-- 分页 -->
-			<pagination
-				:total="state.total"
-				v-model:page="state.queryParams.PageIndex"
-				v-model:limit="state.queryParams.PageSize"
-				@pagination="queryList"
-			/>
-		</el-card>
-	</div>
-</template>
-
-<script lang="ts" setup name="knowledgeDraft">
-import { ref, reactive, onMounted, onActivated } from 'vue';
-import type { FormInstance } from 'element-plus';
-import { ElMessage, ElMessageBox } from 'element-plus';
-import { auth } from '/@/utils/authFunction';
-import other from '/@/utils/other';
-import { treeList } from '/@/api/knowledge/type';
-import { formatDate } from '/@/utils/formatTime';
-import { useRouter } from 'vue-router';
-import { throttle } from '/@/utils/tools';
-import {shortcuts} from '/@/utils/constants';
-import { KnowledgeDel, myDraftsList } from '/@/api/knowledge';
-
-// 定义变量内容
-const state = reactive(<any>{
-	queryParams: {
-		PageIndex: 1, // 当前页
-		PageSize: 10, // 每页显示条数
-		Status: '0',  // 状态 0 草稿箱 1 已发布
-		ApplyType: '',  // 申请类型
-		IsOvertime: '',   // 是否超时
-		StartTime: '',  // 开始时间
-		EndTime: '',  // 结束时间
-	},
-	typeData: [], // 知识分类
-	tableList: [],  // 表格数据
-	loading: false, // 加载状态
-	total: 0, // 总条数
-});
-const router = useRouter(); // 路由
-const ruleFormRef = ref<FormInstance>();  // 表单ref
-// 创建时间
-const timeChange = (val: string[]) => {
-	state.queryParams.StartTime = val[0];
-	state.queryParams.EndTime = val[1];
-};
-/** 获取草稿箱列表 */
-const queryList = throttle(() => {
-	if (!auth('knowledge:draft:query')) ElMessage.error('抱歉,您没有权限获取草稿箱列表');
-	else {
-		state.loading = true;
-		let request = other.deepClone(state.queryParams);
-		Reflect.deleteProperty(request, 'crTime'); // 删除无用的参数
-		myDraftsList(request)
-			.then((response: any) => {
-				state.tableList = response?.result.items ?? [];
-				state.total = response?.result.total;
-				state.loading = false;
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	}
-}, 300);
-/** 重置按钮操作 */
-const resetQuery = throttle((formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	state.queryParams.StartTime = '';
-	state.queryParams.EndTime = '';
-	queryList();
-}, 300);
-// 修改知识草稿
-const onEdit = (row: any) => {
-	router.push({
-		name: 'knowledgeEdit',
-		params: {
-			id: row.id,
-			tagsViewName: '编辑草稿',
-			isDraft: 'isDraft',
-		},
-	});
-};
-const onDel = (row: any) => {
-	ElMessageBox.confirm(`确定要从草稿箱删除`, '提示', {
-		confirmButtonText: '确认',
-		cancelButtonText: '取消',
-		type: 'warning',
-		draggable: true,
-		cancelButtonClass: 'default-button',
-	})
-		.then(() => {
-			KnowledgeDel(row.id).then(() => {
-				ElMessage.success('操作成功');
-				queryList();
-			});
-		})
-		.catch(() => {});
-};
-// 知识分类
-const getKnowledgeType = async () => {
-	state.loading = true;
-	try {
-		const res: any = await treeList({ IsEnable: true });
-		state.typeData = res.result ?? [];
-		state.loading = false;
-	} catch (error) {
-		state.loading = false;
-	}
-};
-onMounted(() => {
-	queryList();
-	getKnowledgeType();
-});
-onActivated(() => {
-	queryList();
-});
-</script>

+ 0 - 631
src/views/knowledge/knowledge/index.vue

@@ -1,631 +0,0 @@
-<template>
-	<!-- 如果需要左右顶格布局参考系统设置字典管理 -->
-	<div class="knowledge-knowledge-container layout-padding">
-		<div class="layout-padding-auto layout-padding-view pd20">
-			<el-row :gutter="20" class="h100">
-				<el-col :xs="6" :sm="6" :md="6" :lg="4" :xl="4" class="orgTree">
-					<div class="h100 pr10">
-						<el-tabs v-model="state.activeName" stretch>
-							<el-tab-pane label="部门" name="0">
-								<el-input v-model="filterOrg" placeholder="请输入部门名称" class="input-with-select mt10 mb10" clearable> </el-input>
-							</el-tab-pane>
-							<el-tab-pane label="类型" name="1">
-								<el-input v-model="filterType" placeholder="请输入类型名称" class="input-with-select mt10 mb10" clearable> </el-input>
-							</el-tab-pane>
-							<el-tab-pane label="热点" name="2">
-								<el-input v-model="filterHot" placeholder="请输入热点名称" class="input-with-select mt10 mb10" clearable> </el-input>
-							</el-tab-pane>
-						</el-tabs>
-						<div style="height: calc(100% - 100px);'">
-							<el-scrollbar>
-								<el-tree
-                  v-show="state.activeName === '0'"
-									:data="state.orgData"
-									highlight-current
-									:expand-on-click-node="false"
-									:props="{ children: 'children', label: 'name' }"
-									@node-click="handleNodeClick"
-									ref="orgRef"
-									v-loading="state.loading"
-									:filter-node-method="filterNode"
-									node-key="id"
-                  :style="state.activeName === '0'? '' : 'display:none'"
-									:default-expanded-keys="state.defaultExpandedOrgKeys"
-								>
-								</el-tree>
-                <el-tree
-                    :data="state.knowledgeOptions"
-                    highlight-current
-                    :expand-on-click-node="false"
-                    :props="{ children: 'children', label: 'name' }"
-                    @node-click="handleNodeClick"
-                    ref="typeRef"
-                    v-loading="state.loading"
-                    :filter-node-method="filterNodeType"
-                    node-key="id"
-                    :style="state.activeName === '1'? '' : 'display:none'"
-                    :default-expanded-keys="state.defaultExpandedTypeKeys"
-                >
-                </el-tree>
-                <el-tree
-                    filterable
-                    highlight-current
-                    placeholder="请选择热点分类"
-                    :props="HotspotProps"
-                    @node-click="handleNodeClick"
-                    lazy
-                    :load="load"
-                    node-key="id"
-                    ref="hotRef"
-                    :filter-node-method="filterNodeHot"
-                    :expand-on-click-node="false"
-                    :style="state.activeName === '2'? '' : 'display:none'"
-                >
-                  <template #default="{ data }">
-										<span :title="data.hotSpotName">
-											{{ data.hotSpotName }}
-										</span>
-                  </template>
-                </el-tree>
-							</el-scrollbar>
-						</div>
-					</div>
-				</el-col>
-				<el-col :xs="18" :sm="18" :md="18" :lg="20" :xl="20" class="rightContent">
-					<el-scrollbar class="pr10 scrollbar__view">
-						<el-tabs v-model="state.queryParams.Status" @tab-change="handleClick">
-							<el-tab-pane label="全部" name=" "></el-tab-pane>
-							<el-tab-pane :label="v.value" :name="v.key" v-for="(v, i) in state.statusOptions" :key="i"></el-tab-pane>
-						</el-tabs>
-						<!-- 搜索条件 -->
-						<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="pl15 pr15 pt15">
-							<el-form-item label="关键字" prop="Keyword">
-								<el-input
-									v-model="state.queryParams.Keyword"
-									placeholder="标题/创建人/创建部门"
-									clearable
-									@keyup.enter="handleQuery"
-									style="width: 300px"
-								/>
-							</el-form-item>
-							<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="timeStartChangeCr"
-									value-format="YYYY-MM-DD[T]HH:mm:ss"
-								/>
-							</el-form-item>
-							<el-form-item label="上架时间" prop="sjTime">
-								<el-date-picker
-									v-model="state.queryParams.sjTime"
-									type="datetimerange"
-									unlink-panels
-									range-separator="至"
-									start-placeholder="开始时间"
-									end-placeholder="结束时间"
-									:shortcuts="shortcuts"
-									@change="timeStartChangeSj"
-									value-format="YYYY-MM-DD[T]HH:mm:ss"
-								/>
-							</el-form-item>
-							<el-form-item label="下架时间" prop="xjTime">
-								<el-date-picker
-									v-model="state.queryParams.xjTime"
-									type="datetimerange"
-									unlink-panels
-									range-separator="至"
-									start-placeholder="开始时间"
-									end-placeholder="结束时间"
-									:shortcuts="shortcuts"
-									@change="timeStartChangeXj"
-									value-format="YYYY-MM-DD[T]HH:mm:ss"
-								/>
-							</el-form-item>
-							<el-form-item>
-								<el-button type="primary" @click="handleQuery" :loading="state.tableLoading">
-									<SvgIcon name="ele-Search" class="mr5" />查询
-								</el-button>
-								<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.tableLoading">
-									<SvgIcon name="ele-Refresh" class="mr5" />重置
-								</el-button>
-							</el-form-item>
-						</el-form>
-						<div class="mb20">
-							<el-button type="primary" @click="onOpenAddUser" v-auth="'knowledge:add'"> <SvgIcon name="ele-Plus" class="mr5" />创建知识 </el-button>
-						</div>
-						<!-- 表格 -->
-						<el-table :data="state.tableData" v-loading="state.tableLoading" row-key="id">
-							<el-table-column prop="title" label="标题" show-overflow-tooltip width="120"></el-table-column>
-							<el-table-column prop="knowledgeTypeName" label="类型" show-overflow-tooltip width="200"></el-table-column>
-							<el-table-column prop="hotspotName" label="热点" show-overflow-tooltip width="200"></el-table-column>
-							<el-table-column prop="creationName" label="创建人" show-overflow-tooltip width="120"></el-table-column>
-							<el-table-column prop="creationBMName" label="创建部门" show-overflow-tooltip width="150"></el-table-column>
-							<el-table-column prop="creationTime" label="创建时间" show-overflow-tooltip width="170">
-								<template #default="{ row }">
-									<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column prop="pageView" label="阅读次数" show-overflow-tooltip></el-table-column>
-							<el-table-column prop="onShelfTime" label="上架时间" show-overflow-tooltip width="170">
-								<template #default="{ row }">
-									<span>{{ formatDate(row.onShelfTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column prop="offShelfTime" label="下架时间" show-overflow-tooltip width="170">
-								<template #default="{ row }">
-									<span>{{ formatDate(row.offShelfTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column prop="lastModificationTime" label="更新时间" show-overflow-tooltip width="170">
-								<template #default="{ row }">
-									<span>{{ formatDate(row.lastModificationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column prop="status" label="状态" show-overflow-tooltip width="100">
-								<template #default="{ row }">
-									<span v-if="row.status === 1" class="color-primary">{{ row.statusName }}</span>
-									<span v-if="row.status === 2" class="color-danger">{{ row.statusName }}</span>
-									<span v-if="row.status === 3" class="color-success">{{ row.statusName }}</span>
-									<span v-if="row.status === 4" class="color-info">{{ row.statusName }}</span>
-								</template>
-							</el-table-column>
-							<el-table-column label="操作" width="300" fixed="right" align="center">
-								<template #default="{ row }">
-									<el-button
-										link
-										type="info"
-										@click="onPreview(row)"
-										title="预览"
-										v-if="[1, 2, 3, 4].includes(row.status)"
-										v-auth="'knowledge:preview'"
-									>
-										预览
-									</el-button>
-									<el-button link type="primary" @click="onEdit(row)" title="编辑" v-if="[2, 3, 4].includes(row.status)" v-auth="'knowledge:edit'">
-										编辑
-									</el-button>
-									<el-button
-										link
-										type="warning"
-										@click="offShelfFn(row)"
-										title="下架"
-										v-if="[3].includes(row.status)"
-										v-auth="'knowledge:undercarriage'"
-									>
-										下架
-									</el-button>
-									<el-button
-										link
-										type="success"
-										@click="groundingFn(row)"
-										title="上架"
-										v-if="[4].includes(row.status)"
-										v-auth="'knowledge:grounding'"
-									>
-										上架
-									</el-button>
-									<el-button
-										link
-										type="primary"
-										@click="onRecord(row)"
-										title="查看审核记录"
-										v-if="[1, 2].includes(row.status)"
-										v-auth="'system:workflow:record'"
-									>
-										查看审核记录
-									</el-button>
-									<el-button link type="danger" @click="onRecall(row)" title="撤回" v-if="[1].includes(row.status)" v-auth="'system:workflow:stop'">
-										撤回
-									</el-button>
-									<el-button link type="danger" @click="onRowDel(row)" title="删除" v-if="[2, 3, 4].includes(row.status)" v-auth="'knowledge:delete'">
-										删除
-									</el-button>
-									<el-button
-										link
-										type="primary"
-										@click="onRenew(row)"
-										title="发起更新申请"
-										v-if="[3, 4].includes(row.status)"
-										v-auth="'knowledge:myApply:add'"
-									>
-										发起更新申请
-									</el-button>
-								</template>
-							</el-table-column>
-							<template #empty>
-								<Empty />
-							</template>
-						</el-table>
-						<!-- 分页 -->
-						<pagination
-							:total="state.total"
-							v-model:page="state.queryParams.PageIndex"
-							v-model:limit="state.queryParams.PageSize"
-							@pagination="queryList"
-						/>
-						<el-backtop target=".scrollbar__view > div" />
-					</el-scrollbar>
-				</el-col>
-			</el-row>
-		</div>
-		<!-- 审核记录 -->
-		<audit-record ref="auditRecordRef" />
-		<!-- 流程组件 -->
-		<knowledge-process ref="knowledgeProcessRef" @knowledgeProcessSuccess="knowledgeProcessSuccess" />
-		<!-- 更新申请 -->
-		<knowledge-update ref="knowledgeUpdateRef" @updateList="queryList" />
-	</div>
-</template>
-
-<script lang="ts" setup name="knowledge">
-import { ref, reactive, onMounted, watch, defineAsyncComponent } from 'vue';
-import { ElMessageBox, ElMessage } from 'element-plus';
-import { useRouter } from 'vue-router';
-import type { FormInstance } from 'element-plus';
-import { formatDate } from '/@/utils/formatTime';
-import { throttle} from '/@/utils/tools';
-import {commonEnum, shortcuts } from '/@/utils/constants';
-import { auth } from '/@/utils/authFunction';
-import { KnowledgePaged, KnowledgeOffShelf, KnowledgeOnTheShelf, baseData } from '/@/api/knowledge';
-import { workflowTerminate } from '/@/api/system/workflow';
-import { getOrgList } from '/@/api/system/organize';
-import { treeList } from '/@/api/knowledge/type';
-import { hotSpotType } from '/@/api/business/order';
-
-// 引入组件
-const KnowledgeProcess = defineAsyncComponent(() => import('/@/views/knowledge/component/Knowledge-process.vue'));  //流程组件
-const KnowledgeUpdate = defineAsyncComponent(() => import('/@/views/knowledge/knowledge/component/Knowledge-update.vue'));  //更新申请
-const AuditRecord = defineAsyncComponent(() => import('/@/components/AuditRecord/index.vue'));  //审核记录
-
-// 定义变量内容
-const state = reactive<any>({
-	queryParams: {
-		PageIndex: 1, //页码
-		PageSize: 10, //每页条数
-		Keyword: '',  //关键字
-		Status: ' ',  //状态
-    OrgId: '',    //组织机构
-    HotSpotTypeId: '', //热点分类
-    CreationStartTime: '', //创建开始时间
-    CreationEndTime: '', //创建结束时间
-    StartOnShelfTime: '', //上架开始时间
-    EndOnShelfTime: '', //上架结束时间
-    StartOffShelfTime: '', //下架开始时间
-    EndOffShelfTime: '', //下架结束时间
-	},
-	activeName: '0', //tab切换
-	tableData: [],  //表格数据
-	total: 0, //总条数
-	loading: false, //表格loading
-	tableLoading: false,  //表格loading
-	orgData: [],  //组织机构数据
-	knowledgeOptions: [], //知识库类型数据
-	statusOptions: [], //状态数据
-	defaultExpandedOrgKeys: [], //默认展开的组织机构
-	defaultExpandedTypeKeys: [],  //默认展开的知识库类型
-});
-const router = useRouter(); //路由
-const ruleFormRef = ref<FormInstance>(); //表单ref
-// 热点分类远程搜索
-const HotspotProps = {
-	label: 'hotSpotFullName',
-	children: 'children',
-	isLeaf: 'isLeaf',
-};
-// 热点分类懒加载
-const load = async (node: any, resolve: any) => {
-	if (node.isLeaf) return resolve([]);
-	const res: any = await hotSpotType({ id: node.data.id ? node.data.id : '' });
-	resolve(res.result);
-};
-// 三个类型的搜索
-const filterOrg = ref('');
-const orgRef = ref<RefType>();
-watch(filterOrg, (val) => {
-	orgRef.value!.filter(val);
-});
-const filterNode = (value: string, data: any) => {
-	if (!value) return true;
-	return data.orgName.includes(value);
-};
-const filterType = ref('');
-const typeRef = ref<RefType>();
-watch(filterType, (val) => {
-	typeRef.value!.filter(val);
-});
-const filterNodeType = (value: string, data: any) => {
-	if (!value) return true;
-	return data.name.includes(value);
-};
-const filterHot = ref('');
-const hotRef = ref<RefType>();
-watch(filterHot, (val) => {
-	hotRef.value!.filter(val);
-});
-const filterNodeHot = (value: string, data: any) => {
-	if (!value) return true;
-	return data.hotSpotName.includes(value);
-};
-
-// 切换tab 查询列表
-const handleClick = () => {
-	queryList();
-};
-const handleTimeChange = (val: string[], startKey: string, endKey: string) => {
-	if (val) {
-		state.queryParams[startKey] = val[0];
-		state.queryParams[endKey] = val[1];
-	} else {
-		state.queryParams[startKey] = '';
-		state.queryParams[endKey] = '';
-	}
-	queryList();
-};
-// 创建时间
-const timeStartChangeCr = (val: string[]) => {
-	handleTimeChange(val, 'CreationStartTime', 'CreationEndTime');
-};
-// 上架时间
-const timeStartChangeSj = (val: string[]) => {
-	handleTimeChange(val, 'StartOnShelfTime', 'EndOnShelfTime');
-};
-// 下架时间
-const timeStartChangeXj = (val: string[]) => {
-	handleTimeChange(val, 'StartOffShelfTime', 'EndOffShelfTime');
-};
-/** 搜索按钮操作 节流操作 */
-const handleQuery = throttle(() => {
-	state.queryParams.PageIndex = 1;
-	queryList();
-}, 500);
-// 获取所有组织结构 和基础数据
-const getOrgListApi = async () => {
-	state.loading = true;
-	try {
-		const res: any = await Promise.all([getOrgList(), treeList({ IsEnable: true }),baseData()]);
-		state.orgData = res[0].result ?? []; //部门
-		state.knowledgeOptions = res[1].result ?? []; // 知识类型
-    state.statusOptions = res[2].result ?? []; // 列表状态
-		state.loading = false;
-	} catch (error) {
-		state.loading = false;
-	}
-};
-/** 获取知识列表 */
-const queryList = () => {
-	if (!auth('knowledge:query')) ElMessage.error('抱歉,您没有权限获取知识库列表');
-	else {
-		state.tableLoading = true;
-    let request = {
-      PageIndex: state.queryParams.PageIndex,
-      PageSize: state.queryParams.PageSize,
-      Keyword: state.queryParams.Keyword,
-      Status: state.queryParams.Status,
-      OrgId: state.queryParams.OrgId,
-      HotSpotTypeId: state.queryParams.HotSpotTypeId,
-      CreationStartTime: state.queryParams.CreationStartTime,
-      CreationEndTime: state.queryParams.CreationEndTime,
-      StartOnShelfTime: state.queryParams.StartOnShelfTime,
-      EndOnShelfTime: state.queryParams.EndOnShelfTime,
-      StartOffShelfTime: state.queryParams.StartOffShelfTime,
-      EndOffShelfTime: state.queryParams.EndOffShelfTime,
-    }
-		KnowledgePaged(request)
-			.then((response: any) => {
-				state.tableData = response?.result.items ?? [];
-				state.total = response?.result.total;
-				state.tableLoading = false;
-			})
-			.catch(() => {
-				state.tableLoading = false;
-			});
-	}
-};
-// 点击节点
-const handleNodeClick = (data: any) => {
-	switch (state.activeName) {
-		case '0':
-			state.queryParams.CreateOrgId = data.orgCode;
-			break;
-		case '1':
-			state.queryParams.KnowledgeTypeId = data.id;
-			break;
-		case '2':
-			state.queryParams.HotspotId = data.id;
-			break;
-		default:
-			break;
-	}
-	queryList();
-};
-/** 重置按钮操作 */
-const resetQuery = throttle((formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	state.queryParams.CreateOrgId = '';
-	state.queryParams.HotspotId = '';
-	state.queryParams.KnowledgeTypeId = '';
-	state.queryParams.CreationStartTime = '';
-	state.queryParams.CreationEndTime = '';
-	state.queryParams.StartOffShelfTime = '';
-	state.queryParams.EndOffShelfTime = '';
-	state.queryParams.StartOnShelfTime = '';
-	state.queryParams.EndOnShelfTime = '';
-	typeRef.value?.setCurrentKey(null);
-	orgRef.value?.setCurrentKey(null);
-	hotRef.value?.setCurrentKey(null);
-	handleQuery();
-}, 500);
-// 创建知识
-const onOpenAddUser = () => {
-	router.push({
-		name: 'knowledgeEdit',
-		params: {
-			tagsViewName: '创建知识',
-		},
-	});
-};
-// 修改知识
-const onEdit = (row: any) => {
-	router.push({
-		name: 'knowledgeEdit',
-		params: {
-			id: row.id,
-			tagsViewName: '编辑知识',
-		},
-	});
-};
-// 预览
-const onPreview = (row: any) => {
-	router.push({
-		name: 'knowledgePreview',
-		params: {
-			id: row.id,
-			tagsViewName: '知识预览',
-		},
-	});
-};
-// 查看审核记录
-const auditRecordRef = ref<RefType>();  //审核记录ref
-const onRecord = (row: any) => {
-	const params = {
-		dialogTitle: `审核记录 (${row.title})`,
-		...row,
-	};
-	auditRecordRef.value.openDialog(params);
-};
-// 发起更新
-const knowledgeUpdateRef = ref<RefType>();  //更新申请ref
-const onRenew = (row: any) => {
-	knowledgeUpdateRef.value.openDialog(row, state.orgData, state.knowledgeOptions);
-};
-// 申请流程成功
-const knowledgeProcessSuccess = () => {
-	handleQuery();
-};
-// 下架
-const offShelfFn = (row: any) => {
-	ElMessageBox.confirm(`是否确定要下架?知识下架后,将不会被检索到!`, '提示', {
-		confirmButtonText: '确认',
-		cancelButtonText: '取消',
-		type: 'warning',
-		draggable: true,
-		cancelButtonClass: 'default-button',
-	})
-		.then(() => {
-			KnowledgeOffShelf(row.id).then(() => {
-				ElMessage.success('操作成功');
-				handleQuery();
-				state.queryParams.OrgCode = '';
-				getOrgListApi();
-			});
-		})
-		.catch(() => {});
-};
-// 上架
-const groundingFn = (row: any) => {
-	ElMessageBox.confirm(`是否确定要上架?`, '提示', {
-		confirmButtonText: '确认',
-		cancelButtonText: '取消',
-		type: 'warning',
-		draggable: true,
-		cancelButtonClass: 'default-button',
-	})
-		.then(() => {
-			KnowledgeOnTheShelf(row.id).then(() => {
-				ElMessage.success('操作成功');
-				handleQuery();
-				state.queryParams.OrgCode = '';
-				getOrgListApi();
-			});
-		})
-		.catch(() => {});
-	// ElMessageBox.confirm(`知识已过有效期,无法直接上架,请到【编辑】页面,修改有效期。`, '提示', {
-	// 	confirmButtonText: '去编辑',
-	// 	cancelButtonText: '取消',
-	// 	type: 'warning',
-	// 	draggable: true,
-	// 	cancelButtonClass: 'default-button',
-	// })
-	// 	.then(() => {
-	// 		restPwd(row.id).then(() => {
-	// 			ElMessage.success('操作成功');
-	// 			handleQuery();
-	// 			state.queryParams.OrgCode = '';
-	// 			getOrgListApi();
-	// 		});
-	// 	})
-	// 	.catch(() => {});
-};
-
-// 撤回
-const onRecall = (row: any) => {
-	ElMessageBox.prompt('撤回原因', '提示', {
-		confirmButtonText: '确定',
-		cancelButtonText: '取消',
-		inputPlaceholder: '请输入撤回原因,不超过50字符',
-		draggable: true,
-		inputErrorMessage: '请输入撤回原因',
-		inputType: 'textarea',
-		inputValidator: (value) => {
-			if (value) return true;
-			else return '请输入撤回原因';
-		},
-	})
-		.then(({ value }) => {
-			let req = {
-				workflowId: row.workflowId,
-				opinion: value,
-			};
-			ElMessageBox.confirm(`是否确定要撤回?撤回成功后请到【我的草稿箱】中进行查看和管理`, '提示', {
-				confirmButtonText: '确认',
-				cancelButtonText: '取消',
-				type: 'warning',
-				draggable: true,
-				cancelButtonClass: 'default-button',
-				autofocus: false,
-			})
-				.then(() => {
-					workflowTerminate(req)
-						.then(() => {
-							ElMessage.success('操作成功');
-							handleQuery();
-							state.queryParams.OrgCode = '';
-							getOrgListApi();
-						})
-						.catch(() => {});
-				})
-				.catch(() => {});
-		})
-		.catch(() => {});
-};
-// 删除知识
-const knowledgeProcessRef = ref<RefType>(); //流程组件ref
-const onRowDel = (row: any) => {
-	knowledgeProcessRef.value.openDialog({ id: row.id, title: '删除知识', commonEnum: commonEnum.Seat, processType: 'deleteStart' });
-};
-onMounted(() => {
-	queryList();
-	getOrgListApi();
-});
-</script>
-<style lang="scss" scoped>
-.knowledge-knowledge-container {
-	.orgTree {
-		border-right: 1px solid var(--el-border-color);
-		height: 100%;
-	}
-	.rightContent {
-		height: 100%;
-	}
-	:deep(.el-tree-node__content) {
-		height: 40px;
-	}
-}
-</style>

+ 0 - 213
src/views/knowledge/process/index.vue

@@ -1,213 +0,0 @@
-<template>
-	<div class="knowledge-process-container layout-pd">
-		<el-card shadow="never">
-			<el-tabs v-model="state.queryParams.EKnowledgeWorkFlowStatus" @tab-change="handleClick">
-				<el-tab-pane label="全部" name=" "></el-tab-pane>
-				<el-tab-pane :label="v.value" :name="v.key" v-for="(v, i) in state.statusOptions" :key="i"></el-tab-pane>
-				<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="mt15">
-					<el-form-item label="审核类型" prop="EKnowledgeApplyType">
-						<el-select v-model="state.queryParams.EKnowledgeApplyType" placeholder="请选择审核类型" class="w100">
-							<el-option v-for="(item, index) in state.eKnowledgeApplyType" :key="index" :label="item.value" :value="item.key" />
-						</el-select>
-					</el-form-item>
-					<el-form-item label="关键字" prop="Keyword">
-						<el-input v-model="state.queryParams.Keyword" placeholder="标题/创建人/创建部门" clearable style="width: 300px"> </el-input>
-					</el-form-item>
-					<el-form-item>
-						<el-button type="primary" @click="queryList" :loading="state.loading" v-waves> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-						<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-					</el-form-item>
-				</el-form>
-			</el-tabs>
-		</el-card>
-		<el-card shadow="never">
-			<div class="mb20">
-				
-			</div>
-			<!-- 表格 -->
-			<el-table :data="state.tableList" v-loading="state.loading" row-key="id">
-				<el-table-column prop="knowledgeTypeName" label="审核类型" show-overflow-tooltip>
-					<template #default="{ row }">
-						<span v-if="row.workflowModuleStatus === 0" class="color-primary">{{ row.workflowModuleStatusName }}</span>
-						<span v-if="row.workflowModuleStatus === 2" class="color-danger">{{ row.workflowModuleStatusName }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="title" label="标题" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="knowledgeTypeName" label="类型" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="creationName" label="创建人" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="createBMName" label="创建部门" show-overflow-tooltip width="170"></el-table-column>
-				<el-table-column label="状态" show-overflow-tooltip>
-					<template #default="{ row }">
-						<span v-if="row.workFlowApplyStatus === 1" class="color-primary">{{ row.workFlowApplyStatusName }}</span>
-						<span v-if="row.workFlowApplyStatus === 2" class="color-success">{{ row.workFlowApplyStatusName }}</span>
-						<span v-if="row.workFlowApplyStatus === 3" class="color-danger">{{ row.workFlowApplyStatusName }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="创建时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="到达该节点时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.currentStepTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="toNo" label="审核时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.handleTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column label="操作" width="160" fixed="right" align="center">
-					<template #default="{ row }">
-						<el-button
-							link
-							type="primary"
-							@click="onPreview(row)"
-							title="预览"
-							v-auth="'knowledge:preview'"
-							v-if="[1, 2, 3].includes(row.workFlowApplyStatus)"
-						>
-							预览
-						</el-button>
-						<el-button
-							link
-							type="primary"
-							@click="onProcess(row)"
-							title="审核"
-							v-auth="'system:workflow:handle'"
-							v-if="[1].includes(row.workFlowApplyStatus) && row.canHandle"
-						>
-							审核
-						</el-button>
-						<el-button
-							link
-							type="info"
-							@click="onRecord(row)"
-							title="查看审核记录"
-							v-auth="'system:workflow:record'"
-							v-if="[2, 3].includes(row.workFlowApplyStatus)"
-							>查看审核记录
-						</el-button>
-					</template>
-				</el-table-column>
-				<template #empty>
-					<Empty />
-				</template>
-			</el-table>
-			<!-- 分页 -->
-			<pagination
-				:total="state.total"
-				v-model:page="state.queryParams.PageIndex"
-				v-model:limit="state.queryParams.PageSize"
-				@pagination="queryList"
-			/>
-		</el-card>
-		<!-- 审核记录 -->
-    <audit-record ref="auditRecordRef" />
-		<!-- 流程组件 -->
-		<knowledge-process ref="knowledgeProcessRef" @knowledgeProcessSuccess="knowledgeProcessSuccess" />
-	</div>
-</template>
-
-<script lang="ts" setup name="knowledgeProcess">
-import { ref, reactive, onMounted, defineAsyncComponent } from 'vue';
-import { ElMessage } from 'element-plus';
-import type { FormInstance } from 'element-plus';
-import { auth } from '/@/utils/authFunction';
-import { useRouter } from 'vue-router';
-import { formatDate } from '/@/utils/formatTime';
-import { throttle } from '/@/utils/tools';
-import {commonEnum} from '/@/utils/constants';
-import { KnowledgeApprovedList, approvedBaseData } from '/@/api/knowledge';
-
-// 引入组件
-const KnowledgeProcess = defineAsyncComponent(() => import('/@/views/knowledge/component/Knowledge-process.vue'));  // 流程组件
-const AuditRecord = defineAsyncComponent(() => import('/@/components/AuditRecord/index.vue'));  // 审核记录组件
-
-// 定义变量内容
-const state = reactive(<any>{
-	queryParams: {
-		PageIndex: 1, // 当前页
-		PageSize: 10, // 每页显示条数
-		EKnowledgeWorkFlowStatus: ' ',  // 审核状态
-		EKnowledgeApplyType: '',  // 审核类型
-	},
-	tableList: [],  // 表格数据
-	loading: false, // 加载状态
-	total: 0, // 总条数
-	eKnowledgeApplyType: [],  // 审核类型数据
-	statusOptions: [], // 审核状态数据
-});
-const ruleFormRef = ref<FormInstance>();  // 表单ref
-const router = useRouter(); // 路由
-/** 获取审核列表 */
-const queryList = throttle(() => {
-	if (!auth('knowledge:process:query')) ElMessage.error('抱歉,您没有权限查询知识审核列表');
-	else {
-		state.loading = true;
-		KnowledgeApprovedList(state.queryParams)
-			.then((response: any) => {
-				state.tableList = response.result.items ?? [];
-				state.total = response?.result.total;
-				state.loading = false;
-			})
-			.catch(() => {
-				state.loading = false;
-			});
-	}
-}, 500);
-/** 重置按钮操作 */
-const resetQuery = throttle((formEl: FormInstance | undefined) => {
-	if (!formEl) return;
-	formEl.resetFields();
-	queryList();
-}, 500);
-// 切换tab 查询列表
-const handleClick = () => {
-	queryList();
-};
-// 预览
-const onPreview = (row: any) => {
-	router.push({
-		name: 'knowledgePreview',
-		params: {
-			id: row.id,
-			tagsViewName: '知识预览',
-		},
-	});
-};
-// 审核
-const knowledgeProcessRef = ref<RefType>(); // 流程组件ref
-const onProcess = (row: any) => {
-  knowledgeProcessRef.value.openDialog({ id: row.workflowId, title: '提交', processType: 'next', commonEnum: commonEnum.KnowledgeLocution });
-};
-// 发起更新成功
-const knowledgeProcessSuccess = () => {
-	queryList();
-};
-// 查看审核记录
-const auditRecordRef = ref<RefType>();  // 审核记录ref
-const onRecord = (row: any) => {
-  const params = {
-    title: `审核记录 (${row.title})`,
-    ...row,
-  };
-  auditRecordRef.value.openDialog(params);
-};
-// 页面基础数据
-const getBaseData = async () => {
-	try {
-		const { result } = await approvedBaseData();
-		state.statusOptions = result.eKnowledgeWorkFlowStatus;
-		state.eKnowledgeApplyType = result.eKnowledgeApplyType;
-	} catch (error) {
-		console.log(error);
-	}
-};
-onMounted(() => {
-	queryList();
-	getBaseData();
-});
-</script>
-<style lang="scss" scoped></style>

+ 168 - 0
src/views/knowledge/question/components/Question-add.vue

@@ -0,0 +1,168 @@
+<template>
+	<el-drawer title="知识提问" v-model="drawerVisible" size="40%" destroy-on-close @close="close">
+		<el-form :model="state.ruleForm" label-width="110px" ref="ruleFormRef">
+			<el-row :gutter="0">
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="知识标题"> {{ state.ruleForm.title }} </el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+					<el-form-item label="知识创建部门:"> {{ state.ruleForm.creatorOrgName }} </el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+					<el-form-item label="知识创建人:"> {{ state.ruleForm.creatorName }} </el-form-item>
+				</el-col>
+        <template v-if="isReply">
+          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+            <el-form-item label="提问人部门:"> {{ state.ruleForm.orgName }} </el-form-item>
+          </el-col>
+          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+            <el-form-item label="提问人:"> {{ state.ruleForm.name }} </el-form-item>
+          </el-col>
+        </template>
+				<template v-else>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="提问人部门:"> {{ userInfos.orgName }} </el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
+						<el-form-item label="提问人:"> {{ userInfos.orgName }} </el-form-item>
+					</el-col>
+				</template>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="提问内容" prop="opinion" :rules="[{ required: true, message: '请填写提问内容', trigger: 'blur' }]">
+						<el-input
+							type="textarea"
+							v-model="state.ruleForm.opinion"
+							placeholder="请填写提问内容"
+							:autosize="{ minRows: 4, maxRows: 8 }"
+							:disabled="isReply"
+						></el-input>
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+					<el-form-item label="附件">
+						<annex-list ref="annexListRef" classify="知识提问上传" />
+					</el-form-item>
+				</el-col>
+				<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="isReply">
+					<el-divider style="margin: 15px 0" />
+					<el-form-item label="答复内容" prop="replyContent" :rules="[{ required: true, message: '请填写答复内容', trigger: 'blur' }]">
+						<el-input
+							type="textarea"
+							v-model="state.ruleForm.replyContent"
+							placeholder="请填写答复内容"
+							:autosize="{ minRows: 6, maxRows: 8 }"
+						></el-input>
+					</el-form-item>
+				</el-col>
+			</el-row>
+		</el-form>
+		<template #footer v-if="isReply">
+			<span class="dialog-footer">
+				<el-button @click="drawerVisible = false" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onReply(ruleFormRef)" :loading="state.loading">答 复</el-button>
+			</span>
+		</template>
+		<template #footer v-else>
+			<span class="dialog-footer">
+				<el-button @click="drawerVisible = false" class="default-button">取 消</el-button>
+				<el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading">提 交</el-button>
+			</span>
+		</template>
+	</el-drawer>
+</template>
+<script setup lang="ts" name="knowledgeQuestionAdd">
+import { ref, defineAsyncComponent, reactive } from 'vue';
+import { ElMessage, FormInstance } from 'element-plus';
+import { storeToRefs } from 'pinia';
+import { useUserInfo } from '/@/stores/userInfo';
+import { questionAdd, questionReply, questionDetail } from '/@/api/knowledge/question';
+
+const emit = defineEmits(['submitSuccess']);
+
+const state = reactive<any>({
+	ruleForm: {
+		title: '', // 标题
+		content: '', // 内容
+		additions: [], // 附件
+	},
+	loading: false, // 加载状态
+});
+
+const AnnexList = defineAsyncComponent(() => import('/@/components/AnnexList/index.vue')); // 附件列表
+const drawerVisible = ref<boolean>(false);
+const storesUserInfo = useUserInfo();
+const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
+
+const isReply = ref<boolean>(false); // 是否答复
+// 打开弹窗
+const openDialog = (row: any, reply = false) => {
+	isReply.value = reply;
+	if (reply) {
+		questionDetail(row.id)
+			.then((res) => {
+				state.ruleForm = res.result;
+				state.ruleForm.opinion = state.ruleForm.content;
+        state.ruleForm.title = state.ruleForm.knowledge?.title;
+        state.ruleForm.creatorOrgName = state.ruleForm.knowledge?.creatorOrgName; //知识创建人
+        state.ruleForm.creatorName = state.ruleForm.knowledge?.creatorName; // 知识创建人
+        state.ruleForm.name = state.ruleForm.creatorName; // 提问人
+        state.ruleForm.orgName = state.ruleForm.creatorOrgName; // 提问人部门
+				drawerVisible.value = true;
+			})
+			.catch(() => {
+				ElMessage.error('获取详情失败');
+			});
+	} else {
+		state.ruleForm = row;
+		drawerVisible.value = true;
+	}
+};
+// 关闭弹窗
+const closeDialog = () => {
+	drawerVisible.value = false;
+};
+const close = () => {
+	ruleFormRef.value?.resetFields();
+	ruleFormRef.value?.clearValidate();
+};
+// 提交
+const ruleFormRef = ref<RefType>();
+const annexListRef = ref<RefType>(); // 附件列表
+const onSubmit = async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		const request = {
+			knowledgeId: state.ruleForm.id,
+			content: state.ruleForm.opinion,
+			files: annexListRef.value?.fileList,
+		};
+		questionAdd(request).then(() => {
+			ElMessage.success('操作成功');
+			closeDialog();
+			emit('submitSuccess');
+		});
+	});
+};
+// 答复
+const onReply = async (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	await formEl.validate((valid: boolean) => {
+		if (!valid) return;
+		const request = {
+			id: state.ruleForm.id,
+      replyContent: state.ruleForm.replyContent,
+		};
+		questionReply(request).then(() => {
+			ElMessage.success('操作成功');
+			closeDialog();
+			emit('submitSuccess');
+		});
+	});
+};
+defineExpose({
+	openDialog,
+	closeDialog,
+});
+</script>
+<style scoped lang="scss"></style>

+ 152 - 0
src/views/knowledge/question/index.vue

@@ -0,0 +1,152 @@
+<template>
+	<div class="knowledge-question-container layout-pd">
+		<el-card shadow="never">
+			<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
+				<el-form-item label="知识分类" prop="KnowledgeTypeId">
+            <el-cascader
+                :options="state.typeData"
+                filterable
+                :props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
+                placeholder="请选择知识分类"
+                v-model="state.queryParams.KnowledgeTypeId"
+                ref="cascadeRef"
+            >
+            </el-cascader>
+				</el-form-item>
+				<el-form-item label="提问人" prop="CreatorName">
+					<el-input v-model="state.queryParams.CreatorName" placeholder="请输入提问人" clearable @keyup.enter="queryList" style="width: 250px" />
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="queryList" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+				</el-form-item>
+			</el-form>
+		</el-card>
+		<el-card shadow="never">
+			<!-- 表格 -->
+			<el-table :data="state.tableData" v-loading="state.loading">
+        <el-table-column prop="knowledge.title" label="知识标题" show-overflow-tooltip width="130"></el-table-column>
+        <el-table-column prop="knowledgeTypeText" label="知识分类" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="knowledge.statusText" label="知识状态" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="stateText" label="答复状态" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="creatorName" label="提问人" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="creationTime" label="提问时间" show-overflow-tooltip width="170">
+          <template #default="{ row }">
+            <span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="content" label="提问内容" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="replyContent" label="答复内容" show-overflow-tooltip></el-table-column>
+        <el-table-column label="答复时间" show-overflow-tooltip width="170">
+          <template #default="{ row }">
+            <span>{{ formatDate(row.replyTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+          </template>
+        </el-table-column>
+				<el-table-column label="操作" width="140" fixed="right" align="center">
+					<template #default="{ row }">
+						<el-button link type="primary" @click="onPreview(row)" v-auth="'knowledge:index:preview'" title="知识详情"> 知识详情 </el-button>
+						<el-button link type="primary" @click="onReply(row)" v-auth="'knowledge:question:reply'" title="答复" v-if="[0].includes(row.state)"> 答复 </el-button>
+					</template>
+				</el-table-column>
+				<template #empty>
+					<Empty />
+				</template>
+			</el-table>
+			<!-- 分页 -->
+			<pagination
+				:total="state.total"
+				v-model:page="state.queryParams.PageIndex"
+				v-model:limit="state.queryParams.PageSize"
+				@pagination="queryList"
+			/>
+		</el-card>
+    <!-- 知识提问 -->
+    <question-add ref="questionRef" @submitSuccess="queryList"/>
+	</div>
+</template>
+
+<script lang="ts" setup name="knowledgeQuestion">
+import { reactive, ref, onMounted, defineAsyncComponent } from 'vue';
+import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
+import { formatDate } from '/@/utils/formatTime';
+import { auth } from '/@/utils/authFunction';
+import {useRouter} from "vue-router";
+import {questionList} from '/@/api/knowledge/question';
+import {treeList} from "/@/api/knowledge/type";
+
+// 引入组件
+const QuestionAdd = defineAsyncComponent(() => import('/@/views/knowledge/question/components/Question-add.vue')); // 知识提问
+
+// 定义变量内容
+const state = reactive<any>({
+	loading: false, // 加载状态
+	queryParams: {
+		// 查询参数
+		PageIndex: 1,
+		PageSize: 10,
+    KnowledgeTypeId: null, // 知识分类
+    CreatorName: null, // 提问人
+	},
+	total: 0, // 总条数
+	tableData: [], // 表格数据
+  typeData: [], // 知识分类
+});
+const ruleFormRef = ref<RefType>(null); // 表单ref
+const getBaseData = async () => {
+	try {
+		const typeDataRes = await treeList({ IsEnable: true });
+    state.typeData = typeDataRes.result ?? [];
+	} catch (error) {
+		console.log(error);
+	}
+};
+// 获取参数列表
+const queryList = () => {
+	state.loading = true;
+	if (!auth('knowledge:question:query')) ElMessage.error('抱歉,您没有权限获取知识提问列表!');
+	else {
+    questionList(state.queryParams)
+			.then((res) => {
+				state.loading = false;
+				state.tableData = res.result.items ?? [];
+				state.total = res.result.total ?? 0;
+			})
+			.finally(() => {
+				state.loading = false;
+			});
+	}
+};
+// 重置表单
+const resetQuery = (formEl: FormInstance | undefined) => {
+	if (!formEl) return;
+	formEl.resetFields();
+	queryList();
+};
+// 答复
+const questionRef = ref<RefType>();
+const onReply = (row: any) => {
+  questionRef.value.openDialog(row,true);
+};
+// 知识详情
+const router = useRouter();
+const onPreview = (row: any) => {
+  router.push({
+    name: 'knowledgePreview',
+    params: {
+      id: row.knowledge.id,
+      tagsViewName: '知识详情',
+    },
+  });
+};
+
+// 页面加载时
+onMounted(() => {
+	getBaseData();
+	queryList();
+});
+</script>
+
+<style lang="scss" scoped>
+.knowledge-question-container {
+}
+</style>

+ 346 - 84
src/views/knowledge/retrieval/index.vue

@@ -1,63 +1,194 @@
 <template>
-	<div class="knowledge-retrieval-container layout-pd">
-    <el-card shadow="never">
-      <div class="input-box">
-        <el-input v-model="state.queryParams.Keyword" placeholder="关键词" class="input-with-select" @input="queryList" clearable>
-          <template #prepend>
-            <el-select v-model="state.queryParams.RetrievalType" size="large" placeholder="请选择" style="width: 100px">
-              <el-option v-for="item in state.typeList" :key="item.value" :label="item.label" :value="item.value" class="w1" />
-            </el-select>
-          </template>
-          <template #append>
-            <el-button type="primary" size="large" class="btn" :loading="state.loading" @click="queryList" v-auth="'knowledge:process:query'"
-            >搜索</el-button
-            >
-          </template>
-        </el-input>
-      </div>
-      <el-divider />
-      <div v-loading="state.loading">
-        <template v-if="state.retrievalList.length && state.queryParams.Keyword">
-          <div v-for="(v, i) in state.retrievalList" :key="i" class="retrieval-content-item" @click="onPreview(v)" title="查看详情">
-            <h4 class="mb10">{{ v.title }}</h4>
-            <div class="text-ellipsis2" v-html="queryTitleLight(v.content)"></div>
-          </div>
-        </template>
-        <template v-else>
-          <Empty type="search" description="暂无结果" />
-        </template>
-      </div>
+	<div class="knowledge-retrieval-container layout-padding">
+		<el-card shadow="never" class="h100">
+			<el-tabs v-model="state.queryParams.Attribution" @tab-change="handleClick">
+				<el-tab-pane label="全部" name=" "></el-tab-pane>
+				<el-tab-pane label="中心知识库" name="中心知识库"></el-tab-pane>
+				<el-tab-pane label="部门知识库" name="部门知识库"></el-tab-pane>
+			</el-tabs>
+			<el-row :gutter="20" class="h100">
+				<el-col :xs="6" :sm="6" :md="6" :lg="4" :xl="4" class="left-container">
+					<div class="h100 pr10">
+						<el-tabs v-model="state.activeName" stretch>
+							<el-tab-pane label="部门" name="0">
+								<el-input v-model="filterOrg" placeholder="请输入部门名称" class="input-with-select mt10 mb10" clearable> </el-input>
+							</el-tab-pane>
+							<el-tab-pane label="知识分类" name="1">
+								<el-input v-model="filterType" placeholder="请输入知识分类名称" class="input-with-select mt10 mb10" clearable> </el-input>
+							</el-tab-pane>
+							<el-tab-pane label="热点" name="2">
+								<el-input v-model="filterHot" placeholder="请输入热点名称" class="input-with-select mt10 mb10" clearable> </el-input>
+							</el-tab-pane>
+						</el-tabs>
+						<div style="height: calc(100% - 100px);'">
+							<el-scrollbar>
+								<el-tree
+									v-show="state.activeName === '0'"
+									:data="state.orgData"
+									highlight-current
+									:expand-on-click-node="false"
+									:props="{ children: 'children', label: 'name' }"
+									@node-click="handleNodeClick"
+									ref="orgRef"
+									v-loading="state.loading"
+									:filter-node-method="filterNode"
+									node-key="id"
+									:style="state.activeName === '0' ? '' : 'display:none'"
+									:default-expanded-keys="state.defaultExpandedOrgKeys"
+								>
+								</el-tree>
+								<el-tree
+									:data="state.knowledgeOptions"
+									highlight-current
+									:expand-on-click-node="false"
+									:props="{ children: 'children', label: 'name' }"
+									@node-click="handleNodeClick"
+									ref="typeRef"
+									v-loading="state.loading"
+									:filter-node-method="filterNodeType"
+									node-key="id"
+									:style="state.activeName === '1' ? '' : 'display:none'"
+									:default-expanded-keys="state.defaultExpandedTypeKeys"
+								>
+								</el-tree>
+								<el-tree
+									filterable
+									highlight-current
+									placeholder="请选择热点分类"
+									:props="HotspotProps"
+									@node-click="handleNodeClick"
+									lazy
+									:load="load"
+									node-key="id"
+									ref="hotRef"
+									:filter-node-method="filterNodeHot"
+									:expand-on-click-node="false"
+									:style="state.activeName === '2' ? '' : 'display:none'"
+								>
+									<template #default="{ data }">
+										<span :title="data.hotSpotName">
+											{{ data.hotSpotName }}
+										</span>
+									</template>
+								</el-tree>
+							</el-scrollbar>
+						</div>
+					</div>
+				</el-col>
 
-      <!-- 分页 -->
-      <pagination
-          :total="state.total"
-          v-model:page="state.queryParams.PageIndex"
-          v-model:limit="state.queryParams.PageSize"
-          @pagination="queryList"
-      />
-    </el-card>
+				<el-col :xs="12" :sm="12" :md="14" :lg="14" :xl="14" class="center-container">
+					<div class="input-box">
+						<el-select v-model="state.queryParams.RetrievalType" placeholder="请选择" style="width: 120px">
+							<el-option v-for="item in state.typeList" :key="item.value" :label="item.label" :value="item.value" class="w1" />
+						</el-select>
+						<div class="input-with-button w100">
+							<div class="flex">
+                <el-input v-model="state.queryParams.Keyword" placeholder="关键词" clearable class="mr10"></el-input>
+                <el-button type="primary" class="btn" :loading="state.loading" @click="queryList"><SvgIcon name="ele-Search" class="mr5" />搜索</el-button>
+                <el-button @click="resetQuery" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置</el-button>
+              </div>
+							<div class="flex-center-align mt5">
+								<div style="height: 32px; line-height: 32px">排序:</div>
+								<el-radio-group v-model="state.queryParams.Sort" @change="queryList">
+									<el-radio label="1">浏览量</el-radio>
+									<el-radio label="2">评分</el-radio>
+									<el-radio label="3">创建时间</el-radio>
+								</el-radio-group>
+							</div>
+						</div>
+					</div>
+					<div v-loading="centerLoading" class="center-container-box" style="height: calc(100% - 180px)">
+						<template v-if="state.retrievalList.length">
+							<el-scrollbar>
+								<div v-for="(v, i) in state.retrievalList" :key="i" class="retrieval-content-item" @click="onPreview(v)" title="查看详情">
+									<h4 class="mb10 text-no-wrap">{{ v.title }}</h4>
+									<div class="text-ellipsis2" v-html="queryTitleLight(v.content)"></div>
+                  <div class="flex-center-between mt10 color-info">
+                    <div>
+                      <span class="mr10">创建部门:{{ v.creatorOrgName }}</span>
+                      <span>创建时间:{{ formatDate(v.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+                    </div>
+                    <div class="flex-center-align">
+                      <span class="flex-center-align"><SvgIcon name="ele-StarFilled" size="18px" class="mr3"/>{{v.score}}</span>
+                      <span class="flex-center-align ml10"><SvgIcon name="ele-ChatDotSquare" size="16px" class="mr3"/>{{v.commentNum}}</span>
+                      <span class="flex-center-align ml10"><SvgIcon name="ele-View" size="16px" class="mr3"/>{{v.pageView}}</span>
+                    </div>
+                  </div>
+								</div>
+							</el-scrollbar>
+						</template>
+						<template v-else>
+							<Empty type="search" description="暂无结果" />
+						</template>
+					</div>
+					<pagination
+						:total="state.total"
+						v-model:page="state.queryParams.PageIndex"
+						v-model:limit="state.queryParams.PageSize"
+						@pagination="queryList"
+					/>
+				</el-col>
 
+				<el-col :xs="6" :sm="6" :md="6" :lg="6" :xl="6" class="right-container">
+					<p class="flex-center-between pt10">
+						<span class="font16">常用知识前10</span>
+						<el-button link type="primary" @click="onRefresh"><SvgIcon name="ele-Refresh" class="mr4" /> 刷新</el-button>
+					</p>
+					<el-divider />
+					<p class="flex-center-between">
+						<span>排名</span>
+						<span>搜索频率</span>
+					</p>
+					<div class="top10 mt10" style="height: calc(100% - 160px)" v-loading="rightLoading">
+						<template v-if="topList.length">
+							<el-scrollbar>
+								<div class="flex-center-between top10-items" v-for="(item, index) in topList" :key="item.id">
+									<p class="flex-center-align top10-items-title" @click="onPreview(item)">
+										{{ index + 1 }}.<el-link type="primary" :underline="false">{{ item.title }}</el-link>
+									</p>
+									<span class="top10-items-num">{{ item.num }}</span>
+								</div>
+							</el-scrollbar>
+						</template>
+						<template v-else>
+							<Empty />
+						</template>
+					</div>
+				</el-col>
+			</el-row>
+		</el-card>
 	</div>
 </template>
 
 <script setup lang="ts" name="knowledgeRetrieval">
-import {reactive} from 'vue';
-import {useRouter} from 'vue-router';
-import {ElMessage} from 'element-plus';
-import {auth} from '/@/utils/authFunction';
-import {knowledgeRetrieval} from '/@/api/knowledge/retrieval';
+import { onMounted, reactive, ref, watch } from 'vue';
+import { useRouter } from 'vue-router';
+import {ElMessage, FormInstance} from 'element-plus';
+import { auth } from '/@/utils/authFunction';
+import { knowledgeRetrieval } from '/@/api/knowledge/retrieval';
+import { hotSpotType } from '/@/api/business/order';
+import { getOrgList } from '/@/api/system/organize';
+import { treeList } from '/@/api/knowledge/type';
+import { formatDate } from '/@/utils/formatTime';
+import { throttle } from '/@/utils/tools';
 
 const state = reactive<any>({
 	queryParams: {
 		// 查询条件
 		PageIndex: 1, // 当前页
 		PageSize: 10, // 每页条数
-		Keyword: '',  // 关键词
+    Attribution: ' ',
+		Keyword: null, // 关键词
 		RetrievalType: 0, // 检索类型
+    Sort: '1',
 	},
+	activeName: '0',
+	orgData: [], // 部门
+	knowledgeOptions: [], // 知识类型
 	total: 0, // 总条数
 	loading: false, // 加载状态
-	typeList: [ // 检索类型
+	typeList: [
+		// 检索类型
 		{
 			label: '全文',
 			value: 0,
@@ -66,14 +197,91 @@ const state = reactive<any>({
 			label: '标题',
 			value: 1,
 		},
+    {
+      label: '知识内容',
+      value: 2,
+    },
 		{
-			label: '正文',
-			value: 2,
-		},
+			label: '摘要',
+			value: 3,
+		}
 	],
-	retrievalList: [],  // 检索列表
+	retrievalList: [],	// 检索列表
 });
 const router = useRouter(); // 路由
+const topList = ref<EmptyArrayType>([]); // 常用知识前10
+const handleClick = () => {
+	queryList();
+};
+// 热点分类远程搜索
+const HotspotProps = {
+	label: 'hotSpotFullName',
+	children: 'children',
+	isLeaf: 'isLeaf',
+};
+// 热点分类懒加载
+const load = async (node: any, resolve: any) => {
+	if (node.isLeaf) return resolve([]);
+	const res: any = await hotSpotType({ id: node.data.id ? node.data.id : '' });
+	resolve(res.result);
+};
+// 三个类型的搜索
+const filterOrg = ref('');
+const orgRef = ref<RefType>();
+watch(filterOrg, (val) => {
+	orgRef.value!.filter(val);
+});
+const filterNode = (value: string, data: any) => {
+	if (!value) return true;
+	return data.name.includes(value);
+};
+const filterType = ref('');
+const typeRef = ref<RefType>();
+watch(filterType, (val) => {
+	typeRef.value!.filter(val);
+});
+const filterNodeType = (value: string, data: any) => {
+	if (!value) return true;
+	return data.name.includes(value);
+};
+const filterHot = ref('');
+const hotRef = ref<RefType>();
+watch(filterHot, (val) => {
+	hotRef.value!.filter(val);
+});
+const filterNodeHot = (value: string, data: any) => {
+	if (!value) return true;
+	return data.hotSpotName.includes(value);
+};
+// 获取所有组织结构 和基础数据
+const getOrgListApi = async () => {
+	state.loading = true;
+	try {
+		const [orgRes, treeRes] = await Promise.all([getOrgList(), treeList({ IsEnable: true })]);
+		state.orgData = orgRes.result ?? []; //部门
+		state.knowledgeOptions = treeRes.result ?? []; // 知识类型
+		state.loading = false;
+	} catch (error) {
+		state.loading = false;
+	}
+};
+// 点击节点
+const handleNodeClick = (data: any) => {
+	switch (state.activeName) {
+		case '0':
+			state.queryParams.CreateOrgId = data.id;
+			break;
+		case '1':
+			state.queryParams.KnowledgeTypeId = data.id;
+			break;
+		case '2':
+			state.queryParams.HotspotId = data.id;
+			break;
+		default:
+			break;
+	}
+	queryList();
+};
 // 预览
 const onPreview = (row: any) => {
 	router.push({
@@ -85,63 +293,117 @@ const onPreview = (row: any) => {
 		},
 	});
 };
+// 切换tab 查询列表
+const rightLoading = ref(false); // 右侧加载状态
+const onRefresh = () => {
+	rightLoading.value = true;
+	setTimeout(() => {
+		rightLoading.value = false;
+	}, 1000);
+};
 const queryTitleLight = (titleInfo: string) => {
-  return titleInfo.replace(
-      new RegExp(state.queryParams.Keyword, 'g'),
-      `<span class="color-danger">${state.queryParams.Keyword}</span>`
-  );
+	return titleInfo.replace(new RegExp(state.queryParams.Keyword, 'g'), `<span class="color-danger">${state.queryParams.Keyword}</span>`);
 };
+const centerLoading = ref(false); // 中间加载状态
 const queryList = () => {
-	if (!auth('knowledge:process:query')) ElMessage.error('抱歉,您没有权限知识检索');
+	if (!auth('knowledge:retrieval')) ElMessage.error('抱歉,您没有权限知识检索');
 	else {
-    if(!state.queryParams.Keyword) {
-      state.retrievalList = [];
-      state.total = 0;
-      return;
-    }
-		state.loading = true;
-    state.retrievalList = [];
-    state.total = 0;
+    centerLoading.value = true;
 		knowledgeRetrieval(state.queryParams)
 			.then((res: any) => {
 				state.retrievalList = res.result?.items ?? [];
 				state.total = res.result?.total ?? 0;
-				state.loading = false;
+        centerLoading.value = false;
 			})
 			.catch(() => {
-				state.loading = false;
-        state.retrievalList = [];
-        state.total = 0;
+        centerLoading.value = false;
+				state.retrievalList = [];
+				state.total = 0;
 			});
 	}
-}
+};
+/** 重置按钮操作 */
+const resetQuery = throttle(() => {
+  state.queryParams.PageIndex = 1;
+  state.queryParams.PageSize = 10;
+  state.queryParams.Keyword = null;
+  state.queryParams.RetrievalType = 0;
+  state.queryParams.Sort = '1';
+  state.queryParams.Attribution = ' ';
+  state.activeName = '0';
+  state.queryParams.CreateOrgId = null;
+  state.queryParams.KnowledgeTypeId = null;
+  state.queryParams.HotspotId = null;
+  filterOrg.value = '';
+  filterType.value = '';
+  filterHot.value = '';
+  typeRef.value?.setCurrentKey(null);
+  orgRef.value?.setCurrentKey(null);
+  hotRef.value?.setCurrentKey(null);
+  queryList();
+}, 500);
+onMounted(() => {
+	getOrgListApi();
+  queryList();
+});
 </script>
 
 <style scoped lang="scss">
 .knowledge-retrieval-container {
-	.input-box {
-		width: 80%;
-		margin: 10px auto;
-		.input-with-select {
-			:deep(.el-input-group__prepend) {
-				background-color: var(--el-fill-color-blank);
-			}
+	.left-container {
+		border-right: 1px solid var(--el-border-color);
+		height: 100%;
+	}
+	.center-container {
+		border-right: 1px solid var(--el-border-color);
+		height: 100%;
+		.input-box {
+			display: flex;
 		}
+    .retrieval-content {
+      &-item {
+        border-bottom: var(--el-border);
+        padding: 10px 15px;
+        margin-bottom: 10px;
+        cursor: pointer;
+        &:last-child {
+          margin-bottom: 0;
+          border: none;
+        }
+        &:hover {
+          color: var(--el-color-primary);
+        }
+      }
+    }
 	}
-	.retrieval-content {
-		&-item {
-			border: var(--el-border);
-			border-radius: var(--el-border-radius-base);
-			padding: 20px;
-			margin-bottom: 20px;
-			cursor: pointer;
-			&:last-child {
-				margin-bottom: 0;
-			}
-			&:hover {
-				box-shadow: 0 0 0 1px var(--el-color-primary) inset;
+	.right-container {
+    height: 100%;
+		.top10 {
+			&-items {
+				margin-bottom: 20px;
+				&:last-child {
+					margin-bottom: 0;
+				}
+				&-title {
+					flex: 1;
+					overflow: hidden;
+					text-overflow: ellipsis;
+					white-space: nowrap;
+				}
+				&-num {
+					display: inline-block;
+					width: 50px;
+					text-align: center;
+				}
 			}
 		}
 	}
+	:deep(.el-tree-node__content) {
+		height: 40px;
+	}
+	:deep(.el-card__body) {
+		height: 100%;
+	}
+
 }
 </style>

+ 2 - 4
src/views/quality/index/components/Order-detail.vue

@@ -407,13 +407,11 @@
 <script setup lang="ts" name="orderDetail">
 import { defineAsyncComponent, reactive, ref } from 'vue';
 import { useRouter } from 'vue-router';
-import { throttle } from '/@/utils/tools';
-import { commonEnum } from '/@/utils/constants';
 import { orderDetail } from '/@/api/business/order';
 import { formatDate } from '/@/utils/formatTime';
 import { ElMessage } from 'element-plus';
-import { VoiceInterfaceObject } from '/@/utils/PhoneScript';
 import {workflowTraces} from "/@/api/system/workflow";
+import {ola} from "/@/utils/ola_api";
 
 // 引入组件
 const OrderExpandDetail = defineAsyncComponent(() => import('/@/views/business/order/components/Order-expand-detail.vue')); // 扩展信息
@@ -585,7 +583,7 @@ const recordFile = (callId:string)=>{
 }
 // 电话外呼
 const callPhone = (number: number | string) => {
-  VoiceInterfaceObject.DialOut(number); // 呼叫
+  ola.dial(number)
 };
 const orderRepeatRef = ref<RefType>();
 // 展示重复工单列表

+ 8 - 7
src/views/system/config/dict/index.vue

@@ -28,7 +28,8 @@
 				<el-col :xs="18" :sm="18" :md="18" :lg="20" :xl="20" class="rightContent">
 					<el-scrollbar class="pr10">
 						<div class="flex-column">
-							<div class="flex-between mb10">
+                <el-row class="mb20" :gutter="10">
+                  <el-col :xs="24" :sm="12" :md="18" :lg="18" :xl="18">
 								<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
 									<el-form-item label="关键字" prop="keyword" class="mb0">
 										<el-input v-model="state.queryParams.keyword" placeholder="字典值名称/字典值" clearable @keyup.enter="handleQuery" />
@@ -42,8 +43,9 @@
 										</el-button>
 									</el-form-item>
 								</el-form>
-								<div>
-									<el-button type="primary" @click="expand"
+                  </el-col>
+                  <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6" style="text-align: right">
+									  <el-button type="primary" @click="expand"
 										><SvgIcon
 											name="ele-ArrowDownBold"
 											style="transition: transform var(--el-transition-duration)"
@@ -59,10 +61,9 @@
                                     <SvgIcon name="ele-Delete" class="mr5" />注销
                                 </el-button> -->
 									<!-- <el-button type="primary" v-waves @click="onExportTable">
-										<SvgIcon name="iconfont icon-daochu" class="mr5" />导出
-									</el-button> -->
-								</div>
-							</div>
+										<SvgIcon name="iconfont icon-daochu" class="mr5" />导出 </el-button> -->
+                  </el-col>
+                </el-row>
 							<!-- 表格 -->
 							<el-auto-resizer class="table" v-loading="state.tableLoading">
 								<template #default="{ height, width }">

+ 1 - 1
src/views/system/config/workflow/component/Workflow-config.vue

@@ -9,7 +9,7 @@
 				<el-button @click="resetQuery(ruleDialogFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
 			</el-form-item>
 		</el-form>
-		<el-table :data="state.tableData" @current-change="handleSelectionChange" max-height="500" v-loading="state.loading">
+		<el-table :data="state.tableData" @current-change="handleSelectionChange" v-loading="state.loading">
 			<el-table-column prop="phoneNo" label="请选择" width="70">
 				<template #default="{ row }">
 					<el-radio v-model="state.tableRadio" :label="row.id">&nbsp;</el-radio>

+ 26 - 24
src/views/system/menu/index.vue

@@ -1,30 +1,32 @@
 <template>
 	<div class="system-menu-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-			<div class="flex-center-between mb20">
-				<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
-					<el-form-item label="关键字" prop="keyword" class="mb0">
-						<el-input v-model="state.queryParams.keyword" placeholder="菜单名称" clearable @keyup.enter="handleQuery" style="width: 250px" />
-					</el-form-item>
-					<el-form-item class="mb0">
-						<el-button type="primary" @click="handleQuery" :loading="state.loading" v-waves>
-							<SvgIcon name="ele-Search" class="mr5" />查询
-						</el-button>
-						<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-					</el-form-item>
-				</el-form>
-				<div>
-					<el-button type="primary" @click="expand">
-						<SvgIcon
-							name="ele-ArrowDownBold"
-							style="transition: transform var(--el-transition-duration)"
-							:style="state.isExpand ? 'transform: none' : 'transform: rotateZ(180deg)'"
-							class="mr5"
-						/>{{ state.isExpand ? '收起' : '展开' }}</el-button
-					>
-					<el-button type="primary" @click="onOpenAddMenu" v-auth="'system:menu:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
-				</div>
-			</div>
+      <el-row class="mb20" :gutter="10">
+        <el-col :xs="24" :sm="12" :md="18" :lg="18" :xl="18">
+          <el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
+            <el-form-item label="关键字" prop="keyword" class="mb0">
+              <el-input v-model="state.queryParams.keyword" placeholder="菜单名称" clearable @keyup.enter="handleQuery" style="width: 250px" />
+            </el-form-item>
+            <el-form-item class="mb0">
+              <el-button type="primary" @click="handleQuery" :loading="state.loading" v-waves>
+                <SvgIcon name="ele-Search" class="mr5" />查询
+              </el-button>
+              <el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+            </el-form-item>
+          </el-form>
+        </el-col>
+        <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6" style="text-align: right">
+          <el-button type="primary" @click="expand">
+            <SvgIcon
+                name="ele-ArrowDownBold"
+                style="transition: transform var(--el-transition-duration)"
+                :style="state.isExpand ? 'transform: none' : 'transform: rotateZ(180deg)'"
+                class="mr5"
+            />{{ state.isExpand ? '收起' : '展开' }}</el-button
+          >
+          <el-button type="primary" @click="onOpenAddMenu" v-auth="'system:menu:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
+        </el-col>
+      </el-row>
 			<!-- 表格 -->
 			<el-auto-resizer class="table" v-loading="state.loading">
 				<template #default="{ height, width }">

+ 25 - 23
src/views/system/organize/index.vue

@@ -1,29 +1,31 @@
 <template>
 	<div class="system-organize-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-			<div class="flex-center-between mb20">
-				<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
-					<el-form-item label="关键字" prop="keyword" class="mb0">
-						<el-input v-model="state.queryParams.keyword" placeholder="部门名称" clearable @keyup.enter="handleQuery" style="width: 250px" />
-					</el-form-item>
-					<el-form-item class="mb0">
-						<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-						<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-					</el-form-item>
-				</el-form>
-				<div>
-					<el-button type="primary" @click="expand"
-						><SvgIcon
-							name="ele-ArrowDownBold"
-							style="transition: transform var(--el-transition-duration)"
-							:style="state.isExpand ? 'transform: none' : 'transform: rotateZ(180deg)'"
-							class="mr5"
-						/>
-						{{ state.isExpand ? '收起' : '展开' }}</el-button
-					>
-					<el-button type="primary" @click="onOpenAddOrg('')" v-auth="'system:organize:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
-				</div>
-			</div>
+        <el-row class="mb20" :gutter="10">
+          <el-col :xs="24" :sm="12" :md="18" :lg="18" :xl="18">
+            <el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
+              <el-form-item label="关键字" prop="keyword" class="mb0">
+                <el-input v-model="state.queryParams.keyword" placeholder="部门名称" clearable @keyup.enter="handleQuery" style="width: 250px" />
+              </el-form-item>
+              <el-form-item class="mb0">
+                <el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+                <el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+              </el-form-item>
+            </el-form>
+          </el-col>
+          <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6" style="text-align: right">
+            <el-button type="primary" @click="expand"
+            ><SvgIcon
+                name="ele-ArrowDownBold"
+                style="transition: transform var(--el-transition-duration)"
+                :style="state.isExpand ? 'transform: none' : 'transform: rotateZ(180deg)'"
+                class="mr5"
+            />
+              {{ state.isExpand ? '收起' : '展开' }}</el-button
+            >
+            <el-button type="primary" @click="onOpenAddOrg('')" v-auth="'system:organize:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
+          </el-col>
+        </el-row>
 			<!-- 表格 -->
 			<el-auto-resizer class="table" v-loading="state.loading">
 				<template #default="{ height, width }">

+ 2 - 2
src/views/system/parameter/component/Parameter-edit.vue

@@ -4,12 +4,12 @@
 				<el-row :gutter="10">
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
 						<el-form-item label="参数名称" prop="settingName" :rules="[{ required: true, message: '请输入参数名称', trigger: 'blur' }]">
-							<el-input v-model="state.ruleForm.settingName" placeholder="请输入参数名称" clearable :disabled="state.isDisabled"></el-input>
+							<el-input v-model="state.ruleForm.settingName" placeholder="请输入参数名称" clearable disabled></el-input>
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
 						<el-form-item label="参数" prop="code" :rules="[{ required: true, message: '请输入参数', trigger: 'blur' }]">
-							<el-input v-model.trim="state.ruleForm.code" placeholder="请输入参数" clearable :disabled="state.isDisabled"></el-input>
+							<el-input v-model.trim="state.ruleForm.code" placeholder="请输入参数" clearable disabled></el-input>
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">

+ 7 - 6
src/views/system/user/component/User-add.vue

@@ -147,12 +147,13 @@ const getKnowledgeList = () => {
 // 获取分机列表
 const getTelsListFn = async (object?: object) => {
 	const res: any = await getTelList(object);
-	state.telsList = res?.data ?? [];
-	state.telsList = state.telsList.map((item: any) => ({
-		value: item.device,
-		label: item.device,
-		...item,
-	}));
+	state.telsList = res?.result ?? [];
+  state.telsList = state.telsList.map((item: any) => ({
+    value: item.telNo,
+    label: item.telNo,
+    queue: item.description === '默认' ? '10010' : item.description,
+    ...item,
+  }));
 };
 // 查询页面基础信息
 const getBaseDataFn = () => {

+ 7 - 6
src/views/system/user/component/User-edit.vue

@@ -154,12 +154,13 @@ const getKnowledgeList = () => {
 // 获取分机列表
 const getTelsListFn = async (object?: object) => {
 	const res: any = await getTelList(object);
-	state.telsList = res?.data ?? [];
-	state.telsList = state.telsList.map((item: any) => ({
-		value: item.device,
-		label: item.device,
-		...item,
-	}));
+	state.telsList = res?.result ?? [];
+  state.telsList = state.telsList.map((item: any) => ({
+    value: item.telNo,
+    label: item.telNo,
+    queue: item.description === '默认' ? '10010' : item.description,
+    ...item,
+  }));
 };
 // 查询页面基础信息
 const getBaseDataFn = () => {

+ 18 - 37
src/views/tels/blacklist/component/Blacklist-add.vue

@@ -4,37 +4,17 @@
 			<el-form :model="state.ruleForm" ref="blacklistFormRef" label-width="80px" label-position="left">
 				<el-row :gutter="35">
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="电话号码" prop="telePhone" :rules="[{ required: true, message: '请输入电话号码', trigger: 'blur' }]">
-							<el-input v-model="state.ruleForm.telePhone" placeholder="请输入电话号码" clearable></el-input>
+						<el-form-item label="电话号码" prop="phone" :rules="[{ required: true, message: '请输入电话号码', trigger: 'blur' }]">
+							<el-input v-model="state.ruleForm.phone" placeholder="请输入电话号码" clearable></el-input>
 						</el-form-item>
 					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="时间" prop="time" :rules="[{ required: false, message: '请选择时间', trigger: 'change' }]">
-							<el-date-picker
-								v-model="state.ruleForm.time"
-								type="datetimerange"
-								range-separator="至"
-								start-placeholder="开始时间"
-								end-placeholder="结束时间"
-								value-format="YYYY-MM-DD HH:mm:ss"
-                @change="(val:any) => {
-                    state.ruleForm.setTime = val[0];
-                    state.ruleForm.removeTime = val[1]
-                  }"
-							/>
+						<el-form-item label="类型" prop="specialFlag" :rules="[{ required: true, message: '请选择类型', trigger: 'change' }]">
+              <el-select v-model="state.ruleForm.specialFlag" placeholder="请选择类型" class="w100">
+                <el-option v-for="item in props.specialFlagList" :key="item.value" :label="item.label" :value="item.value" />
+              </el-select>
 						</el-form-item>
 					</el-col>
-          <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-            <el-form-item label="备注" prop="remark" :rules="[{ required: true, message: '请填写备注', trigger: 'blur' }]">
-              <el-input
-                  type="textarea"
-                  :autosize="{ minRows: 6, maxRows: 10 }"
-                  maxlength="2000"
-                  placeholder="请填写备注"
-                  v-model="state.ruleForm.remark"
-              ></el-input>
-            </el-form-item>
-          </el-col>
 				</el-row>
 			</el-form>
 			<template #footer>
@@ -50,19 +30,23 @@
 <script lang="ts" setup name="blackAdd">
 import { ref, reactive } from 'vue';
 import {ElMessage, FormInstance} from 'element-plus';
-import { blacklistAdd } from '/@/api/public/wex';
+import { addBlacklist } from '/@/api/public/wex';
 
+const props = defineProps({
+  specialFlagList: {
+    type: Array,
+    default: () => [],
+  },
+})
 // 定义子组件向父组件传值/事件
-const emit = defineEmits(['updateList', 'openDialog', 'closeDialog']);
+const emit = defineEmits(['updateList']);
 
 // 定义变量内容
 
 const state = reactive<any>({
 	ruleForm: {
-    telePhone: '',  // 电话号码
-    time:[],  // 时间
-    setTime: '',  // 开始时间
-    removeTime: '', // 结束时间
+    phone: null,  // 电话号码
+    specialFlag:null,
 	},
 	dialogVisible: false, // 弹窗显示隐藏
 });
@@ -71,21 +55,18 @@ const blacklistFormRef = ref<RefType>();
 const openDialog = () => {
 	blacklistFormRef.value?.resetFields();
 	state.dialogVisible = true;
-	emit('openDialog');
 };
 // 关闭弹窗
 const closeDialog = () => {
 	state.dialogVisible = false;
-	emit('closeDialog');
 };
 // 新增保存
 const onSubmit = (formEl: FormInstance | undefined) => {
   if (!formEl) return;
   formEl.validate((valid: boolean) => {
     if(!valid) return;
-    Reflect.deleteProperty(state.ruleForm, 'time');
-    blacklistAdd(state.ruleForm).then(() => {
-      ElMessage.success('新增成功');
+    addBlacklist(state.ruleForm).then(() => {
+      ElMessage.success('操作成功');
       emit('updateList');
       state.dialogVisible = false;
     });

+ 39 - 53
src/views/tels/blacklist/index.vue

@@ -3,13 +3,14 @@
 		<el-card shadow="never">
 			<!-- 通用搜索 -->
 			<el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="mt15">
-				<el-form-item label="黑名单号码" prop="telePhone">
-					<el-input v-model="state.queryParams.telePhone" placeholder="请输入黑名单号码" clearable @keyup.enter="handleQuery" />
+				<el-form-item label="黑名单号码" prop="Phone">
+					<el-input v-model="state.queryParams.Phone" placeholder="请输入黑名单号码" clearable @keyup.enter="handleQuery" />
 				</el-form-item>
-				<el-form-item label="备注" prop="remark">
-					<el-input v-model="state.queryParams.remark" placeholder="请输入备注" clearable @keyup.enter="handleQuery" />
+				<el-form-item label="类型" prop="SpecialFlag">
+					<el-select v-model="state.queryParams.SpecialFlag" placeholder="请选择类型" class="w100">
+						<el-option v-for="item in specialFlagList" :key="item.value" :label="item.label" :value="item.value" />
+					</el-select>
 				</el-form-item>
-
 				<el-form-item>
 					<el-button type="primary" @click="handleQuery" :loading="state.loading" v-waves> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
 					<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading">
@@ -21,40 +22,32 @@
 		<el-card shadow="never">
 			<div class="mb20">
 				<el-button type="primary" @click="onAddBlacklist" v-auth="'tels:blackList:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
-				<el-button type="primary" @click="onRemove" v-auth="'tels:blackList:delete'" :disabled="!multipleSelection.length">
-					<SvgIcon name="ele-Delete" class="mr5" />解除
-				</el-button>
 			</div>
 			<!-- 表格 -->
-			<el-table :data="state.tableData" v-loading="state.loading" row-key="id" ref="multipleTableRef" @selection-change="handleSelectionChange">
-				<el-table-column type="selection" width="55" :reserve-selection="true"/>
-				<el-table-column prop="telePhone" label="黑名单号码" show-overflow-tooltip></el-table-column>
-				<el-table-column label="开始时间" show-overflow-tooltip width="170">
+			<el-table :data="state.tableData" v-loading="state.loading">
+				<el-table-column prop="phone" label="黑白名单号码" show-overflow-tooltip></el-table-column>
+        <el-table-column prop="phone" label="类型" show-overflow-tooltip>
+          <template #default="{ row }">
+            <span>{{ specialFlagList.find(item=>row.specialFlag === item.value).label }}</span>
+          </template>
+        </el-table-column>
+				<el-table-column label="创建时间" show-overflow-tooltip width="170">
 					<template #default="{ row }">
-						<span>{{ formatDate(row.setTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
+						<span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column label="失效时间" show-overflow-tooltip width="170">
-					<template #default="{ row }">
-						<span>{{ formatDate(row.removeTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
-					</template>
-				</el-table-column>
-				<el-table-column prop="remark" label="备注" show-overflow-tooltip></el-table-column>
-				<el-table-column prop="platFromCode" label="平台编码" show-overflow-tooltip></el-table-column>
+        <el-table-column label="操作" width="200" fixed="right" align="center">
+          <template #default="{ row }">
+            <el-button link type="primary" @click="onRemove(row)" v-auth="'system:parameter:edit'" title="删除黑名单"> 删除 </el-button>
+          </template>
+        </el-table-column>
 				<template #empty>
 					<Empty />
 				</template>
 			</el-table>
-			<!-- 分页 -->
-			<pagination
-				:total="state.total"
-				v-model:page="state.queryParams.pageIndex"
-				v-model:limit="state.queryParams.pageSize"
-				@pagination="queryList"
-			/>
 		</el-card>
-    <!--  新增黑名单  -->
-		<blacklist-add ref="blacklistAddRef" @updateList="handleQuery" />
+		<!--  新增黑名单  -->
+		<blacklist-add ref="blacklistAddRef" @updateList="handleQuery" :specialFlagList="specialFlagList"/>
 	</div>
 </template>
 
@@ -64,7 +57,7 @@ import { ElMessageBox, ElMessage } from 'element-plus';
 import type { FormInstance } from 'element-plus';
 import { formatDate } from '/@/utils/formatTime';
 import { auth } from '/@/utils/authFunction';
-import { blacklistPaged, blacklistRemove } from '/@/api/public/wex';
+import { queryBlacklist, removeBlacklist } from '/@/api/public/wex';
 import { throttle } from '/@/utils/tools';
 
 // 引入组件
@@ -73,32 +66,33 @@ const BlacklistAdd = defineAsyncComponent(() => import('/@/views/tels/blacklist/
 // 定义变量内容
 const state = reactive<any>({
 	queryParams: {
-		// 查询参数
-		pageIndex: 1, // 当前页码
-		pageSize: 100, // 每页条数
-		telePhone: '', // 电话号码
-		remark: '', // 备注
+    Phone: null, // 电话号码
+    SpecialFlag: null, // 备注
 	},
 	loading: false, // 加载状态
 	total: 0, // 总条数
-	tableData: [],  // 表格数据
-	multipleSelection: [],  // 多选数据
+	tableData: [], // 表格数据
+	multipleSelection: [], // 多选数据
 });
-const ruleFormRef = ref<FormInstance>();  // 表单ref
+const ruleFormRef = ref<FormInstance>(); // 表单ref
 /** 搜索按钮操作 节流操作 */
 const handleQuery = throttle(() => {
-	state.queryParams.pageIndex = 1;
 	queryList();
 }, 300);
+const specialFlagList = ref<EmptyArrayType>([
+	{ value: 1, label: '白名单' },
+	{ value: 2, label: '呼入黑名单' },
+	{ value: 3, label: '呼出黑名单' },
+	{ value: 4, label: '呼入呼出黑名单' },
+]); // 黑白名单类型
 /** 获取黑名单列表 */
 const queryList = () => {
 	if (!auth('tels:blackList:query')) ElMessage.error('抱歉,您没有权限获取黑名单列表!');
 	else {
 		state.loading = true;
-		blacklistPaged(state.queryParams)
+		queryBlacklist(state.queryParams)
 			.then((response: any) => {
-				state.tableData = response.data ?? [];
-				state.total = response.count ?? 0;
+				state.tableData = response.result ?? [];
 				state.loading = false;
 			})
 			.catch(() => {
@@ -117,17 +111,9 @@ const blacklistAddRef = ref<RefType>();
 const onAddBlacklist = () => {
 	blacklistAddRef.value.openDialog();
 };
-// 表格多选
-const multipleTableRef = ref<RefType>();
-const multipleSelection = ref<any>([]);
-const handleSelectionChange = (val: any[]) => {
-	multipleSelection.value = val;
-};
 // 删除黑名单
-const onRemove = () => {
-  const ids:string = multipleSelection.value.map((item: any) => item.blackId).join(',');
-  const phoneNo:string = multipleSelection.value.map((item: any) => item.telePhone).join(',');
-	ElMessageBox.confirm(`此操作将解除:【${phoneNo}】的黑名单,是否继续?`, '提示', {
+const onRemove = (row:any) => {
+	ElMessageBox.confirm(`此操作将解除:【${row.phone}】的黑名单,是否继续?`, '提示', {
 		confirmButtonText: '确认',
 		cancelButtonText: '取消',
 		type: 'warning',
@@ -136,7 +122,7 @@ const onRemove = () => {
 		autofocus: false,
 	})
 		.then(() => {
-			blacklistRemove(ids).then(() => {
+      removeBlacklist({...row}).then(() => {
 				ElMessage.success('操作成功');
 				queryList();
 			});

+ 0 - 93
src/views/tels/whitelist/component/Whitelist-add.vue

@@ -1,93 +0,0 @@
-<template>
-	<div class="system-blacklist-add-container">
-		<el-dialog v-model="state.dialogVisible" width="500px" draggable :title="dialogTitle">
-			<el-form :model="state.ruleForm" ref="whitelistFormRef" label-width="80px" label-position="left">
-				<el-row :gutter="10">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-						<el-form-item label="电话号码" prop="telPhone" :rules="[{ required: true, message: '请输入电话号码', trigger: 'blur' }]">
-							<el-input v-model="state.ruleForm.telPhone" placeholder="请输入电话号码" clearable></el-input>
-						</el-form-item>
-					</el-col>
-          <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
-            <el-form-item label="备注" prop="remark" :rules="[{ required: false, message: '请填写备注', trigger: 'blur' }]">
-              <el-input
-                  type="textarea"
-                  :autosize="{ minRows: 4, maxRows: 6 }"
-                  maxlength="2000"
-                  placeholder="请填写备注"
-                  v-model="state.ruleForm.remark"
-              ></el-input>
-            </el-form-item>
-          </el-col>
-				</el-row>
-			</el-form>
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="closeDialog" class="default-button">取 消</el-button>
-					<el-button type="primary" @click="onSubmit(whitelistFormRef)">保 存</el-button>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-
-<script lang="ts" setup name="whitelistAdd">
-import {nextTick, reactive, ref} from 'vue';
-import {ElMessage, FormInstance} from 'element-plus';
-import {whitelistAdd,whitelistEdit} from '/@/api/public/wex';
-import other from "/@/utils/other";
-
-// 定义子组件向父组件传值/事件
-const emit = defineEmits(['updateList', 'openDialog', 'closeDialog']);
-
-// 定义变量内容
-const dialogTitle = ref<string>('新增白名单');
-const state = reactive<any>({
-	ruleForm: {
-    telPhone: '',  // 电话号码
-    remark: '', // 备注
-	},
-	dialogVisible: false, // 弹窗显示隐藏
-});
-// 打开弹窗
-const whitelistFormRef = ref<RefType>();
-const openDialog = async (row?:any) => {
-	state.dialogVisible = true;
-	emit('openDialog');
-  await nextTick(() => {
-    whitelistFormRef.value?.resetFields();
-    whitelistFormRef.value?.clearValidate();
-    if(row && row.zTelPhoneID) {
-      dialogTitle.value = '编辑白名单';
-      state.ruleForm = other.deepClone(row);
-    }else{
-      dialogTitle.value = '新增白名单';
-      state.ruleForm = {
-        telPhone: '',  // 电话号码
-        remark: '', // 备注
-      };
-    }
-  });
-};
-// 关闭弹窗
-const closeDialog = () => {
-	state.dialogVisible = false;
-	emit('closeDialog');
-};
-// 新增保存
-const onSubmit = (formEl: FormInstance | undefined) => {
-  if (!formEl) return;
-  formEl.validate((valid: boolean) => {
-    if(!valid) return;
-    const operation = state.ruleForm.zTelPhoneID ? whitelistEdit : whitelistAdd; // 判断是新增还是编辑
-      Reflect.deleteProperty(state.ruleForm, 'time');
-    operation(state.ruleForm).then(() => {
-        ElMessage.success('操作成功');
-        emit('updateList');
-        state.dialogVisible = false;
-      });
-	});
-};
-//暴漏变量和方法
-defineExpose({ closeDialog, openDialog });
-</script>

+ 0 - 146
src/views/tels/whitelist/index.vue

@@ -1,146 +0,0 @@
-<template>
-  <div class="tels-whitelist-container layout-pd">
-    <el-card shadow="never">
-      <!-- 通用搜索 -->
-      <el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent class="mt15">
-        <el-form-item label="白名单号码" prop="telPhone">
-          <el-input v-model="state.queryParams.telPhone" placeholder="请输入白名单号码" clearable @keyup.enter="handleQuery" />
-        </el-form-item>
-        <el-form-item label="备注" prop="remark">
-          <el-input v-model="state.queryParams.remark" placeholder="请输入备注" clearable @keyup.enter="handleQuery" />
-        </el-form-item>
-
-        <el-form-item>
-          <el-button type="primary" @click="handleQuery" :loading="state.loading" v-waves> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-          <el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.loading">
-            <SvgIcon name="ele-Refresh" class="mr5" />重置
-          </el-button>
-        </el-form-item>
-      </el-form>
-    </el-card>
-    <el-card shadow="never">
-      <div class="mb20">
-        <el-button type="primary" @click="onAddWhitelist" v-auth="'tels:whitelist:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
-        <el-button type="primary" @click="onRemove" v-auth="'tels:whitelist:delete'" :disabled="!multipleSelection.length">
-          <SvgIcon name="ele-Delete" class="mr5" />解除
-        </el-button>
-      </div>
-      <!-- 表格 -->
-      <el-table :data="state.tableData" v-loading="state.loading" row-key="id" ref="multipleTableRef" @selection-change="handleSelectionChange">
-        <el-table-column type="selection" width="55" />
-        <el-table-column prop="telPhone" label="白名单号码" show-overflow-tooltip></el-table-column>
-        <el-table-column prop="remark" label="备注" show-overflow-tooltip></el-table-column>
-        <el-table-column label="操作" width="70" fixed="right" align="center">
-          <template #default="{ row }">
-            <el-button type="primary" link @click="onEdit(row)" v-auth="'tels:whitelist:edit'">编辑</el-button>
-          </template>
-        </el-table-column>
-        <template #empty>
-          <Empty />
-        </template>
-      </el-table>
-      <!-- 分页 -->
-      <pagination
-          :total="state.total"
-          v-model:page="state.queryParams.pageIndex"
-          v-model:limit="state.queryParams.pageSize"
-          @pagination="queryList"
-      />
-    </el-card>
-    <!--  新增白名单  -->
-    <whitelist-add ref="whitelistAddRef" @updateList="handleQuery" />
-  </div>
-</template>
-
-<script lang="ts" setup name="whitelist">
-import { defineAsyncComponent, ref, reactive, onMounted } from 'vue';
-import { ElMessageBox, ElMessage } from 'element-plus';
-import type { FormInstance } from 'element-plus';
-import { auth } from '/@/utils/authFunction';
-import { whitelistPaged, whitelistRemove } from '/@/api/public/wex';
-import { throttle } from '/@/utils/tools';
-
-// 引入组件
-const WhitelistAdd = defineAsyncComponent(() => import('/@/views/tels/whitelist/component/Whitelist-add.vue')); // 新增白名单
-
-// 定义变量内容
-const state = reactive<any>({
-  queryParams: {
-    // 查询参数
-    pageIndex: 1, // 当前页码
-    pageSize: 100, // 每页条数
-    telPhone: '', // 电话号码
-    remark: '', // 备注
-  },
-  loading: false, // 加载状态
-  total: 0, // 总条数
-  tableData: [],  // 表格数据
-  multipleSelection: [],  // 多选数据
-});
-const ruleFormRef = ref<FormInstance>();  // 表单ref
-/** 搜索按钮操作 节流操作 */
-const handleQuery = throttle(() => {
-  state.queryParams.pageIndex = 1;
-  queryList();
-}, 300);
-/** 获取白名单列表 */
-const queryList = () => {
-  if (!auth('tels:whitelist:query')) ElMessage.error('抱歉,您没有权限获取白名单列表!');
-  else {
-    state.loading = true;
-    whitelistPaged(state.queryParams)
-        .then((response: any) => {
-          state.tableData = response.data ?? [];
-          state.total = response.count ?? 0;
-          state.loading = false;
-        })
-        .catch(() => {
-          state.loading = false;
-        });
-  }
-};
-/** 重置按钮操作 */
-const resetQuery = throttle((formEl: FormInstance | undefined) => {
-  if (!formEl) return;
-  formEl.resetFields();
-  handleQuery();
-}, 300);
-// 打开新增百名单弹窗
-const whitelistAddRef = ref<RefType>();
-const onAddWhitelist = () => {
-  whitelistAddRef.value.openDialog();
-};
-// 编辑白名单
-const onEdit = (row: any) => {
-  whitelistAddRef.value.openDialog(row);
-};
-// 表格多选
-const multipleTableRef = ref<RefType>();
-const multipleSelection = ref<any>([]);
-const handleSelectionChange = (val: any[]) => {
-  multipleSelection.value = val;
-};
-// 删除白名单
-const onRemove = () => {
-  const ids:string = multipleSelection.value.map((item: any) => item.zTelPhoneID).join(',');
-  const phoneNo:string = multipleSelection.value.map((item: any) => item.telPhone).join(',');
-  ElMessageBox.confirm(`此操作将解除:【${phoneNo}】的白名单,是否继续?`, '提示', {
-    confirmButtonText: '确认',
-    cancelButtonText: '取消',
-    type: 'warning',
-    draggable: true,
-    cancelButtonClass: 'default-button',
-    autofocus: false,
-  })
-      .then(() => {
-        whitelistRemove(ids).then(() => {
-          ElMessage.success('操作成功');
-          queryList();
-        });
-      })
-      .catch(() => {});
-};
-onMounted(() => {
-  queryList();
-});
-</script>