From f6ba464aa7856b8201e313fe79e651aab34e6509 Mon Sep 17 00:00:00 2001 From: zhangxiao <898441624@qq.com> Date: 星期一, 05 八月 2024 10:25:44 +0800 Subject: [PATCH] Merge branch 'master' of http://192.168.5.5:10010/r/web/flow_web --- src/api/Agent.ts | 34 src/api/kbList.ts | 62 src/views/dmx/IntelligentAgent/components/rules-preset.vue | 51 src/views/dmx/IntelligentAgent/components/editAgent.vue | 351 ++ public/logo.svg | 29 public/logo.jpg | 0 src/views/dmx/knowledgeLib/tool.vue | 641 +++- src/views/dmx/knowledgeLib/index.vue | 632 +++-- src/views/session/sessionManager/index.vue | 726 +++-- src/router/routes/modules/dmx.ts | 11 public/logo.png | 0 src/views/authority/resource/index.vue | 377 +- src/views/sessionRecords/sessionRecordsManager/index.vue | 777 +++-- src/views/dmx/IntelligentAgent/locale/zh-CN.ts | 20 src/views/dmx/knowledgeLib/eidtDetails.vue | 156 + src/views/session/sessionManager/components/addSession.vue | 124 src/api/session.ts | 44 src/views/dmx/knowledgeLib/components/excel.vue | 42 src/views/dmx/knowledgeLib/test.vue | 343 +- src/views/dmx/IntelligentAgent/locale/en-US.ts | 20 src/views/dmx/knowledgeLib/addDetails.vue | 193 + public/logo1.png | 0 src/views/authority/users/index.vue | 953 ++++--- src/views/dmx/IntelligentAgent/mock.ts | 186 + src/views/dmx/knowledgeLib/components/docx.vue | 42 src/views/dmx/knowledgeLib/components/txtPdf.vue | 37 src/views/dmx/IntelligentAgent/components/quality-inspection.vue | 115 .idea/codeStyles/Project.xml | 4 .env.development | 2 src/views/dmx/IntelligentAgent/components/custom-settings.vue | 244 ++ src/views/dmx/IntelligentAgent/index.vue | 341 ++ src/views/dmx/model/components/addModel.vue | 136 yarn.lock | 10 src/api/interceptor.ts | 4 package.json | 2 src/api/authority.ts | 100 src/views/dmx/IntelligentAgent/components/addAgent.vue | 148 + src/views/dmx/IntelligentAgent/components/card-wrap.vue | 204 + src/views/dmx/IntelligentAgent/components/the-service.vue | 57 39 files changed, 5,200 insertions(+), 2,018 deletions(-) diff --git a/.env.development b/.env.development index 22b240e..ab9243a 100644 --- a/.env.development +++ b/.env.development @@ -1,2 +1,2 @@ VUE_APP_BASE_API=/api/v1 -VITE_API_BASE_URL= 'http://aiotlink.com:8189' \ No newline at end of file +VITE_API_BASE_URL= 'http://192.168.20.116:1080' \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 3e22f4b..70dac63 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -3,7 +3,7 @@ <HTMLCodeStyleSettings> <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" /> </HTMLCodeStyleSettings> - <JSCodeStyleSettings version="0"> + <JSCodeStyleSettings> <option name="FORCE_SEMICOLON_STYLE" value="true" /> <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> <option name="FORCE_QUOTE_STYlE" value="true" /> @@ -11,7 +11,7 @@ <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" /> <option name="SPACES_WITHIN_IMPORTS" value="true" /> </JSCodeStyleSettings> - <TypeScriptCodeStyleSettings version="0"> + <TypeScriptCodeStyleSettings> <option name="FORCE_SEMICOLON_STYLE" value="true" /> <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> <option name="FORCE_QUOTE_STYlE" value="true" /> diff --git a/package.json b/package.json index 4236183..ffd9425 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,8 @@ }, "dependencies": { "@arco-design/web-vue": "^2.44.7", + "@vue-office/docx": "^1.6.2", + "@vue-office/excel": "^1.7.11", "@vueuse/core": "^9.3.0", "arco-design-pro-vue": "^2.7.3", "axios": "^0.24.0", diff --git a/public/logo.jpg b/public/logo.jpg new file mode 100644 index 0000000..d788bdb --- /dev/null +++ b/public/logo.jpg Binary files differ diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..bc22092 --- /dev/null +++ b/public/logo.png Binary files differ diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000..54167d2 --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,29 @@ +<svg width="32" height="34" viewBox="0 0 32 34" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M3.43265 20.7677C4.15835 21.5062 4.15834 22.7035 3.43262 23.4419L3.39546 23.4797C2.66974 24.2182 1.49312 24.2182 0.767417 23.4797C0.0417107 22.7412 0.0417219 21.544 0.767442 20.8055L0.804608 20.7677C1.53033 20.0292 2.70694 20.0293 3.43265 20.7677Z" + fill="#B2DDFF" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M12.1689 21.3375C12.8933 22.0773 12.8912 23.2746 12.1641 24.0117L7.01662 29.2307C6.2896 29.9678 5.11299 29.9657 4.38859 29.2259C3.66419 28.4861 3.66632 27.2888 4.39334 26.5517L9.54085 21.3327C10.2679 20.5956 11.4445 20.5977 12.1689 21.3375Z" + fill="#53B1FD" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M19.1551 30.3217C19.7244 29.4528 20.8781 29.218 21.7321 29.7973L21.8436 29.8729C22.6975 30.4522 22.9283 31.6262 22.359 32.4952C21.7897 33.3641 20.6359 33.5989 19.782 33.0196L19.6705 32.944C18.8165 32.3647 18.5858 31.1907 19.1551 30.3217Z" + fill="#B2DDFF" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M31.4184 20.6544C32.1441 21.3929 32.1441 22.5902 31.4184 23.3286L28.8911 25.9003C28.1654 26.6388 26.9887 26.6388 26.263 25.9003C25.5373 25.1619 25.5373 23.9646 26.263 23.2261L28.7903 20.6544C29.516 19.916 30.6927 19.916 31.4184 20.6544Z" + fill="#53B1FD" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M31.4557 11.1427C32.1814 11.8812 32.1814 13.0785 31.4557 13.8169L12.7797 32.8209C12.054 33.5594 10.8774 33.5594 10.1517 32.8209C9.42599 32.0825 9.42599 30.8852 10.1517 30.1467L28.8277 11.1427C29.5534 10.4043 30.73 10.4043 31.4557 11.1427Z" + fill="#1570EF" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M27.925 5.29994C28.6508 6.0384 28.6508 7.23568 27.925 7.97414L17.184 18.9038C16.4583 19.6423 15.2817 19.6423 14.556 18.9038C13.8303 18.1653 13.8303 16.9681 14.556 16.2296L25.297 5.29994C26.0227 4.56148 27.1993 4.56148 27.925 5.29994Z" + fill="#1570EF" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M22.256 1.59299C22.9822 2.33095 22.983 3.52823 22.2578 4.26718L8.45055 18.3358C7.72533 19.0748 6.54871 19.0756 5.82251 18.3376C5.09631 17.5996 5.09552 16.4024 5.82075 15.6634L19.6279 1.59478C20.3532 0.855827 21.5298 0.855022 22.256 1.59299Z" + fill="#1570EF" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M8.58225 6.09619C9.30671 6.83592 9.30469 8.0332 8.57772 8.77038L3.17006 14.2541C2.4431 14.9913 1.26649 14.9893 0.542025 14.2495C-0.182438 13.5098 -0.180413 12.3125 0.546548 11.5753L5.95421 6.09159C6.68117 5.3544 7.85778 5.35646 8.58225 6.09619Z" + fill="#53B1FD" /> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M11.893 0.624023C12.9193 0.624023 13.7513 1.47063 13.7513 2.51497V2.70406C13.7513 3.7484 12.9193 4.59501 11.893 4.59501C10.8667 4.59501 10.0347 3.7484 10.0347 2.70406V2.51497C10.0347 1.47063 10.8667 0.624023 11.893 0.624023Z" + fill="#B2DDFF" /> +</svg> \ No newline at end of file diff --git a/public/logo1.png b/public/logo1.png new file mode 100644 index 0000000..b3ee314 --- /dev/null +++ b/public/logo1.png Binary files differ diff --git a/src/api/Agent.ts b/src/api/Agent.ts new file mode 100644 index 0000000..81e0713 --- /dev/null +++ b/src/api/Agent.ts @@ -0,0 +1,34 @@ +import axios from 'axios'; +import qs from 'query-string'; +import type { DescData } from '@arco-design/web-vue/es/descriptions/interface'; + +// 鏅鸿兘浣撳垪琛ㄦ帴鍙� +export function querydialogList(params) { + return axios.get('/api/v1/dialog/list', { + params, + }); +} + +// 鏅鸿兘浣撹鎯呮帴鍙� +export function querydialogdetail(params) { + return axios.get('/api/v1/dialog/get', { + params, + }); +} + +// 鏅鸿兘浣撹亰澶╂帴鍙� +export function conversationList(params) { + return axios.get('/api/v1/conversation/list', { + params, + }); +} + +// 鏅鸿兘浣撳垱寤�/鏇存柊鎺ュ彛 +export function dialogSet(params) { + return axios.post('/api/v1/dialog/set', params); +} + +// 鏅鸿兘浣撳垹闄ゆ帴鍙� +export function deletedialog(params) { + return axios.post('/api/v1/dialog/rm', params); +} diff --git a/src/api/authority.ts b/src/api/authority.ts index 0a68b1b..76e14c9 100644 --- a/src/api/authority.ts +++ b/src/api/authority.ts @@ -1,5 +1,5 @@ -import axios from "axios"; -import { Pagination } from "@/types/global"; +import axios from 'axios'; +import { Pagination } from '@/types/global'; export interface User { userId: string; @@ -9,7 +9,8 @@ phoneNumber: string; dept: any; resources: any; - knowledges:any; + knowledges: any; + dialogs: any; createTime: string; status: string; } @@ -28,30 +29,30 @@ } export interface Resource { - "menuId": string; - "createTime": string; - "updateTime": string; - "menuName": string; - "component": string; - "description": string; - "icon": string; - "orderNum": string; - "target": string; - "parentId": string; - "parentName": string; - "children": any; - "syesourcetype": string; - "status": string; - "path": string; - "perms": string; - "menuType": string; + menuId: string; + createTime: string; + updateTime: string; + menuName: string; + component: string; + description: string; + icon: string; + orderNum: string; + target: string; + parentId: string; + parentName: string; + children: any; + syesourcetype: string; + status: string; + path: string; + perms: string; + menuType: string; } export interface Knowledge { - "id": string; - "createTime": string; - "updateTime": string; - "name": string; + id: string; + createTime: string; + updateTime: string; + name: string; } export interface Result<T> { @@ -62,75 +63,78 @@ } export function UserList(params: Pagination) { - return axios.get<Result<User[]>>("/base/system/user/list", { params }); + return axios.get<Result<User[]>>('/base/system/user/list', { params }); } export function Userstatus(userID, status) { - return axios.put("/base/system/user/changeStatus", { "userId": userID, "status": status }); + return axios.put('/base/system/user/changeStatus', { + userId: userID, + status: status, + }); } export function UserChangePwd(userId) { - return axios.put("/base/system/user/profile/updatePwd", { "userId": userId }); + return axios.put('/base/system/user/profile/updatePwd', { userId: userId }); } - export function UserEdit(user) { - return axios.put("/base/system/user", { user }); + return axios.put('/base/system/user', { user }); } export function UserAdd(user) { - return axios.post("/base/system/user", { user }); + return axios.post('/base/system/user', { user }); } export function UserDelete(userId) { - return axios.delete("/base/system/user/" + userId); + return axios.delete('/base/system/user/' + userId); } export function OrganizationList(key: string) { - return axios.post<Result<Organization[]>>("/base/system/dept/list", { "deptName": key }); + return axios.post<Result<Organization[]>>('/base/system/dept/list', { + deptName: key, + }); } - export function OrganizationAdd(organization) { - return axios.post("/base/system/dept", { organization }); + return axios.post('/base/system/dept', { organization }); } export function OrganizationDelete(id) { - return axios.delete("/base/system/dept/" + id); + return axios.delete('/base/system/dept/' + id); } export function OrganizationUpdate(organization) { - return axios.put("/base/system/dept", { organization }); + return axios.put('/base/system/dept', { organization }); } - export function OrganizationById(id) { - return axios.get<Result<Organization>>("/base/system/dept/" + id); + return axios.get<Result<Organization>>('/base/system/dept/' + id); } - export function ResourceList(key: string) { - return axios.get<Result<Resource[]>>("/base/system/menu/treeselect"); + return axios.get<Result<Resource[]>>('/base/system/menu/treeselect'); } - export function ResourceAdd(resource) { - return axios.post("/base/system/menu", { resource }); + return axios.post('/base/system/menu', { resource }); } export function ResourceDelete(id) { - return axios.delete("/base/system/menu/" + id); + return axios.delete('/base/system/menu/' + id); } export function ResourceUpdate(resource) { - return axios.put("/base/system/menu", { resource }); + return axios.put('/base/system/menu', { resource }); } - export function ResourceById(id) { - return axios.get<Result<Resource>>("/base/system/menu/" + id); + return axios.get<Result<Resource>>('/base/system/menu/' + id); } export function KnowledgeList() { - return axios.get<Result<Knowledge>>("/base/system/knowledge/list"); -} \ No newline at end of file + return axios.get<Result<Knowledge>>('/base/system/knowledge/list'); +} + +export function DialogList() { + return axios.get<Result<Knowledge>>('/base/system/dialog/list'); +} diff --git a/src/api/interceptor.ts b/src/api/interceptor.ts index 005e4b7..f094164 100644 --- a/src/api/interceptor.ts +++ b/src/api/interceptor.ts @@ -55,7 +55,7 @@ (response: AxiosResponse<HttpResponse>) => { const res = response.data; // if the custom code is not 20000, it is judged as an error. - if ( + /*if ( (res.retcode && res.retcode !== 0) || (res.code && res.code !== 20000 && res.code !== 200) ) { @@ -88,7 +88,7 @@ response.config.url === '/base/login' ) { setAuthorization(response.headers.authorization); - } + }*/ return res; }, (error) => { diff --git a/src/api/kbList.ts b/src/api/kbList.ts index 1f0448e..3206e58 100644 --- a/src/api/kbList.ts +++ b/src/api/kbList.ts @@ -22,29 +22,32 @@ list: PolicyRecord[]; total: number; } + // 鐭ヨ瘑搴撳垪琛ㄦ帴鍙� export function queryKbList(params) { return axios.get('/api/v1/kb/list', { - params + params, }); } + // 鐭ヨ瘑搴撹鎯呮帴鍙� export function queryKbdetail(params) { return axios.get('/api/v1/kb/detail', { - params + params, }); } // 淇℃伅鎺ュ彛 export function queryKbtenantInfo(params) { return axios.get('/api/v1/user/tenant_info', { - params + params, }); } + // 鏂囨。鍒楄〃鎺ュ彛 export function queryKbDocumentList(params) { return axios.get('/api/v1/document/list', { - params + params, }); } @@ -52,10 +55,12 @@ export function kbcreate(params) { return axios.post('/api/v1/kb/create', params); } + // 鐭ヨ瘑搴撳垹闄ゆ帴鍙� export function deleteKnow(params) { return axios.post('/api/v1/kb/rm', params); } + //鐭ヨ瘑搴撴洿鏂版帴鍙� export function querykbupdate(params) { @@ -74,14 +79,9 @@ 'Content-Type': 'application/x-www-form-urlencoded', // token: token, }, - } - return axios.post( - '/api/v1/document/upload', - params, - config - ) + }; + return axios.post('/api/v1/document/upload', params, config); } - // 鏂囨。鍚姩/鍙栨秷瑙f瀽鎺ュ彛 @@ -95,17 +95,17 @@ return axios.post('/api/v1/document/rm', params); } - // 鏂囨。閲嶅懡鍚嶆帴鍙� export function kbdocumentrename(params) { return axios.post('/api/v1/document/rename', params); } + // 鏂囦欢瑙f瀽鏂规硶鎺ュ彛 export function kbdocumentchangeparser(params) { return axios.post('/api/v1/document/change_parser', params); } - // 鏂囨。鍚敤/绂佺敤鎺ュ彛 +// 鏂囨。鍚敤/绂佺敤鎺ュ彛 export function kbdocumentchangeStatus(params) { return axios.post('/api/v1/document/change_status', params); } @@ -113,25 +113,47 @@ // 妯″瀷鍒楄〃鎺ュ彛 export function queryModelList(params) { return axios.get('/api/v1/llm/list', { - params + params, }); } - // 娴嬭瘯鎺ュ彛 export function kbretrievalTest(params) { return axios.post('/api/v1/chunk/retrieval_test', params); } - // 閰嶇疆鎺ュ彛 export function kbUpdate(params) { return axios.post('/api/v1/kb/update', params); } +// 鏂囨。涓嬭浇鎺ュ彛 +export const downloadFile = ({ + url, + filename, + target, +}: { + url: string; + filename?: string; + target?: string; +}) => { + const downloadElement = document.createElement('a'); + downloadElement.style.display = 'none'; + downloadElement.href = url; + if (target) { + downloadElement.target = '_blank'; + } + downloadElement.rel = 'noopener noreferrer'; + if (filename) { + downloadElement.download = filename; + } + document.body.appendChild(downloadElement); + downloadElement.click(); + document.body.removeChild(downloadElement); +}; - - - - +// 鏂板瑙f瀽鍧� +export function achunkCreate(params) { + return axios.post('/api/v1/chunk/create', params); +} diff --git a/src/api/session.ts b/src/api/session.ts index fe2b47f..ce11bb4 100644 --- a/src/api/session.ts +++ b/src/api/session.ts @@ -1,29 +1,47 @@ import axios from 'axios'; export interface ISessionListResult { - code:number; - msg:string; - data:any; + code: number; + msg: string; + data: any; } // 浼氳瘽鍒楄〃 export function sessionListApi() { - return axios.get<ISessionListResult>('/api/conversation/list?modeltype=localragflow'); + return axios.get<ISessionListResult>( + '/api/conversation/list?modeltype=localragflow' + ); } // 鍒犻櫎浼氳瘽 -export function deleteSessionApi(conversation_ids:string[]) { - return axios.post<ISessionListResult>('/api/conversation/del?modeltype=localragflow',{conversation_ids}); +export function deleteSessionApi(conversation_ids: string[]) { + return axios.post<ISessionListResult>( + '/api/conversation/del?modeltype=localragflow', + { conversation_ids } + ); } // 鏂板浼氳瘽 -export function addSessionApi(params:any) { - return axios.get<ISessionListResult>('/api/getConId/kdwithai?platform=localragflow',{params}); +export function addSessionApi(params: any) { + return axios.get<ISessionListResult>( + '/api/getConId/kdwithai?platform=localragflow', + { params } + ); } // 鑱婂ぉ -export function chatApi(data:{conversation_id:string,messages:string}) { - return axios.post<ISessionListResult>('/api/tech/cloudminds/query?modeltype=localragflow',data); +export function chatApi(data: { conversation_id: string; messages: string }) { + return axios.post<ISessionListResult>( + '/api/tech/cloudminds/query?modeltype=localragflow', + data + ); } // 鑾峰彇浼氳瘽璇︽儏 -export function getSessionDetailsApi(conversation_id:string) { - return axios.get<ISessionListResult>('/api/conversation/get?modeltype=localragflow',{params:{conversation_id}}); -} \ No newline at end of file +export function getSessionDetailsApi(conversation_id: string) { + return axios.get<ISessionListResult>( + '/api/conversation/get?modeltype=localragflow', + { params: { conversation_id } } + ); +} +// 鑾峰彇鏅鸿兘鍔╂墜鍒楄〃 +export function getDialogListApi() { + return axios.get<ISessionListResult>('/api/dialog/list'); +} diff --git a/src/router/routes/modules/dmx.ts b/src/router/routes/modules/dmx.ts index bd3ec29..d794aab 100644 --- a/src/router/routes/modules/dmx.ts +++ b/src/router/routes/modules/dmx.ts @@ -32,8 +32,17 @@ roles: ['*'], }, }, + { + path: 'intelligentAgent', + name: 'IntelligentAgent', + component: () => import('@/views/dmx/IntelligentAgent/index.vue'), + meta: { + locale: '鏅鸿兘浣撶鐞�', + requiresAuth: true, + roles: ['*'], + }, + }, ], - }; export default DMX; diff --git a/src/views/authority/resource/index.vue b/src/views/authority/resource/index.vue index 38f1e06..a8e8e21 100644 --- a/src/views/authority/resource/index.vue +++ b/src/views/authority/resource/index.vue @@ -3,8 +3,11 @@ <authheader :items="menuTips"></authheader> <a-row :gutter="20"> <a-col :span="8"> - <a-card :title="$t('menu.resource.title')" :bordered="false" - :style="{ width: '100%',height: '900px', 'overflow-y': 'auto' }"> + <a-card + :title="$t('menu.resource.title')" + :bordered="false" + :style="{ 'width': '100%', 'height': '900px', 'overflow-y': 'auto' }" + > <a-tree class="tree-demo" draggable @@ -12,47 +15,75 @@ :data="treeData" :show-line="showLine" :fieldNames="{ - key:'menuId', - title:'menuName', - children:'children', + key: 'menuId', + title: 'menuName', + children: 'children', }" @drop="onDrop" @select="showDetail" > <template #extra="nodeData"> <IconPlus - style="position: absolute; right: 60px; font-size: 12px; top: 10px; color: #3370ff;" + style=" + position: absolute; + right: 60px; + font-size: 12px; + top: 10px; + color: #3370ff; + " @click="() => onIconClick(nodeData)" /> - <IconDelete style="position: absolute; right: 40px; font-size: 12px; top: 10px; color: #3370ff;" - @click="() => onIconClickDelete(nodeData)" /> + <IconDelete + style=" + position: absolute; + right: 40px; + font-size: 12px; + top: 10px; + color: #3370ff; + " + @click="() => onIconClickDelete(nodeData)" + /> </template> </a-tree> - </a-card> </a-col> <a-col :span="16"> - <a-card :title="$t('menu.resource.detail')" :bordered="false" :style="{ width: '100%' }"> + <a-card + :title="$t('menu.resource.detail')" + :bordered="false" + :style="{ width: '100%' }" + > <a-form :model="resourceform" layout="horizontal"> <a-form-item field="parentName" label="涓婄骇璧勬簮" disabled> <a-input v-model="resourceform.parentName" /> </a-form-item> <a-form-item field="status" label="璧勬簮鐘舵��"> - <a-switch checked-value="0" unchecked-value="1" v-model="resourceform.status"></a-switch> + <a-switch + checked-value="0" + unchecked-value="1" + v-model="resourceform.status" + ></a-switch> </a-form-item> <a-form-item field="menuName" label="璧勬簮鍚嶇О"> <a-input v-model="resourceform.menuName" /> </a-form-item> <a-form-item field="menuType" label="璧勬簮绫诲瀷"> - <a-select v-model="resourceform.menuType" :options="options" :field-names="fieldNames" - :style="{width:'320px'}" - placeholder="璇烽�夋嫨" /> - + <a-select + v-model="resourceform.menuType" + :options="options" + :field-names="fieldNames" + :style="{ width: '320px' }" + placeholder="璇烽�夋嫨" + /> </a-form-item> <a-form-item field="perms" label="璧勬簮鎺у埗鏉冮檺瀛楃"> <a-input v-model="resourceform.perms" /> </a-form-item> - <a-form-item field="component" label="璧勬簮鍦板潃" style="align: start"> + <a-form-item + field="component" + label="璧勬簮鍦板潃" + style="align: start" + > <a-input v-model="resourceform.component" /> </a-form-item> <a-form-item> @@ -65,21 +96,35 @@ </a-card> </a-col> </a-row> - <a-modal width="50%" v-model:visible="visible" title="鏂板" @cancel="handleCancel" @ok="addresource"> + <a-modal + width="50%" + v-model:visible="visible" + title="鏂板" + @cancel="handleCancel" + @ok="addresource" + > <a-form :model="resourceform" layout="horizontal"> <a-form-item field="parentName" label="涓婄骇璧勬簮" disabled> <a-input v-model="resourceform.parentName" /> </a-form-item> <a-form-item field="status" label="璧勬簮鐘舵��"> - <a-switch checked-value="0" unchecked-value="1" v-model="resourceform.status"></a-switch> + <a-switch + checked-value="0" + unchecked-value="1" + v-model="resourceform.status" + ></a-switch> </a-form-item> <a-form-item field="menuName" label="璧勬簮鍚嶇О"> <a-input v-model="resourceform.menuName" /> </a-form-item> <a-form-item field="menuType" label="璧勬簮绫诲瀷"> - <a-select v-model="resourceform.menuType" :options="options" :field-names="fieldNames" - :style="{width:'320px'}" - placeholder="璇烽�夋嫨" /> + <a-select + v-model="resourceform.menuType" + :options="options" + :field-names="fieldNames" + :style="{ width: '320px' }" + placeholder="璇烽�夋嫨" + /> </a-form-item> <a-form-item field="perms" label="璧勬簮鎺у埗鏉冮檺瀛楃"> <a-input v-model="resourceform.perms" /> @@ -93,156 +138,178 @@ </template> <script lang="ts" setup> -import { ref } from "vue"; -import { IconPlus } from "@arco-design/web-vue/es/icon"; -import { Resource, ResourceAdd, ResourceById, ResourceDelete, ResourceList, ResourceUpdate } from "@/api/authority"; -import Authheader from "@/views/authority/components/authheader.vue"; -import { Modal } from "@arco-design/web-vue"; + import { ref } from 'vue'; + import { IconPlus } from '@arco-design/web-vue/es/icon'; + import { + Resource, + ResourceAdd, + ResourceById, + ResourceDelete, + ResourceList, + ResourceUpdate, + } from '@/api/authority'; + import Authheader from '@/views/authority/components/authheader.vue'; + import { Modal } from '@arco-design/web-vue'; -let visible = ref(false); -let treeData = ref([]); -let showLine = ref(true); -let menuTips = ref(["鏉冮檺绠$悊", "璧勬簮"]); -const fieldNames = { value: "key", label: "value" }; -// 0鐩綍 1鑿滃崟 2鎸夐挳 -let options = ref([ - { - key: "0", - value: "鐩綍" - }, - { - key: "1", - value: "鑿滃崟" - }, - { - key: "2", - value: "鎸夐挳" - } -]); -let resourceform = ref<Resource>({ - component: "", - createTime: "", - description: "", - icon: "", - menuId: "", - menuName: "", - menuType: "", - orderNum: "", - parentId: "", - parentName: "", - children: [], - path: "", - perms: "", - status: "", - syesourcetype: "", - target: "", - updateTime: "" -}); + let visible = ref(false); + let treeData = ref([]); + let showLine = ref(true); + let menuTips = ref(['鏉冮檺绠$悊', '璧勬簮']); + const fieldNames = { value: 'key', label: 'value' }; + // 0鐩綍 1鑿滃崟 2鎸夐挳 + let options = ref([ + { + key: '3', + value: '鐩綍', + }, + { + key: '0', + value: '鑿滃崟', + }, + { + key: '1', + value: '鎸夐挳', + }, + ]); + let resourceform = ref<Resource>({ + component: '', + createTime: '', + description: '', + icon: '', + menuId: '', + menuName: '', + menuType: '', + orderNum: '', + parentId: '', + parentName: '', + children: [], + path: '', + perms: '', + status: '', + syesourcetype: '', + target: '', + updateTime: '', + }); -const onIconClick = (nodeData) => { - resourceform.value.parentId = nodeData.menuId; - visible.value = true; -}; + const onIconClick = (nodeData) => { + resourceform.value.parentId = nodeData.menuId; + resourceform.value.component = ''; + resourceform.value.createTime = ''; + resourceform.value.description = ''; + resourceform.value.icon = ''; + resourceform.value.menuId = ''; + resourceform.value.menuName = ''; + resourceform.value.menuType = ''; + resourceform.value.orderNum = '0'; + resourceform.value.parentName = nodeData.menuName; + resourceform.value.path = ''; + resourceform.value.perms = ''; + resourceform.value.status = ''; + resourceform.value.syesourcetype = ''; -const addresource = async () => { - await ResourceAdd({ - ...resourceform.value - } as unknown as Resource).then((res) => { - ResourceData(""); - }); -}; + visible.value = true; + }; -const onIconClickDelete = (nodeData) => { - ResourceDelete(nodeData.menuId).then(() => { - ResourceData(""); - }); -}; - -const showDetail = (id) => { - ResourceById(id).then((res) => { - resourceform.value = { ...res.data }; - }); -}; -const editresource = () => { - ResourceUpdate({ - ...resourceform.value - } as unknown as Resource).then((res) => { - ResourceData(""); - Modal.success({ - title: "淇濆瓨鎴愬姛", - content: "淇濆瓨鎴愬姛" - }); - }); -}; -const reset = (id) => { - ResourceById(id).then((res) => { - resourceform.value = { ...res.data }; - }); -}; - -const onDrop = ({ dragNode, dropNode, dropPosition }) => { - const data = treeData.value; - ResourceUpdate({ - orderNum: "0", parentId: dropNode.menuId, menuId: dragNode.menuId - }); - const loop = (data, key, callback) => { - data.some((item, index, arr) => { - if (item.menuId === key) { - callback(item, index, arr); - return true; - } - if (item.children) { - return loop(item.children, key, callback); - } - return false; + const addresource = async () => { + await ResourceAdd({ + ...resourceform.value, + } as unknown as Resource).then((res) => { + ResourceData(''); }); }; - loop(data, dragNode.menuId, (_, index, arr) => { - arr.splice(index, 1); - }); - - if (dropPosition === 0) { - loop(data, dropNode.menuId, (item) => { - item.children = item.children || []; - item.children.push(dragNode); + const onIconClickDelete = (nodeData) => { + ResourceDelete(nodeData.menuId).then(() => { + ResourceData(''); }); - } else { - loop(data, dropNode.menuId, (_, index, arr) => { - arr.splice(dropPosition < 0 ? index : index + 1, 0, dragNode); + }; + + const showDetail = (id) => { + ResourceById(id).then((res) => { + resourceform.value = { ...res.data }; }); - } -}; + }; + const editresource = () => { + ResourceUpdate({ + ...resourceform.value, + } as unknown as Resource).then((res) => { + ResourceData(''); + Modal.success({ + title: '淇濆瓨鎴愬姛', + content: '淇濆瓨鎴愬姛', + }); + }); + }; + const reset = (id) => { + ResourceById(id).then((res) => { + resourceform.value = { ...res.data }; + }); + }; -const handleCancel = (type) => { - if (type == 1) { - visible.value = false; - } -}; + const onDrop = ({ dragNode, dropNode, dropPosition }) => { + const data = treeData.value; + ResourceUpdate({ + orderNum: '0', + parentId: dropNode.menuId, + menuId: dragNode.menuId, + }); + const loop = (data, key, callback) => { + data.some((item, index, arr) => { + if (item.menuId === key) { + callback(item, index, arr); + return true; + } + if (item.children) { + return loop(item.children, key, callback); + } + return false; + }); + }; -const ResourceData = async (key) => { - await ResourceList(key).then((res) => { - treeData.value = [...res.rows]; - }); -}; + loop(data, dragNode.menuId, (_, index, arr) => { + arr.splice(index, 1); + }); -ResourceData(""); + if (dropPosition === 0) { + loop(data, dropNode.menuId, (item) => { + item.children = item.children || []; + item.children.push(dragNode); + }); + } else { + loop(data, dropNode.menuId, (_, index, arr) => { + arr.splice(dropPosition < 0 ? index : index + 1, 0, dragNode); + }); + } + }; + + const handleCancel = (type) => { + if (type == 1) { + visible.value = false; + } + }; + + const ResourceData = async (key) => { + await ResourceList(key).then((res) => { + treeData.value = [...res.rows]; + }); + }; + + ResourceData(''); </script> - <style scoped> -.tree-demo :deep(.tree-node-dropover) > :deep(.arco-tree-node-title), -.tree-demo :deep(.tree-node-dropover) > :deep(.arco-tree-node-title):hover { - animation: blinkBg 0.4s 2; -} - -@keyframes blinkBg { - 0% { - background-color: transparent; + .tree-demo :deep(.tree-node-dropover) > :deep(.arco-tree-node-title), + .tree-demo :deep(.tree-node-dropover) > :deep(.arco-tree-node-title):hover { + animation: blinkBg 0.4s 2; } - 100% { - background-color: var(--color-primary-light-1); + @keyframes blinkBg { + 0% { + background-color: transparent; + } + + 100% { + background-color: var(--color-primary-light-1); + } } -} </style> diff --git a/src/views/authority/users/index.vue b/src/views/authority/users/index.vue index 17787c8..cf5ddba 100644 --- a/src/views/authority/users/index.vue +++ b/src/views/authority/users/index.vue @@ -7,7 +7,11 @@ <a-col :flex="1"> <a-form :model="formModel"> <a-form-item field="name"> - <a-input v-model="formModel.name" :style="{width:'320px'}" :placeholder="$t('璇疯緭鍏�')" /> + <a-input + v-model="formModel.name" + :style="{ width: '320px' }" + :placeholder="$t('璇疯緭鍏�')" + /> </a-form-item> </a-form> </a-col> @@ -17,13 +21,13 @@ <template #icon> <icon-refresh /> </template> - {{ $t("searchTable.form.reset") }} + {{ $t('searchTable.form.reset') }} </a-button> <a-button type="primary" @click="search"> <template #icon> <icon-search /> </template> - {{ $t("searchTable.form.search") }} + {{ $t('searchTable.form.search') }} </a-button> </a-col> </a-row> @@ -31,7 +35,9 @@ <a-row style="margin-bottom: 16px"> <a-col :span="12"> <a-space> - <a-button type="primary" :align="'right'" @click="operation(0)">+ 鏂板缓璐︽埛</a-button> + <a-button type="primary" :align="'right'" @click="operation(0)" + >+ 鏂板缓璐︽埛</a-button + > </a-space> </a-col> <a-col @@ -39,10 +45,8 @@ style="display: flex; align-items: center; justify-content: end" > <a-tooltip :content="$t('searchTable.actions.refresh')"> - <div class="action-icon" @click="search" - > - <icon-refresh size="18" - /> + <div class="action-icon" @click="search"> + <icon-refresh size="18" /> </div> </a-tooltip> <a-dropdown @select="handleSelectDensity"> @@ -77,23 +81,44 @@ <template #index="{ rowIndex }"> {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }} </template> - <template #dept="{ record }">{{ record.dept ? record.dept.deptName : "" }}</template> - <template #status="{record}"> - <a-switch checked-value="1" unchecked-value="0" @change="statusChange(record.status,record)" - v-model="record.status" /> + <template #dept="{ record }">{{ + record.dept ? record.dept.deptName : '' + }}</template> + <template #status="{ record }"> + <a-switch + checked-value="1" + unchecked-value="0" + @change="statusChange(record.status, record)" + v-model="record.status" + /> </template> <template #operations="{ record }"> - <a-button type="outline" @click="operation(1,record)">閲嶇疆瀵嗙爜</a-button> - <a-button type="outline" @click="operation(2,record)">缂栬緫</a-button> - <a-popconfirm content="Are you sure you want to delete?" type="success" @ok="operation(3,record)"> + <a-button type="outline" @click="operation(1, record)" + >閲嶇疆瀵嗙爜</a-button + > + <a-button type="outline" @click="operation(2, record)">缂栬緫</a-button> + <a-popconfirm + content="Are you sure you want to delete?" + type="success" + @ok="operation(3, record)" + > <a-button type="outline">鍒犻櫎</a-button> </a-popconfirm> - <a-button type="outline" @click="operation(4,record)">鏉冮檺閰嶇疆</a-button> - <a-button type="outline" @click="operation(5,record)">閮ㄩ棬閰嶇疆</a-button> + <a-button type="outline" @click="operation(4, record)" + >鏉冮檺閰嶇疆</a-button + > + <a-button type="outline" @click="operation(5, record)" + >閮ㄩ棬閰嶇疆</a-button + > </template> </a-table> </a-card> - <a-modal v-model:visible="visible" :title="save" @cancel="handleCancel(1)" @ok="editHandleOk"> + <a-modal + v-model:visible="visible" + :title="save" + @cancel="handleCancel(1)" + @ok="editHandleOk" + > <a-form :model="editform"> <a-form-item field="name" label="鏄电О"> <a-input v-model="editform.nickName" /> @@ -109,10 +134,19 @@ </a-form-item> </a-form> </a-modal> - <a-modal width="50%" v-model:visible="deptvisible" title="閮ㄩ棬閰嶇疆" @cancel="handleCancel(2)" - @ok="editDeptHandleOk"> + <a-modal + width="50%" + v-model:visible="deptvisible" + title="閮ㄩ棬閰嶇疆" + @cancel="handleCancel(2)" + @ok="editDeptHandleOk" + > <div :style="{ display: 'flex' }"> - <a-card :style="{ width: '460px',height: '500px', 'overflow-y': 'auto' }" title="鏈烘瀯" hoverable> + <a-card + :style="{ 'width': '460px', 'height': '500px', 'overflow-y': 'auto' }" + title="鏈烘瀯" + hoverable + > <a-tree class="tree-demo" v-model:checked-keys="checkedKeys" @@ -122,19 +156,15 @@ :show-line="showLine" @check="onCheck" :fieldNames="{ - key:'deptId', - title:'deptName', - children:'children', + key: 'deptId', + title: 'deptName', + children: 'children', }" :check-strictly="checkStrictly" > </a-tree> </a-card> - <a-card - class="card-demo" - title="鐢ㄦ埛鎵�灞炴満鏋�" - hoverable - > + <a-card class="card-demo" title="鐢ㄦ埛鎵�灞炴満鏋�" hoverable> <a-space wrap> <a-tag v-for="(tag, index) of checkStrictly" @@ -146,12 +176,18 @@ </a-space> </a-card> </div> - </a-modal> - <a-modal width="30%" v-model:visible="resourcevisible" title="鏉冮檺閰嶇疆" @cancel="handleCancel(3)" - @ok="editResourceHandleOk"> - <div :style="{ display:'flex', 'flex-direction':'column' }"> - <a-tabs :style="{ width: '100%',height: '500px', 'overflow-y': 'auto' }"> + <a-modal + width="30%" + v-model:visible="resourcevisible" + title="鏉冮檺閰嶇疆" + @cancel="handleCancel(3)" + @ok="editResourceHandleOk" + > + <div :style="{ 'display': 'flex', 'flex-direction': 'column' }"> + <a-tabs + :style="{ 'width': '100%', 'height': '500px', 'overflow-y': 'auto' }" + > <a-tab-pane key="1"> <template #title> <icon-calendar /> @@ -166,10 +202,10 @@ :show-line="showLineMenu" @check="onCheckMenu" :fieldNames="{ - key:'menuId', - title:'menuName', - children:'children', - }" + key: 'menuId', + title: 'menuName', + children: 'children', + }" :check-strictly="checkStrictlyMenu" > </a-tree> @@ -180,7 +216,11 @@ 鐭ヨ瘑搴� </template> <a-space direction="vertical" size="large"> - <a-checkbox-group v-model="checkedKeysKnowledge" direction="vertical" @change="onCheckKnowledge"> + <a-checkbox-group + v-model="checkedKeysKnowledge" + direction="vertical" + @change="onCheckKnowledge" + > <a-checkbox v-for="(knowledg, index) of knowledgeList" :value="knowledg.id" @@ -197,13 +237,32 @@ <icon-user /> 鏅鸿兘浣� </template> - Content of Tab Panel 3 + <a-checkbox-group + v-model="checkedKeysDialog" + direction="vertical" + @change="onCheckDialog" + > + <a-checkbox + v-for="(dialog, index) of DialogsList" + :value="dialog.id" + :lable="dialog.name" + @change="onCheckDialog" + > + {{ dialog.name }} + </a-checkbox> + </a-checkbox-group> </a-tab-pane> </a-tabs> - <a-card :style="{ width: '100%',height: '200px', 'overflow-y': 'auto', margin:'1px'}" - class="card-demo" - title="鐢ㄦ埛鎵�鏈夋潈闄�" - hoverable + <a-card + :style="{ + 'width': '100%', + 'height': '200px', + 'overflow-y': 'auto', + 'margin': '1px', + }" + class="card-demo" + title="鐢ㄦ埛鎵�鏈夋潈闄�" + hoverable > <a-space wrap> 鑿滃崟鍔熻兘锛� @@ -226,403 +285,471 @@ {{ tag.knowledgeName }} </a-tag> </a-space> + <a-divider /> + <a-space wrap> + 鏅鸿兘浣�: + <a-tag + v-for="(tag, index) of checkStrictlyDialog" + :key="tag.dialogId" + @close="handleDialogRemove(tag)" + > + {{ tag.dialogName }} + </a-tag> + </a-space> </a-card> </div> - </a-modal> </div> </template> <script lang="ts" setup> -import { computed, reactive, ref } from "vue"; -import { useI18n } from "vue-i18n"; -import useLoading from "@/hooks/loading"; -import { Pagination } from "@/types/global"; -import type { TableColumnData } from "@arco-design/web-vue/es/table/interface"; -import { - KnowledgeList, - OrganizationList, - ResourceList, - User, - UserAdd, - UserChangePwd, - UserDelete, - UserEdit, - UserList, - Userstatus -} from "@/api/authority"; -import { Modal } from "@arco-design/web-vue"; -import Authheader from "@/views/authority/components/authheader.vue"; + import { computed, reactive, ref } from 'vue'; + import { useI18n } from 'vue-i18n'; + import useLoading from '@/hooks/loading'; + import { Pagination } from '@/types/global'; + import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'; + import { + DialogList, + KnowledgeList, + OrganizationList, + ResourceList, + User, + UserAdd, + UserChangePwd, + UserDelete, + UserEdit, + UserList, + Userstatus, + } from '@/api/authority'; + import { Modal } from '@arco-design/web-vue'; + import Authheader from '@/views/authority/components/authheader.vue'; -let treeData = ref([]); -let checkedKeys = ref([]); -let expandKdys = ref([]); -let checkStrictly = ref([]); + let treeData = ref([]); + let checkedKeys = ref([]); + let expandKdys = ref([]); + let checkStrictly = ref([]); + let treeDataMenu = ref([]); + let checkedKeysMenu = ref([]); + let expandKdysMenu = ref([]); + let checkStrictlyMenu = ref([]); -let treeDataMenu = ref([]); -let checkedKeysMenu = ref([]); -let expandKdysMenu = ref([]); -let checkStrictlyMenu = ref([]); + let checkedKeysKnowledge = ref([]); + let checkStrictlyKnowledge = ref([]); -let checkedKeysKnowledge= ref([]); -let checkStrictlyKnowledge= ref([]); + let checkedKeysDialog = ref([]); + let checkStrictlyDialog = ref([]); -let knowledgeList = ref([]); + let knowledgeList = ref([]); + let DialogsList = ref([]); -let menuTips = ref(["鏉冮檺绠$悊", "璐﹀彿"]); -type SizeProps = "mini" | "small" | "medium" | "large"; -const account = ref(null); -const generateFormModel = () => { - return { - name: "" + let menuTips = ref(['鏉冮檺绠$悊', '璐﹀彿']); + type SizeProps = 'mini' | 'small' | 'medium' | 'large'; + const account = ref(null); + const generateFormModel = () => { + return { + name: '', + }; }; -}; -let showLine = ref(true); -const { loading, setLoading } = useLoading(true); -const { t } = useI18n(); -let save = ref("鏂板"); -let renderData = ref<User[]>([]); -let formModel = ref(generateFormModel()); -let editform = ref<User>({ - createTime: "", - dept: undefined, - email: "", - nickName: "", - phoneNumber: "", - status: "", - userId: "", - userName: "" -}); - -let size = ref<SizeProps>("medium"); -let visible = ref(false); -let deptvisible = ref(false); -let resourcevisible = ref(false); -let selectUser = ref({}); - -const onCheck = (newCheckedKeys, event) => { - let o = { "deptId": event.node.deptId, "deptName": event.node.deptName }; - if (event.checked) { - checkStrictly.value.push(o); - } else { - checkStrictly.value.forEach((val, idx, array) => { - // val: 褰撳墠鍊� - if (val.deptId == event.node.deptId) { - checkStrictly.value.splice(idx, 1); - return true; - } - }); - - } -}; -const onCheckMenu = (newCheckedKeys, event) => { - let o = { "menuId": event.node.menuId, "menuName": event.node.menuName }; - if (event.checked) { - checkStrictlyMenu.value.push(o); - } else { - checkStrictlyMenu.value.forEach((val, idx, array) => { - // val: 褰撳墠鍊� - if (val.menuId == event.node.menuId) { - checkStrictlyMenu.value.splice(idx, 1); - return true; - } - }); - } -}; -const onCheckKnowledge = (newCheckedKeys, event) => { - let o = { "knowledgeId": event.target.value, "knowledgeName": event.target.labels[0].innerText }; - if (event.target.checked) { - checkStrictlyKnowledge.value.push(o); - } else { - checkStrictlyKnowledge.value.forEach((val, idx, array) => { - // val: 褰撳墠鍊� - if (val.knowledgeId == event.target.value) { - checkStrictlyKnowledge.value.splice(idx, 1); - return true; - } - }); - } -}; -const handleRemove = (key) => { - checkStrictly.value = checkStrictly.value.filter((tag) => tag !== key); -}; -const handleMenuRemove = (key) => { - checkStrictlyMenu.value = checkStrictlyMenu.value.filter((tag) => tag !== key); -}; -const handleKnowledgeRemove = (key) => { - checkStrictlyKnowledge.value = checkStrictlyKnowledge.value.filter((tag) => tag !== key); -}; - -const basePagination: Pagination = { - current: 1, - pageSize: 20 -}; -const pagination = reactive({ - ...basePagination -}); - -const densityList = computed(() => [ - { - name: t("searchTable.size.mini"), - value: "mini" - }, - { - name: t("searchTable.size.small"), - value: "small" - }, - { - name: t("searchTable.size.medium"), - value: "medium" - }, - { - name: t("searchTable.size.large"), - value: "large" - } -]); -const columns = computed<TableColumnData[]>(() => [ - { - title: t("搴忓彿"), - dataIndex: "index", - slotName: "index" - }, - { - title: t("鐢ㄦ埛鍚�"), - dataIndex: "userName" - }, - { - title: t("鍒涘缓鏃堕棿"), - dataIndex: "createTime" - }, - { - title: t("鎵�灞為儴闂�"), - dataIndex: "dept", - slotName: "dept" - }, - { - title: t("鐘舵��"), - dataIndex: "status", - slotName: "status" - }, - { - title: t("searchTable.columns.operations"), - dataIndex: "operations", - slotName: "operations" - } -]); - -const statusChange = async (value, record) => { - await Userstatus(record.userId, value).then((res) => { - + let showLine = ref(true); + const { loading, setLoading } = useLoading(true); + const { t } = useI18n(); + let save = ref('鏂板'); + let renderData = ref<User[]>([]); + let formModel = ref(generateFormModel()); + let editform = ref<User>({ + createTime: '', + dept: undefined, + email: '', + nickName: '', + phoneNumber: '', + status: '', + userId: '', + userName: '', }); -}; -const handleCancel = (type) => { - if (type == 1) { - visible.value = false; - } - if (type == 2) { - deptvisible.value = false; - } - if (type == 2) { - resourcevisible.value = false; - } + let size = ref<SizeProps>('medium'); + let visible = ref(false); + let deptvisible = ref(false); + let resourcevisible = ref(false); + let selectUser = ref({}); -}; + const onCheck = (newCheckedKeys, event) => { + let o = { deptId: event.node.deptId, deptName: event.node.deptName }; + if (event.checked) { + checkStrictly.value.push(o); + } else { + checkStrictly.value.forEach((val, idx, array) => { + // val: 褰撳墠鍊� + if (val.deptId == event.node.deptId) { + checkStrictly.value.splice(idx, 1); + return true; + } + }); + } + }; + const onCheckMenu = (newCheckedKeys, event) => { + let o = { menuId: event.node.menuId, menuName: event.node.menuName }; + if (event.checked) { + checkStrictlyMenu.value.push(o); + } else { + checkStrictlyMenu.value.forEach((val, idx, array) => { + // val: 褰撳墠鍊� + if (val.menuId == event.node.menuId) { + checkStrictlyMenu.value.splice(idx, 1); + return true; + } + }); + } + }; + const onCheckKnowledge = (newCheckedKeys, event) => { + let o = { + knowledgeId: event.target.value, + knowledgeName: event.target.labels[0].innerText, + }; + if (event.target.checked) { + checkStrictlyKnowledge.value.push(o); + } else { + checkStrictlyKnowledge.value.forEach((val, idx, array) => { + // val: 褰撳墠鍊� + if (val.knowledgeId == event.target.value) { + checkStrictlyKnowledge.value.splice(idx, 1); + return true; + } + }); + } + }; -const editDeptHandleOk = async () => { - let depts: Array = [], user: User = { "userId": selectUser.value.userId }; - checkStrictly.value.forEach((val) => { - depts.push(val.deptId); - }); - user.dept = depts; - await UserEdit(user).then((res) => { - fetchData(); - }); -}; + const onCheckDialog = (newCheckedKeys, event) => { + let o = { + dialogId: event.target.value, + dialogName: event.target.labels[0].innerText, + }; + if (event.target.checked) { + checkStrictlyDialog.value.push(o); + } else { + checkStrictlyDialog.value.forEach((val, idx, array) => { + // val: 褰撳墠鍊� + if (val.dialogId == event.target.value) { + checkStrictlyDialog.value.splice(idx, 1); + return true; + } + }); + } + }; -const editResourceHandleOk = async () => { - let resources: Array = [],Knowledges: Array = [], user: User = { "userId": selectUser.value.userId }; - checkStrictlyMenu.value.forEach((val) => { - resources.push(val.menuId); - }); - user.resources = resources; - checkStrictlyKnowledge.value.forEach((val) => { - Knowledges.push(val.knowledgeId); - }); - user.knowledges = Knowledges; + const handleRemove = (key) => { + checkStrictly.value = checkStrictly.value.filter((tag) => tag !== key); + }; + const handleMenuRemove = (key) => { + checkStrictlyMenu.value = checkStrictlyMenu.value.filter( + (tag) => tag !== key + ); + }; + const handleKnowledgeRemove = (key) => { + checkStrictlyKnowledge.value = checkStrictlyKnowledge.value.filter( + (tag) => tag !== key + ); + }; + const handleDialogRemove = (key) => { + checkStrictlyDialog.value = checkStrictlyDialog.value.filter( + (tag) => tag !== key + ); + }; - await UserEdit(user).then((res) => { - fetchData(); - }); -}; - -const editHandleOk = async () => { - if (editform.value.userId.length > 0) { - await UserEdit({ - ...editform.value - } as unknown as User).then((res) => { - fetchData(); - }); - } else { - await UserAdd({ - ...editform.value - } as unknown as User).then((res) => { - fetchData(); - }); - } -}; -const operation = async (t, record) => { - if (t == 0) { - save.value = "鏂板"; - visible.value = true; - editform.value.userId = ""; - editform.value.userName = ""; - editform.value.nickName = ""; - editform.value.email = ""; - editform.value.phoneNumber = ""; - } -//閲嶇疆瀵嗙爜 - if (t == 1) { - await UserChangePwd(record.userId).then((res) => { - if (res.code == 20000) { - Modal.success({ - title: "閲嶇疆瀵嗙爜", - content: "璇ョ敤鎴峰瘑鐮侀噸缃负000000" - }); - } else { - Modal.error({ - title: "閲嶇疆瀵嗙爜", - content: "璇ョ敤鎴峰瘑鐮侀噸缃け璐�" - }); - } - }); - } - //缂栬緫 - if (t == 2) { - visible.value = true; - save.value = "缂栬緫"; - editform.value.userId = record.userId; - editform.value.userName = record.userName; - editform.value.nickName = record.nickName; - editform.value.email = record.email; - editform.value.phoneNumber = record.phoneNumber; - } - //鍒犻櫎 - if (t == 3) { - await UserDelete(record.userId).then((res) => { - if (res.code == 20000) { - fetchData(); - } - }); - } - //鏉冮檺 - if (t == 4) { - resourcevisible.value = true; - checkedKeysMenu.value = []; - expandKdysMenu.value = []; - checkStrictlyMenu.value = []; - checkStrictlyKnowledge.value=[]; - checkedKeysKnowledge.value=[]; - selectUser.value = record; - record.resources.forEach((val) => { - checkStrictlyMenu.value.push({ "menuId": val.menuId, "menuName": val.menuName }); - checkedKeysMenu.value.push(val.menuId); - expandKdysMenu.value.push(val.menuId); - }); - record.knowledges.forEach((val) => { - checkStrictlyKnowledge.value.push({ "knowledgeId": val.id, "knowledgeName": val.name }); - checkedKeysKnowledge.value.push(val.id); - }); - - } - //鏈烘瀯 - if (t == 5) { - deptvisible.value = true; - checkedKeys.value = []; - expandKdys.value = []; - checkStrictly.value = []; - selectUser.value = record; - expandKdys.value.push("0"); - record.dept.forEach((val) => { - checkStrictly.value.push({ "deptId": val.deptId, "deptName": val.deptName }); - checkedKeys.value.push(val.deptId); - expandKdys.value.push(val.deptId); - }); - - } -}; - -const fetchData = async ( - params: Pagination = { current: 1, pageSize: 20 } -) => { - setLoading(true); - try { - await UserList(params).then((res) => { - renderData.value = res.rows; - console.log(renderData); - pagination.current = params.current; - pagination.total = res.total; - }); - } catch (err) { - // you can report use errorHandler or other - } finally { - setLoading(false); - } -}; - -const search = () => { - fetchData({ + const basePagination: Pagination = { + current: 1, + pageSize: 20, + }; + const pagination = reactive({ ...basePagination, - ...formModel.value - } as unknown as Pagination); -}; - -const onPageChange = (current: number) => { - fetchData({ ...basePagination, current }); -}; - -const OrganizationData = async (key) => { - await OrganizationList(key).then((res) => { - treeData.value = [...res.rows]; }); -}; -const MenuData = async (key) => { - await ResourceList(key).then((res) => { - treeDataMenu.value = [...res.rows]; + + const densityList = computed(() => [ + { + name: t('searchTable.size.mini'), + value: 'mini', + }, + { + name: t('searchTable.size.small'), + value: 'small', + }, + { + name: t('searchTable.size.medium'), + value: 'medium', + }, + { + name: t('searchTable.size.large'), + value: 'large', + }, + ]); + const columns = computed<TableColumnData[]>(() => [ + { + title: t('搴忓彿'), + dataIndex: 'index', + slotName: 'index', + }, + { + title: t('鐢ㄦ埛鍚�'), + dataIndex: 'userName', + }, + { + title: t('鍒涘缓鏃堕棿'), + dataIndex: 'createTime', + }, + { + title: t('鎵�灞為儴闂�'), + dataIndex: 'dept', + slotName: 'dept', + }, + { + title: t('鐘舵��'), + dataIndex: 'status', + slotName: 'status', + }, + { + title: t('searchTable.columns.operations'), + dataIndex: 'operations', + slotName: 'operations', + }, + ]); + + const statusChange = async (value, record) => { + await Userstatus(record.userId, value).then((res) => {}); + }; + + const handleCancel = (type) => { + if (type == 1) { + visible.value = false; + } + if (type == 2) { + deptvisible.value = false; + } + if (type == 2) { + resourcevisible.value = false; + } + }; + + const editDeptHandleOk = async () => { + let depts: Array = [], + user: User = { userId: selectUser.value.userId }; + checkStrictly.value.forEach((val) => { + depts.push(val.deptId); + }); + user.dept = depts; + await UserEdit(user).then((res) => { + fetchData(); + }); + }; + + const editResourceHandleOk = async () => { + let resources: Array = [], + dialogs: Array = [], + Knowledges: Array = [], + user: User = { userId: selectUser.value.userId }; + checkStrictlyMenu.value.forEach((val) => { + resources.push(val.menuId); + }); + user.resources = resources; + + checkStrictlyKnowledge.value.forEach((val) => { + Knowledges.push(val.knowledgeId); + }); + user.knowledges = Knowledges; + + checkStrictlyDialog.value.forEach((val) => { + dialogs.push(val.dialogId); + }); + user.dialogs = dialogs; + + await UserEdit(user).then((res) => { + fetchData(); + }); + }; + + const editHandleOk = async () => { + if (editform.value.userId.length > 0) { + await UserEdit({ + ...editform.value, + } as unknown as User).then((res) => { + fetchData(); + }); + } else { + await UserAdd({ + ...editform.value, + } as unknown as User).then((res) => { + fetchData(); + }); + } + }; + const operation = async (t, record) => { + if (t == 0) { + save.value = '鏂板'; + visible.value = true; + editform.value.userId = ''; + editform.value.userName = ''; + editform.value.nickName = ''; + editform.value.email = ''; + editform.value.phoneNumber = ''; + } + //閲嶇疆瀵嗙爜 + if (t == 1) { + await UserChangePwd(record.userId).then((res) => { + if (res.code == 20000) { + Modal.success({ + title: '閲嶇疆瀵嗙爜', + content: '璇ョ敤鎴峰瘑鐮侀噸缃负000000', + }); + } else { + Modal.error({ + title: '閲嶇疆瀵嗙爜', + content: '璇ョ敤鎴峰瘑鐮侀噸缃け璐�', + }); + } + }); + } + //缂栬緫 + if (t == 2) { + visible.value = true; + save.value = '缂栬緫'; + editform.value.userId = record.userId; + editform.value.userName = record.userName; + editform.value.nickName = record.nickName; + editform.value.email = record.email; + editform.value.phoneNumber = record.phoneNumber; + } + //鍒犻櫎 + if (t == 3) { + await UserDelete(record.userId).then((res) => { + if (res.code == 20000) { + fetchData(); + } + }); + } + //鏉冮檺 + if (t == 4) { + resourcevisible.value = true; + checkedKeysMenu.value = []; + expandKdysMenu.value = []; + checkStrictlyMenu.value = []; + checkStrictlyKnowledge.value = []; + checkedKeysKnowledge.value = []; + checkStrictlyDialog.value = []; + checkedKeysDialog.value = []; + selectUser.value = record; + record.resources.forEach((val) => { + checkStrictlyMenu.value.push({ + menuId: val.menuId, + menuName: val.menuName, + }); + checkedKeysMenu.value.push(val.menuId); + expandKdysMenu.value.push(val.menuId); + }); + record.knowledges.forEach((val) => { + checkStrictlyKnowledge.value.push({ + knowledgeId: val.id, + knowledgeName: val.name, + }); + checkedKeysKnowledge.value.push(val.id); + }); + record.dialogs.forEach((val) => { + checkStrictlyDialog.value.push({ + dialogId: val.id, + dialogName: val.name, + }); + checkedKeysDialog.value.push(val.id); + }); + } + //鏈烘瀯 + if (t == 5) { + deptvisible.value = true; + checkedKeys.value = []; + expandKdys.value = []; + checkStrictly.value = []; + selectUser.value = record; + expandKdys.value.push('0'); + record.dept.forEach((val) => { + checkStrictly.value.push({ + deptId: val.deptId, + deptName: val.deptName, + }); + checkedKeys.value.push(val.deptId); + expandKdys.value.push(val.deptId); + }); + } + }; + + const fetchData = async ( + params: Pagination = { current: 1, pageSize: 20 } + ) => { + setLoading(true); + try { + await UserList(params).then((res) => { + renderData.value = res.rows; + console.log(renderData); + pagination.current = params.current; + pagination.total = res.total; + }); + } catch (err) { + // you can report use errorHandler or other + } finally { + setLoading(false); + } + }; + + const search = () => { + fetchData({ + ...basePagination, + ...formModel.value, + } as unknown as Pagination); + }; + + const onPageChange = (current: number) => { + fetchData({ ...basePagination, current }); + }; + + const OrganizationData = async (key) => { + await OrganizationList(key).then((res) => { + treeData.value = [...res.rows]; + }); + }; + const MenuData = async (key) => { + await ResourceList(key).then((res) => { + treeDataMenu.value = [...res.rows]; + }); + }; + + KnowledgeList().then((res) => { + knowledgeList.value = res.rows; }); -}; -KnowledgeList().then((res) => { - knowledgeList.value = res.rows; -}); -fetchData(); -OrganizationData(""); -MenuData(); + DialogList().then((res) => { + DialogsList.value = res.rows; + }); + fetchData(); + OrganizationData(''); + MenuData(); -const reset = () => { - formModel.value = generateFormModel(); -}; + const reset = () => { + formModel.value = generateFormModel(); + }; -const handleSelectDensity = ( - val: string | number | Record<string, any> | undefined, - e: Event -) => { - size.value = val as SizeProps; -}; - + const handleSelectDensity = ( + val: string | number | Record<string, any> | undefined, + e: Event + ) => { + size.value = val as SizeProps; + }; </script> - <style scoped> -.card-demo { - width: 460px; - margin-left: 24px; - transition-property: all; -} + .card-demo { + width: 460px; + margin-left: 24px; + transition-property: all; + } -.card-demo:hover { - transform: translateY(-4px); -} + .card-demo:hover { + transform: translateY(-4px); + } </style> - diff --git a/src/views/dmx/IntelligentAgent/components/addAgent.vue b/src/views/dmx/IntelligentAgent/components/addAgent.vue new file mode 100644 index 0000000..8e609d1 --- /dev/null +++ b/src/views/dmx/IntelligentAgent/components/addAgent.vue @@ -0,0 +1,148 @@ +<template> + <!-- <a-button type="primary" @click="handleClick" style="margin-left: 10px">--> + <!-- <template #icon>--> + <!-- <icon-plus />--> + <!-- </template>--> + <!-- </a-button>--> + <a-modal + v-model:visible="visible" + title="鍒涘缓鏅鸿兘浣�" + @before-open="handleOpened" + @cancel="handleCancel" + :footer="false" + title-align="start" + width="600px" + > + <a-form + ref="formRef" + :rules="rules" + :model="form" + @submit="handleSubmit" + :style="{ width: '90%', margin: '0 auto' }" + layout="vertical" + > + <a-form-item field="name" label="鏅鸿兘浣撳悕绉�"> + <a-input v-model="form.name" placeholder="璇疯緭鍏ュ悕绉�" /> + </a-form-item> + <a-form-item label="浣犲笇鏈涙櫤鑳戒綋鐨勮鑹叉槸浠�涔堬紝鍏蜂綋瀹屾垚浠�涔堜换鍔★紵"> + <a-textarea + v-model="form.prompt_config.system" + placeholder="" + style="height: 180px" + /> + </a-form-item> + <a-form-item> + <div style="width: 100%; text-align: right"> + <a-button @click="visible = false">鍙栨秷</a-button> + <a-button style="margin-left: 10px" type="primary" html-type="submit" + >纭畾</a-button + > + <editAgent + ref="editAgentKuai" + typeAngint="add" + :formData="form" + @cancelModal="handleCancel" + ></editAgent> + </div> + </a-form-item> + </a-form> + </a-modal> +</template> + +<script lang="ts" setup> + import { onMounted, onBeforeMount, reactive, ref } from 'vue'; + import editAgent from '@/views/dmx/IntelligentAgent/components/editAgent.vue'; + + const visible = ref(false); + const loading = ref(false); + const editAgentKuai = ref(); + const form = reactive({ + name: '', + icon: '', + language: 'English', + prompt_config: { + empty_response: '', + prologue: '浣犲ソ锛� 鎴戞槸浣犵殑鍔╃悊锛屾湁浠�涔堝彲浠ュ府鍒颁綘鐨勫悧锛�', + quote: true, + self_rag: true, + system: + '绀轰緥锛歕n' + + '浣犳槸 XX锛屽叿鏈� XX 缁忛獙锛屾搮闀� XX锛屸�n' + + '浣犵殑浠诲姟鏄� XX 锛岄渶瑕佹寜鐓т互涓嬫楠ゆ墽琛岋細\n' + + '1. XX\n' + + '2. XX\n' + + '3. 鈥n', + parameters: [ + { + key: 'knowledge', + optional: false, + }, + ], + }, + kb_ids: ['985eda244efc11ef9a7a0242ac120006'], + llm_id: 'qwen-plus', + llm_setting: { + temperature: 0.1, + top_p: 0.3, + presence_penalty: 0.4, + frequency_penalty: 0.7, + max_tokens: 512, + }, + similarity_threshold: 0.2, + vector_similarity_weight: 0.30000000000000004, + top_n: 8, + }); + const formRef = ref(null); + + const rules = { + name: [ + { + required: true, + message: '鍚嶇О涓嶅厑璁镐负绌�', + }, + ], + }; + + const handleSubmit = ({ values, errors }) => { + console.log('values:', values, '\nerrors:', errors); + if (!errors) { + editAgentKuai.value.handleClick(form); + } + }; + + const handleClick = () => { + visible.value = true; + }; + defineExpose({ + handleClick, + }); + + const handleCancel = () => { + visible.value = false; + formRef.value.resetFields(); + form.name = ''; + }; + + const handleOpened = (el) => { + // Object.assign(form,{ + // name: '',// 鐢ㄦ埛鍚� + // nameJoin: '',// 鏄电О + // post: '',// 宀椾綅 + // txt: '',// 澶囨敞 + // }); + formRef.value.resetFields(); + form.name = ''; + form.prompt_config.system = + '绀轰緥锛歕n' + + '浣犳槸 XX锛屽叿鏈� XX 缁忛獙锛屾搮闀� XX锛屸�n' + + '浣犵殑浠诲姟鏄� XX 锛岄渶瑕佹寜鐓т互涓嬫楠ゆ墽琛岋細\n' + + '1. XX\n' + + '2. XX\n' + + '3. 鈥n'; + }; + + const file = ref(); + + onBeforeMount(() => {}); + onMounted(() => {}); +</script> diff --git a/src/views/dmx/IntelligentAgent/components/card-wrap.vue b/src/views/dmx/IntelligentAgent/components/card-wrap.vue new file mode 100644 index 0000000..9b876d8 --- /dev/null +++ b/src/views/dmx/IntelligentAgent/components/card-wrap.vue @@ -0,0 +1,204 @@ +<template> + <div class="card-wrap"> + <a-card v-if="loading" :bordered="false" hoverable> + <slot name="skeleton"></slot> + </a-card> + <a-card v-else :bordered="false" hoverable> + <a-space align="start"> + <a-avatar + v-if="icon" + :size="24" + style="margin-right: 8px; background-color: #626aea" + > + <icon-filter /> + </a-avatar> + <a-card-meta> + <template #title> + <a-typography-text style="margin-right: 10px"> + {{ title }} + </a-typography-text> + <template v-if="showTag"> + <a-tag + v-if="open && isExpires === false" + size="small" + color="green" + > + <template #icon> + <icon-check-circle-fill /> + </template> + <span>{{ tagText }}</span> + </a-tag> + <a-tag v-else-if="isExpires" size="small" color="red"> + <template #icon> + <icon-check-circle-fill /> + </template> + <span>{{ expiresTagText }}</span> + </a-tag> + </template> + </template> + <template #description> + {{ description }} + <slot></slot> + </template> + </a-card-meta> + </a-space> + <template #actions> + <a-switch v-if="actionType === 'switch'" v-model="open" /> + <a-space v-else-if="actionType === 'button'"> + <template v-if="isExpires"> + <a-button type="outline" @click="renew"> + {{ expiresText }} + </a-button> + </template> + <template v-else> + <a-button v-if="open" @click="handleToggle"> + {{ closeTxt }} + </a-button> + <a-button v-else-if="!open" type="outline" @click="handleToggle"> + {{ openTxt }} + </a-button> + </template> + </a-space> + <div v-else> + <a-space> + <a-button @click="toggle(false)"> + {{ closeTxt }} + </a-button> + <a-button type="primary" @click="toggle(true)"> + {{ openTxt }} + </a-button> + </a-space> + </div> + </template> + </a-card> + </div> +</template> + +<script lang="ts" setup> + import { ref } from 'vue'; + import { useToggle } from '@vueuse/core'; + + const props = defineProps({ + loading: { + type: Boolean, + default: false, + }, + title: { + type: String, + default: '', + }, + description: { + type: String, + default: '', + }, + actionType: { + type: String, + default: '', + }, + defaultValue: { + type: Boolean, + default: false, + }, + openTxt: { + type: String, + default: '', + }, + closeTxt: { + type: String, + default: '', + }, + expiresText: { + type: String, + default: '', + }, + icon: { + type: String, + default: '', + }, + showTag: { + type: Boolean, + default: true, + }, + tagText: { + type: String, + default: '', + }, + expires: { + type: Boolean, + default: false, + }, + expiresTagText: { + type: String, + default: '', + }, + }); + const [open, toggle] = useToggle(props.defaultValue); + const handleToggle = () => { + toggle(); + }; + const isExpires = ref(props.expires); + const renew = () => { + isExpires.value = false; + }; +</script> + +<style scoped lang="less"> + .card-wrap { + height: 100%; + transition: all 0.3s; + border: 1px solid var(--color-neutral-3); + border-radius: 4px; + &:hover { + transform: translateY(-4px); + // box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1); + } + :deep(.arco-card) { + height: 100%; + border-radius: 4px; + .arco-card-body { + height: 100%; + .arco-space { + width: 100%; + height: 100%; + .arco-space-item { + height: 100%; + &:last-child { + flex: 1; + } + .arco-card-meta { + height: 100%; + display: flex; + flex-flow: column; + .arco-card-meta-content { + flex: 1; + .arco-card-meta-description { + margin-top: 8px; + color: rgb(var(--gray-6)); + line-height: 20px; + font-size: 12px; + } + } + .arco-card-meta-footer { + margin-top: 0; + } + } + } + } + } + } + :deep(.arco-card-meta-title) { + display: flex; + align-items: center; + + // To prevent the shaking + line-height: 28px; + } + :deep(.arco-skeleton-line) { + &:last-child { + display: flex; + justify-content: flex-end; + margin-top: 20px; + } + } + } +</style> diff --git a/src/views/dmx/IntelligentAgent/components/custom-settings.vue b/src/views/dmx/IntelligentAgent/components/custom-settings.vue new file mode 100644 index 0000000..808f80f --- /dev/null +++ b/src/views/dmx/IntelligentAgent/components/custom-settings.vue @@ -0,0 +1,244 @@ +<template> + <div class="list-wrap"> + <a-typography-title class="block-title" :heading="6"> + {{ $t('cardList.tab.title.content') }} + </a-typography-title> + <a-button class="add-button" type="primary" @click="addCard">娣诲姞</a-button> + + <a-row class="list-row" :gutter="24"> + <a-col + :xs="12" + :sm="12" + :md="12" + :lg="6" + :xl="6" + :xxl="6" + class="list-col" + > + <div class="card-wrap empty-wrap"> + <a-card :bordered="false" hoverable> + <a-result :status="null" title="Xinference妯″瀷鏄釜寰堝帀瀹崇殑妯″瀷"> + <template #icon> + <icon-plus style="font-size: 20px" /> + </template> + </a-result> + </a-card> + </div> + </a-col> + <a-col + v-for="item in renderData" + :key="item.id" + class="list-col" + :xs="12" + :sm="12" + :md="12" + :lg="6" + :xl="6" + :xxl="6" + > + <CardWrap + :loading="loading" + :title="item.title" + :description="item.description" + :default-value="item.enable" + :action-type="item.actionType" + :icon="item.icon" + :open-txt="$t('cardList.content.inspection')" + :close-txt="$t('cardList.content.delete')" + :show-tag="false" + > + <a-descriptions + style="margin-top: 16px" + :data="item.data" + layout="inline-horizontal" + :column="2" + /> + <template #skeleton> + <a-skeleton :animation="true"> + <a-skeleton-line + :widths="['50%', '50%', '100%', '40%']" + :rows="4" + /> + <a-skeleton-line :widths="['40%']" :rows="1" /> + </a-skeleton> + </template> + </CardWrap> + </a-col> + </a-row> + + <a-modal v-model:visible="visible" @Ok="handleOk" @cancel="handleCancel"> + <template #title> 娣诲姞LLM </template> + <a-form + ref="formRef" + :size="form.size" + :model="form" + auto-label-width + @submit="handleSubmit" + > + <a-form-item + field="type" + label="妯″瀷绫诲瀷" + :rules="[{ required: true, message: '涓嶈兘涓虹┖' }]" + :validate-trigger="['change', 'input']" + > + <a-select + v-model="form.type" + placeholder="璇烽�夋嫨妯″瀷绫诲瀷" + allow-clear + > + <a-option>chartGpt 4</a-option> + <a-option>chartGpt o</a-option> + <a-option>LLM</a-option> + </a-select> + </a-form-item> + + <a-form-item + field="UID" + label="妯″瀷UID" + :rules="[ + { required: true, message: '涓嶈兘涓虹┖' }, + { minLength: 1, message: '鑷冲皯涓�涓瓧绗�' }, + ]" + :validate-trigger="['change', 'input']" + > + <a-input v-model="form.UID" placeholder="璇疯緭鍏ユā鍨婾ID" /> + </a-form-item> + + <a-form-item + field="Url" + label="鍩虹Url" + :rules="[ + { required: true, message: '涓嶈兘涓虹┖' }, + { minLength: 1, message: '鑷冲皯涓�涓瓧绗�' }, + ]" + :validate-trigger="['change', 'input']" + > + <a-input v-model="form.Url" placeholder="璇疯緭鍏ュ熀纭�Url" /> + </a-form-item> + + <a-form-item + field="vision" + label="鏄惁鏀寔 vision" + :validate-trigger="['change', 'input']" + > + <a-switch v-model="form.vision" /> + </a-form-item> + </a-form> + </a-modal> + </div> +</template> + +<script lang="ts" setup> + import { nextTick, reactive, ref } from 'vue'; + import { queryInspectionList, ServiceRecord } from '@/api/list'; + import useRequest from '@/hooks/request'; + import CardWrap from './card-wrap.vue'; + + const defaultValue: ServiceRecord[] = new Array(3).fill({}); + const { loading, response: renderData } = useRequest<ServiceRecord[]>( + queryInspectionList, + defaultValue + ); + const visible = ref(false); + const addCard = () => { + visible.value = true; + }; + + const formRef = ref(null); + const form = reactive({ + size: 'medium', + type: '', + UID: '', + Url: '', + vision: false, + }); + const handleOk = () => { + formRef.value.validate().then((res) => { + if (res) { + return; + } + renderData.value = renderData.value.concat({ + id: renderData.value.length + 1, + title: form.type, + description: form.Url, + icon: 'icon-setting', + actionType: 'inspection', + enable: true, + data: [ + { + label: '寰呰川妫�鏁�', + value: '120', + }, + { + label: '绉帇鏃堕暱', + value: '60s', + }, + { + label: '寰呮娊妫�鏁�', + value: '0', + }, + ], + }); + visible.value = false; + }); + nextTick(() => { + visible.value = true; + }); + return false; + }; + const handleCancel = () => { + formRef.value.resetFields(); + visible.value = false; + }; +</script> + +<style scoped lang="less"> + .card-wrap { + height: 100%; + transition: all 0.3s; + border: 1px solid var(--color-neutral-3); + &:hover { + transform: translateY(-4px); + } + :deep(.arco-card-meta-description) { + color: rgb(var(--gray-6)); + .arco-descriptions-item-label-inline { + font-weight: normal; + font-size: 12px; + color: rgb(var(--gray-6)); + } + .arco-descriptions-item-value-inline { + color: rgb(var(--gray-8)); + } + } + } + .empty-wrap { + height: 200px; + border-radius: 4px; + :deep(.arco-card) { + height: 100%; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + .arco-result-title { + color: rgb(var(--gray-6)); + } + } + } + + .list-wrap { + position: relative; + + ::v-deep .block-title { + height: 36px; + lin-height: 36px; + } + + .add-button { + position: absolute; + right: 20px; + top: 0; + } + } +</style> diff --git a/src/views/dmx/IntelligentAgent/components/editAgent.vue b/src/views/dmx/IntelligentAgent/components/editAgent.vue new file mode 100644 index 0000000..6e140ad --- /dev/null +++ b/src/views/dmx/IntelligentAgent/components/editAgent.vue @@ -0,0 +1,351 @@ +<template> + <a-button + v-if="typeAngint == 'edit'" + type="text" + size="small" + @click="editClick" + > + <template #icon> + <icon-tool /> + </template> + </a-button> + <!-- <a-button v-if="typeAngint=='add'" style="margin-left: 10px" type="primary" @click="handleClick">纭畾</a-button>--> + <a-modal + v-model:visible="visible" + title="" + @before-open="handleOpened" + @cancel="handleCancel" + :footer="false" + title-align="start" + fullscreen + > + <div class="main-container"> + <div class="main-container-lf"> + <div style="padding: 10px; font-size: 16px; background: #eeeeee" + >鏅鸿兘浣撻厤缃�</div + > + <div style="display: flex; width: 100%" :style="{ height: height }"> + <div style="width: 50%; height: 100%"> + <div style="padding: 10px; font-size: 12px; color: #2a2a2b" + >鏅鸿兘浣撶敾鍍�</div + > + <div> + <a-textarea + v-model="system" + placeholder="" + disabled + style="height: 400px; background: #ffffff; color: #666666" + /> + </div> + </div> + <div style="background: #eeeeee; width: 50%"> + <a-form + ref="formRef" + :rules="rules" + :model="form" + @submit="handleSubmit" + layout="vertical" + > + <a-collapse :default-active-key="['1']"> + <a-collapse-item + header="鍩虹淇℃伅" + key="0" + v-if="typeAngint == 'edit'" + > + <a-input + v-model="form.name" + placeholder="璇疯緭鍏ユ櫤鑳戒綋鍚嶇О" + style="width: 200px; margin-top: 10px" + /> + </a-collapse-item> + <a-collapse-item header="AI妯″瀷閰嶇疆" key="1"> + <a-space direction="vertical" size="large"> + <a-select + :size="'large'" + v-model="form.llm_id" + :style="{ width: '25rem' }" + placeholder="璇烽�夋嫨 ..." + > + <a-optgroup + :label="index" + v-for="(item, index) in modelList" + :key="index" + > + <a-option + v-for="obj in item" + :key="obj.fid" + :value="obj.llm_id" + > + {{ obj.llm_name }} + </a-option> + </a-optgroup> + </a-select> + </a-space> + </a-collapse-item> + <a-collapse-item header="寮�鍦哄紩瀵�" :key="'2'" disabled> + </a-collapse-item> + <a-collapse-item header="鐭ヨ瘑搴�" key="3"> + <a-select + v-model="form.kb_ids" + :style="{ width: '25rem' }" + placeholder="璇烽�夋嫨 ..." + multiple + > + <a-option + v-for="item in tabs" + :key="item.id" + :value="item.id" + >{{ item.name }}</a-option + > + </a-select> + </a-collapse-item> + <a-collapse-item header="宸ュ叿" key="4" disabled> + </a-collapse-item> + <a-collapse-item header="宸ヤ綔娴�" key="5" disabled> + </a-collapse-item> + </a-collapse> + + <a-form-item> + <div + style=" + position: absolute; + right: 10px; + top: 0px; + z-index: 99999; + " + > + <!-- <a-button @click="visible = false">鍙栨秷</a-button>--> + <a-button + style="margin-left: 10px" + type="primary" + html-type="submit" + >淇濆瓨</a-button + > + </div> + </a-form-item> + </a-form> + </div> + </div> + </div> + <div class="main-container-rt"> + <div :style="{ height: heightrg }"> + <div style="padding: 10px"> + <a-avatar :style="{ backgroundColor: '#3370ff' }"> + <img + :style="{ width: '100%' }" + alt="dessert" + src="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a20012a2d4d5b9db43dfc6a01fe508c0.png~tplv-uwbnlip3yd-webp.webp" + /> + </a-avatar> + 璋冭瘯棰勮 + </div> + <a-divider style="margin: 0; margin-left: 10px" /> + + <div class="bottom"> + <div class="input"> + <a-input placeholder="杈撳叆鎮ㄦ兂浜嗚В鐨勫唴瀹癸紝鎸塃nter鍙戦��"> + <template #suffix> + <icon-send style="cursor: pointer" /> + </template> </a-input + ></div> + <div class="text">鍐呭鐢盇I鐢熸垚锛屼粎渚涘弬鑰�</div> + </div> + </div> + </div> + </div> + </a-modal> +</template> + +<script lang="ts" setup> + import { onMounted, onBeforeMount, reactive, ref, nextTick } from 'vue'; + import { IconSend } from '@arco-design/web-vue/es/icon'; + import { queryKbList, queryModelList } from '@/api/kbList'; + import useLoading from '@/hooks/loading'; + import { dialogSet } from '@/api/Agent'; + import { Message } from '@arco-design/web-vue'; + const { setLoading } = useLoading(true); + const props = defineProps(['typeAngint', 'formData']); + const visible = ref(false); + const loading = ref(false); + const form = reactive({ + name: '', + icon: '', + language: 'English', + prompt_config: { + empty_response: '', + prologue: '浣犲ソ锛� 鎴戞槸浣犵殑鍔╃悊锛屾湁浠�涔堝彲浠ュ府鍒颁綘鐨勫悧锛�', + quote: true, + self_rag: true, + system: + '绀轰緥锛歕n' + + '浣犳槸 XX锛屽叿鏈� XX 缁忛獙锛屾搮闀� XX锛屸�n' + + '浣犵殑浠诲姟鏄� XX 锛岄渶瑕佹寜鐓т互涓嬫楠ゆ墽琛岋細\n' + + '1. XX\n' + + '2. XX\n' + + '3. 鈥n', + parameters: [ + { + key: 'knowledge', + optional: false, + }, + ], + }, + kb_ids: ['985eda244efc11ef9a7a0242ac120006'], + llm_id: 'qwen-plus', + llm_setting: { + temperature: 0.1, + top_p: 0.3, + presence_penalty: 0.4, + frequency_penalty: 0.7, + max_tokens: 512, + }, + similarity_threshold: 0.2, + vector_similarity_weight: 0.30000000000000004, + top_n: 8, + }); + const system = ref(''); + const embdId = ref(''); + const modelList = ref({}); + const renderData = ref([]); + const formRef = ref(null); + let tabs = ref([]); + const height = ref('calc(100vh - 150px)'); + const heightrg = ref('calc(100vh - 100px)'); + const emit = defineEmits(['cancelModal']); + const rules = { + name: [ + { + required: true, + message: '鍚嶇О涓嶅厑璁镐负绌�', + }, + ], + }; + + const handleSubmit = async ({ values, errors }) => { + // console.log('values:', values, '\nerrors:', errors) + let title = '鍒涘缓鎴愬姛'; + let formNew = { ...form }; + if (props.typeAngint == 'edit') { + formNew.dialog_id = form.id; + delete formNew.id; + delete formNew.off; + title = '淇敼鎴愬姛'; + } + + const data = await dialogSet(formNew); + if (data.code == 0) { + Message.success(title); + handleCancel(); + } + }; + + const editClick = (data) => { + visible.value = true; + + console.log(props.formData); + Object.assign(form, props.formData); + console.log(form); + system.value = form.prompt_config.system; + }; + + const handleClick = (data) => { + visible.value = true; + nextTick(() => { + Object.assign(form, data); + console.log(form); + system.value = form.prompt_config.system; + }); + }; + defineExpose({ + handleClick, + }); + const handleBeforeOk = (done) => { + formRef.value.validate().then((res) => { + console.log('form:', form); + if (!form.name) { + done(false); + } else { + console.log('璇锋眰鏁版嵁'); + } + }); + }; + const handleCancel = () => { + visible.value = false; + emit('cancelModal'); + }; + + const handleOpened = (el) => { + // formRef.value.resetFields(); + }; + const queryModel = async (params) => { + try { + const data = await queryModelList(params); + console.log(data.data, '澶фā鍨嬪垪琛�'); + modelList.value = data.data; + } catch (err) { + // you can report use errorHandler or other + } finally { + } + }; + const file = ref(); + + const onChange = (_, currentFile) => { + file.value = { + ...currentFile, + // url: URL.createObjectURL(currentFile.file), + }; + }; + const onProgress = (currentFile) => { + file.value = currentFile; + }; + + const knowledgeData = async (params = { page: 1, page_size: 20 }) => { + setLoading(true); + try { + const { data } = await queryKbList(params); + console.log(data, 'data'); + tabs.value = data; + console.log(tabs.value, 'tabs'); + } catch (err) { + // you can report use errorHandler or other + } finally { + setLoading(false); + } + }; + + onBeforeMount(() => { + queryModel({}); + knowledgeData(); + }); + onMounted(() => {}); +</script> + +<style scoped lang="less"> + .main-container { + width: 100%; + display: flex; + .main-container-lf { + width: 60%; + } + .main-container-rt { + position: relative; + width: 40%; + } + } + .bottom { + width: 100%; + position: absolute; + bottom: 40px; + left: 0; + .input { + margin-left: 20%; + width: 60%; + } + .text { + margin-left: 40%; + font-size: 12px; + color: lightgrey; + line-height: 40px; + } + } +</style> diff --git a/src/views/dmx/IntelligentAgent/components/quality-inspection.vue b/src/views/dmx/IntelligentAgent/components/quality-inspection.vue new file mode 100644 index 0000000..88167b6 --- /dev/null +++ b/src/views/dmx/IntelligentAgent/components/quality-inspection.vue @@ -0,0 +1,115 @@ +<template> + <div class="list-wrap"> + <a-typography-title class="block-title" :heading="6"> + {{ $t('cardList.tab.title.content') }} + </a-typography-title> + <a-row class="list-row" :gutter="24"> + <a-col + :xs="12" + :sm="12" + :md="12" + :lg="6" + :xl="6" + :xxl="6" + class="list-col" + > + <div class="card-wrap empty-wrap"> + <a-card :bordered="false" hoverable> + <a-result :status="null" :title="$t('cardList.content.action')"> + <template #icon> + <icon-plus style="font-size: 20px" /> + </template> + </a-result> + </a-card> + </div> + </a-col> + <a-col + v-for="item in renderData" + :key="item.id" + class="list-col" + :xs="12" + :sm="12" + :md="12" + :lg="6" + :xl="6" + :xxl="6" + > + <CardWrap + :loading="loading" + :title="item.title" + :description="item.description" + :default-value="item.enable" + :action-type="item.actionType" + :icon="item.icon" + :open-txt="$t('cardList.content.inspection')" + :close-txt="$t('cardList.content.delete')" + :show-tag="false" + > + <a-descriptions + style="margin-top: 16px" + :data="item.data" + layout="inline-horizontal" + :column="2" + /> + <template #skeleton> + <a-skeleton :animation="true"> + <a-skeleton-line + :widths="['50%', '50%', '100%', '40%']" + :rows="4" + /> + <a-skeleton-line :widths="['40%']" :rows="1" /> + </a-skeleton> + </template> + </CardWrap> + </a-col> + </a-row> + </div> +</template> + +<script lang="ts" setup> + import { queryInspectionList, ServiceRecord } from '@/api/list'; + import useRequest from '@/hooks/request'; + import CardWrap from './card-wrap.vue'; + + const defaultValue: ServiceRecord[] = new Array(3).fill({}); + const { loading, response: renderData } = useRequest<ServiceRecord[]>( + queryInspectionList, + defaultValue + ); +</script> + +<style scoped lang="less"> + .card-wrap { + height: 100%; + transition: all 0.3s; + border: 1px solid var(--color-neutral-3); + &:hover { + transform: translateY(-4px); + } + :deep(.arco-card-meta-description) { + color: rgb(var(--gray-6)); + .arco-descriptions-item-label-inline { + font-weight: normal; + font-size: 12px; + color: rgb(var(--gray-6)); + } + .arco-descriptions-item-value-inline { + color: rgb(var(--gray-8)); + } + } + } + .empty-wrap { + height: 200px; + border-radius: 4px; + :deep(.arco-card) { + height: 100%; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + .arco-result-title { + color: rgb(var(--gray-6)); + } + } + } +</style> diff --git a/src/views/dmx/IntelligentAgent/components/rules-preset.vue b/src/views/dmx/IntelligentAgent/components/rules-preset.vue new file mode 100644 index 0000000..e5a2878 --- /dev/null +++ b/src/views/dmx/IntelligentAgent/components/rules-preset.vue @@ -0,0 +1,51 @@ +<template> + <div class="list-wrap"> + <a-typography-title class="block-title" :heading="6"> + {{ $t('cardList.tab.title.preset') }} + </a-typography-title> + <a-row class="list-row" :gutter="24"> + <a-col + v-for="item in renderData" + :key="item.id" + :xs="12" + :sm="12" + :md="12" + :lg="6" + :xl="6" + :xxl="6" + class="list-col" + style="min-height: 140px" + > + <CardWrap + :loading="loading" + :title="item.title" + :description="item.description" + :default-value="item.enable" + :action-type="item.actionType" + :tag-text="$t('cardList.preset.tag')" + > + <template #skeleton> + <a-skeleton :animation="true"> + <a-skeleton-line :widths="['100%', '40%']" :rows="2" /> + <a-skeleton-line :widths="['40%']" :rows="1" /> + </a-skeleton> + </template> + </CardWrap> + </a-col> + </a-row> + </div> +</template> + +<script lang="ts" setup> + import { queryRulesPresetList, ServiceRecord } from '@/api/list'; + import useRequest from '@/hooks/request'; + import CardWrap from './card-wrap.vue'; + + const defaultValue: ServiceRecord[] = new Array(6).fill({}); + const { loading, response: renderData } = useRequest<ServiceRecord[]>( + queryRulesPresetList, + defaultValue + ); +</script> + +<style scoped lang="less"></style> diff --git a/src/views/dmx/IntelligentAgent/components/the-service.vue b/src/views/dmx/IntelligentAgent/components/the-service.vue new file mode 100644 index 0000000..2f4748e --- /dev/null +++ b/src/views/dmx/IntelligentAgent/components/the-service.vue @@ -0,0 +1,57 @@ +<template> + <div class="list-wrap"> + <a-typography-title class="block-title" :heading="6"> + {{ $t('cardList.tab.title.service') }} + </a-typography-title> + <a-row class="list-row" :gutter="24"> + <a-col + v-for="item in renderData" + :key="item.id" + :xs="12" + :sm="12" + :md="12" + :lg="6" + :xl="6" + :xxl="6" + class="list-col" + style="min-height: 162px" + > + <CardWrap + :loading="loading" + :title="item.title" + :description="item.description" + :default-value="item.enable" + :action-type="item.actionType" + :expires="item.expires" + :open-txt="$t('cardList.service.open')" + :close-txt="$t('cardList.service.cancel')" + :expires-text="$t('cardList.service.renew')" + :tag-text="$t('cardList.service.tag')" + :expires-tag-text="$t('cardList.service.expiresTag')" + :icon="item.icon" + > + <template #skeleton> + <a-skeleton :animation="true"> + <a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" /> + <a-skeleton-line :widths="['40%']" :rows="1" /> + </a-skeleton> + </template> + </CardWrap> + </a-col> + </a-row> + </div> +</template> + +<script lang="ts" setup> + import { queryTheServiceList, ServiceRecord } from '@/api/list'; + import useRequest from '@/hooks/request'; + import CardWrap from './card-wrap.vue'; + + const defaultValue: ServiceRecord[] = new Array(4).fill({}); + const { loading, response: renderData } = useRequest<ServiceRecord[]>( + queryTheServiceList, + defaultValue + ); +</script> + +<style scoped lang="less"></style> diff --git a/src/views/dmx/IntelligentAgent/index.vue b/src/views/dmx/IntelligentAgent/index.vue new file mode 100644 index 0000000..6954a65 --- /dev/null +++ b/src/views/dmx/IntelligentAgent/index.vue @@ -0,0 +1,341 @@ +<template> + <div class="container"> + <Breadcrumb :items="['澶фā鍨�', '鏅鸿兘浣撶鐞�']" /> + <a-row :gutter="20" align="stretch"> + <a-col :span="24"> + <a-card class="general-card" :title="$t('鏅鸿兘浣撶鐞�')"> + <div style="display: flex; justify-content: right"> + <a-input-search + :placeholder="$t('cardList.searchInput.placeholder')" + style="width: 240px" + @change="queryList" + /> + </div> + <a-divider style="margin: 10px 0" /> + <a-row justify="space-between"> + <a-col :span="24"> + <div style="display: flex; flex-wrap: wrap"> + <div + class="card-wrap" + style="cursor: pointer" + @click="handleAdd" + > + <a-card :bordered="false" hoverable> + <div style="margin-top: 30px; text-align: center"> + <a-avatar style="background: #3370ff"> + <icon-plus /> + </a-avatar> + </div> + <div class="arco-card-body-content"> + <div style="text-align: center; margin-top: 10px"> + 鏂板缓鏅鸿兘浣� + </div> + <div + style=" + text-align: center; + margin-top: 10px; + font-size: 12px; + color: #999999; + " + > + 閫氳繃鎻忚堪瑙掕壊鍜屼换鍔℃潵鍒涘缓浣犵殑鏅鸿兘浣�<br /> + 鏅鸿兘浣撳彲浠ヨ皟鐢ㄥ涓伐浣滄祦鍜屽伐鍏� + </div> + </div> + <add-agent ref="addAgents"></add-agent> + <!-- <div style="position: absolute; bottom: 1rem; right: 1rem;">--> + <!-- <a-space>--> + <!-- </a-space>--> + <!-- </div>--> + </a-card> + </div> + <div + class="card-wrap" + v-for="(item, index) of agentList" + :key="item.id" + > + <a-card :bordered="false" hoverable> + <a-avatar :style="{ backgroundColor: '#3370ff' }"> + <img + :style="{ width: '100%' }" + alt="dessert" + src="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/a20012a2d4d5b9db43dfc6a01fe508c0.png~tplv-uwbnlip3yd-webp.webp" + /> + </a-avatar> + <a-switch + v-model="item.off" + style="position: absolute; top: 10px; right: 10px" + size="medium" + @change="handleChange(item)" + > + <template #checked> 涓婄嚎 </template> + <template #unchecked> 涓嬬嚎 </template> + </a-switch> + <div class="arco-card-body-content"> + <div class="arco-card-body-content-top"> + <span style="font-size: 18px; font-weight: 900"> + {{ item.name }} + </span> + </div> + <div class="arco-card-body-content-down"> + {{ item.prompt_config.prologue }} + </div> + </div> + <div style="position: absolute; bottom: 1.4rem; left: 1rem"> + <icon-user /> + <span style="font-size: 12px"> + <!-- {{ item.name }}--> + </span> + </div> + <div style="position: absolute; bottom: 1rem; right: 1rem"> + <a-space> + <span v-show="!item.off"> + <editAgent + ref="editAgentKuai" + typeAngint="edit" + :formData="form" + @cancelModal="handleCancel" + ></editAgent> + </span> + <a-popconfirm + :content="'纭畾鍒犻櫎鍚�'" + type="warning" + @ok="deleteItem(item)" + > + <a-button type="text" size="small"> + <template #icon> + <icon-delete /> + </template> + </a-button> + </a-popconfirm> + </a-space> + </div> + </a-card> + </div> + </div> + </a-col> + </a-row> + </a-card> + </a-col> + </a-row> + </div> +</template> + +<script lang="ts" setup> + import { ref, reactive, nextTick, onBeforeMount } from 'vue'; + import addAgent from '@/views/dmx/IntelligentAgent/components/addAgent.vue'; + import editAgent from '@/views/dmx/IntelligentAgent/components/editAgent.vue'; + import { kbdocumentrm, queryKbList } from '@/api/kbList'; + import { Message } from '@arco-design/web-vue'; + import { deletedialog, querydialogList } from '@/api/Agent'; + import useLoading from '@/hooks/loading'; + const { loading, setLoading } = useLoading(true); + + let count = 5; + const activeKey = ref(1); + const addAgents = ref(); + const editAgentKuai = ref(); + const agentList = ref([ + // { + // key: 2, + // title: '鍐呭璐ㄦ', + // content: 'Content of Tab Panel 2', + // }, + // { + // key: 3, + // title: '寮�閫氭湇鍔�', + // content: 'Content of Tab Panel 3', + // }, + // { + // key: 4, + // title: '瑙勫垯棰勭疆', + // content: 'Content of Tab Panel 4', + // }, + ]); + const changeTabs = (val) => { + activeKey.value = val; + }; + const handleAdd = () => { + addAgents.value.handleClick(); + }; + const handleDelete = (key: any) => { + data.value = data.value.filter((item) => item.key !== key); + }; + + const visible = ref(false); + const formRef = ref(null); + const form = reactive({ + // size: 'medium', + // name: '', + }); + + const queryList = async (params = {}) => { + setLoading(true); + try { + const { data } = await querydialogList(params); + console.log(data, 'data'); + agentList.value = data.map((item) => { + return { + ...item, + off: true, + }; + }); + } catch (err) { + // you can report use errorHandler or other + } finally { + setLoading(false); + } + }; + + const deleteItem = async (row) => { + console.log(row); + let data = await deletedialog({ dialog_ids: [row.id] }); + if (data.code == 0) { + Message.success('鍒犻櫎鎴愬姛'); + queryList(); + } + }; + const handleChange = async (item) => { + if (item) { + Object.assign(form, item); + } + }; + const handleCancel = () => { + queryList(); + }; + const handleSubmit = ({ values, errors }) => { + this.$refs.formRef.validate().then((res, a, b) => { + debugger; + console.log('values', values); + }); + }; + onBeforeMount(() => { + queryList(); + }); +</script> + +<script lang="ts"> + export default { + name: 'Card', + }; +</script> + +<style scoped lang="less"> + .container { + padding: 0 20px 20px 20px; + :deep(.arco-list-content) { + overflow-x: hidden; + } + + :deep(.arco-card-meta-title) { + font-size: 14px; + } + } + :deep(.arco-list-col) { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + } + + :deep(.arco-list-item) { + width: 33%; + } + + :deep(.block-title) { + margin: 0 0 12px 0; + font-size: 14px; + } + :deep(.list-wrap) { + // min-height: 140px; + .list-row { + align-items: stretch; + .list-col { + margin-bottom: 16px; + } + } + :deep(.arco-space) { + width: 100%; + .arco-space-item { + &:last-child { + flex: 1; + } + } + } + } + .card-wrap { + width: 23%; + height: 200px; + margin: 1%; + transition: all 0.3s; + border: 1px solid var(--color-neutral-3); + border-radius: 4px; + position: relative; + &:hover { + transform: translateY(-4px); + // box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1); + } + :deep(.arco-card) { + height: 100%; + border-radius: 4px; + .arco-card-body { + height: 100%; + .arco-space { + width: 100%; + height: 100%; + .arco-space-item { + height: 100%; + &:last-child { + flex: 1; + } + .arco-card-meta { + height: 100%; + display: flex; + flex-flow: column; + .arco-card-meta-content { + flex: 1; + .arco-card-meta-description { + margin-top: 8px; + color: rgb(var(--gray-6)); + line-height: 20px; + font-size: 12px; + } + } + .arco-card-meta-footer { + margin-top: 0; + } + } + } + } + } + } + :deep(.arco-card-meta-title) { + display: flex; + align-items: center; + + // To prevent the shaking + line-height: 28px; + } + :deep(.arco-skeleton-line) { + &:last-child { + display: flex; + justify-content: flex-end; + margin-top: 20px; + } + } + } + .arco-card-body-content { + .arco-card-body-content-top { + margin-top: 10px; + text-align: center; + } + .arco-card-body-content-down { + text-align: center; + margin-top: 10px; + font-size: 12px; + color: #999999; + width: 100%; + height: 60px; + } + } +</style> diff --git a/src/views/dmx/IntelligentAgent/locale/en-US.ts b/src/views/dmx/IntelligentAgent/locale/en-US.ts new file mode 100644 index 0000000..04cddd0 --- /dev/null +++ b/src/views/dmx/IntelligentAgent/locale/en-US.ts @@ -0,0 +1,20 @@ +export default { + // 'menu.list.cardList': 'Card List', + 'menu.dmx.setting': 'GPT Setting', + 'cardList.tab.title.all': 'All', + 'cardList.tab.title.content': 'Quality Inspection', + 'cardList.tab.title.service': 'The service', + 'cardList.tab.title.preset': 'Rules Preset', + 'cardList.searchInput.placeholder': 'Search', + 'cardList.enable': 'Enable', + 'cardList.disable': 'Disable', + 'cardList.content.delete': 'Delete', + 'cardList.content.inspection': 'Inspection', + 'cardList.content.action': 'Click Create Qc Content queue', + 'cardList.service.open': 'Open', + 'cardList.service.cancel': 'Cancel', + 'cardList.service.renew': 'Contract of service', + 'cardList.service.tag': 'Opened', + 'cardList.service.expiresTag': 'Expired', + 'cardList.preset.tag': 'Enable', +}; diff --git a/src/views/dmx/IntelligentAgent/locale/zh-CN.ts b/src/views/dmx/IntelligentAgent/locale/zh-CN.ts new file mode 100644 index 0000000..49a4478 --- /dev/null +++ b/src/views/dmx/IntelligentAgent/locale/zh-CN.ts @@ -0,0 +1,20 @@ +export default { + // 'menu.list.cardList': '鍗$墖鍒楄〃', + 'menu.dmx.setting': '澶фā鍨嬭缃�', + 'cardList.tab.title.all': '鍏ㄩ儴', + 'cardList.tab.title.content': '鍐呭璐ㄦ', + 'cardList.tab.title.service': '寮�閫氭湇鍔�', + 'cardList.tab.title.preset': '瑙勫垯棰勭疆', + 'cardList.searchInput.placeholder': '鎼滅储', + // 'cardList.statistic.enable': '宸插惎鐢�', + // 'cardList.statistic.disable': '鏈惎鐢�', + 'cardList.content.delete': '鍒犻櫎', + 'cardList.content.inspection': '璐ㄦ', + 'cardList.content.action': '鐐瑰嚮鍒涘缓璐ㄦ鍐呭闃熷垪', + 'cardList.service.open': '寮�閫氭湇鍔�', + 'cardList.service.cancel': '鍙栨秷鏈嶅姟', + 'cardList.service.renew': '缁害鏈嶅姟', + 'cardList.service.tag': '宸插紑閫�', + 'cardList.service.expiresTag': '宸茶繃鏈�', + 'cardList.preset.tag': '宸插惎鐢�', +}; diff --git a/src/views/dmx/IntelligentAgent/mock.ts b/src/views/dmx/IntelligentAgent/mock.ts new file mode 100644 index 0000000..68cf096 --- /dev/null +++ b/src/views/dmx/IntelligentAgent/mock.ts @@ -0,0 +1,186 @@ +import Mock from 'mockjs'; +import setupMock, { successResponseWrap } from '@/utils/setup-mock'; +import { ServiceRecord } from '@/api/list'; + +const qualityInspectionList: ServiceRecord[] = [ + { + id: 1, + name: 'quality', + title: '瑙嗛绫�-鍘嗗彶瀵煎叆', + description: '2021-10-12 00:00:00', + data: [ + { + label: '寰呰川妫�鏁�', + value: '120', + }, + { + label: '绉帇鏃堕暱', + value: '60s', + }, + { + label: '寰呮娊妫�鏁�', + value: '0', + }, + ], + }, + { + id: 2, + name: 'quality', + title: '鍥炬枃绫�-鍥剧墖鐗堟潈', + description: '2021-12-11 18:30:00', + data: [ + { + label: '寰呰川妫�鏁�', + value: '120', + }, + { + label: '绉帇鏃堕暱', + value: '60s', + }, + { + label: '寰呮娊妫�鏁�', + value: '0', + }, + ], + }, + { + id: 3, + name: 'quality', + title: '鍥炬枃绫�-楂樻竻鍥剧墖', + description: '2021-10-15 08:10:00', + data: [ + { + label: '寰呰川妫�鏁�', + value: '120', + }, + { + label: '绉帇鏃堕暱', + value: '60s', + }, + { + label: '寰呮娊妫�鏁�', + value: '0', + }, + ], + }, +]; +const theServiceList: ServiceRecord[] = [ + { + id: 1, + icon: 'code', + title: '婕忔枟鍒嗘瀽', + description: + '鐢ㄦ埛琛屼负鍒嗘瀽涔嬫紡鏂楀垎鏋愭ā鍨嬫槸浼佷笟瀹炵幇绮剧粏鍖栬繍钀ャ�佽繘琛岀敤鎴疯涓哄垎鏋愮殑閲嶈鏁版嵁鍒嗘瀽妯″瀷銆�', + enable: true, + actionType: 'button', + }, + { + id: 2, + icon: 'edit', + title: '鐢ㄦ埛鍒嗗竷', + description: + '蹇�熻瘖鏂敤鎴蜂汉缇わ紝鍦板煙缁嗗垎鎯呭喌锛屼簡瑙f暟鎹垎甯冪殑闆嗕腑搴︼紝浠ュ強涓昏鐨勬暟鎹垎甯冪殑鍖洪棿娈垫槸浠�涔堛��', + enable: true, + actionType: 'button', + expires: true, + }, + { + id: 3, + icon: 'user', + title: '璧勬簮鍒嗗彂', + description: + '绉诲姩绔姩鎬佸寲璧勬簮鍒嗗彂瑙e喅鏂规銆傛彁渚涚ǔ瀹氬ぇ娴侀噺鏈嶅姟鏀寔銆佺伒娲诲畾鍒剁殑鍒嗗彂鍦堥�夎鍒欙紝閫氳繃绂荤嚎鍖栭鍔犺浇銆�', + enable: false, + actionType: 'button', + }, + { + id: 4, + icon: 'user', + title: '鐢ㄦ埛鐢诲儚鍒嗘瀽', + description: + '鐢ㄦ埛鐢诲儚灏辨槸灏嗗吀鍨嬬敤鎴蜂俊鎭爣绛惧寲锛屾牴鎹敤鎴风壒寰併�佷笟鍔″満鏅拰鐢ㄦ埛琛屼负绛変俊鎭紝鏋勫缓涓�涓爣绛惧寲鐨勭敤鎴锋ā鍨嬨��', + enable: true, + actionType: 'button', + }, +]; +const rulesPresetList: ServiceRecord[] = [ + { + id: 1, + title: '鍐呭灞忚斀瑙勫垯', + description: + '鐢ㄦ埛鍦ㄦ墽琛岀壒瀹氱殑鍐呭鍒嗗彂浠诲姟鏃讹紝鍙娇鐢ㄥ唴瀹瑰睆钄借鍒欐牴鎹壒瀹氭爣绛撅紝杩囨护鍐呭闆嗗悎銆�', + enable: true, + actionType: 'switch', + }, + { + id: 2, + title: '鍐呭缃《瑙勫垯', + description: + '璇ヨ鍒欐敮鎸佺敤鎴峰湪鎵ц鐗瑰畾鍐呭鍒嗗彂浠诲姟鏃讹紝瀵瑰浐瀹氱殑鍑犳潯鍐呭缃《銆�', + enable: true, + actionType: 'switch', + }, + { + id: 3, + title: '鍐呭鍔犳潈瑙勫垯', + description: '閫夊畾鍐呭鍔犳潈瑙勫垯鍚庡彲鑷畾涔変粠涓嶅悓鍐呭闆嗗悎鑾峰彇鍐呭鐨勬鐜囥��', + enable: false, + actionType: 'switch', + }, + { + id: 4, + title: '鍐呭鍒嗗彂瑙勫垯', + description: '鍐呭鍒嗗彂鏃讹紝瀵规煇浜涘唴瀹归渶瑕佸浐瀹氬湪C绔睍绀虹殑浣嶇疆銆�', + enable: true, + actionType: 'switch', + }, + { + id: 5, + title: '杩濈鍐呭璇嗗埆', + description: '绮惧噯璇嗗埆璧屽崥銆佸垁鏋�佹瘨鍝併�侀�犲亣銆佽穿鍋囩瓑杩濊鐗╁搧鍜岃繚瑙勮涓恒��', + enable: false, + actionType: 'switch', + }, + { + id: 6, + title: '澶氳瑷�鏂囧瓧绗﹀彿璇嗗埆', + description: + '绮惧噯璇嗗埆鑻辫銆佺淮璇�佽棌璇�佽挋鍙よ銆佹湞椴滆绛夊绉嶈瑷�浠ュ強emoji琛ㄦ儏褰㈡�佺殑璇箟璇嗗埆銆�', + enable: false, + actionType: 'switch', + }, +]; + +setupMock({ + setup() { + // Quality Inspection + Mock.mock(new RegExp('/api/list/quality-inspection'), () => { + return successResponseWrap( + qualityInspectionList.map((_, index) => ({ + ...qualityInspectionList[index % qualityInspectionList.length], + id: Mock.Random.guid(), + })) + ); + }); + + // the service + Mock.mock(new RegExp('/api/list/the-service'), () => { + return successResponseWrap( + theServiceList.map((_, index) => ({ + ...theServiceList[index % theServiceList.length], + id: Mock.Random.guid(), + })) + ); + }); + + // rules preset + Mock.mock(new RegExp('/api/list/rules-preset'), () => { + return successResponseWrap( + rulesPresetList.map((_, index) => ({ + ...rulesPresetList[index % rulesPresetList.length], + id: Mock.Random.guid(), + })) + ); + }); + }, +}); diff --git a/src/views/dmx/knowledgeLib/addDetails.vue b/src/views/dmx/knowledgeLib/addDetails.vue index 07db2d2..9285d39 100644 --- a/src/views/dmx/knowledgeLib/addDetails.vue +++ b/src/views/dmx/knowledgeLib/addDetails.vue @@ -1,19 +1,66 @@ - <template> <a-button type="primary" @click="handleClick" style="margin-left: 10px"> <template #icon> <icon-plus /> </template> </a-button> - <a-modal v-model:visible="visible" title="鍒涘缓鐭ヨ瘑搴�" @before-open="handleOpened" @cancel="handleCancel" :footer="false" title-align="start"> - <a-form ref="formRef" :rules="rules" :model="form" @submit="handleSubmit" > - <a-form-item field="name" label="鍚嶇О"> - <a-input v-model="form.name" placeholder="璇疯緭鍏ュ悕绉�"/> + <a-modal + v-model:visible="visible" + title="鍒涘缓瑙f瀽鍧�" + @before-open="handleOpened" + @cancel="handleCancel" + :footer="false" + title-align="start" + > + <a-form + ref="formRef" + :rules="rules" + :model="form" + @submit="handleSubmit" + layout="vertical" + > + <a-form-item field="content_with_weight" label="瑙f瀽鍧�"> + <a-textarea + v-model="form.content_with_weight" + placeholder="" + style="height: 100px" + auto-size + /> </a-form-item> + <a-form-item field="important_kwd_key" label="鍏抽敭璇� *"> + <div style="width: auto"> + <a-tag + v-for="(item, index) in form.important_kwd" + :key="index" + closable + bordered + @close="form.important_kwd.splice(index, 1)" + style="margin-right: 10px" + > + {{ item }} + </a-tag> + + <a-input + ref="formInput" + v-show="keyVisible" + v-model="form.important_kwd_key" + placeholder="" + size="small" + style="width: 80px; margin-right: 16px" + @blur="inputChange" + /> + <a-button type="dashed" shape="circle" size="small" @click="addKey"> + <icon-plus /> + </a-button> + </div> + </a-form-item> + <a-form-item> - <div style="width: 100%;text-align: right"> + <div style="width: 100%; text-align: right"> <a-button @click="visible = false">鍙栨秷</a-button> - <a-button style="margin-left: 10px" type="primary" html-type="submit">纭畾</a-button> + <a-button style="margin-left: 10px" type="primary" html-type="submit" + >纭畾</a-button + > </div> </a-form-item> </a-form> @@ -21,74 +68,80 @@ </template> <script lang="ts" setup> -import { onMounted ,onBeforeMount, reactive, ref } from "vue"; + import { onMounted, onBeforeMount, reactive, ref } from 'vue'; + import { achunkCreate } from '@/api/kbList'; -const visible = ref(false); -const loading = ref(false); -const form = reactive({ - name: '',// 鐢ㄦ埛鍚� - nameJoin: '',// 鏄电О - post: '',// 宀椾綅 - txt: '',// 澶囨敞 -}); -const formRef = ref(null); + const props = defineProps(['item']); -const rules = { - name: [ - { - required: true, - message:'鍚嶇О涓嶅厑璁镐负绌�', - }, - ], -} - - -const handleSubmit = ({values, errors}) => { - console.log('values:', values, '\nerrors:', errors) -} - -const handleClick = () => { - visible.value = true; -}; -const handleBeforeOk = (done) => { - formRef.value.validate().then(res => { - console.log('form:', form) - if (!form.name) { - done(false) - }else { - console.log('璇锋眰鏁版嵁'); - - } - }) -}; -const handleCancel = () => { - visible.value = false; -} - -const handleOpened =(el) => { - Object.assign(form,{ - name: '',// 鐢ㄦ埛鍚� - nameJoin: '',// 鏄电О - post: '',// 宀椾綅 - txt: '',// 澶囨敞 + const visible = ref(false); + const keyVisible = ref(false); + const loading = ref(false); + const form = reactive({ + content_with_weight: '', + important_kwd: [], + important_kwd_key: '', }); - formRef.value.resetFields(); -} + const formRef = ref(null); + const formInput = ref(null); + const rules = { + content_with_weight: [ + { + required: true, + message: '璇疯緭鍏ュ�硷紒', + }, + ], + }; -onBeforeMount(()=>{ + const handleSubmit = async ({ values, errors }) => { + console.log(props.item.id); + if (!errors) { + const res = await achunkCreate({ + content_with_weight: values.content_with_weight, + important_kwd: values.important_kwd, + doc_id: props.item.id, + }); + } + }; -}) -onMounted(()=>{ + const handleClick = () => { + visible.value = true; + }; + const handleBeforeOk = (done) => { + formRef.value.validate().then((res) => { + console.log('form:', form); + }); + }; + const handleCancel = () => { + visible.value = false; + }; + const handleOpened = (el) => { + Object.assign(form, { + content_with_weight: '', + important_kwd: [], + important_kwd_key: '', + }); + formRef.value.resetFields(); + keyVisible.value = false; + }; -}) + const addKey = () => { + form.important_kwd_key = ''; + formInput.value.focus(); + keyVisible.value = true; + }; + + const inputChange = (e) => { + if ( + !form.important_kwd.includes(form.important_kwd_key) && + form.important_kwd_key + ) { + form.important_kwd.push(form.important_kwd_key); + } else { + } + keyVisible.value = false; + }; + + onBeforeMount(() => {}); + onMounted(() => {}); </script> - -<script lang="ts"> -export default { - name: 'add', - methods: { - - } -}; -</script> \ No newline at end of file diff --git a/src/views/dmx/knowledgeLib/components/docx.vue b/src/views/dmx/knowledgeLib/components/docx.vue new file mode 100644 index 0000000..396e03e --- /dev/null +++ b/src/views/dmx/knowledgeLib/components/docx.vue @@ -0,0 +1,42 @@ +<template> + <vue-office-docx + :src="previewSrc" + :style="comStyle" + @rendered="renderedHandler" + @error="errorHandler" + /> +</template> + +<script setup> + // 鑾峰彇鐖剁粍浠朵紶閫掔殑璧勬簮url + const props = defineProps({ + previewSrc: { + type: String, + required: false, + default: () => '', + }, + }); + //寮曞叆VueOfficeDocx缁勪欢鐩稿叧 + import VueOfficeDocx from '@vue-office/docx'; + import '@vue-office/docx/lib/index.css'; + + const comStyle = { + width: '100%', + height: '100%', + }; + + const renderedHandler = () => { + console.log('rendered'); + }; + const errorHandler = (err) => { + console.log('error', err); + }; +</script> + +<style scoped lang="less"> + .aUpload { + position: absolute; + top: 0; + left: 0; + } +</style> diff --git a/src/views/dmx/knowledgeLib/components/excel.vue b/src/views/dmx/knowledgeLib/components/excel.vue new file mode 100644 index 0000000..8735164 --- /dev/null +++ b/src/views/dmx/knowledgeLib/components/excel.vue @@ -0,0 +1,42 @@ +<template> + <vue-office-excel + :src="previewSrc" + :style="comStyle" + @rendered="renderedHandler" + @error="errorHandler" + /> +</template> + +<script setup> + // 鑾峰彇鐖剁粍浠朵紶閫掔殑璧勬簮url + const props = defineProps({ + previewSrc: { + type: String, + required: false, + default: () => '', + }, + }); + //寮曞叆VueOfficeExcel缁勪欢鐩稿叧 + import VueOfficeExcel from '@vue-office/excel'; + import '@vue-office/excel/lib/index.css'; + + const comStyle = { + width: '100%', + height: '100%', + }; + + const renderedHandler = () => { + console.log('rendered'); + }; + const errorHandler = (err) => { + console.log('error', err); + }; +</script> + +<style scoped lang="less"> + .aUpload { + position: absolute; + top: 0; + left: 0; + } +</style> diff --git a/src/views/dmx/knowledgeLib/components/txtPdf.vue b/src/views/dmx/knowledgeLib/components/txtPdf.vue new file mode 100644 index 0000000..a76003a --- /dev/null +++ b/src/views/dmx/knowledgeLib/components/txtPdf.vue @@ -0,0 +1,37 @@ +<template> + <iframe :src="previewSrc"></iframe> +</template> + +<script setup> + // 鑾峰彇鐖剁粍浠朵紶閫掔殑璧勬簮url + const props = defineProps({ + previewSrc: { + type: String, + required: false, + default: () => '', + }, + }); + //寮曞叆VueOfficeExcel缁勪欢鐩稿叧 + import VueOfficeExcel from '@vue-office/excel'; + import '@vue-office/excel/lib/index.css'; + + const comStyle = { + width: '100%', + height: '100%', + }; + + const renderedHandler = () => { + console.log('rendered'); + }; + const errorHandler = (err) => { + console.log('error', err); + }; +</script> + +<style scoped lang="less"> + .aUpload { + position: absolute; + top: 0; + left: 0; + } +</style> diff --git a/src/views/dmx/knowledgeLib/eidtDetails.vue b/src/views/dmx/knowledgeLib/eidtDetails.vue new file mode 100644 index 0000000..68facfa --- /dev/null +++ b/src/views/dmx/knowledgeLib/eidtDetails.vue @@ -0,0 +1,156 @@ +<template> + <a-modal + v-model:visible="visible" + title="缂栬緫瑙f瀽鍧�" + @before-open="handleOpened" + @cancel="handleCancel" + :footer="false" + title-align="start" + > + <a-form + ref="formRef" + :rules="rules" + :model="form" + @submit="handleSubmit" + layout="vertical" + > + <a-form-item field="content_with_weight" label="瑙f瀽鍧�"> + <a-textarea + v-model="form.content_with_weight" + placeholder="" + style="height: 100px" + auto-size + /> + </a-form-item> + <a-form-item field="important_kwd_key" label="鍏抽敭璇� *"> + <div style="width: auto"> + <a-tag + v-for="(item, index) in form.important_kwd" + :key="index" + closable + bordered + @close="form.important_kwd.splice(index, 1)" + style="margin-right: 10px" + > + {{ item }} + </a-tag> + <a-input + ref="formInput" + v-show="keyVisible" + v-model="form.important_kwd_key" + placeholder="" + size="small" + style="width: 80px; margin-right: 16px" + @blur="inputChange" + /> + <a-button type="dashed" shape="circle" size="small" @click="addKey"> + <icon-plus /> + </a-button> + </div> + </a-form-item> + + <div> + <a-divider style="margin: 10px 0" /> + <a-switch size="small" /> + <span style="color: var(--color-text-2)">鍚敤</span> + <a-button type="text" style="color: var(--color-text-2)"> + <template #icon> + <icon-delete /> + </template> + 鍒犻櫎 + </a-button> + </div> + <a-form-item> + <div style="width: 100%; text-align: right"> + <a-button @click="visible = false">鍙栨秷</a-button> + <a-button style="margin-left: 10px" type="primary" html-type="submit" + >纭畾</a-button + > + </div> + </a-form-item> + </a-form> + </a-modal> +</template> + +<script lang="ts" setup> + import { onMounted, onBeforeMount, reactive, ref } from 'vue'; + import { achunkCreate } from '@/api/kbList'; + + const props = defineProps(['item']); + + const visible = ref(false); + const keyVisible = ref(false); + const loading = ref(false); + const form = reactive({ + content_with_weight: '', + important_kwd: [], + important_kwd_key: '', + }); + const formRef = ref(null); + const formInput = ref(null); + const rules = { + content_with_weight: [ + { + required: true, + message: '璇疯緭鍏ュ�硷紒', + }, + ], + }; + + const handleSubmit = async ({ values, errors }) => { + console.log(props.item.id); + if (!errors) { + const res = await achunkCreate({ + content_with_weight: values.content_with_weight, + important_kwd: values.important_kwd, + doc_id: props.item.id, + }); + } + }; + + const handleClick = () => { + visible.value = true; + }; + + defineExpose({ + handleClick, + }); + const handleBeforeOk = (done) => { + formRef.value.validate().then((res) => { + console.log('form:', form); + }); + }; + const handleCancel = () => { + visible.value = false; + }; + + const handleOpened = (el) => { + Object.assign(form, { + content_with_weight: '', + important_kwd: [], + important_kwd_key: '', + }); + formRef.value.resetFields(); + keyVisible.value = false; + }; + + const addKey = () => { + form.important_kwd_key = ''; + formInput.value.focus(); + keyVisible.value = true; + }; + + const inputChange = (e) => { + if ( + !form.important_kwd.includes(form.important_kwd_key) && + form.important_kwd_key + ) { + form.important_kwd.push(form.important_kwd_key); + } else { + } + keyVisible.value = false; + }; + + onBeforeMount(() => {}); + onMounted(() => {}); +</script> diff --git a/src/views/dmx/knowledgeLib/index.vue b/src/views/dmx/knowledgeLib/index.vue index 8df5eb4..a1af5df 100644 --- a/src/views/dmx/knowledgeLib/index.vue +++ b/src/views/dmx/knowledgeLib/index.vue @@ -6,37 +6,51 @@ <div class="lf-container-top"> <a-input-search :placeholder="$t('cardList.searchInput.placeholder')" - style="width: 130px;" + style="width: 130px" /> <addKnow @knowledgeData="knowledgeData"></addKnow> </div> <div class="lf-container-down"> - <div class="tabs"> + <a-scrollbar style="height: 56rem; overflow: auto"> <div class="tab" v-for="(tab, index) in tabs" :key="index" - @click="selectTab(index,tab)" - :class="{ 'active': selectedTab === index }" + @click="selectTab(index, tab)" + :class="{ active: selectedTab === index }" > {{ tab.name }} <a-popover position="bl"> - <icon-more :style="{position: 'absolute',top:'10px',right:'20px'}"/> + <icon-more + :style="{ position: 'absolute', top: '10px', right: '20px' }" + /> <template #content> - <a-popconfirm content="纭畾鍒犻櫎鍚�?" @ok="deleteKnowledge(tab.id)" type="warning"> - <span style="cursor: pointer;color: #0960bd;font-size: 12px"><icon-delete />鍒犻櫎</span> + <a-popconfirm + content="纭畾鍒犻櫎鍚�?" + @ok="deleteKnowledge(tab.id)" + type="warning" + > + <span + style="cursor: pointer; color: #0960bd; font-size: 12px" + ><icon-delete />鍒犻櫎</span + > </a-popconfirm> </template> </a-popover> </div> - </div> + </a-scrollbar> </div> </div> <div class="rt-container"> <a-tabs default-active-key="1"> - <a-tab-pane key="1" :title= "t('dmx.list.DataSet')"> + <a-tab-pane key="1" :title="t('dmx.list.DataSet')"> <div class="rt-container-main"> - <a-card ref="account" class="general-card" title="" style="padding-top: 20px"> + <a-card + ref="account" + class="general-card" + title="" + style="padding-top: 20px" + > <a-row> <a-col :flex="1" :span="12"> <a-form @@ -46,15 +60,27 @@ label-align="left" > <a-row :gutter="16"> - <a-col :span="24" style="margin-bottom: 10px;display: flex;justify-content: right"> + <a-col + :span="24" + style=" + margin-bottom: 10px; + display: flex; + justify-content: right; + " + > <a-input-search - :placeholder="$t('cardList.searchInput.placeholder')" - style="width: 200px;margin-right: 10px" + :placeholder=" + $t('cardList.searchInput.placeholder') + " + style="width: 200px; margin-right: 10px" v-model="keywords" @change="search" /> <!--鏂板缓--> - <add :kbobj="kbobj" @changeFetchData="changeFetchData"/> + <add + :kbobj="kbobj" + @changeFetchData="changeFetchData" + /> </a-col> </a-row> </a-form> @@ -81,7 +107,11 @@ </a-col> <a-col :span="12" - style="display: flex; align-items: center; justify-content: end" + style=" + display: flex; + align-items: center; + justify-content: end; + " > <!-- <a-button>--> <!-- <template #icon>--> @@ -90,13 +120,13 @@ <!-- {{ $t('searchTable.operation.download') }}--> <!-- </a-button>--> <a-tooltip :content="$t('searchTable.actions.refresh')"> - <div class="action-icon" - ><icon-refresh size="18" - /></div> + <div class="action-icon"><icon-refresh size="18" /></div> </a-tooltip> <a-dropdown @select="handleSelectDensity"> <a-tooltip :content="$t('searchTable.actions.density')"> - <div class="action-icon"><icon-line-height size="18" /></div> + <div class="action-icon" + ><icon-line-height size="18" + /></div> </a-tooltip> <template #content> <a-doption @@ -157,75 +187,130 @@ :scroll="{ y: 580 }" > <template #name="{ record }"> -<!-- <icon-file style="color: #0960bd;margin-right: 4px;" />--> - <icon-file style="margin-right: 4px;" /> -<!-- <span style="color: #0960bd;cursor: pointer" @click="fileClick">--> -<!-- {{record.name}}--> -<!-- </span>--> - {{record.name}} + <!-- <icon-file style="color: #0960bd;margin-right: 4px;" />--> + <icon-file style="margin-right: 4px" /> + <!-- <span style="color: #0960bd;cursor: pointer" @click="fileClick">--> + <!-- {{record.name}}--> + <!-- </span>--> + {{ record.name }} </template> <template #create_time="{ record }"> - <span>{{parseTime(record.create_time)}}</span> + <span>{{ parseTime(record.create_time) }}</span> </template> -<!-- <template #parser_id="{ record }">--> -<!-- <span>{{ parser_ids[record.parser_id]}}</span>--> -<!-- </template>--> + <!-- <template #parser_id="{ record }">--> + <!-- <span>{{ parser_ids[record.parser_id]}}</span>--> + <!-- </template>--> <template #status="{ record }"> - <a-switch v-model="record.status" size="small" checked-value="1" unchecked-value="0" @change="handleChangeStatus(record)"/> + <a-switch + v-model="record.status" + size="small" + checked-value="1" + unchecked-value="0" + @change="handleChangeStatus(record)" + /> </template> <template #run="{ record }"> - <div style="display: flex;align-items: center;"> + <div style="display: flex; align-items: center"> <div style="width: 100px"> <a-popover title="Title" v-if="record.run == '3'"> - <a-tag :loading="record.loading" :color="'blue'" border>{{$t('dmx.list.complete')}}</a-tag> + <a-tag + :loading="record.loading" + :color="'blue'" + border + >{{ $t('dmx.list.complete') }}</a-tag + > <template #content> <p>Here is the text content</p> </template> </a-popover> <a-popover title="Title" v-if="record.run == '1'"> - <a-tag :loading="record.loading" :color="'blue'" border>{{$t('dmx.list.complete')}}</a-tag> + <a-tag + :loading="record.loading" + :color="'blue'" + border + >{{ $t('dmx.list.complete') }}</a-tag + > <template #content> <p>Here is the text content</p> </template> </a-popover> <a-popover title="Title" v-if="record.run == '2'"> - <a-tag :loading="record.loading" :color="'gold'" border>{{$t('dmx.list.cancel')}}</a-tag> + <a-tag + :loading="record.loading" + :color="'gold'" + border + >{{ $t('dmx.list.cancel') }}</a-tag + > <template #content> <p>Here is the text content</p> </template> </a-popover> <a-popover title="Title" v-if="record.run == '0'"> - <a-tag :loading="record.loading" :color="'green'" border>{{$t('dmx.list.NotStarted')}}</a-tag> + <a-tag + :loading="record.loading" + :color="'green'" + border + >{{ $t('dmx.list.NotStarted') }}</a-tag + > <template #content> <p>Here is the text content</p> </template> </a-popover> </div> - <div > - <a-button type="text" size="large" @click="run(record)" :loading="record.loading"> + <div> + <a-button + type="text" + size="large" + @click="run(record)" + :loading="record.loading" + > <template #icon> - <icon-sync v-if="record.run == '3'"/> - <icon-sync v-if="record.run == '2'"/> - <icon-sync style="color: green" v-if="record.run == '1'"/> - <icon-play-circle style="color: green" v-if="record.run == '0'"/> + <icon-sync v-if="record.run == '3'" /> + <icon-sync v-if="record.run == '2'" /> + <icon-sync + style="color: green" + v-if="record.run == '1'" + /> + <icon-play-circle + style="color: green" + v-if="record.run == '0'" + /> </template> </a-button> </div> </div> </template> - <template #action="{ record }" > - <tool :kbtenantInfo="kbtenantInfo" :item="record" :kbdetail="kbdetail" /> - <edit :item="record" @upTabdateItem="upTabdateItem"/> - <a-popconfirm :content="'纭畾鍒犻櫎鍚�'" type="warning" @ok="deleteItem(record)"> - <a-button type="text" size="small"> + <template #action="{ record }"> + <tool + :kbtenantInfo="kbtenantInfo" + :item="record" + :kbdetail="kbdetail" + /> + <edit :item="record" @upTabdateItem="upTabdateItem" /> + <a-popconfirm + :content="'纭畾鍒犻櫎鍚�'" + type="warning" + @ok="deleteItem(record)" + > + <a-button type="text" size="small"> <template #icon> <icon-delete /> </template> </a-button> </a-popconfirm> - <a-button type="text" size="small"> + <a-button + type="text" + size="small" + @click="onDownloadDocument(record)" + > <template #icon> <icon-download /> + </template> + </a-button> + + <a-button type="text" size="small" @click="seeload(record)"> + <template #icon> + <icon-eye /> </template> </a-button> </template> @@ -240,83 +325,106 @@ </a-tab-pane> <a-tab-pane key="3" :title="t('dmx.list.disposition')"> <div class="rt-container-main"> - <config ref="configForm" :kbtenantInfo="kbtenantInfo" :kbobj="kbobj"></config> + <config + ref="configForm" + :kbtenantInfo="kbtenantInfo" + :kbobj="kbobj" + ></config> </div> </a-tab-pane> </a-tabs> - <div v-if="detailsShow" class="details"> - <div class="details-header"> - <div style="display: flex;align-items: center"> - <span><icon-arrow-left size="20px" style="cursor: pointer;color: #0960bd;margin: 10px" @click="goBackClick" /></span> - <icon-file style="color: #0960bd;margin-right: 4px;" /> - <span style="">123.docx</span> - </div> - <div style="display: flex; align-items: center;"> - <a-radio-group v-model="position" type="button" style="margin-right: 10px"> - <a-radio value="top">{{'dmx.list.EntireArticle'}}</a-radio> - <a-radio value="right">{{'dmx.list.omit'}}</a-radio> - </a-radio-group> - <a-popover position="bottom"> - <a-button type="outline" class="button" style="margin-right: 10px">{{'dmx.list.batch'}} <icon-down style="margin-left: 4px" /></a-button> - <template #content> - <p>Here is the text content</p> - <p>Here is the text content</p> - </template> - </a-popover> - <a-button type="outline" class="button" style="margin-right: 10px"> - <template #icon> - <icon-search /> - </template> - </a-button> - <a-popover position="bottom"> - <a-button type="outline" class="button" style="margin-right: 10px"><icon-sort /></a-button> - <template #content> - <p>Here is the text content</p> - <p>Here is the text content</p> - </template> - </a-popover> - <addDetails></addDetails> - </div> - </div> - <a-divider style="margin-top: 10px" /> - </div> + <!-- <div v-if="detailsShow" class="details">--> + <!-- <div class="details-header">--> + <!-- <div style="display: flex;align-items: center">--> + <!-- <span><icon-arrow-left size="20px" style="cursor: pointer;color: #0960bd;margin: 10px" @click="goBackClick" /></span>--> + <!-- <icon-file style="color: #0960bd;margin-right: 4px;" />--> + <!-- <span style="">123.docx</span>--> + <!-- </div>--> + <!-- <div style="display: flex; align-items: center;">--> + <!-- <a-radio-group v-model="position" type="button" style="margin-right: 10px">--> + <!-- <a-radio value="top">{{'dmx.list.EntireArticle'}}</a-radio>--> + <!-- <a-radio value="right">{{'dmx.list.omit'}}</a-radio>--> + <!-- </a-radio-group>--> + <!-- <a-popover position="bottom">--> + <!-- <a-button type="outline" class="button" style="margin-right: 10px">{{'dmx.list.batch'}} <icon-down style="margin-left: 4px" /></a-button>--> + <!-- <template #content>--> + <!-- <p>Here is the text content</p>--> + <!-- <p>Here is the text content</p>--> + <!-- </template>--> + <!-- </a-popover>--> + <!-- <a-button type="outline" class="button" style="margin-right: 10px">--> + <!-- <template #icon>--> + <!-- <icon-search />--> + <!-- </template>--> + <!-- </a-button>--> + <!-- <a-popover position="bottom">--> + <!-- <a-button type="outline" class="button" style="margin-right: 10px"><icon-sort /></a-button>--> + <!-- <template #content>--> + <!-- <p>Here is the text content</p>--> + <!-- <p>Here is the text content</p>--> + <!-- </template>--> + <!-- </a-popover>--> + <!-- <addDetails></addDetails>--> + <!-- </div>--> + <!-- </div>--> + <!-- <a-divider style="margin-top: 10px" />--> + <!-- </div>--> </div> </div> + <a-modal title=" " v-model:visible="visible" :footer="false" fullscreen> + <!-- <docx v-if="documenttype=='docx'" previewSrc="http://192.168.20.116:1080/v1/document/get/405c3efa4d8c11ef97560242ac120006"></docx>--> + <docx v-if="documenttype == 'docx'" :previewSrc="previewSrc"></docx> + <excel v-if="documenttype == 'excel'" :previewSrc="previewSrc"></excel> + <txtPdf v-if="documenttype == 'txtPdf'" :previewSrc="previewSrc"></txtPdf> + </a-modal> </div> </template> <script lang="ts" setup> -import { computed, ref, reactive, watch, nextTick, onBeforeMount, onMounted } from "vue"; + import { + computed, + ref, + reactive, + watch, + nextTick, + onBeforeMount, + onMounted, + } from 'vue'; import { useI18n } from 'vue-i18n'; import useLoading from '@/hooks/loading'; -import { - queryKbList, - PolicyRecord, - PolicyParams, - queryKbDocumentList, - deleteKnow, - queryKbdetail, - queryKbtenantInfo, kbdocumentrm, kbdocumentchangeparser, kbdocumentrun, kbdocumentchangeStatus -} from "@/api/kbList"; + import { + queryKbList, + PolicyRecord, + PolicyParams, + queryKbDocumentList, + deleteKnow, + queryKbdetail, + queryKbtenantInfo, + kbdocumentrm, + kbdocumentchangeparser, + kbdocumentrun, + kbdocumentchangeStatus, + downloadFile, + } from '@/api/kbList'; import { Pagination } from '@/types/global'; import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface'; import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'; import cloneDeep from 'lodash/cloneDeep'; import Sortable from 'sortablejs'; - import add from '@/views/dmx/knowledgeLib/add.vue' - import edit from '@/views/dmx/knowledgeLib/edit.vue' - import addKnow from '@/views/dmx/knowledgeLib/addKnow.vue' - import config from '@/views/dmx/knowledgeLib/config.vue' - import test from '@/views/dmx/knowledgeLib/test.vue' - import tool from '@/views/dmx/knowledgeLib/tool.vue' - import addDetails from '@/views/dmx/knowledgeLib/addDetails.vue' - import { Message } from "@arco-design/web-vue"; - import { parseTime } from "@/utils"; - import { usePinia } from "@/store"; - const store = usePinia(); + import add from '@/views/dmx/knowledgeLib/add.vue'; + import edit from '@/views/dmx/knowledgeLib/edit.vue'; + import addKnow from '@/views/dmx/knowledgeLib/addKnow.vue'; + import config from '@/views/dmx/knowledgeLib/config.vue'; + import test from '@/views/dmx/knowledgeLib/test.vue'; + import tool from '@/views/dmx/knowledgeLib/tool.vue'; + import docx from '@/views/dmx/knowledgeLib/components/docx.vue'; + import excel from '@/views/dmx/knowledgeLib/components/excel.vue'; + import txtPdf from '@/views/dmx/knowledgeLib/components/txtPdf.vue'; + import { Message } from '@arco-design/web-vue'; + import { parseTime } from '@/utils'; type SizeProps = 'mini' | 'small' | 'medium' | 'large'; type Column = TableColumnData & { checked?: true }; - const account = ref(null) + const account = ref(null); const generateFormModel = () => { return { number: '', @@ -335,43 +443,47 @@ const showColumns = ref<Column[]>([]); const size = ref<SizeProps>('medium'); - let visible = ref(false) - let keywords = ref('') - let detailsShow = ref(false) - let selectedTab = ref(0) - let testForm = ref(null) - let configForm = ref(null) - let kbId = ref('') - let kbobj = reactive({}) - let kbdetail = reactive({}) - let parser_ids = reactive({}) + let visible = ref(false); + let keywords = ref(''); + let detailsShow = ref(false); + let selectedTab = ref(0); + let testForm = ref(null); + let configForm = ref(null); + let documenttype = ref('docx'); + let previewSrc = ref(''); + let kbId = ref(''); + let kbobj = reactive({}); + let kbdetail = reactive({}); + let parser_ids = reactive({}); + let seeObj = reactive({}); let kbtenantInfo = reactive({ - "asr_id": "paraformer-realtime-8k-v1", - "embd_id": "BAAI/bge-large-zh-v1.5", - "img2txt_id": "qwen-vl-max", - "llm_id": "qwen-plus", - "name": "wanghao鈥榮 Kingdom", - "parser_ids": "naive:General,qa:Q&A,resume:Resume,manual:Manual,table:Table,paper:Paper,book:Book,laws:Laws,presentation:Presentation,picture:Picture,one:One", - "rerank_id": "BAAI/bge-reranker-v2-m3", - "role": "owner", - "tenant_id": "948fc6fa41ab11ef8fb80242ac120004", - parser_idObj:{} - }) - let tabs = ref([]) + asr_id: 'paraformer-realtime-8k-v1', + embd_id: 'BAAI/bge-large-zh-v1.5', + img2txt_id: 'qwen-vl-max', + llm_id: 'qwen-plus', + name: 'wanghao鈥榮 Kingdom', + parser_ids: + 'naive:General,qa:Q&A,resume:Resume,manual:Manual,table:Table,paper:Paper,book:Book,laws:Laws,presentation:Presentation,picture:Picture,one:One', + rerank_id: 'BAAI/bge-reranker-v2-m3', + role: 'owner', + tenant_id: '948fc6fa41ab11ef8fb80242ac120004', + parser_idObj: {}, + }); + let tabs = ref([]); - const selectTab = (index,item) => { - selectedTab.value= index; + const selectTab = (index, item) => { + selectedTab.value = index; // console.log(item.id); - kbobj= item; + kbobj = item; kbId = kbobj.id; testForm.value.changekbid(kbId); configForm.value.changekbObj(kbobj); fetchData({ kb_id: kbobj.id, page: 1, - page_size: 20 - }) - } + page_size: 20, + }); + }; const basePagination: Pagination = { current: 1, @@ -412,7 +524,7 @@ title: t('dmx.column.UploadTime'), dataIndex: 'create_time', slotName: 'create_time', - width:200 + width: 200, }, { title: t('瑙f瀽鏂规硶'), @@ -433,8 +545,8 @@ title: t('dmx.column.Operate'), dataIndex: 'action', slotName: 'action', - width: 150, - minWidth: 150, + width: 200, + minWidth: 200, }, ]); const contentTypeOptions = computed<SelectOptionData[]>(() => [ @@ -474,9 +586,9 @@ const fetchData = async (params) => { setLoading(true); try { - const data = await queryKbDocumentList(params); + const data = await queryKbDocumentList(params); console.log(data, 'data'); - if(data.code=='0'){ + if (data.code == '0') { // 璇︽儏 // const kbtenantInfo = await queryKbtenantInfo(); parser_ids = kbtenantInfo.parser_ids.split(',').reduce((acc, pair) => { @@ -486,7 +598,7 @@ }, {}); // console.log(parser_ids, 'parser_ids'); kbtenantInfo.parser_idObj = parser_ids; - renderData.value = data.data.docs||[]; + renderData.value = data.data.docs || []; renderData.value = renderData.value.map((item) => { return { ...item, @@ -499,13 +611,9 @@ pagination.current = params.page; pagination.total = data.data.total; // 鏌ヨ鐭ヨ瘑搴撹鎯� - kbdetail = await queryKbdetail({ - kb_id:params.kb_id, + kbdetail = await queryKbdetail({ + kb_id: params.kb_id, }); - - - - } } catch (err) { // you can report use errorHandler or other @@ -519,37 +627,35 @@ kb_id: kbobj.id, page: 1, page_size: 20, - keywords:keywords.value - }) + keywords: keywords.value, + }); }; - const handleClick = ()=>{ + const handleClick = () => { visible.value = true; - } + }; const onPageChange = (current: number) => { fetchData({ ...basePagination, current }); }; - const knowledgeData = async ( - params = { page: 1, page_size: 20 } - ) => { + const knowledgeData = async (params = { page: 1, page_size: 20 }) => { setLoading(true); try { const { data } = await queryKbList(params); console.log(data, 'data'); tabs.value = data; console.log(tabs.value, 'tabs'); - if(tabs.value.length>0 && tabs.value[0]){ - kbobj = tabs.value[0] + if (tabs.value.length > 0 && tabs.value[0]) { + kbobj = tabs.value[0]; kbId = kbobj.id; testForm.value.changekbid(kbId); configForm.value.changekbObj(kbobj); fetchData({ kb_id: kbobj.id, page: 1, - page_size: 20 - }) + page_size: 20, + }); } // renderData.value = data.list; // console.log(renderData, 'renderData'); @@ -564,13 +670,13 @@ const deleteKnowledge = async (id) => { let data = await deleteKnow({ - kb_id:id - }) - if(data.code == 0){ + kb_id: id, + }); + if (data.code == 0) { Message.success('鍒犻櫎鎴愬姛'); - knowledgeData() + knowledgeData(); } - } + }; const reset = () => { formModel.value = generateFormModel(); }; @@ -629,84 +735,104 @@ } }; - const fileClick = ()=>{ - detailsShow.value = true + const fileClick = () => { + detailsShow.value = true; + }; - } - - const goBackClick = ()=>{ - detailsShow.value = false - - } + const goBackClick = () => { + detailsShow.value = false; + }; function upTabdateItem(id, newName) { console.log(id, newName); - const itemToUpdate = renderData.value.find(item => item.id === id); + const itemToUpdate = renderData.value.find((item) => item.id === id); if (itemToUpdate) { itemToUpdate.name = newName; } } -const deleteItem = async (row)=>{ + const deleteItem = async (row) => { console.log(row); - let data = await kbdocumentrm({doc_id: row.id}) - if(data.code == 0){ + let data = await kbdocumentrm({ doc_id: row.id }); + if (data.code == 0) { Message.success('鍒犻櫎鎴愬姛'); console.log(kbobj, 'kbobj'); fetchData({ kb_id: kbobj.id, page: 1, - page_size: 20 - }) + page_size: 20, + }); } - } + }; + const onDownloadDocument = async (record) => { + console.log(record); + downloadFile({ + url: `/api/v1/document/get/${record.id}`, + filename: record.name, + }); + }; + const seeload = async (row) => { + Object.assign(seeObj, row); + // console.log(seeObj.name, 'seeObj'); + let type = row.name.split('.')[1]; + console.log(type); + if (type == 'pdf') { + documenttype.value = 'txtPdf'; + } else if (type == 'docx') { + documenttype.value = 'docx'; + } else if (type == 'xlsx') { + documenttype.value = 'excel'; + } else if (type == 'txt') { + documenttype.value = 'txtPdf'; + } else { + return false; + } + previewSrc.value = `${import.meta.env.VITE_API_BASE_URL}/v1/document/get/${ + row.id + }`; + visible.value = true; + }; -const handleChangeStatus = async (row)=>{ - console.log(row); - let data = await kbdocumentchangeStatus({ - doc_id: row.id, - status: row.status - }) - if(data.code == 0){ - Message.success('鎿嶄綔鎴愬姛'); - } -} + const handleChangeStatus = async (row) => { + console.log(row); + let data = await kbdocumentchangeStatus({ + doc_id: row.id, + status: row.status, + }); + if (data.code == 0) { + Message.success('鎿嶄綔鎴愬姛'); + } + }; + const run = async (row) => { + console.log(row); + row.loading = true; + let run = '1'; + if (row.run != '2') { + run = '1'; + } else { + run = '2'; + } + let data = await kbdocumentrun({ + doc_ids: [row.id], + run: run, + }); + if (data.code == 0) { + Message.success('瑙f瀽鎴愬姛'); + row.run = '3'; + } else { + Message.error('瑙f瀽澶辫触'); + row.run = '1'; + } + row.loading = false; + }; -const run = async (row)=>{ - console.log(row); - row.loading = true; - let run = '1' - if(row.run!='2'){ - run = '1' - }else { - run = '2' - } - let data = await kbdocumentrun({ - doc_ids: [row.id], - run: run - }) - // let data = await kbdocumentchangeparser({ - // parser_id: row.parser_id, - // doc_id: row.id, - // parser_config: row.parser_config, - // }) - if(data.code == 0){ - Message.success('瑙f瀽鎴愬姛'); - row.run = '3'; - }else{ - Message.error('瑙f瀽澶辫触'); - row.run = '1'; - } - row.loading = false; -} - -const changeFetchData = async (row)=>{ - fetchData({ - kb_id: kbobj.id, - page: 1, - page_size: 20 - }) -} + const changeFetchData = async (row) => { + fetchData({ + kb_id: kbobj.id, + page: 1, + page_size: 20, + }); + }; watch( () => columns.value, (val) => { @@ -720,52 +846,56 @@ { deep: true, immediate: true } ); - onBeforeMount(()=>{ - - }) - onMounted(()=>{ - knowledgeData() - }) - + onBeforeMount(() => {}); + onMounted(() => { + knowledgeData(); + }); </script> <script lang="ts"> export default { name: 'SearchTable', - methods: { - - } + methods: {}, }; </script> <style scoped lang="less"> .container { padding: 0 20px 20px 20px; - .main-container{ + .main-container { display: flex; - .lf-container{ + width: 100%; + height: 100%; + .lf-container { display: flex; flex-direction: column; align-items: center; justify-content: space-evenly; background: #ffffff; width: 200px; - .lf-container-top{ + .lf-container-top { display: flex; + margin: 10px 0; } - .lf-container-down{ + .lf-container-down { display: flex; flex-direction: column; + box-sizing: border-box; width: 90%; - height: calc(100% - 5rem); + //height: 56rem; border: 1px solid #eeeeee; - overflow: auto; - padding: 10px; - .tabs .tab { + //padding: 10px; + margin-bottom: 10px; + //.tabs{ + // width: 100%; + // height: 100%; + // overflow: auto; + //} + .tab { cursor: pointer; box-sizing: border-box; - margin: 10px 0; - padding:0 10px; + margin: 10px 10px; + padding: 0 10px; color: rgba(0, 0, 0, 0.88); font-size: 14px; height: 40px; @@ -776,35 +906,37 @@ border: 1px solid #f0f0f0; border-radius: 8px; } - .tabs .tab:hover { + .tab:hover { border: 1px solid #ffffff; background: #e8e8ea; - box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16), 0 3px 6px 0 rgba(0, 0, 0, 0.12), 0 5px 12px 4px rgba(0, 0, 0, 0.09); + box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16), + 0 3px 6px 0 rgba(0, 0, 0, 0.12), + 0 5px 12px 4px rgba(0, 0, 0, 0.09); } - .tabs .tab.active { + .tab.active { border: 1px solid #e8e8ea; background: #e8e8ea; cursor: pointer; } } } - .rt-container{ + .rt-container { position: relative; //background: #626aea; margin-left: 20px; width: calc(100% - 200px); - height: calc(100% - 5rem); - .rt-container-main{ + height: 56rem; + .rt-container-main { height: 76vh; } - .details{ + .details { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #ffffff; - .details-header{ + .details-header { display: flex; justify-content: space-between; margin-top: 10px; diff --git a/src/views/dmx/knowledgeLib/test.vue b/src/views/dmx/knowledgeLib/test.vue index fbeab3e..69df71d 100644 --- a/src/views/dmx/knowledgeLib/test.vue +++ b/src/views/dmx/knowledgeLib/test.vue @@ -1,188 +1,215 @@ - <template> - <div class="main-container"> - <div class="main-container-lf"> - <div class="main-container-lf-top">妫�绱㈡祴璇�</div> - <div class="main-container-lf-down"> - <div style="color: #999;">鏈�鍚庝竴姝ワ紒 鎴愬姛鍚庯紝鍓╀笅鐨勫氨浜ょ粰Infiniflow AI鍚с��</div> - <a-divider style="margin-top: 10px" /> - <a-form ref="formRef" :model="form" :style="{width:'100%'}" layout="vertical" @submit="handleSubmit"> - <a-form-item field="similarity_threshold" label="鐩镐技搴﹂槇鍊�"> - <a-slider v-model="form.similarity_threshold" /> - </a-form-item> - <a-form-item field="slider" label="鍏抽敭瀛楃浉浼煎害鏉冮噸" :rules="[{type:'number', min:5,message:'slider is min than 5'}]"> - <a-slider v-model="form.vector_similarity_weight" /> - </a-form-item> - <a-form-item field="section" label="Rerank妯″瀷" :rules="[{match:/section one/,message:'璇烽�夋嫨'}]"> - <a-space direction="vertical" size="large"> - <a-select :size="'large'" v-model="form.rerank_id" :style="{width:'100%'}" placeholder="璇烽�夋嫨 ..." allow-clear> - <a-optgroup :label="index" v-for="(item,index) in modelList" :key=index> - <a-option - v-for="(obj) in item" - :key="obj.fid" - :disabled="!obj.available" - :value="obj.llm_name" - > - {{obj.llm_name}} - </a-option> - </a-optgroup> - </a-select> - </a-space> - </a-form-item> - <a-form-item field="slider" label="Top-K" :rules="[{type:'number', min:5,message:'slider is min than 5'}]"> - <a-slider v-model="form.top_k" :min="1" :max="2048" /> - </a-form-item> - <a-form-item > - <div class="main-container-form-item-extra"> - <div class="main-container-form-item-extra-top">娴嬭瘯鏂囨湰</div> - <div class="main-container-form-item-extra-down"> - <a-textarea v-model="form.question" style="height: 10rem;border: 1px solid var(--color-fill-3);border-radius: 4px" placeholder="" allow-clear/> - </div> - <div class="main-container-form-item-extra-btn"> - <a-button type="primary" html-type="submit">娴嬭瘯</a-button> - </div> + <div class="main-container"> + <div class="main-container-lf"> + <div class="main-container-lf-top">妫�绱㈡祴璇�</div> + <div class="main-container-lf-down"> + <div style="color: #999" + >鏈�鍚庝竴姝ワ紒 鎴愬姛鍚庯紝鍓╀笅鐨勫氨浜ょ粰Infiniflow AI鍚с��</div + > + <a-divider style="margin-top: 10px" /> + <a-form + ref="formRef" + :model="form" + :style="{ width: '100%' }" + layout="vertical" + @submit="handleSubmit" + > + <a-form-item field="similarity_threshold" label="鐩镐技搴﹂槇鍊�"> + <a-slider v-model="form.similarity_threshold" /> + </a-form-item> + <a-form-item + field="slider" + label="鍏抽敭瀛楃浉浼煎害鏉冮噸" + :rules="[ + { type: 'number', min: 5, message: 'slider is min than 5' }, + ]" + > + <a-slider v-model="form.vector_similarity_weight" /> + </a-form-item> + <a-form-item + field="section" + label="Rerank妯″瀷" + :rules="[{ match: /section one/, message: '璇烽�夋嫨' }]" + > + <a-space direction="vertical" size="large"> + <a-select + :size="'large'" + v-model="form.rerank_id" + :style="{ width: '100%' }" + placeholder="璇烽�夋嫨 ..." + allow-clear + > + <a-optgroup + :label="index" + v-for="(item, index) in modelList" + :key="index" + > + <a-option + v-for="obj in item" + :key="obj.fid" + :disabled="!obj.available" + :value="obj.llm_name" + > + {{ obj.llm_name }} + </a-option> + </a-optgroup> + </a-select> + </a-space> + </a-form-item> + <a-form-item + field="slider" + label="Top-K" + :rules="[ + { type: 'number', min: 5, message: 'slider is min than 5' }, + ]" + > + <a-slider v-model="form.top_k" :min="1" :max="2048" /> + </a-form-item> + <a-form-item> + <div class="main-container-form-item-extra"> + <div class="main-container-form-item-extra-top">娴嬭瘯鏂囨湰</div> + <div class="main-container-form-item-extra-down"> + <a-textarea + v-model="form.question" + style=" + height: 10rem; + border: 1px solid var(--color-fill-3); + border-radius: 4px; + " + placeholder="" + allow-clear + /> </div> - </a-form-item> - </a-form> - </div> - </div> - <div class="main-container-rt"> - <a-collapse style="width: 96%;margin-top: 1rem;margin-left: 2%"> - <a-collapse-item header="0/0 閫夊畾鐨勬枃浠�" key="3"> - <template #extra> - <a-tag size="small">鍛戒腑鏁�</a-tag> - <a-tag size="small">鐪嬫硶</a-tag> - </template> - <div> - <a-empty /> + <div class="main-container-form-item-extra-btn"> + <a-button type="primary" html-type="submit">娴嬭瘯</a-button> + </div> </div> - </a-collapse-item> - </a-collapse> + </a-form-item> + </a-form> </div> </div> + <div class="main-container-rt"> + <a-collapse style="width: 96%; margin-top: 1rem; margin-left: 2%"> + <a-collapse-item header="0/0 閫夊畾鐨勬枃浠�" key="3"> + <template #extra> + <a-tag size="small">鍛戒腑鏁�</a-tag> + <a-tag size="small">鐪嬫硶</a-tag> + </template> + <div> + <a-empty /> + </div> + </a-collapse-item> + </a-collapse> + </div> + </div> </template> <script lang="ts" setup> -import { onMounted, onBeforeMount, reactive, ref, watch } from "vue"; -import { Message } from '@arco-design/web-vue'; -import { kbretrievalTest, queryModelList } from "@/api/kbList"; -// import { usePinia } from "../../../store"; -// const store = usePinia(); -// const props = defineProps(['kbId']) + import { onMounted, onBeforeMount, reactive, ref, watch } from 'vue'; + import { Message } from '@arco-design/web-vue'; + import { kbretrievalTest, queryModelList } from '@/api/kbList'; + // const props = defineProps(['kbId']) -// watch(() => props.kbId, (newValue, oldValue) => { -// console.log('kbId 鍙樺寲浜�', newValue, oldValue); -// },{ -// deep:true, -// }); + // watch(() => props.kbId, (newValue, oldValue) => { + // console.log('kbId 鍙樺寲浜�', newValue, oldValue); + // },{ + // deep:true, + // }); - -let visible = ref(false); -let loading = ref(false); -const formRef = ref(null); -const kbid = ref(''); -const modelList = ref({}); -let form = reactive({ - page: 1, - question: '', - rerank_id: '', - similarity_threshold: 20, - size: 10, - top_k: 1024, - vector_similarity_weight: 30, -}); - - -const formatter = (value) => { - // return String(Math.round(value / 100)) -}; - -const handleSubmit = async ({values, errors}) => { - // console.log(props.kbobj, 'props.kbobj'); - if (!form.question){ - return - } - let formObj = { - ...form, - kb_id:kbid.value, - } - formObj.similarity_threshold = formObj.similarity_threshold/100; - formObj.vector_similarity_weight = formObj.vector_similarity_weight/100; - const data = await kbretrievalTest(formObj); -} - -const handleClick = () => { - visible.value = true; -}; -const handleCancel = () => { - visible.value = false; -} - -const handleOpened =(el) => { - Object.assign(form,{ - + let visible = ref(false); + let loading = ref(false); + const formRef = ref(null); + const kbid = ref(''); + const modelList = ref({}); + let form = reactive({ + page: 1, + question: '', + rerank_id: '', + similarity_threshold: 20, + size: 10, + top_k: 1024, + vector_similarity_weight: 30, }); - formRef.value.resetFields(); -} -const changekbid = (value) => { - kbid.value = value; -} + const formatter = (value) => { + // return String(Math.round(value / 100)) + }; -const queryModel = async (params) => { - try { - const data = await queryModelList(params); - console.log(data.data, '澶фā鍨嬪垪琛�'); - modelList.value = { - BAAI: [data.data.BAAI[1]], - Jina: data.data.Jina, - youdao: data.data.youdao + const handleSubmit = async ({ values, errors }) => { + // console.log(props.kbobj, 'props.kbobj'); + if (!form.question) { + return; + } + let formObj = { + ...form, + kb_id: kbid.value, }; - } catch (err) { - // you can report use errorHandler or other - } finally { + formObj.similarity_threshold = formObj.similarity_threshold / 100; + formObj.vector_similarity_weight = formObj.vector_similarity_weight / 100; + const data = await kbretrievalTest(formObj); + }; - } -}; + const handleClick = () => { + visible.value = true; + }; + const handleCancel = () => { + visible.value = false; + }; + const handleOpened = (el) => { + Object.assign(form, {}); + formRef.value.resetFields(); + }; -defineExpose({ - changekbid -}) + const changekbid = (value) => { + kbid.value = value; + }; -onBeforeMount(()=>{ - queryModel({}) -}) -onMounted(()=>{ + const queryModel = async (params) => { + try { + const data = await queryModelList(params); + console.log(data.data, '澶фā鍨嬪垪琛�'); + modelList.value = { + BAAI: [data.data.BAAI[1]], + Jina: data.data.Jina, + youdao: data.data.youdao, + }; + } catch (err) { + // you can report use errorHandler or other + } finally { + } + }; + defineExpose({ + changekbid, + }); -}) - - + onBeforeMount(() => { + queryModel({}); + }); + onMounted(() => {}); </script> <script lang="ts"> -export default { - name: 'config', - methods: { - - } -}; + export default { + name: 'config', + methods: {}, + }; </script> <style scoped lang="less"> - .main-container{ + .main-container { display: flex; justify-content: space-between; height: 100%; //background: #626aea; - &-lf{ + &-lf { width: 30%; height: 100%; //border: 1px solid #cccccc; background: #ffffff; border-radius: 10px; overflow: hidden; - &-top{ + &-top { width: 100%; height: 60px; line-height: 60px; @@ -190,38 +217,38 @@ color: #ffffff; text-align: center; } - &-down{ + &-down { padding: 20px; width: 100%; } } - &-form-item-extra{ + &-form-item-extra { width: 100%; height: 20rem; border: 1px solid var(--color-fill-3); border-radius: 6px; overflow: hidden; - &-top{ + &-top { width: 100%; height: 40px; line-height: 40px; - border-bottom: 1px solid var(--color-fill-3); + border-bottom: 1px solid var(--color-fill-3); //background: rgb(var(--primary-6)); color: #999999; text-align: center; } - &-down{ + &-down { width: 92%; margin-left: 4%; margin-top: 30px; } - &-btn{ + &-btn { width: 96%; text-align: right; margin-top: 1rem; } } - &-rt{ + &-rt { width: 69%; height: 100%; //background: #626aea; @@ -230,4 +257,4 @@ border-radius: 10px; } } -</style> \ No newline at end of file +</style> diff --git a/src/views/dmx/knowledgeLib/tool.vue b/src/views/dmx/knowledgeLib/tool.vue index f055f2d..50da491 100644 --- a/src/views/dmx/knowledgeLib/tool.vue +++ b/src/views/dmx/knowledgeLib/tool.vue @@ -1,4 +1,3 @@ - <template> <a-button type="text" @click="handleClick" size="small"> <template #icon> @@ -7,125 +6,361 @@ </a-button> <a-modal v-model:visible="visible" - title="瑙f瀽鏂规硶" + title=" " @before-open="handleOpened" @cancel="handleCancel" - @opened="handleOpened" :footer="false" title-align="start" - width="700px" + width="900px" > - <div style="display: flex;align-items: center;"> - <div> - 瑙f瀽鏂规硶: - </div> - <div style="margin-left: 10px"> - <a-select v-model="form.parser_id" placeholder="璇烽�夋嫨" > - <a-option v-for="item in parser_ids" :key="item.value" :label="item.name" :value="item.value"></a-option> - </a-select> - </div> - </div> - <a-form ref="formRef" :rules="rules" :model="form" auto-label-width @submit="handleSubmit" > - <a-divider style="margin-top: 10px" /> - <a-form-item field="slider" label="鍧梩oken鏁�" - :rules="[{type:'number', min:1,message:'slider is min than 1'}]"> - <a-slider v-model="form.chunk_token_num" :max="1000" show-input /> - </a-form-item> - <a-divider style="margin-top: 10px" /> - <a-form-item field="raptor" label="浣跨敤鍙洖澧炲己RAPTOR绛栫暐"> - <a-space direction="vertical" size="large"> - <a-switch v-model="form.use_raptor" @change="onChangeRAPTOR" /> - </a-space> - </a-form-item> - <div v-if="form.use_raptor"> - <a-form-item field="prompt" label="鎻愮ず璇�"> - <a-textarea - v-model="form.prompt" - style="height: 10rem;border: 1px solid var(--color-fill-3);border-radius: 4px" placeholder="璇峰~鍐欐彁绀鸿瘝" /> - </a-form-item> - <a-form-item field="slider" label="鏈�澶oken鏁�" - :rules="[{type:'number', min:5,message:'slider is min than 5'}]"> - <a-slider v-model="form.max_token" :min="1" :max="1000" show-input/> - </a-form-item> - <a-form-item field="slider" label="闃堝��" :rules="[{type:'number', min:5,message:'slider is min than 5'}]"> - <a-slider v-model="form.threshold" show-tooltip show-input/> - </a-form-item> - <a-form-item field="slider" label="鏈�澶ц仛绫绘暟" - :rules="[{type:'number', min:5,message:'slider is min than 5'}]"> - <a-slider v-model="form.max_cluster" :max="1000" show-input/> - </a-form-item> - <a-form-item field="slider" label="闅忔満绉嶅瓙" v-model="form.random_seed" - :rules="[{type:'number', min:5,message:'slider is min than 5'}]"> - <a-input-number v-model="form.random_seed" :style="{width:'300px',marginRight:'1rem',borderRadius:'4px'}" - placeholder="璇疯緭鍏�" class="input-demo" :min="10" :max="100" /> - <a-button type="primary" @click="randomNumber"> - <icon-plus /> - </a-button> - - </a-form-item> - - </div> - <a-form-item> - <div style="width: 100%;text-align: right"> - <a-button @click="visible = false">鍙栨秷</a-button> - <a-button style="margin-left: 10px" type="primary" html-type="submit">纭畾</a-button> + <a-tabs default-active-key="1"> + <a-tab-pane key="1"> + <template #title> <icon-calendar /> 瑙f瀽鏂规硶 </template> + <div style="width: 100%"> + <div style="display: flex; align-items: center"> + <div> 瑙f瀽鏂规硶: </div> + <div style="margin-left: 10px"> + <a-select v-model="form.parser_id" placeholder="璇烽�夋嫨"> + <a-option + v-for="item in parser_ids" + :key="item.value" + :label="item.name" + :value="item.value" + ></a-option> + </a-select> + </div> + </div> + <div class="parser"> + <a-form + ref="formRef" + :rules="rules" + :model="form" + auto-label-width + @submit="handleSubmit" + > + <a-divider style="margin-top: 10px" /> + <a-form-item + field="slider" + label="鍧梩oken鏁�" + :rules="[ + { type: 'number', min: 1, message: 'slider is min than 1' }, + ]" + > + <a-slider + v-model="form.chunk_token_num" + :max="1000" + show-input + /> + </a-form-item> + <a-divider style="margin-top: 10px" /> + <a-form-item field="raptor" label="浣跨敤鍙洖澧炲己RAPTOR绛栫暐"> + <a-space direction="vertical" size="large"> + <a-switch + v-model="form.use_raptor" + @change="onChangeRAPTOR" + /> + </a-space> + </a-form-item> + <div v-if="form.use_raptor"> + <a-form-item field="prompt" label="鎻愮ず璇�"> + <a-textarea + v-model="form.prompt" + style=" + height: 10rem; + border: 1px solid var(--color-fill-3); + border-radius: 4px; + " + placeholder="璇峰~鍐欐彁绀鸿瘝" + /> + </a-form-item> + <a-form-item + field="slider" + label="鏈�澶oken鏁�" + :rules="[ + { type: 'number', min: 5, message: 'slider is min than 5' }, + ]" + > + <a-slider + v-model="form.max_token" + :min="1" + :max="1000" + show-input + /> + </a-form-item> + <a-form-item + field="slider" + label="闃堝��" + :rules="[ + { type: 'number', min: 5, message: 'slider is min than 5' }, + ]" + > + <a-slider v-model="form.threshold" show-tooltip show-input /> + </a-form-item> + <a-form-item + field="slider" + label="鏈�澶ц仛绫绘暟" + :rules="[ + { type: 'number', min: 5, message: 'slider is min than 5' }, + ]" + > + <a-slider v-model="form.max_cluster" :max="1000" show-input /> + </a-form-item> + <a-form-item + field="slider" + label="闅忔満绉嶅瓙" + v-model="form.random_seed" + :rules="[ + { type: 'number', min: 5, message: 'slider is min than 5' }, + ]" + > + <a-input-number + v-model="form.random_seed" + :style="{ + width: '300px', + marginRight: '1rem', + borderRadius: '4px', + }" + placeholder="璇疯緭鍏�" + class="input-demo" + :min="10" + :max="100" + /> + <a-button type="primary" @click="randomNumber"> + <icon-plus /> + </a-button> + </a-form-item> + </div> + <a-form-item> + <div style="width: 100%; text-align: right"> + <a-button @click="visible = false">鍙栨秷</a-button> + <a-button + style="margin-left: 10px" + type="primary" + html-type="submit" + >纭畾</a-button + > + </div> + </a-form-item> + </a-form> + </div> </div> - </a-form-item> - </a-form> + </a-tab-pane> + <a-tab-pane key="2"> + <template #title> <icon-clock-circle /> 鍒涘缓瑙f瀽鍧� </template> + <div class="details"> + <div class="details-header"> + <div + style=" + display: flex; + align-items: center; + justify-content: flex-end; + " + > + <a-radio-group + v-model="radio" + type="button" + style="margin-right: 10px" + @change="onRadioChange" + > + <a-radio value="1">鍏ㄦ枃</a-radio> + <a-radio value="2">鐪佺暐</a-radio> + </a-radio-group> + <a-popover position="bottom"> + <a-button + type="outline" + class="button" + style="margin-right: 10px" + >鎵归噺<icon-down style="margin-left: 4px" + /></a-button> + <template #content> + <a-space direction="vertical"> + <a-checkbox + :model-value="checkedAll" + :indeterminate="indeterminate" + @change="handleChangeAll" + style="margin-left: 10px" + > + 閫夋嫨鎵�鏈� + </a-checkbox> + </a-space> + <a-divider style="margin: 10px 0" /> + <p> + <a-button type="text" class="button" style="color: #2a2a2b"> + <template #icon> + <icon-check-circle /> + </template> + 鍚敤閫夊畾鐨� + </a-button> + </p> + <p> + <a-button type="text" class="button" style="color: #2a2a2b"> + <template #icon> + <icon-close-circle /> + </template> + 绂佺敤閫夊畾鐨� + </a-button> + </p> + <a-divider style="margin: 10px 0" /> + <p> + <a-button type="text" class="button" style="color: #2a2a2b"> + <template #icon> + <icon-delete /> + </template> + 鍒犻櫎閫夊畾鐨� + </a-button> + </p> + </template> + </a-popover> + <a-button + type="outline" + class="button" + style="margin-right: 10px" + > + <template #icon> + <icon-search /> + </template> + </a-button> + <a-popover position="bottom"> + <a-button + type="outline" + class="button" + style="margin-right: 10px" + ><icon-sort + /></a-button> + <template #content> + <a-radio-group + v-model="available_int" + direction="vertical" + size="large" + @change="onChangeavailable" + > + <a-radio value="">鎵�鏈�</a-radio> + <a-radio value="1">鍚敤</a-radio> + <a-radio value="0">绂佺敤</a-radio> + </a-radio-group> + </template> + </a-popover> + <addDetails :item="item"></addDetails> + </div> + </div> + <a-divider style="margin-top: 10px" /> + <div class="groupMain"> + <a-checkbox-group v-model="data" @change="handleChange"> + <div + class="groupList" + :style="{ background: keyBg == '1' ? '#eff8ff' : 'white' }" + > + <a-checkbox value="1"></a-checkbox> + <div + class="groupList-content" + @click="groupListContentClick('1')" + @dblclick="contentClick(1)" + > + 鑰� stable version 鏄渶鏂扮ǔ瀹氱増锛岀粡杩囧厖鍒嗘祴璇曞拰楠岃瘉锛宐ug 杈冨皯锛� + 閫傚悎鐢ㄤ簬鐢熶骇鐜銆傚叾鐗堟湰鍙烽�氬父涓哄弻鏁帮紝濡� 1.26銆俵egacy versions + 鍒欐槸涔嬪墠鍙戝竷鐨勭ǔ瀹氱増锛屽浜庨渶瑕� + 鐗瑰畾鏃х増鏈殑鍏煎鎬ф垨瀹夊叏鎬ф敮鎸佺殑鐢ㄦ埛鏈夌敤锛屼絾涓�鑸笉 + 鎺ㄨ崘鐢ㄤ簬鏂伴」鐩紝闄ら潪鏈夌壒娈婇渶姹傘�傚湪瀹為檯浣跨敤涓紝濡傛灉杩芥眰鏈�鏂板姛鑳� + 涓旀効鎰忛潰瀵瑰彲鑳藉瓨鍦ㄧ殑涓�浜涗笉绋冲畾鍥犵礌锛屽彲浠ュ皾璇曚娇鐢ㄤ富绾跨増鏈繘琛屾祴璇曞拰鐮旂┒锛涘鏋滄槸鐢ㄤ簬鐢熶骇鐜 + </div> + <div class="groupList-right"> + <a-switch + v-model="switchType" + checked-value="1" + unchecked-value="0" + @change="handleChangeStatus()" + /> + </div> + </div> + + <div + class="groupList" + :style="{ background: keyBg == '2' ? '#eff8ff' : 'white' }" + > + <a-checkbox value="1"></a-checkbox> + <div + class="groupList-content" + @click="groupListContentClick('2')" + @dblclick="contentClick(1)" + > + 鑰� stable version 鏄渶鏂扮ǔ瀹氱増锛岀粡杩囧厖鍒嗘祴璇曞拰楠岃瘉锛宐ug 杈冨皯锛� + 閫傚悎鐢ㄤ簬鐢熶骇鐜銆傚叾鐗堟湰鍙烽�氬父涓哄弻鏁帮紝濡� 1.26銆俵egacy versions + 鍒欐槸涔嬪墠鍙戝竷鐨勭ǔ瀹氱増锛屽浜庨渶瑕� + </div> + <div class="groupList-right"> + <a-switch + v-model="switchType" + checked-value="1" + unchecked-value="0" + @change="handleChangeStatus()" + /> + </div> + </div> + </a-checkbox-group> + </div> + </div> + <eidtDetails ref="eidtDil"></eidtDetails> + </a-tab-pane> + </a-tabs> </a-modal> </template> <script lang="ts" setup> -import { onMounted, onBeforeMount, reactive, ref, computed } from "vue"; -import { Message } from "@arco-design/web-vue"; -import {kbdocumentchangeparser} from "@/api/kbList"; -const visible = ref(false); -const loading = ref(false); + import { onMounted, onBeforeMount, reactive, ref, computed } from 'vue'; + import { Message } from '@arco-design/web-vue'; + import { kbdocumentchangeparser } from '@/api/kbList'; + import addDetails from '@/views/dmx/knowledgeLib/addDetails.vue'; + import eidtDetails from '@/views/dmx/knowledgeLib/eidtDetails.vue'; + const visible = ref(false); + const loading = ref(false); + const radio = ref('1'); + const keyBg = ref(''); + const eidtDil = ref(); -const props = defineProps(['kbtenantInfo','item','kbdetail']) -// const emit = defineEmits(['upTabdateItem']) + const props = defineProps(['kbtenantInfo', 'item', 'kbdetail']); + // const emit = defineEmits(['upTabdateItem']) -let threshold = computed(()=>{ - return form.threshold/100; -}) + let threshold = computed(() => { + return form.threshold / 100; + }); -const kbtenantInfo = props.kbtenantInfo; + const kbtenantInfo = props.kbtenantInfo; -let parser_ids = kbtenantInfo.parser_ids.split(',').map((item) => { - const [value1, value2] = item.split(':'); - return { - name: value2, - value: value1, + let parser_ids = kbtenantInfo.parser_ids.split(',').map((item) => { + const [value1, value2] = item.split(':'); + return { + name: value2, + value: value1, + }; + }); + + const form = reactive({ + parser_id: props.item.parser_id, + doc_id: props.item.id, + max_token: 698, + threshold: 30, + max_cluster: 233, + random_seed: 1500, + chunk_token_num: 128, + use_raptor: false, + pages: {}, + prompt: + '璇锋�荤粨浠ヤ笅娈佃惤銆� 灏忓績鏁板瓧锛屼笉瑕佺紪閫犮�� 娈佃惤濡備笅锛歕n' + + ' {cluster_content}\n' + + '浠ヤ笂灏辨槸浣犻渶瑕佹�荤粨鐨勫唴瀹广��', + }); + const formRef = ref(null); + const rules = { + prompt: [ + { + required: true, + message: '鎻愮ず璇嶄笉鍏佽涓虹┖', + }, + ], }; -}); - -const form = reactive({ - parser_id: props.item.parser_id, - doc_id: props.item.id, - max_token: 698, - threshold: 30, - max_cluster: 233, - random_seed: 1500, - chunk_token_num: 128, - use_raptor: false, - pages: {}, - prompt: '璇锋�荤粨浠ヤ笅娈佃惤銆� 灏忓績鏁板瓧锛屼笉瑕佺紪閫犮�� 娈佃惤濡備笅锛歕n' + - ' {cluster_content}\n' + - '浠ヤ笂灏辨槸浣犻渶瑕佹�荤粨鐨勫唴瀹广��', -}); -const formRef = ref(null); - -const rules = { - prompt: [ - { - required: true, - message:'鎻愮ず璇嶄笉鍏佽涓虹┖', - }, - ], -} -const formatter = (value) => { - return value / 100 -}; + const formatter = (value) => { + return value / 100; + }; function randomNumber() { // 鐢熸垚涓�涓粙浜巑in鍜宮ax涔嬮棿鐨勯殢鏈烘暣鏁帮紙鍖呭惈min鍜宮ax锛� const min = 1; // 鏈�灏忓�� @@ -133,85 +368,147 @@ form.random_seed = Math.floor(Math.random() * (max - min + 1)) + min; } -const handleSubmit = async ({values, errors}) => { - if(!errors){ - let data = await kbdocumentchangeparser({ - parser_id: form.parser_id, - doc_id: form.doc_id, - parser_config: { - raptor: { - use_raptor: form.use_raptor, - prompt: form.prompt, - max_token: form.max_token, - threshold: form.threshold, - max_cluster: form.max_cluster, - random_seed: form.random_seed, + const handleSubmit = async ({ values, errors }) => { + if (!errors) { + let data = await kbdocumentchangeparser({ + parser_id: form.parser_id, + doc_id: form.doc_id, + parser_config: { + raptor: { + use_raptor: form.use_raptor, + prompt: form.prompt, + max_token: form.max_token, + threshold: form.threshold, + max_cluster: form.max_cluster, + random_seed: form.random_seed, + }, + chunk_token_num: form.chunk_token_num, + pages: [], }, - chunk_token_num: form.chunk_token_num, - pages: [ - - ] + }); + if (data.code == 0) { + Message.success('閰嶇疆鎴愬姛'); + } else { + Message.error('閰嶇疆澶辫触'); } - }) - if(data.code == 0){ - Message.success('閰嶇疆鎴愬姛'); - }else{ - Message.error('閰嶇疆澶辫触'); + visible.value = false; } + }; + + const handleClick = () => { + visible.value = true; + }; + const handleCancel = () => { visible.value = false; - } -} + }; -const handleClick = () => { - visible.value = true; -}; -const handleBeforeOk = (done) => { - formRef.value.validate().then(res => { - console.log('form:', form) - if (!form.name) { - done(false) - }else { - console.log('璇锋眰鏁版嵁'); + const contentClick = (done) => { + eidtDil.value.handleClick(); + }; + const handleOpened = (el) => { + // console.log('props',props.kbtenantInfo); + // console.log('props',props.item); + // console.log('props',props.kbdetail); + console.log(parser_ids, 'parser_ids'); + // Object.assign(form,{ + // name: '',// 鐢ㄦ埛鍚� + // nameJoin: '',// 鏄电О + // post: '',// 宀椾綅 + // txt: '',// 澶囨敞 + // }); + // formRef.value.resetFields(); + console.log(props.item.id); + }; + const onChangeRAPTOR = () => {}; + + const indeterminate = ref(false); + const checkedAll = ref(false); + const data = ref([]); + const switchType = ref(false); + const available_int = ref(''); + const onRadioChange = () => { + console.log(radio.value); + }; + const handleChangeAll = (value) => { + indeterminate.value = false; + if (value) { + checkedAll.value = true; + data.value = ['1', '2', '3']; + } else { + checkedAll.value = false; + data.value = []; } - }) -}; -const handleCancel = () => { - visible.value = false; -} + }; -const handleOpened =(el) => { - console.log('props',props.kbtenantInfo); - console.log('props',props.item); - console.log('props',props.kbdetail); - console.log(parser_ids, 'parser_ids'); - // Object.assign(form,{ - // name: '',// 鐢ㄦ埛鍚� - // nameJoin: '',// 鏄电О - // post: '',// 宀椾綅 - // txt: '',// 澶囨敞 - // }); - // formRef.value.resetFields(); -} + const handleChange = (values) => { + if (values.length === 3) { + checkedAll.value = true; + indeterminate.value = false; + } else if (values.length === 0) { + checkedAll.value = false; + indeterminate.value = false; + } else { + checkedAll.value = false; + indeterminate.value = true; + } + }; -const onChangeRAPTOR = () => { + const groupListContentClick = (value) => { + keyBg.value = value; + }; -}; + const onChangeavailable = () => { + console.log(available_int.value); + }; -onBeforeMount(()=>{ + const handleChangeStatus = () => { + console.log(switchType.value); + }; -}) -onMounted(()=>{ - - -}) + onBeforeMount(() => {}); + onMounted(() => {}); </script> -<script lang="ts"> -export default { - name: 'add', - methods: { - +<style scoped lang="less"> + .parser { + width: 100%; + ::v-deep .arco-btn-outline:hover, + .arco-btn-outline, + .arco-btn-outline[type='button'] { + color: #2a2a2b; + border: 1px solid #2a2a2b; + } + .button { + //color: #2a2a2b!important; + } } -}; -</script> \ No newline at end of file + .groupMain { + width: 100%; + height: 500px; + overflow: auto; + display: flex; + justify-content: center; + .groupList { + display: flex; + padding: 24px; + border-radius: 8px; + //background: #eff8ff; + border: 1px solid #f0f0f0; + margin-bottom: 20px; + overflow: auto; + .groupList-content { + width: 700px; + //height: 100px; + overflow: auto; + box-sizing: border-box; + margin: 0; + padding: 0; + color: rgba(0, 0, 0, 0.88); + font-size: 14px; + font-family: Inter; + position: relative; + } + } + } +</style> diff --git a/src/views/dmx/model/components/addModel.vue b/src/views/dmx/model/components/addModel.vue index 35c9ce5..42f0482 100644 --- a/src/views/dmx/model/components/addModel.vue +++ b/src/views/dmx/model/components/addModel.vue @@ -100,28 +100,27 @@ </template> <script lang="ts" setup> - import { onMounted, onBeforeMount, reactive, ref } from 'vue'; + import { onMounted, onBeforeMount, reactive, ref } from 'vue'; const visible = ref(false); const loading = ref(false); const form = reactive({ - size: 'medium', - name: '', + size: "medium", + name: "", age: undefined, - section: '0', - province: 'haidian', + section: "0", + province: "haidian", options: [], - date: '', - time: '', - radio: 'radio one', + date: "", + time: "", + radio: "radio one", slider: 5, score: 5, switch: false, - multiSelect: ['section one'], - treeSelect: '', + multiSelect: ["section one"], + treeSelect: "", raptor: false, - prompt: - '璇锋�荤粨浠ヤ笅娈佃惤銆� 灏忓績鏁板瓧锛屼笉瑕佺紪閫犮�� 娈佃惤濡備笅锛歕n' + + prompt: '璇锋�荤粨浠ヤ笅娈佃惤銆� 灏忓績鏁板瓧锛屼笉瑕佺紪閫犮�� 娈佃惤濡備笅锛歕n' + ' {cluster_content}\n' + '浠ヤ笂灏辨槸浣犻渶瑕佹�荤粨鐨勫唴瀹广��', }); @@ -131,61 +130,94 @@ name: [ { required: true, - message: '鍚嶇О涓嶅厑璁镐负绌�', + message:'鍚嶇О涓嶅厑璁镐负绌�', }, ], - }; + } - const handleSubmit = ({ values, errors }) => { - console.log('values:', values, '\nerrors:', errors); - }; + + const handleSubmit = ({values, errors}) => { + console.log('values:', values, '\nerrors:', errors) + } const handleClick = () => { visible.value = true; }; const handleBeforeOk = (done) => { - formRef.value.validate().then((res) => { - console.log('form:', form); - if (!form.name) { - done(false); - } else { - console.log('璇锋眰鏁版嵁'); - } - }); + formRef.value.validate().then(res => { + console.log('form:', form) + if (!form.name) { + done(false) + }else { + console.log('璇锋眰鏁版嵁'); + } + }) }; const handleCancel = () => { visible.value = false; - }; + } - const handleOpened = (el) => { - Object.assign(form, { - name: '', // 鐢ㄦ埛鍚� - nameJoin: '', // 鏄电О - post: '', // 宀椾綅 - txt: '', // 澶囨敞 + const handleOpened =(el) => { + Object.assign(form,{ + name: '',// 鐢ㄦ埛鍚� + nameJoin: '',// 鏄电О + post: '',// 宀椾綅 + txt: '',// 澶囨敞 }); - formRef.value.resetFields(); - }; + const formRef = ref(null); - const file = ref(); - - const onChange = (_, currentFile) => { - file.value = { - ...currentFile, - // url: URL.createObjectURL(currentFile.file), + const rules = { + name: [ + { + required: true, + message: '鍚嶇О涓嶅厑璁镐负绌�', + }, + ], }; - }; - const onProgress = (currentFile) => { - file.value = currentFile; - }; - onBeforeMount(() => {}); - onMounted(() => {}); -</script> + const handleSubmit = ({ values, errors }) => { + console.log('values:', values, '\nerrors:', errors); + }; -<script lang="ts"> - export default { - name: 'add', - methods: {}, - }; + const handleClick = () => { + visible.value = true; + }; + const handleBeforeOk = (done) => { + formRef.value.validate().then((res) => { + console.log('form:', form); + if (!form.name) { + done(false); + } else { + console.log('璇锋眰鏁版嵁'); + } + }); + }; + const handleCancel = () => { + visible.value = false; + }; + + const handleOpened = (el) => { + Object.assign(form, { + name: '', // 鐢ㄦ埛鍚� + nameJoin: '', // 鏄电О + post: '', // 宀椾綅 + txt: '', // 澶囨敞 + }); + formRef.value.resetFields(); + }; + + const file = ref(); + + const onChange = (_, currentFile) => { + file.value = { + ...currentFile, + // url: URL.createObjectURL(currentFile.file), + }; + }; + const onProgress = (currentFile) => { + file.value = currentFile; + }; + + onBeforeMount(() => {}); + onMounted(() => {}); </script> diff --git a/src/views/session/sessionManager/components/addSession.vue b/src/views/session/sessionManager/components/addSession.vue index 0a1c997..c46000c 100644 --- a/src/views/session/sessionManager/components/addSession.vue +++ b/src/views/session/sessionManager/components/addSession.vue @@ -1,40 +1,98 @@ <script setup lang="ts"> - import { defineProps ,ref,defineEmits} from 'vue'; - import { Message } from '@arco-design/web-vue'; - import { addSessionApi }from '@/api/session'; - const props=defineProps({ - modalObj:Object - }); - const conversation_name=ref(''); - const emit = defineEmits(['addSession']); - const handleOk=async ()=>{ - if(conversation_name.value){ - const {code}=await addSessionApi({conversation_name:conversation_name.value}); - if(code===200){ - Message.success('娣诲姞鎴愬姛'); - emit('addSession') - } - }else{ - Message.warning('浼氳瘽鍚嶇О涓嶈兘涓虹┖'); - } + import { defineProps, ref, defineEmits, onMounted } from 'vue'; + import { Message } from '@arco-design/web-vue'; + import { addSessionApi, getDialogListApi } from '@/api/session'; + const props = defineProps({ + modalObj: Object, + }); + const conversation = ref({ dialog_id: '', conversation_desc: '' }); + const dialogList = ref([]); + const emit = defineEmits(['addSession']); + const queryDialogList = async () => { + const { code, data } = await getDialogListApi(); + if (code === 200) { + dialogList.value = data; } + }; + + const rules = { + dialog_id: [ + { + required: true, + message: '鏅鸿兘鍔╂墜涓嶈兘涓虹┖', + }, + ], + conversation_desc: [ + { + required: true, + message: '鎻忚堪涓嶈兘涓虹┖', + }, + ], + }; + onMounted(() => { + queryDialogList(); + }); + const formRef = ref(); + const handleOk = () => { + formRef.value.validate().then(async (res) => { + if (!res) { + const { code } = await addSessionApi({ ...conversation.value }); + if (code === 200) { + Message.success('娣诲姞鎴愬姛'); + emit('addSession'); + setTimeout(() => { + props.modalObj.add = false; + }, 500); + } else { + Message.warning('娣诲姞澶辫触'); + } + } + }); + + return false; + }; + const destroyData = () => { + formRef.value.resetFields(); + }; </script> <template> - <div> - <a-modal v-model:visible="modalObj.add" @ok="handleOk" @cancel="modalObj.add=false"> - <template #title> - 鏂板浼氳瘽 - </template> - <a-form> - <a-form-item label="浼氳瘽鍚嶇О:"> - <a-input placeholder="璇疯緭鍏ヤ細璇濆悕绉�" v-model="conversation_name" style="width: 80%"></a-input> - </a-form-item> - </a-form> - </a-modal> - </div> + <div> + <a-modal + v-model:visible="modalObj.add" + @before-ok="handleOk" + @cancel="modalObj.add = false" + @before-close="destroyData" + > + <template #title> 鏂板浼氳瘽 </template> + <a-form ref="formRef" :model="conversation" :rules="rules"> + <a-form-item label="鍔╂墜鍏宠仈:" field="dialog_id" @submit="handleSubmit"> + <a-select + style="width: 80%" + v-model="conversation.dialog_id" + placeholder="璇烽�夋嫨鍏宠仈鍔╂墜" + > + <a-option + v-for="dialog in dialogList" + :key="dialog.id" + :value="dialog.id" + >{{ dialog.name }}</a-option + > + </a-select> + </a-form-item> + <a-form-item label="鎻忚堪:" field="conversation_desc"> + <a-textarea + placeholder="璇疯緭鍏ユ弿杩�" + :max-length="100" + show-word-limit + :auto-size="{ minRows: 4, maxRows: 5 }" + v-model="conversation.conversation_desc" + style="width: 80%" + ></a-textarea> + </a-form-item> + </a-form> + </a-modal> + </div> </template> -<style scoped lang="scss"> - -</style> +<style scoped lang="scss"></style> diff --git a/src/views/session/sessionManager/index.vue b/src/views/session/sessionManager/index.vue index 6cdb28a..1ab6516 100644 --- a/src/views/session/sessionManager/index.vue +++ b/src/views/session/sessionManager/index.vue @@ -1,357 +1,421 @@ <script setup lang="ts"> - import { IconMoreVertical,IconQuestionCircleFill,IconPoweroff,IconCommon ,IconSend} from '@arco-design/web-vue/es/icon'; - import img1 from '@/assets/images/u64.png' - import img2 from '@/assets/images/u69.png' - import img3 from '@/assets/images/u74.png'; - import AddSession from './components/addSession.vue' - import { ref, onMounted, computed, reactive, nextTick,watch } from 'vue'; - import { useUserStore,useAppStore } from '@/store'; - import { sessionListApi, deleteSessionApi,getSessionDetailsApi,chatApi }from '@/api/session'; - import { Message } from '@arco-design/web-vue'; - const userStore = useUserStore(); - const appStore = useAppStore(); - const theme = computed(() => { - return appStore.theme; - }); - const sessionList=ref([]);//浼氳瘽鍒楄〃 - const sessionDetailList=ref([]);//鏍规嵁浼氳瘽id鍑烘潵鐨勪細璇濊鎯� - const activeSessionId=ref(''); - const inputMsg=ref(''); - const scrollbar = ref(null); + import { + IconMoreVertical, + IconQuestionCircleFill, + IconPoweroff, + IconCommon, + IconSend, + } from '@arco-design/web-vue/es/icon'; + import img1 from '@/assets/images/u64.png'; + import img2 from '@/assets/images/u69.png'; + import img3 from '@/assets/images/u74.png'; + import AddSession from './components/addSession.vue'; + import { ref, onMounted, computed, reactive, nextTick, watch } from 'vue'; + import { useUserStore, useAppStore } from '@/store'; + import { + sessionListApi, + deleteSessionApi, + getSessionDetailsApi, + chatApi, + } from '@/api/session'; + import { Message } from '@arco-design/web-vue'; + const userStore = useUserStore(); + const appStore = useAppStore(); + const theme = computed(() => { + return appStore.theme; + }); + const sessionList = ref([]); //浼氳瘽鍒楄〃 + const sessionDetailList = ref([]); //鏍规嵁浼氳瘽id鍑烘潵鐨勪細璇濊鎯� + const activeSessionId = ref(''); + const inputMsg = ref(''); + const scrollbar = ref(null); - const currIndex = ref(0) - const displayedText = ref('');// 姝e湪鏄剧ず鐨勬枃瀛� - let timer: number|null = null; - const streamStr=ref(''); - const modalObj=reactive({ add:false }); - //鏌ヨ浼氳瘽鍒楄〃 + const currIndex = ref(0); + const displayedText = ref(''); // 姝e湪鏄剧ず鐨勬枃瀛� + let timer: number | null = null; + const streamStr = ref(''); + const modalObj = reactive({ add: false }); + //鏌ヨ浼氳瘽鍒楄〃 const querySessionList = async () => { - const { code, data } =await sessionListApi(); + const { code, data } = await sessionListApi(); if (code === 200) { sessionList.value = data; - if(Array.isArray(data)&&data.length>0){ - activeSessionId.value=data[0].id; - const res= await getSessionDetailsApi(data[0].id); - if(res.code===200){ - sessionDetailList.value=res.data.message; - refreshScroll(); - } - } - }else{ - Message.warning('鏌ヨ澶辫触'); + if (Array.isArray(data) && data.length > 0) { + activeSessionId.value = data[0].id; + const res = await getSessionDetailsApi(data[0].id); + if (res.code === 200) { + sessionDetailList.value = res.data.message; + refreshScroll(); } - }; - //鏍规嵁浼氳瘽id鍒犻櫎浼氳瘽 - const deleteSession=async (session)=>{ - const {code}=await deleteSessionApi([session.id]); - if(code===200){ - Message.success('鍒犻櫎鎴愬姛'); - querySessionList(); - } - }; - // eslint-disable-next-line prettier/prettier - // 鏂板浼氳瘽涔嬪悗鍒锋柊浼氳瘽鍒楄〃 - const addSession=()=>{ - querySessionList(); - }; - // 鍒濆鍖栨暟鎹� - const initData =()=>{ - querySessionList(); - }; - // 鑾峰彇鐧诲綍淇℃伅 - const userName=computed(()=>{ - return userStore.name; - }); - const avatar = computed(() => { - return userStore.avatar; - }); - const refreshScroll=()=>{ - nextTick(()=>{ - const container = document.getElementById('home'); - scrollbar.value.scrollTop(container.scrollHeight); - }); - }; - // 鏍规嵁浼氳瘽id 鏌ヨ浼氳瘽璇︽儏 - const querySessionDetail=async (session)=>{ - activeSessionId.value=session.id; - const {code,data}= await getSessionDetailsApi(session.id); - if(code===200){ - sessionDetailList.value=data.message; - refreshScroll();//鍒锋柊婊氬姩鏉′綅缃� - } - }; - const sendMessage= async ()=>{ - if(inputMsg.value){ - const {code,data} =await chatApi({conversation_id:activeSessionId.value,messages:inputMsg.value}); - const res= await getSessionDetailsApi(activeSessionId.value); - if(res.code===200){ - sessionDetailList.value=res.data.message.map((item,index)=>{ - if(index===res.data.message.length-1){ - item.role='last'; - displayedText.value=''; - currIndex.value=0; - streamStr.value=item.content; - startDisplayStr(); - } - return item; - }); - refreshScroll(); - } - inputMsg.value=''; - }else{ - Message.warning('娑堟伅涓嶈兘涓虹┖'); - } - }; - onMounted(()=>{ - initData(); - }); - //鏂囧瓧鍔ㄦ�佽緭鍑� - const startDisplayStr = () => { - if (timer) { - clearTimeout(timer!); - } - const res = streamStr.value; - // 灏嗘暟缁勪腑鐨勫瓧绗︿覆鎷兼帴璧锋潵 - if (currIndex.value < res.length) { - displayedText.value += res[currIndex.value]; - currIndex.value++; - setTimeout(startDisplayStr, 100); - } else { - clearTimeout(timer!); - timer = null - } + } + } else { + Message.warning('鏌ヨ澶辫触'); } - watch(() => scrollbar.value, (newScroll, oldScroll) => { + }; + //鏍规嵁浼氳瘽id鍒犻櫎浼氳瘽 + const deleteSession = async (session) => { + const { code } = await deleteSessionApi([session.id]); + if (code === 200) { + Message.success('鍒犻櫎鎴愬姛'); + querySessionList(); + } + }; + // eslint-disable-next-line prettier/prettier + // 鏂板浼氳瘽涔嬪悗鍒锋柊浼氳瘽鍒楄〃 + const addSession = () => { + querySessionList(); + }; + // 鍒濆鍖栨暟鎹� + const initData = () => { + querySessionList(); + }; + // 鑾峰彇鐧诲綍淇℃伅 + const userName = computed(() => { + return userStore.name; + }); + const avatar = computed(() => { + return userStore.avatar; + }); + const refreshScroll = () => { + nextTick(() => { + const container = document.getElementById('home'); + scrollbar.value.scrollTop(container.scrollHeight); + }); + }; + // 鏍规嵁浼氳瘽id 鏌ヨ浼氳瘽璇︽儏 + const querySessionDetail = async (session) => { + activeSessionId.value = session.id; + const { code, data } = await getSessionDetailsApi(session.id); + if (code === 200) { + sessionDetailList.value = data.message; + refreshScroll(); //鍒锋柊婊氬姩鏉′綅缃� + } + }; + const sendMessage = async () => { + if (inputMsg.value) { + const { code, data } = await chatApi({ + conversation_id: activeSessionId.value, + messages: inputMsg.value, + }); + const res = await getSessionDetailsApi(activeSessionId.value); + if (res.code === 200) { + sessionDetailList.value = res.data.message.map((item, index) => { + if (index === res.data.message.length - 1) { + item.role = 'last'; + displayedText.value = ''; + currIndex.value = 0; + streamStr.value = item.content; + startDisplayStr(); + } + return item; + }); + refreshScroll(); + } + inputMsg.value = ''; + } else { + Message.warning('娑堟伅涓嶈兘涓虹┖'); + } + }; + onMounted(() => { + initData(); + }); + //鏂囧瓧鍔ㄦ�佽緭鍑� + const startDisplayStr = () => { + if (timer) { + clearTimeout(timer!); + } + const res = streamStr.value; + // 灏嗘暟缁勪腑鐨勫瓧绗︿覆鎷兼帴璧锋潵 + if (currIndex.value < res.length) { + displayedText.value += res[currIndex.value]; + currIndex.value++; + setTimeout(startDisplayStr, 100); + } else { + clearTimeout(timer!); + timer = null; + } + }; + watch( + () => scrollbar.value, + (newScroll, oldScroll) => { if (newScroll) { // 鑾峰彇a-scroll鐨勯珮搴� const height = newScroll.$el.offsetHeight; console.log('a-scroll height changed to:', height); } - },{deep:true}) + }, + { deep: true } + ); </script> <template> - <div class="container"> - <AddSession :modalObj="modalObj" @addSession="addSession"></AddSession> - <a-row :gutter="[0,0]"> - <a-col :span="5"> - <a-card class="left"> - <template #cover> - <a-button type="outline" class="card-btn" @click="modalObj.add=true"> - +鏂板缓浼氳瘽 - </a-button> - </template> - <a-scrollbar class="left-list" style="height: 60vh;overflow-y: auto;"> - <div class="item" :class="{isLeftActive:activeSessionId===session.id}" v-for="session in sessionList" :key="session.id" @click="querySessionDetail(session)"> - <div class="item-left"> - <IconQuestionCircleFill/>銆� - {{session.name}} - </div> - <div class="item-right"> - <a-popover position="bottom"> - <icon-more-vertical></icon-more-vertical> - <template #content> - <!--<div> + <div class="container"> + <AddSession :modalObj="modalObj" @addSession="addSession"></AddSession> + <a-row :gutter="[0, 0]"> + <a-col :span="5"> + <a-card class="left"> + <template #cover> + <a-button + type="outline" + class="card-btn" + @click="modalObj.add = true" + > + +鏂板缓浼氳瘽 + </a-button> + </template> + <a-scrollbar class="left-list" style="height: 60vh; overflow-y: auto"> + <div + class="item" + :class="{ isLeftActive: activeSessionId === session.id }" + v-for="session in sessionList" + :key="session.id" + @click="querySessionDetail(session)" + > + <div class="item-left"> + <IconQuestionCircleFill />銆� + {{ session.name }} + </div> + <div class="item-right"> + <a-popover position="bottom"> + <icon-more-vertical></icon-more-vertical> + <template #content> + <!--<div> <a-button type="text" size="mini">缂栬緫</a-button> </div>--> - <div> - <a-button type="text" size="mini" @click="deleteSession(session)">鍒犻櫎</a-button> - </div> - </template> - </a-popover> - </div> - </div> - </a-scrollbar> - <div class="left-bottom"> - <div class="item"><IconCommon/>銆�<span>鍚戞湅鍙嬫帹鑽�</span></div> - <div class="item"><IconCommon/>銆�<span>鏈�鏂版秷鎭�</span></div> - <div class="item"><IconCommon/>銆�<span>闂鍙嶉</span></div> - <div class="item"><IconCommon/>銆�<span>甯歌闂</span></div> - <div class="item"><IconPoweroff/>銆�<span>閫�鍑�</span></div> + <div> + <a-button + type="text" + size="mini" + @click="deleteSession(session)" + >鍒犻櫎</a-button + > </div> - </a-card> - </a-col> - <a-col :span="19"> - <a-card class="right"> - <div v-if="sessionDetailList.length===0"> - <div class="right-title">ChatAI</div> - <a-row justify="center" class="right-middle"> - <a-col :span="5" class="item"> - <p><a-image :src="img1" width="50px"></a-image></p> - <p>绀轰緥</p> - </a-col> - <a-col :span="5" class="item"> - <p><a-image :src="img2" width="50px"></a-image></p> - <p>鏍稿績鍔熻兘</p> - </a-col> - <a-col :span="5" class="item"> - <p><a-image :src="img3" width="50px"></a-image></p> - <p>灞�闄愭��</p> - </a-col> - </a-row> - <a-row justify="center" class="right-middle-list"> - <a-col :span="6" class="item">鈥滆鐢ㄧ畝鍗曠殑鏈瑙i噴閲忓瓙璁$畻鈥�</a-col> - <a-col :span="6" class="item">鍙互瀵瑰巻鍙插璇濊繘琛岃蹇�</a-col> - <a-col :span="6" class="item">鍙兘浼氬嚭鐜伴敊璇殑鍐呭</a-col> - </a-row> - <a-row justify="center" class="right-middle-list"> - <a-col :span="6" class="item">鈥滄彁渚涗竴浜涘簡绁�10宀佸瀛愮敓鏃ョ殑鍒涙剰锛熲��</a-col> - <a-col :span="6" class="item">鍏佽鐢ㄦ埛瀵圭瓟妗堣繘琛屼慨姝�</a-col> - <a-col :span="6" class="item">鍙兘浼氫骇鐢熸湁瀹虫垨铏氬亣鐨勫唴瀹�</a-col> - </a-row> - <a-row justify="center" class="right-middle-list"> - <a-col :span="6" class="item">鈥滃浣曞湪Javascript涓彂鍑篽ttp璇锋眰锛熲��</a-col> - <a-col :span="6" class="item">鍙互鎺ュ彈鎴栨嫆缁濅笉鎭板綋鐨勮缁�</a-col> - <a-col :span="6" class="item">瀵�2023骞翠互鍚庡緱涓栫晫鍜屼簨浠朵簡瑙f湁闄�</a-col> - </a-row> - </div> - <a-scrollbar ref="scrollbar" id="home" v-else class="chat-list" style="width:90%;overflow:auto;height: 70vh;margin: 0px auto"> - <div class="chat-item" v-for="sessionDetail in sessionDetailList"> - <a-comment - v-if="sessionDetail.role==='user'" - avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp" - > - <template #content> - <div :class="{light:theme==='light'}">{{sessionDetail.content}}</div> - </template> - </a-comment> - <a-comment - v-else-if="sessionDetail.role==='assistant'" - avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/9eeb1800d9b78349b24682c3518ac4a3.png~tplv-uwbnlip3yd-webp.webp" - > - <template #content> - <a-card class="chat-item-answer" style="background-color: rgba(63, 64, 79, 1);"> - <div :class="{light:theme==='light'}">{{sessionDetail.content}}</div> - </a-card> - </template> - </a-comment> - <a-comment - v-else-if="sessionDetail.role==='last'" - avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/9eeb1800d9b78349b24682c3518ac4a3.png~tplv-uwbnlip3yd-webp.webp" - > - <template #content> - <a-textarea readonly auto-size v-model="displayedText" class="chat-item-answer" style="background-color: rgba(63, 64, 79, 1);"> - </a-textarea> - </template> - </a-comment> - </div> - </a-scrollbar> - <div class="bottom"> - <div class="input"> - <a-input v-model="inputMsg" @keydown.enter="sendMessage"> - <template #suffix> - <icon-send style="cursor: pointer" @click="sendMessage"/> - </template> - </a-input></div> - <div class="text">鍐呭鐢盇I鐢熸垚锛屼粎渚涘弬鑰冿紝璇烽伒瀹堛�婄敤鎴峰崗璁�嬨�併�婁釜浜轰俊鎭繚鎶よ鍒欍�嬶紝鍩轰簬ChatGPT澶фā鍨嬶紝鐗堟湰锛歏3.3.0</div> - </div> - </a-card> - </a-col> - </a-row> - </div> + </template> + </a-popover> + </div> + </div> + </a-scrollbar> + <div class="left-bottom"> + <div class="item"><IconCommon />銆�<span>鍚戞湅鍙嬫帹鑽�</span></div> + <div class="item"><IconCommon />銆�<span>鏈�鏂版秷鎭�</span></div> + <div class="item"><IconCommon />銆�<span>闂鍙嶉</span></div> + <div class="item"><IconCommon />銆�<span>甯歌闂</span></div> + <div class="item"><IconPoweroff />銆�<span>閫�鍑�</span></div> + </div> + </a-card> + </a-col> + <a-col :span="19"> + <a-card class="right"> + <div v-if="sessionDetailList.length === 0"> + <div class="right-title">ChatAI</div> + <a-row justify="center" class="right-middle"> + <a-col :span="5" class="item"> + <p><a-image :src="img1" width="50px"></a-image></p> + <p>绀轰緥</p> + </a-col> + <a-col :span="5" class="item"> + <p><a-image :src="img2" width="50px"></a-image></p> + <p>鏍稿績鍔熻兘</p> + </a-col> + <a-col :span="5" class="item"> + <p><a-image :src="img3" width="50px"></a-image></p> + <p>灞�闄愭��</p> + </a-col> + </a-row> + <a-row justify="center" class="right-middle-list"> + <a-col :span="6" class="item">鈥滆鐢ㄧ畝鍗曠殑鏈瑙i噴閲忓瓙璁$畻鈥�</a-col> + <a-col :span="6" class="item">鍙互瀵瑰巻鍙插璇濊繘琛岃蹇�</a-col> + <a-col :span="6" class="item">鍙兘浼氬嚭鐜伴敊璇殑鍐呭</a-col> + </a-row> + <a-row justify="center" class="right-middle-list"> + <a-col :span="6" class="item" + >鈥滄彁渚涗竴浜涘簡绁�10宀佸瀛愮敓鏃ョ殑鍒涙剰锛熲��</a-col + > + <a-col :span="6" class="item">鍏佽鐢ㄦ埛瀵圭瓟妗堣繘琛屼慨姝�</a-col> + <a-col :span="6" class="item">鍙兘浼氫骇鐢熸湁瀹虫垨铏氬亣鐨勫唴瀹�</a-col> + </a-row> + <a-row justify="center" class="right-middle-list"> + <a-col :span="6" class="item" + >鈥滃浣曞湪Javascript涓彂鍑篽ttp璇锋眰锛熲��</a-col + > + <a-col :span="6" class="item">鍙互鎺ュ彈鎴栨嫆缁濅笉鎭板綋鐨勮缁�</a-col> + <a-col :span="6" class="item" + >瀵�2023骞翠互鍚庡緱涓栫晫鍜屼簨浠朵簡瑙f湁闄�</a-col + > + </a-row> + </div> + <a-scrollbar + ref="scrollbar" + id="home" + v-else + class="chat-list" + style="width: 90%; overflow: auto; height: 70vh; margin: 0px auto" + > + <div class="chat-item" v-for="sessionDetail in sessionDetailList"> + <a-comment + v-if="sessionDetail.role === 'user'" + avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp" + > + <template #content> + <div :class="{ light: theme === 'light' }">{{ + sessionDetail.content + }}</div> + </template> + </a-comment> + <a-comment + v-else-if="sessionDetail.role === 'assistant'" + avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/9eeb1800d9b78349b24682c3518ac4a3.png~tplv-uwbnlip3yd-webp.webp" + > + <template #content> + <a-card + class="chat-item-answer" + style="background-color: rgba(63, 64, 79, 1)" + > + <div :class="{ light: theme === 'light' }">{{ + sessionDetail.content + }}</div> + </a-card> + </template> + </a-comment> + <a-comment + v-else-if="sessionDetail.role === 'last'" + avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/9eeb1800d9b78349b24682c3518ac4a3.png~tplv-uwbnlip3yd-webp.webp" + > + <template #content> + <a-textarea + readonly + auto-size + v-model="displayedText" + class="chat-item-answer" + style="background-color: rgba(63, 64, 79, 1)" + > + </a-textarea> + </template> + </a-comment> + </div> + </a-scrollbar> + <div class="bottom"> + <div class="input"> + <a-input + v-model="inputMsg" + @keydown.enter="sendMessage" + placeholder="杈撳叆鎮ㄦ兂浜嗚В鐨勫唴瀹癸紝鎸塃nter鍙戦��" + > + <template #suffix> + <icon-send style="cursor: pointer" @click="sendMessage" /> + </template> </a-input + ></div> + <div class="text" + >鍐呭鐢盇I鐢熸垚锛屼粎渚涘弬鑰冿紝璇烽伒瀹堛�婄敤鎴峰崗璁�嬨�併�婁釜浜轰俊鎭繚鎶よ鍒欍�嬶紝鍩轰簬ChatGPT澶фā鍨嬶紝鐗堟湰锛歏3.3.0</div + > + </div> + </a-card> + </a-col> + </a-row> + </div> </template> <style scoped lang="scss"> - .isLeftActive{ - background-color:rgba(52, 53, 66, 1) ; + .isLeftActive { + background-color: rgba(52, 53, 66, 1); + } + .light { + color: white !important; + } + .container { + background-color: #1d2129; + .left, + .right { + color: white; + height: calc(100vh - 60px); + border: 0px; } - .light{ - color: white !important; - } - .container{ - background-color: #1d2129; - .left,.right{ - color: white; - height: calc(100vh - 60px); - border: 0px; - } - .left{ - position: relative; - background-color: rgba(30, 33, 34, 1); - .card-btn { - width: 90%; - margin: 15px auto; - border: 1px solid white; - color: white; - } - .left-list{ - .item{ - display: flex; - justify-content: space-between; - padding-left: 30px; - color: white; - cursor: pointer; - line-height: 40px; - .item-right{ - margin-right: 10px; - } - &:hover{ - background-color:rgba(52, 53, 66, 1) ; - } - } - } - .left-bottom{ - position: absolute; - bottom: 30px; - left:40px; - .item{ - text-align: left; - color: white; - font-size: 12px; - line-height: 30px; - } - } - } - .right{ - position: relative; + .left { + position: relative; + background-color: rgba(30, 33, 34, 1); + .card-btn { + width: 90%; + margin: 15px auto; + border: 1px solid white; + color: white; + } + .left-list { + .item { + display: flex; + justify-content: space-between; + padding-left: 30px; + color: white; + cursor: pointer; + line-height: 40px; + .item-right { + margin-right: 10px; + } + &:hover { background-color: rgba(52, 53, 66, 1); - .right-title{ - font-size: 30px; - color: white; - text-align: center; - margin-top: 100px; - } - .right-middle{ - margin-top: 40px; - text-align: center; - color: white; - } - .right-middle-list{ - color: white; - .item{ - padding-top:15px; - text-align: center; - height: 50px; - background-color: rgba(63, 64, 79, 1); - margin:8px 20px; - border-radius: 10px; - } - } - .bottom{ - width: 100%; - position: absolute; - bottom: 40px; - left:20%; - .input{ - width: 60%; - } - .text{ - font-size: 12px; - color: lightgrey; - line-height: 40px; - } - } - .chat-list{ - width: 90%; - margin: 0px auto; - .chat-item{ - margin-top: 20px; - .chat-item-answer{ - color: white; - } - } - } - + } } + } + .left-bottom { + position: absolute; + bottom: 30px; + left: 40px; + .item { + text-align: left; + color: white; + font-size: 12px; + line-height: 30px; + } + } } + .right { + position: relative; + background-color: rgba(52, 53, 66, 1); + .right-title { + font-size: 30px; + color: white; + text-align: center; + margin-top: 100px; + } + .right-middle { + margin-top: 40px; + text-align: center; + color: white; + } + .right-middle-list { + color: white; + .item { + padding-top: 15px; + text-align: center; + height: 50px; + background-color: rgba(63, 64, 79, 1); + margin: 8px 20px; + border-radius: 10px; + } + } + .bottom { + width: 100%; + position: absolute; + bottom: 40px; + left: 20%; + .input { + width: 60%; + } + .text { + font-size: 12px; + color: lightgrey; + line-height: 40px; + } + } + .chat-list { + width: 90%; + margin: 0px auto; + .chat-item { + margin-top: 20px; + .chat-item-answer { + color: white; + } + } + } + } + } </style> diff --git a/src/views/sessionRecords/sessionRecordsManager/index.vue b/src/views/sessionRecords/sessionRecordsManager/index.vue index 528c003..1dd9235 100644 --- a/src/views/sessionRecords/sessionRecordsManager/index.vue +++ b/src/views/sessionRecords/sessionRecordsManager/index.vue @@ -1,312 +1,495 @@ <script setup lang="ts"> - import { IconSearch,IconTiktokColor ,IconSend,IconClose} from '@arco-design/web-vue/es/icon'; - import { useAppStore} from '@/store'; - import {computed,ref,onMounted,reactive} from 'vue'; - import {sessionListApi}from '@/api/session'; - import { Message } from '@arco-design/web-vue'; - import moment from 'moment'; - import AddSession from '@/views/session/sessionManager/components/addSession.vue'; - const sessionList=ref([]);//浼氳瘽鍒楄〃 - const modalObj=reactive({add:false}); - //鏌ヨ浼氳瘽鍒楄〃 - const querySessionList=async ()=>{ - const {code,data} =await sessionListApi(); - if(code===200){ - sessionList.value=data; - }else{ - Message.warning('鏌ヨ澶辫触'); - } - }; - //鏂板浼氳瘽涔嬪悗鍒锋柊浼氳瘽鍒楄〃 - const addSession=()=>{ - querySessionList(); - }; - onMounted(()=>{ - querySessionList(); + import { + IconSearch, + IconTiktokColor, + IconSend, + IconClose, + } from '@arco-design/web-vue/es/icon'; + import { useAppStore } from '@/store'; + import { computed, ref, onMounted, reactive, nextTick } from 'vue'; + import { Message } from '@arco-design/web-vue'; + import moment from 'moment'; + import AddSession from '@/views/session/sessionManager/components/addSession.vue'; + import { + sessionListApi, + deleteSessionApi, + getSessionDetailsApi, + chatApi, + } from '@/api/session'; + const sessionDetailList = ref([]); //鏍规嵁浼氳瘽id鍑烘潵鐨勪細璇濊鎯� + const sessionList = ref([]); //浼氳瘽鍒楄〃 + const modalObj = reactive({ add: false }); + + const currIndex = ref(0); + const displayedText = ref(''); // 姝e湪鏄剧ず鐨勬枃瀛� + let timer: number | null = null; + const streamStr = ref(''); + const inputMsg = ref(''); + const activeSessionId = ref(''); + + const sendMessage = async (event) => { + event.preventDefault(); + if (!activeSessionId.value) { + Message.warning('璇烽�夋嫨浼氳瘽'); + return; + } + if (inputMsg.value) { + const { code, data } = await chatApi({ + conversation_id: activeSessionId.value, + messages: inputMsg.value, + }); + const res = await getSessionDetailsApi(activeSessionId.value); + if (res.code === 200) { + sessionDetailList.value = res.data.message.map((item, index) => { + if (index === res.data.message.length - 1) { + item.role = 'last'; + displayedText.value = ''; + currIndex.value = 0; + streamStr.value = item.content; + startDisplayStr(); + } + return item; + }); + refreshScroll(); + } + inputMsg.value = ''; + } else { + Message.warning('娑堟伅涓嶈兘涓虹┖'); + } + }; + const querySessionDetail = async (session) => { + activeSessionId.value = session.id; + const { code, data } = await getSessionDetailsApi(session.id); + if (code === 200) { + sessionDetailList.value = data.message; + refreshScroll(); //鍒锋柊婊氬姩鏉′綅缃� + } + }; + const scrollbar = ref(null); + const refreshScroll = () => { + nextTick(() => { + const container = document.getElementById('home'); + scrollbar.value.scrollTop(container.scrollHeight); }); - const appStore = useAppStore(); - const theme = computed(() => { - return appStore.theme; - }); + }; + // 鏌ヨ浼氳瘽鍒楄〃 + const querySessionList = async () => { + const { code, data } = await sessionListApi(); + if (code === 200) { + sessionList.value = data; + } else { + Message.warning('鏌ヨ澶辫触'); + } + }; + //鏂板浼氳瘽涔嬪悗鍒锋柊浼氳瘽鍒楄〃 + const addSession = () => { + querySessionList(); + }; + onMounted(() => { + querySessionList(); + }); + const appStore = useAppStore(); + const theme = computed(() => { + return appStore.theme; + }); + //鏂囧瓧鍔ㄦ�佽緭鍑� + const startDisplayStr = () => { + if (timer) { + clearTimeout(timer!); + } + const res = streamStr.value; + // 灏嗘暟缁勪腑鐨勫瓧绗︿覆鎷兼帴璧锋潵 + if (currIndex.value < res.length) { + displayedText.value += res[currIndex.value]; + currIndex.value++; + setTimeout(startDisplayStr, 100); + } else { + clearTimeout(timer!); + timer = null; + } + }; </script> <template> - <div class="container"> - <AddSession :modalObj="modalObj" @addSession="addSession"></AddSession> - <a-card class="top-title">AI浼氳瘽璁板綍</a-card> - <a-row :gutter="[5,5]" style="margin-top: 3px"> - <a-col :span="4"> - <a-card style="height: 60px"> - <template #cover> - <div style="display: flex;justify-content: space-between"> - <a-button type="primary" shape="round" class="card-btn-1" @click="modalObj.add=true"> - +鏂板缓浼氳瘽 - </a-button> - <a-button type="text" shape="circle" class="card-btn-2"> - <icon-search /> - </a-button> - </div> - </template> - </a-card> - <a-card class="left"> - <a-scrollbar class="left-list" style="height: calc(100vh - 160px);overflow-y: auto;overflow-x: hidden;"> - <div class="item" v-for="session in sessionList"> - <div class="text" :class="{light:theme==='dark'}">{{session.name}}</div> - <div class="time">{{moment(new Date(session.create_time)).format('YYYY-MM-DD HH:mm:ss')}}</div> - </div> - </a-scrollbar> - </a-card> - </a-col> - <a-col :span="15"> - <a-card class="center"> - <div class="center-title">鏅鸿兘闂瓟</div> - <div class="center-content"> - 鎴戝彲浠ョ悊瑙e拰瀛︿範浜虹被鐨勮瑷�锛屽叿澶囧杞璇濈殑鑳藉姏锛岀幇鍦ㄥ拰鎴戝紑濮嬩氦娴佸惂~ - </div> - <div class="center-question"> - <div class="center-question-left">璇曚竴璇曡繖鏍烽棶鎴�</div> - <div class="center-question-right"> - <a-button type="primary">鎹竴鎹�</a-button> - </div> - </div> - <a-row justify="space-around" class="center-list"> - <a-col :span="7" class="item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </a-col> - <a-col :span="7" class="item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </a-col> - <a-col :span="7" class="item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </a-col> - <a-col :span="7" class="item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </a-col> - <a-col :span="7" class="item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </a-col> - <a-col :span="7" class="item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </a-col> - </a-row> - <div class="center-bottom"> - <a-textarea style="height: 180px" placeholder="杈撳叆鎮ㄦ兂浜嗚В鐨勫唴瀹癸紝Shift+Enter鎹㈣" :max-length="500" allow-clear show-word-limit> - </a-textarea> - </div> - </a-card> - </a-col> - <a-col :span="5"> - <a-card class="right"> - <div class="right-top"> - <div class="right-title">鏁版櫤搴�</div> - <div class="right-btn"> - <a-button type="outline" shape="circle" style="border: none;"> - <icon-search /> - </a-button> - <a-button type="outline" shape="circle" style="border: none;margin-left: -10px"> - <icon-close/> - </a-button> - </div> - </div> - <div class="right-tag"> - <a-space> - <a-button type="primary" shape="round" size="mini" class="btn">鍏ㄩ儴</a-button> - <a-button type="outline" shape="round" size="mini" class="btn">鏂囨。鍒涗綔</a-button> - <a-button type="outline" shape="round" size="mini" class="btn">鐭ヨ瘑瀛︿範</a-button> - </a-space> - <a-space style="margin-top:10px "> - <a-button type="outline" shape="round" size="mini" class="btn">鏁堢巼鎻愬崌</a-button> - </a-space> - </div> - <div class="right-list"> - <div class="right-item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </div> - <div class="right-item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </div> - <div class="right-item"> - <div class="item-title"> - <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 - </div> - <div class="item-content" :class="{dark:theme==='dark'}"> - 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... - </div> - </div> - </div> - </a-card> - </a-col> - </a-row> - </div> + <div class="container"> + <AddSession :modalObj="modalObj" @addSession="addSession"></AddSession> + <a-card class="top-title">AI浼氳瘽璁板綍</a-card> + <a-row :gutter="[5, 5]" style="margin-top: 3px"> + <a-col :span="4"> + <a-card style="height: 60px"> + <template #cover> + <div style="display: flex; justify-content: space-between"> + <a-button + type="primary" + shape="round" + class="card-btn-1" + @click="modalObj.add = true" + > + +鏂板缓浼氳瘽 + </a-button> + <a-button type="text" shape="circle" class="card-btn-2"> + <icon-search /> + </a-button> + </div> + </template> + </a-card> + <a-card class="left"> + <a-scrollbar + class="left-list" + style=" + height: calc(100vh - 160px); + overflow-y: auto; + overflow-x: hidden; + " + > + <div + class="item" + v-for="session in sessionList" + @click="querySessionDetail(session)" + :class="{ isLeftActive: activeSessionId === session.id }" + > + <div class="text" :class="{ light: theme === 'dark' }">{{ + session.name + }}</div> + <div class="time">{{ + moment(new Date(session.create_time)).format( + 'YYYY-MM-DD HH:mm:ss' + ) + }}</div> + </div> + </a-scrollbar> + </a-card> + </a-col> + <a-col :span="15"> + <a-card class="center"> + <div v-if="sessionDetailList.length === 0"> + <div class="center-title">鏅鸿兘闂瓟</div> + <div class="center-content"> + 鎴戝彲浠ョ悊瑙e拰瀛︿範浜虹被鐨勮瑷�锛屽叿澶囧杞璇濈殑鑳藉姏锛岀幇鍦ㄥ拰鎴戝紑濮嬩氦娴佸惂~ + </div> + <div class="center-question"> + <div class="center-question-left">璇曚竴璇曡繖鏍烽棶鎴�</div> + <div class="center-question-right"> + <a-button type="primary">鎹竴鎹�</a-button> + </div> + </div> + <a-row justify="space-around" class="center-list"> + <a-col :span="7" class="item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </a-col> + <a-col :span="7" class="item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </a-col> + <a-col :span="7" class="item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </a-col> + <a-col :span="7" class="item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </a-col> + <a-col :span="7" class="item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </a-col> + <a-col :span="7" class="item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </a-col> + </a-row> + </div> + <a-scrollbar + ref="scrollbar" + id="home" + v-else + class="chat-list" + style="width: 90%; overflow: auto; height: 60vh; margin: 0px auto" + > + <div class="chat-item" v-for="sessionDetail in sessionDetailList"> + <a-comment + v-if="sessionDetail.role === 'user'" + avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp" + > + <template #content> + <div :class="{ light: theme === 'light' }">{{ + sessionDetail.content + }}</div> + </template> + </a-comment> + <a-comment + v-else-if="sessionDetail.role === 'assistant'" + avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/9eeb1800d9b78349b24682c3518ac4a3.png~tplv-uwbnlip3yd-webp.webp" + > + <template #content> + <a-card + class="chat-item-answer" + style="background-color: rgba(63, 64, 79, 1)" + > + <div :class="{ light: theme === 'light' }">{{ + sessionDetail.content + }}</div> + </a-card> + </template> + </a-comment> + <a-comment + v-else-if="sessionDetail.role === 'last'" + avatar="https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/9eeb1800d9b78349b24682c3518ac4a3.png~tplv-uwbnlip3yd-webp.webp" + > + <template #content> + <a-textarea + readonly + auto-size + v-model="displayedText" + class="chat-item-answer" + style="background-color: rgba(63, 64, 79, 1)" + > + </a-textarea> + </template> + </a-comment> + </div> + </a-scrollbar> + + <div class="center-bottom"> + <a-textarea + v-model="inputMsg" + @keydown.shift.enter="sendMessage" + style="height: 180px" + placeholder="杈撳叆鎮ㄦ兂浜嗚В鐨勫唴瀹癸紝Shift+Enter鍙戦��" + :max-length="500" + allow-clear + show-word-limit + > + </a-textarea> + </div> + </a-card> + </a-col> + <a-col :span="5"> + <a-card class="right"> + <div class="right-top"> + <div class="right-title">鏁版櫤搴�</div> + <div class="right-btn"> + <a-button type="outline" shape="circle" style="border: none"> + <icon-search /> + </a-button> + <a-button + type="outline" + shape="circle" + style="border: none; margin-left: -10px" + > + <icon-close /> + </a-button> + </div> + </div> + <div class="right-tag"> + <a-space> + <a-button type="primary" shape="round" size="mini" class="btn" + >鍏ㄩ儴</a-button + > + <a-button type="outline" shape="round" size="mini" class="btn" + >鏂囨。鍒涗綔</a-button + > + <a-button type="outline" shape="round" size="mini" class="btn" + >鐭ヨ瘑瀛︿範</a-button + > + </a-space> + <a-space style="margin-top: 10px"> + <a-button type="outline" shape="round" size="mini" class="btn" + >鏁堢巼鎻愬崌</a-button + > + </a-space> + </div> + <div class="right-list"> + <div class="right-item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </div> + <div class="right-item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </div> + <div class="right-item"> + <div class="item-title"> + <IconTiktokColor></IconTiktokColor>鎶栭煶甯﹁揣鑴氭湰 + </div> + <div class="item-content" :class="{ dark: theme === 'dark' }"> + 缂栧啓寮曚汉娉ㄧ洰涓斿叿鏈夎鏈嶅姏鐨勩�侀�傜敤浜庝骇鍝佺殑... + </div> + </div> + </div> + </a-card> + </a-col> + </a-row> + </div> </template> <style scoped lang="scss"> - .light{ - color: white !important; + .isLeftActive { + background-color: lightgrey; + } + .light { + color: white !important; + } + .dark { + color: gray !important; + } + .container { + .top-title { + line-height: 60px; + font-size: 25px; + font-family: 榛戜綋; } - .dark{ - color: gray !important; + .center, + .right { + box-sizing: border-box; + height: calc(100vh - 100px); } - .container{ - .top-title{ - line-height:60px; - font-size: 25px; - font-family: 榛戜綋; - } - .center,.right{ - box-sizing: border-box; - height: calc(100vh - 100px); - } - .left{ - /* height: calc(100vh - 160px); + .left { + /* height: calc(100vh - 160px); overflow-y: auto; overflow-x: hidden;*/ - border: 0px; - .left-list{ - .item{ - cursor: pointer; - .text,.time{ - line-height: 30px; - } - .text{ - color: black; - } - .time{ - color: gray; - font-size: 12px; - } - } - } + border: 0px; + .left-list { + .item { + cursor: pointer; + .text, + .time { + line-height: 30px; + } + .text { + color: black; + padding-left: 10px; + } + .time { + color: gray; + font-size: 12px; + padding-left: 10px; + } } - .card-btn-1 { - margin: 10px; - width: 75%; - } - .card-btn-2 { - margin:10px 10px; - } - .center{ - position: relative; - .center-title{ - line-height:60px; - font-size: 25px; - font-family: 榛戜綋; - color: deepskyblue; - } - .center-content{ - font-size: 14px; - color: gray; - } - .center-question{ - margin-top: 20px; - display: flex; - justify-content: space-between; - .center-question-left{ - margin-top: 5px; - margin-left: 20px; - } - .center-question-right{ - margin-right: 20px; - } - } - .center-list{ - margin-top: 10px; - .item{ - border-radius: 10px; - margin-top: 10px; - padding: 10px; - height: 120px; - background-color: lightcyan; - .item-title{ - text-align: center; - line-height:40px; - font-size: 20px; - font-family: 榛戜綋; - color: black; - } - } - } - .center-bottom{ - position: absolute; - width: 90%; - bottom: 70px; - left:5%; - } - } - .right{ - .right-top{ - display: flex; - justify-content: space-between; - .right-title{ - font-size: 25px; - font-family: 榛戜綋; - color: black; - } - .right-btn{ - position: relative; - left:20px; - top:0px; - } - } - .right-tag{ - margin-top: 20px; - } - .right-list{ - .right-item{ - border-radius: 10px; - margin-top: 10px; - padding: 10px; - height: 120px; - background-color: lightcyan; - .item-title{ - text-align: center; - line-height:40px; - font-size: 20px; - font-family: 榛戜綋; - color: black; - } - } - } - } + } } + .card-btn-1 { + margin: 10px; + width: 75%; + } + .card-btn-2 { + margin: 10px 10px; + } + .center { + position: relative; + .center-title { + line-height: 60px; + font-size: 25px; + font-family: 榛戜綋; + color: deepskyblue; + } + .center-content { + font-size: 14px; + color: gray; + } + .center-question { + margin-top: 20px; + display: flex; + justify-content: space-between; + .center-question-left { + margin-top: 5px; + margin-left: 20px; + } + .center-question-right { + margin-right: 20px; + } + } + .center-list { + margin-top: 10px; + .item { + border-radius: 10px; + margin-top: 10px; + padding: 10px; + height: 120px; + background-color: lightcyan; + .item-title { + text-align: center; + line-height: 40px; + font-size: 20px; + font-family: 榛戜綋; + color: black; + } + } + } + .center-bottom { + position: absolute; + width: 90%; + bottom: 20px; + left: 5%; + } + } + .right { + .right-top { + display: flex; + justify-content: space-between; + .right-title { + font-size: 25px; + font-family: 榛戜綋; + color: black; + } + .right-btn { + position: relative; + left: 20px; + top: 0px; + } + } + .right-tag { + margin-top: 20px; + } + .right-list { + .right-item { + border-radius: 10px; + margin-top: 10px; + padding: 10px; + height: 120px; + background-color: lightcyan; + .item-title { + text-align: center; + line-height: 40px; + font-size: 20px; + font-family: 榛戜綋; + color: black; + } + } + } + } + } </style> diff --git a/yarn.lock b/yarn.lock index a7ed396..04d8775 100644 --- a/yarn.lock +++ b/yarn.lock @@ -986,6 +986,16 @@ "@volar/language-core" "1.11.1" "path-browserify" "^1.0.1" +"@vue-office/docx@^1.6.2": + version "1.6.2" + resolved "https://registry.npmmirror.com/@vue-office/docx/-/docx-1.6.2.tgz#c97d28db60db5325dd351d90b0202dd3d54ad427" + integrity sha512-OHAoUHeY8nHjhWvwDhlPx+/rmRkxmqLpvPgtfCEOZ4H1c1LCdJ6eDbdV3152ww8dcdZ7fgGQu3fmSSaI7JwdpQ== + +"@vue-office/excel@^1.7.11": + version "1.7.11" + resolved "https://registry.npmmirror.com/@vue-office/excel/-/excel-1.7.11.tgz#e37e5a2c212907a62c9b65e42d9df21f9c68a2cc" + integrity sha512-LF3R9IV573Sf4qTu6Ik5Ee8UMfkrsZQ6HEQE25/2m1c0CMcHX6KanIy6Cz0b0Q+FrLH3TjIsLTm6oPcqAbDGSA== + "@vue/babel-helper-vue-transform-on@1.2.2": "integrity" "sha512-nOttamHUR3YzdEqdM/XXDyCSdxMA9VizUKoroLX6yTyRtggzQMHXcmwh8a7ZErcJttIBIc9s68a1B8GZ+Dmvsw==" "resolved" "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.2.2.tgz" -- Gitblit v1.8.0