Merge branch 'master' of http://192.168.5.5:10010/r/web/flow_web
| | |
| | | VUE_APP_BASE_API=/api/v1 |
| | | VITE_API_BASE_URL= 'http://aiotlink.com:8189' |
| | | VITE_API_BASE_URL= 'http://192.168.20.116:1080' |
| | |
| | | <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" /> |
| | |
| | | <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" /> |
| | |
| | | }, |
| | | "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", |
New file |
| | |
| | | <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> |
New file |
| | |
| | | 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); |
| | | } |
| | |
| | | import axios from "axios"; |
| | | import { Pagination } from "@/types/global"; |
| | | import axios from 'axios'; |
| | | import { Pagination } from '@/types/global'; |
| | | |
| | | export interface User { |
| | | userId: string; |
| | |
| | | phoneNumber: string; |
| | | dept: any; |
| | | resources: any; |
| | | knowledges:any; |
| | | knowledges: any; |
| | | dialogs: any; |
| | | createTime: string; |
| | | status: string; |
| | | } |
| | |
| | | } |
| | | |
| | | 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> { |
| | |
| | | } |
| | | |
| | | 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"); |
| | | } |
| | | return axios.get<Result<Knowledge>>('/base/system/knowledge/list'); |
| | | } |
| | | |
| | | export function DialogList() { |
| | | return axios.get<Result<Knowledge>>('/base/system/dialog/list'); |
| | | } |
| | |
| | | (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) |
| | | ) { |
| | |
| | | response.config.url === '/base/login' |
| | | ) { |
| | | setAuthorization(response.headers.authorization); |
| | | } |
| | | }*/ |
| | | return res; |
| | | }, |
| | | (error) => { |
| | |
| | | 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, |
| | | }); |
| | | } |
| | | |
| | |
| | | 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) { |
| | |
| | | '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); |
| | | } |
| | | |
| | | |
| | | // 文档启动/取消解析接口 |
| | | |
| | |
| | | return axios.post('/api/v1/document/rm', params); |
| | | } |
| | | |
| | | |
| | | // 文档重命名接口 |
| | | export function kbdocumentrename(params) { |
| | | return axios.post('/api/v1/document/rename', params); |
| | | } |
| | | |
| | | // 文件解析方法接口 |
| | | 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); |
| | | } |
| | |
| | | // 模型列表接口 |
| | | 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); |
| | | }; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | // 新增解析块 |
| | | export function achunkCreate(params) { |
| | | return axios.post('/api/v1/chunk/create', params); |
| | | } |
| | |
| | | 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}}); |
| | | } |
| | | 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'); |
| | | } |
| | |
| | | roles: ['*'], |
| | | }, |
| | | }, |
| | | { |
| | | path: 'intelligentAgent', |
| | | name: 'IntelligentAgent', |
| | | component: () => import('@/views/dmx/IntelligentAgent/index.vue'), |
| | | meta: { |
| | | locale: '智能体管理', |
| | | requiresAuth: true, |
| | | roles: ['*'], |
| | | }, |
| | | }, |
| | | ], |
| | | |
| | | }; |
| | | |
| | | export default DMX; |
| | |
| | | <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 |
| | |
| | | :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> |
| | |
| | | </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" /> |
| | |
| | | </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> |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | <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 |
| | |
| | | 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"> |
| | |
| | | <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" /> |
| | |
| | | </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" |
| | |
| | | :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" |
| | |
| | | </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 /> |
| | |
| | | :show-line="showLineMenu" |
| | | @check="onCheckMenu" |
| | | :fieldNames="{ |
| | | key:'menuId', |
| | | title:'menuName', |
| | | children:'children', |
| | | }" |
| | | key: 'menuId', |
| | | title: 'menuName', |
| | | children: 'children', |
| | | }" |
| | | :check-strictly="checkStrictlyMenu" |
| | | > |
| | | </a-tree> |
| | |
| | | 知识库 |
| | | </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" |
| | |
| | | <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> |
| | | 菜单功能: |
| | |
| | | {{ 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> |
| | | |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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="请输入模型UID" /> |
| | | </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> |
New file |
| | |
| | | <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="输入您想了解的内容,按Enter发送"> |
| | | <template #suffix> |
| | | <icon-send style="cursor: pointer" /> |
| | | </template> </a-input |
| | | ></div> |
| | | <div class="text">内容由AI生成,仅供参考</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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | 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', |
| | | }; |
New file |
| | |
| | | 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': '已启用', |
| | | }; |
New file |
| | |
| | | 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: |
| | | '快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。', |
| | | enable: true, |
| | | actionType: 'button', |
| | | expires: true, |
| | | }, |
| | | { |
| | | id: 3, |
| | | icon: 'user', |
| | | title: '资源分发', |
| | | description: |
| | | '移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。', |
| | | 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(), |
| | | })) |
| | | ); |
| | | }); |
| | | }, |
| | | }); |
| | |
| | | |
| | | <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="创建解析块" |
| | | @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="解析块"> |
| | | <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> |
| | |
| | | </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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <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> |
New file |
| | |
| | | <template> |
| | | <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" |
| | | layout="vertical" |
| | | > |
| | | <a-form-item field="content_with_weight" label="解析块"> |
| | | <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> |
| | |
| | | <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 |
| | |
| | | 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> |
| | |
| | | </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>--> |
| | |
| | | <!-- {{ $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 |
| | |
| | | :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> |
| | |
| | | </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: '', |
| | |
| | | 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‘s 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‘s 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, |
| | |
| | | title: t('dmx.column.UploadTime'), |
| | | dataIndex: 'create_time', |
| | | slotName: 'create_time', |
| | | width:200 |
| | | width: 200, |
| | | }, |
| | | { |
| | | title: t('解析方法'), |
| | |
| | | title: t('dmx.column.Operate'), |
| | | dataIndex: 'action', |
| | | slotName: 'action', |
| | | width: 150, |
| | | minWidth: 150, |
| | | width: 200, |
| | | minWidth: 200, |
| | | }, |
| | | ]); |
| | | const contentTypeOptions = computed<SelectOptionData[]>(() => [ |
| | |
| | | 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) => { |
| | |
| | | }, {}); |
| | | // 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, |
| | |
| | | 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 |
| | |
| | | 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'); |
| | |
| | | |
| | | 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(); |
| | | }; |
| | |
| | | } |
| | | }; |
| | | |
| | | 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('解析成功'); |
| | | row.run = '3'; |
| | | } else { |
| | | Message.error('解析失败'); |
| | | 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('解析成功'); |
| | | row.run = '3'; |
| | | }else{ |
| | | Message.error('解析失败'); |
| | | 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) => { |
| | |
| | | { 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; |
| | |
| | | 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; |
| | |
| | | |
| | | <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; |
| | |
| | | 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; |
| | |
| | | border-radius: 10px; |
| | | } |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | |
| | | <template> |
| | | <a-button type="text" @click="handleClick" size="small"> |
| | | <template #icon> |
| | |
| | | </a-button> |
| | | <a-modal |
| | | v-model:visible="visible" |
| | | title="解析方法" |
| | | 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> |
| | | 解析方法: |
| | | </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="块token数" |
| | | :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="最大token数" |
| | | :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 /> 解析方法 </template> |
| | | <div style="width: 100%"> |
| | | <div style="display: flex; align-items: center"> |
| | | <div> 解析方法: </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="块token数" |
| | | :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="最大token数" |
| | | :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 /> 创建解析块 </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 是最新稳定版,经过充分测试和验证,bug 较少, |
| | | 适合用于生产环境。其版本号通常为双数,如 1.26。legacy 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 是最新稳定版,经过充分测试和验证,bug 较少, |
| | | 适合用于生产环境。其版本号通常为双数,如 1.26。legacy 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() { |
| | | // 生成一个介于min和max之间的随机整数(包含min和max) |
| | | const min = 1; // 最小值 |
| | |
| | | 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> |
| | | .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> |
| | |
| | | </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' + |
| | | '以上就是你需要总结的内容。', |
| | | }); |
| | |
| | | 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> |
| | |
| | | <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> |
| | |
| | | <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('');// 正在显示的文字 |
| | | let timer: number|null = null; |
| | | const streamStr=ref(''); |
| | | const modalObj=reactive({ add:false }); |
| | | //查询会话列表 |
| | | const currIndex = ref(0); |
| | | const displayedText = ref(''); // 正在显示的文字 |
| | | 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">“请用简单的术语解释量子计算”</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中发出http请求?”</a-col> |
| | | <a-col :span="6" class="item">可以接受或拒绝不恰当的训练</a-col> |
| | | <a-col :span="6" class="item">对2023年以后得世界和事件了解有限</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">内容由AI生成,仅供参考,请遵守《用户协议》、《个人信息保护规则》,基于ChatGPT大模型,版本:V3.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">“请用简单的术语解释量子计算”</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中发出http请求?”</a-col |
| | | > |
| | | <a-col :span="6" class="item">可以接受或拒绝不恰当的训练</a-col> |
| | | <a-col :span="6" class="item" |
| | | >对2023年以后得世界和事件了解有限</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="输入您想了解的内容,按Enter发送" |
| | | > |
| | | <template #suffix> |
| | | <icon-send style="cursor: pointer" @click="sendMessage" /> |
| | | </template> </a-input |
| | | ></div> |
| | | <div class="text" |
| | | >内容由AI生成,仅供参考,请遵守《用户协议》、《个人信息保护规则》,基于ChatGPT大模型,版本:V3.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> |
| | |
| | | <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(''); // 正在显示的文字 |
| | | 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"> |
| | | 我可以理解和学习人类的语言,具备多轮对话的能力,现在和我开始交流吧~ |
| | | </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"> |
| | | 我可以理解和学习人类的语言,具备多轮对话的能力,现在和我开始交流吧~ |
| | | </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> |
| | |
| | | "@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" |