Merge branch 'master' of http://192.168.5.5:10010/r/web/flow_web
| | |
| | | <HTMLCodeStyleSettings> |
| | | <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" /> |
| | | </HTMLCodeStyleSettings> |
| | | <JSCodeStyleSettings> |
| | | <JSCodeStyleSettings version="0"> |
| | | <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> |
| | | <TypeScriptCodeStyleSettings version="0"> |
| | | <option name="FORCE_SEMICOLON_STYLE" value="true" /> |
| | | <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" /> |
| | | <option name="FORCE_QUOTE_STYlE" value="true" /> |
| | |
| | | return axios.post('/base/system/user', { user }); |
| | | } |
| | | |
| | | export function UserDelete(userId) { |
| | | return axios.delete('/base/system/user/' + userId); |
| | | export function UserDelete(id) { |
| | | return axios.delete('/base/system/user/' + id); |
| | | } |
| | | |
| | | export function OrganizationList(key: string) { |
| | |
| | | import { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'; |
| | | import { useUserStore } from '@/store'; |
| | | import { RouteLocationNormalized, RouteRecordRaw } from "vue-router"; |
| | | import { useUserStore } from "@/store"; |
| | | import { getUserInfo, getUserResources } from "@/utils/auth"; |
| | | |
| | | export default function usePermission() { |
| | | const userStore = useUserStore(); |
| | | return { |
| | | accessRouter(route: RouteLocationNormalized | RouteRecordRaw) { |
| | | return ( |
| | | !route.meta?.requiresAuth || |
| | | !route.meta?.roles || |
| | | route.meta?.roles?.includes('*') || |
| | | route.meta?.roles?.includes(userStore.role) |
| | | ); |
| | | //遍历userStore.resource |
| | | let isok = false; |
| | | let user = getUserResources(); |
| | | let resurces: any; |
| | | if (userStore.resources) { |
| | | resurces = userStore.resources; |
| | | } else { |
| | | if (user) { |
| | | resurces = JSON.parse(user); |
| | | } |
| | | } |
| | | if (resurces) { |
| | | resurces.forEach(r => { |
| | | if ((r.menuType == 0 || r.menuType == 3) && (route.name == r.component || route.path == r.component)) { |
| | | isok = true; |
| | | } |
| | | }); |
| | | return isok; |
| | | } else { |
| | | return ( |
| | | !route.meta?.requiresAuth || |
| | | !route.meta?.roles || |
| | | route.meta?.roles?.includes("*") || |
| | | route.meta?.roles?.includes(userStore.role) |
| | | ); |
| | | } |
| | | |
| | | }, |
| | | findFirstPermissionRoute(_routers: any, role = 'admin') { |
| | | findFirstPermissionRoute(_routers: any, role = "admin") { |
| | | const cloneRouters = [..._routers]; |
| | | while (cloneRouters.length) { |
| | | const firstElement = cloneRouters.shift(); |
| | | if ( |
| | | firstElement?.meta?.roles?.find((el: string[]) => { |
| | | return el.includes('*') || el.includes(role); |
| | | return el.includes("*") || el.includes(role); |
| | | }) |
| | | ) |
| | | return { name: firstElement.name }; |
| | |
| | | } |
| | | } |
| | | return null; |
| | | }, |
| | | } |
| | | // You can add any rules you want |
| | | }; |
| | | } |
| | |
| | | import { useUserStore, useAppStore } from '@/store'; |
| | | import { appRoutes } from '../routes'; |
| | | import { WHITE_LIST, NOT_FOUND } from '../constants'; |
| | | import { defineStore } from "pinia"; |
| | | |
| | | export default function setupPermissionGuard(router: Router) { |
| | | router.beforeEach(async (to, from, next) => { |
| | |
| | | getUserInfo, |
| | | LoginData, |
| | | } from '@/api/user'; |
| | | import { setToken, clearToken,setUserInfo } from '@/utils/auth'; |
| | | import { setToken, clearToken, setUserInfo, setUserResources, clearUserResources } from "@/utils/auth"; |
| | | import { removeRouteListener } from '@/utils/route-listener'; |
| | | import { UserState } from './types'; |
| | | import useAppStore from '../app'; |
| | |
| | | accountId: undefined, |
| | | certification: undefined, |
| | | role: '', |
| | | resources:undefined, |
| | | }), |
| | | |
| | | getters: { |
| | |
| | | |
| | | // Reset user's information |
| | | resetInfo() { |
| | | clearUserResources() |
| | | this.$reset(); |
| | | }, |
| | | |
| | |
| | | name: res.data.nickname, |
| | | email: res.data.email, |
| | | }; |
| | | this.resources=res.data.resources; |
| | | setUserInfo(JSON.stringify(userInfo)); |
| | | setUserResources(JSON.stringify(this.resources)) |
| | | } catch (err) { |
| | | clearToken(); |
| | | throw err; |
| | |
| | | accountId?: string; |
| | | certification?: number; |
| | | role: RoleType; |
| | | resources:any; |
| | | } |
| | |
| | | const TOKEN_KEY = 'token'; |
| | | const Authorization = 'Authorization'; |
| | | const UserInfo = 'userInfo'; |
| | | const UserResources='userResources' |
| | | |
| | | const isLogin = () => { |
| | | return !!localStorage.getItem(TOKEN_KEY); |
| | |
| | | localStorage.setItem(UserInfo, info); |
| | | }; |
| | | |
| | | export { isLogin, getToken, setToken, clearToken,getAuthorization, setAuthorization, getUserInfo, setUserInfo}; |
| | | const getUserResources = () => { |
| | | return localStorage.getItem(UserResources); |
| | | }; |
| | | |
| | | const setUserResources = (info: string) => { |
| | | localStorage.setItem(UserResources, info); |
| | | }; |
| | | |
| | | const clearUserResources = () => { |
| | | localStorage.removeItem(UserResources); |
| | | }; |
| | | |
| | | export { isLogin, getToken, setToken, clearToken,getAuthorization, setAuthorization, getUserInfo, setUserInfo,setUserResources,getUserResources,clearUserResources}; |
| | |
| | | }, |
| | | ], |
| | | }, |
| | | kb_ids: ['985eda244efc11ef9a7a0242ac120006'], |
| | | kb_ids: [], |
| | | llm_id: 'qwen-plus', |
| | | llm_setting: { |
| | | temperature: 0.1, |
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: [], |
| | | 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'+ |
| | | '{knowledge}'; |
| | | }; |
| | | |
| | | const file = ref(); |
| | | |
| | | onBeforeMount(() => {}); |
| | | onMounted(() => {}); |
| | | </script> |
| | |
| | | <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" |
| | | :disabled="!obj.available" |
| | | :value="obj.llm_id" |
| | | <a-form-item field="llm_id" label="模型"> |
| | | <a-space direction="vertical" size="large"> |
| | | <a-select :size="'large'" field="llm_id" v-model="form.llm_id" :style="{width:'25rem'}" placeholder="请选择 ..."> |
| | | <a-optgroup |
| | | :label="index" |
| | | v-for="(item, index) in modelList" |
| | | :key="index" |
| | | > |
| | | {{ obj.llm_name }} |
| | | </a-option> |
| | | </a-optgroup> |
| | | <a-option |
| | | v-for="obj in item" |
| | | :key="obj.fid" |
| | | :disabled="!obj.available" |
| | | :value="obj.llm_id" |
| | | > |
| | | {{ obj.llm_name }} |
| | | </a-option> |
| | | </a-optgroup> |
| | | </a-select> |
| | | </a-space> |
| | | </a-form-item> |
| | | </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-collapse-item header="知识库" key="3"> |
| | | <a-form-item field="kb_ids" label="知识库"> |
| | | <a-select |
| | | v-model="form.kb_ids" |
| | | :style="{ width: '25rem' }" |
| | | placeholder="请选择 ..." |
| | | multiple |
| | | > |
| | | </a-select> |
| | | <a-option |
| | | v-for="item in tabs" |
| | | :key="item.id" |
| | | :value="item.id" |
| | | >{{ item.name }}</a-option |
| | | > |
| | | </a-select> |
| | | </a-form-item> |
| | | </a-collapse-item> |
| | | <a-collapse-item header="工具" key="4" disabled> |
| | | </a-collapse-item> |
| | |
| | | </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> |
| | | <sessionAction></sessionAction> |
| | | </div> |
| | | </div> |
| | | </a-modal> |
| | |
| | | import { dialogSet } from '@/api/Agent'; |
| | | import { Message } from '@arco-design/web-vue'; |
| | | import EventBus from "@/utils/EventBus"; |
| | | import sessionAction from "@/views/dmx/IntelligentAgent/components/sessionAction.vue"; |
| | | const { setLoading } = useLoading(true); |
| | | const props = defineProps(['typeAngint', 'formData']); |
| | | const visible = ref(false); |
| | |
| | | '你的任务是 XX ,需要按照以下步骤执行:\n' + |
| | | '1. XX\n' + |
| | | '2. XX\n' + |
| | | '3. …\n', |
| | | '3. …\n' + |
| | | '{knowlege}', |
| | | parameters: [ |
| | | { |
| | | key: 'knowledge', |
| | |
| | | }, |
| | | ], |
| | | }, |
| | | kb_ids: ['985eda244efc11ef9a7a0242ac120006'], |
| | | kb_ids: [], |
| | | llm_id: 'qwen-plus', |
| | | llm_setting: { |
| | | temperature: 0.1, |
| | |
| | | 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: [ |
| | |
| | | message: '名称不允许为空', |
| | | }, |
| | | ], |
| | | llm_id: [ |
| | | { |
| | | required: true, |
| | | message: '模型不能为空', |
| | | }, |
| | | ], |
| | | kb_ids: [ |
| | | { |
| | | 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(); |
| | | EventBus.emit('queryList'); |
| | | if(!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(); |
| | | EventBus.emit('queryList'); |
| | | } |
| | | } |
| | | }; |
| | | |
| | |
| | | visible.value = true; |
| | | nextTick(() => { |
| | | Object.assign(form, data); |
| | | console.log(form); |
| | | console.log(form,'传值'); |
| | | system.value = form.prompt_config.system; |
| | | if(tabs.value && tabs.value.length>0){ |
| | | form.kb_ids = [tabs.value[0].id]; |
| | | } |
| | | }); |
| | | }; |
| | | defineExpose({ |
| | |
| | | try { |
| | | const { data } = await queryKbList(params); |
| | | console.log(data, 'data'); |
| | | tabs.value = data; |
| | | console.log(tabs.value, 'tabs'); |
| | | nextTick(() => { |
| | | tabs.value = data; |
| | | console.log(tabs.value, 'tabs'); |
| | | }); |
| | | } catch (err) { |
| | | // you can report use errorHandler or other |
| | | } finally { |
| | |
| | | line-height: 40px; |
| | | } |
| | | } |
| | | :deep(.arco-textarea-wrapper.arco-textarea-disabled){ |
| | | background: var(--color-bg-2); |
| | | color: var(--color-text-1); |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <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" /> |
| | | <a-scrollbar |
| | | ref="scrollbar" |
| | | id="home" |
| | | 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' }" style="background-color: var(--color-bg-2);color: var(--color-text-3);border: none;padding: 16px;">{{ |
| | | 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: var(--color-bg-2);color: var(--color-text-3);border: none" |
| | | > |
| | | <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: var(--color-bg-2);color: var(--color-text-3);border: none" |
| | | > |
| | | </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生成,仅供参考</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <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 { 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 heightrg = ref('calc(100vh - 100px)'); |
| | | 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 querySessionList = async () => { |
| | | const { code, data } = await sessionListApi(); |
| | | if (code === 200) { |
| | | sessionList.value = data; |
| | | if (Array.isArray(data) && data.length > 0) { |
| | | activeSessionId.value = data[1].id; |
| | | const res = await getSessionDetailsApi(data[0].id); |
| | | if (res.code === 200) { |
| | | sessionDetailList.value = res.data.message; |
| | | refreshScroll(); |
| | | } |
| | | } |
| | | } else { |
| | | Message.warning('查询失败'); |
| | | } |
| | | }; |
| | | //根据会话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 } |
| | | ); |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .container { |
| | | width: 100%; |
| | | display: flex; |
| | | } |
| | | //.light { |
| | | // color: white !important; |
| | | //} |
| | | .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; |
| | | } |
| | | } |
| | | .chat-list { |
| | | width: 90%; |
| | | margin: 0px auto; |
| | | .chat-item { |
| | | margin-top: 20px; |
| | | .chat-item-answer { |
| | | color: white; |
| | | } |
| | | } |
| | | } |
| | | </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: [], |
| | | 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'+ |
| | | '{knowledge}'; |
| | | }; |
| | | |
| | | 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: var(--color-neutral-3);">智能体配置</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;" /> |
| | | </div> |
| | | |
| | | </div> |
| | | <div style="width: 50%;border: 1px solid var(--color-neutral-3);background: var(--color-neutral-3)"> |
| | | <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-form-item field="llm_id" label="模型"> |
| | | <a-space direction="vertical" size="large"> |
| | | <a-select :size="'large'" field="llm_id" 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" |
| | | :disabled="!obj.available" |
| | | :value="obj.llm_id" |
| | | > |
| | | {{ obj.llm_name }} |
| | | </a-option> |
| | | </a-optgroup> |
| | | </a-select> |
| | | </a-space> |
| | | </a-form-item> |
| | | </a-collapse-item> |
| | | <a-collapse-item header="开场引导" :key="'2'" disabled> |
| | | </a-collapse-item> |
| | | <a-collapse-item header="知识库" key="3"> |
| | | <a-form-item field="kb_ids" label="知识库"> |
| | | <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-form-item> |
| | | </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"> |
| | | <sessionAction></sessionAction> |
| | | </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'; |
| | | import EventBus from "@/utils/EventBus"; |
| | | import sessionAction from "@/views/dmx/IntelligentAgent/components/sessionAction.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' + |
| | | '{knowlege}', |
| | | parameters: [ |
| | | { |
| | | key: 'knowledge', |
| | | optional: false, |
| | | }, |
| | | ], |
| | | }, |
| | | kb_ids: [], |
| | | 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 emit = defineEmits(['cancelModal']); |
| | | const rules = { |
| | | name: [ |
| | | { |
| | | required: true, |
| | | message: '名称不允许为空', |
| | | }, |
| | | ], |
| | | llm_id: [ |
| | | { |
| | | required: true, |
| | | message: '模型不能为空', |
| | | }, |
| | | ], |
| | | kb_ids: [ |
| | | { |
| | | required: true, |
| | | message: '知识库不能为空', |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | const handleSubmit = async ({ values, errors }) => { |
| | | // console.log('values:', values, '\nerrors:', errors) |
| | | if(!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(); |
| | | EventBus.emit('queryList'); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | 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; |
| | | if(tabs.value && tabs.value.length>0){ |
| | | form.kb_ids = [tabs.value[0].id]; |
| | | } |
| | | }); |
| | | }; |
| | | 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'); |
| | | nextTick(() => { |
| | | 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; |
| | | } |
| | | } |
| | | :deep(.arco-textarea-wrapper.arco-textarea-disabled){ |
| | | background: var(--color-bg-2); |
| | | color: var(--color-text-1); |
| | | } |
| | | </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 :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" /> |
| | | <a-scrollbar |
| | | ref="scrollbar" |
| | | id="home" |
| | | 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' }" style="background-color: var(--color-bg-2);color: var(--color-text-3);border: none;padding: 16px;">{{ |
| | | 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: var(--color-bg-2);color: var(--color-text-3);border: none" |
| | | > |
| | | <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: var(--color-bg-2);color: var(--color-text-3);border: none" |
| | | > |
| | | </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生成,仅供参考</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <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 { 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 heightrg = ref('calc(100vh - 100px)'); |
| | | 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 querySessionList = async () => { |
| | | const { code, data } = await sessionListApi(); |
| | | if (code === 200) { |
| | | sessionList.value = data; |
| | | if (Array.isArray(data) && data.length > 0) { |
| | | activeSessionId.value = data[1].id; |
| | | const res = await getSessionDetailsApi(data[0].id); |
| | | if (res.code === 200) { |
| | | sessionDetailList.value = res.data.message; |
| | | refreshScroll(); |
| | | } |
| | | } |
| | | } else { |
| | | Message.warning('查询失败'); |
| | | } |
| | | }; |
| | | //根据会话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 } |
| | | ); |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .container { |
| | | width: 100%; |
| | | display: flex; |
| | | } |
| | | //.light { |
| | | // color: white !important; |
| | | //} |
| | | .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; |
| | | } |
| | | } |
| | | .chat-list { |
| | | width: 90%; |
| | | margin: 0px auto; |
| | | .chat-item { |
| | | margin-top: 20px; |
| | | .chat-item-answer { |
| | | color: white; |
| | | } |
| | | } |
| | | } |
| | | </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, onMounted, onBeforeUnmount } 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); |
| | | import EventBus from '@/utils/EventBus'; |
| | | |
| | | 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(); |
| | | }); |
| | | onMounted(()=>{ |
| | | EventBus.on('queryList',()=>{ |
| | | queryList(); |
| | | }) |
| | | }) |
| | | onBeforeUnmount(()=>{ |
| | | EventBus.off('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> |
| | | <div class="main-container"> |
| | | <div style="position: absolute;top: 0;left: 0;width: 100%;padding: 0 20px"> |
| | | <h4 style="margin-bottom: 10px">配置</h4> |
| | | <h4 style="margin-bottom: 10px"></h4> |
| | | <div style="color: #666666;">在这里更新您的知识库详细信息,尤其是解析方法。</div> |
| | | <a-divider style="margin-top: 20px" /> |
| | | </div> |
| | |
| | | height: 100%; |
| | | overflow: auto; |
| | | //background: #626aea; |
| | | //background: #ffffff; |
| | | background: var(--color-bg-2); |
| | | padding-top: 80px; |
| | | |
| | | &-lf { |
| | |
| | | //height: 100%; |
| | | //border: 1px solid #cccccc; |
| | | border-radius: 10px; |
| | | |
| | | //border: 1px solid var(--color-fill-3); |
| | | &-top { |
| | | width: 100%; |
| | | height: 60px; |
| | |
| | | border-radius: 10px; |
| | | overflow: hidden; |
| | | padding: 20px; |
| | | |
| | | section { |
| | | width: 100%; |
| | | color: #333333; |
| | | //color: #333333; |
| | | color: var(--color-text-1); |
| | | } |
| | | } |
| | | } |
| | |
| | | <template #run="{ record }"> |
| | | <div style="display: flex;align-items: center;"> |
| | | <div style="width: 100px"> |
| | | <a-popover title="Title" v-if="record.run == '4'"> |
| | | <a-tag :loading="record.loading" :color="'blue'" border>{{$t('dmx.list.complete')}}</a-tag> |
| | | <template #content> |
| | | <p></p> |
| | | </template> |
| | | </a-popover> |
| | | <a-popover title="Title" v-if="record.run == '3'"> |
| | | <a-tag :loading="record.loading" :color="'blue'" border>{{$t('dmx.list.complete')}}</a-tag> |
| | | <template #content> |
| | | <p>Here is the text content</p> |
| | | <p></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> |
| | | <template #content> |
| | | <p>Here is the text content</p> |
| | | <p></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> |
| | | <template #content> |
| | | <p>Here is the text content</p> |
| | | <p></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> |
| | | <template #content> |
| | | <p>Here is the text content</p> |
| | | <p></p> |
| | | </template> |
| | | </a-popover> |
| | | </div> |
| | | <div > |
| | | <a-button type="text" size="large" @click="run(record)" :loading="record.loading"> |
| | | <template #icon> |
| | | <icon-sync v-if="record.run == '4'"/> |
| | | <icon-sync v-if="record.run == '3'"/> |
| | | <icon-sync v-if="record.run == '2'"/> |
| | | <icon-sync style="color: green" v-if="record.run == '1'"/> |
| | |
| | | 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) { |
| | |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: space-evenly; |
| | | background: #ffffff; |
| | | //background: #ffffff; |
| | | background: var(--color-bg-2); |
| | | width: 200px; |
| | | .lf-container-top{ |
| | | display: flex; |
| | |
| | | box-sizing: border-box; |
| | | width: 90%; |
| | | //height: 56rem; |
| | | border: 1px solid #eeeeee; |
| | | border: 1px solid var(--color-fill-3); |
| | | //padding: 10px; |
| | | margin-bottom: 10px; |
| | | //.tabs{ |
| | |
| | | &-lf{ |
| | | width: 30%; |
| | | height: 100%; |
| | | //border: 1px solid #cccccc; |
| | | background: #ffffff; |
| | | //border: 1px solid var(--color-fill-3); |
| | | background: var(--color-bg-2); |
| | | border-radius: 10px; |
| | | overflow: hidden; |
| | | &-top{ |
| | |
| | | width: 69%; |
| | | height: 100%; |
| | | //background: #626aea; |
| | | //border: 1px solid #cccccc; |
| | | background: #ffffff; |
| | | //border: 1px solid var(--color-fill-3); |
| | | background: var(--color-bg-2); |
| | | border-radius: 10px; |
| | | } |
| | | } |
| | |
| | | <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'}"> |
| | | <div class="groupList" :class="{groupActive:keyBg=='1',groupNoActive:keyBg!='1'}"> |
| | | <a-checkbox value="1"></a-checkbox> |
| | | <div class="groupList-content" @click="groupListContentClick('1')" @dblclick="contentClick(1)"> |
| | | 而 stable version 是最新稳定版,经过充分测试和验证,bug 较少, |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="groupList" :style="{background:keyBg=='2'?'#eff8ff':'white'}"> |
| | | <div class="groupList" :class="{groupActive:keyBg=='2',groupNoActive:keyBg!='2'}"> |
| | | <a-checkbox value="1"></a-checkbox> |
| | | <div class="groupList-content" @click="groupListContentClick('2')" @dblclick="contentClick(1)"> |
| | | 而 stable version 是最新稳定版,经过充分测试和验证,bug 较少, |
| | |
| | | box-sizing: border-box; |
| | | margin: 0; |
| | | padding: 0; |
| | | color: rgba(0, 0, 0, 0.88); |
| | | color: #2a2a2b; |
| | | font-size: 14px; |
| | | font-family: Inter; |
| | | position: relative; |
| | | |
| | | |
| | | } |
| | | } |
| | | } |
| | | .groupActive{ |
| | | background: #eff8ff; |
| | | } |
| | | .groupNoActive{ |
| | | background: var(--color-bg-1); |
| | | color: var(--color-text-1); |
| | | } |
| | | </style> |
| | |
| | | |
| | | const loginConfig = useStorage('login-config', { |
| | | rememberPassword: true, |
| | | email: '1750082535@qq.com', // 演示默认值 |
| | | password: 'basic2024', // demo default value |
| | | email: '', // 演示默认值 |
| | | password: '', // demo default value |
| | | }); |
| | | const userInfo = reactive({ |
| | | email: '1750082535@qq.com', // 演示默认值 |
| | | password: 'basic2024', // demo default value |
| | | email: '', // 演示默认值 |
| | | password: '', // demo default value |
| | | }); |
| | | |
| | | const handleSubmit = async ({ |