customer_list/yw/static/config/route.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/admin/llm.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/login/UserMenuData.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/yw/systemManage/llmMgr/LLMMgr.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/yw/systemManage/llmMgr/components/LLMConfigDlg.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/yw/systemManage/llmMgr/components/LLMConnectDrawer.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/project/yw/systemManage/llmMgr/components/ModelConfigDlg.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
customer_list/yw/static/config/route.js
@@ -21,6 +21,13 @@ component: '/project/yw/systemManage/flowApp/FlowApp.vue', }, { name: 'LLMMgr', isKeepAlive: true, isAffix: false, path: '/llm/mgr', component: '/project/yw/systemManage/llmMgr/LLMMgr.vue', }, { name: 'FlowAppView', isKeepAlive: true, isAffix: false, src/api/admin/llm.ts
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,10 @@ import request from '/@/utils/request'; export const GetLLMInfoList = async ( req: any = request) => { return req({ url: '/admin/sample/get_llm_info_list', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }); }; src/api/login/UserMenuData.ts
@@ -113,6 +113,22 @@ }, { Children: [], ID: '1126', ParentID: '1742436890822447104', Type: 2, Name: '大模å管ç', Path: '/llm/mgr', Permission: '', Icon: 'ywifont ywicon-tishici', IsIframe: false, OutLink: '', IsHide: false, Weight: 0, SortCode: 2, Description: '', }, { Children: [], ID: '1127', ParentID: '1742436890822447104', Type: 2, src/views/project/yw/systemManage/llmMgr/LLMMgr.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,244 @@ <template> <HMContainer type="card"> <template #header> <el-form ref="queryFormRef" :inline="true" :model="queryParams"> <el-form-item label="æ é¢" prop="title"> <el-input v-model="queryParams.title" style="width: 226.4px" placeholder="æ é¢" clearable @input="debounceQueryTable" /> </el-form-item> <el-form-item> <!-- <el-button type="primary" icon="ele-Search" @click="handleQueryTable"> æ¥è¯¢ </el-button> --> <el-button icon="ele-Refresh" @click="resetQuery">éç½® </el-button> <!-- <el-button icon="ele-Plus" @click="openOptDlg()"> æ·»å </el-button> --> </el-form-item> </el-form> </template> <template #main> <div class="h-full flex-column"> <!-- <div class="flex-0 flex"> <ColFilter class="ml-auto" :columnList="columnList" /> </div> --> <el-table v-loading="tableLoading" ref="draggableTableRef" class="flex-auto" border :row-class-name="isDragStatus ? 'cursor-move' : 'cursor-pointer'" :data="displayTableData" highlight-current-row > <template v-for="item in columnList"> <el-table-column :key="item.prop" v-if="item.isShow ?? true" :type="item.type" :prop="item.prop" :label="item.label" :fixed="item.fixed" :width="item.width" :align="item.align" showOverflowTooltip > <template #default="scope" v-if="item.prop === 'operate'"> <div class="space-x-3 items-center flex"> <!-- <el-tooltip effect="dark" content="AMISä½ä»£ç ç¼è¾" placement="top"> <i class="ywifont ywicon-didaima !text-[21px] text-blue-400 cursor-pointer" @click="gotoAmisPage(scope.row)"></i> </el-tooltip> <el-tooltip effect="dark" content="æ°æ®å¯¹æ¥" placement="top"> <i class="ywifont ywicon-sjdj !text-[17px] text-blue-400 cursor-pointer" @click="editSqlClick(scope.row)"></i> </el-tooltip> <el-tooltip effect="dark" content="å¯¹è¯æµè¯" placement="top"> <i class="ywifont ywicon-ceshi !text-[20px] text-blue-400 cursor-pointer" @click="openChatTest(scope.row)"></i> </el-tooltip> --> <el-tooltip effect="dark" content="æ¥çé ç½®" placement="top"> <i class="ywifont ywicon-shezhi !text-[19px] text-blue-400 cursor-pointer" @click="openConfigDlg(scope.row)"></i> </el-tooltip> <el-tooltip effect="dark" content="è¿æ¥æ¨¡å" placement="top"> <i class="ywifont ywicon-lizi !text-[16px] text-blue-400 cursor-pointer" @click="openConnectDrawer(scope.row)"></i> </el-tooltip> <!-- <el-tooltip effect="dark" content="ç¼è¾" placement="top"> <i class="ywifont ywicon-bianji !text-[15px] text-blue-400 cursor-pointer" @click="openOptDlg(scope.row)"></i> </el-tooltip> <el-tooltip effect="dark" content="å é¤" placement="top"> <i class="ywifont ywicon-shanchu !text-[17px] text-red-400 cursor-pointer" @click=" () => { deleteCurrentRow(scope.row, '页é¢', supervisorAdminApi.deleteSupervisor, () => { const foundIndex = tableData.findIndex((item) => item === scope.row); foundIndex > -1 && tableData.splice(foundIndex, 1); }); } " ></i> </el-tooltip> --> </div> </template> </el-table-column> </template> </el-table> </div> </template> <LLMConfigDlg v-model="configDlgIsShow" :item="configDlgMapRow"></LLMConfigDlg> <!-- <OptDlg v-model="optDlgIsShow" :item="optDlgMapRow" @insert="insertOpt" @update="updateOpt"></OptDlg> --> <LLMConnectDrawer v-model="connectDrawerIsShow" :item="connectDrawerMapRow"></LLMConnectDrawer> </HMContainer> </template> <script setup lang="ts"> import { debounce, deleteCurrentRow } from '/@/utils/util'; import { onMounted, ref } from 'vue'; import { usePageDisplay } from '/@/hooks/usePageDisplay'; import { useQueryTable } from '/@/hooks/useQueryTable'; // import { useTableSort } from '/@/hooks/useTableSort'; // import { useValidateUniqueness } from '/@/hooks/useValidateUniqueness'; import { ElMessage } from 'element-plus'; import { SupervisorPublished } from '../../lowCode/sqlAmis/types'; // import OptDlg from './optDlg/OptDlg.vue'; import * as supervisorAdminApi from '/@/api/supervisorAdmin'; import { updatePublishStatus } from '/@/api/supervisorAdmin'; import { GetLLMInfoList } from '/@/api/admin/llm'; import HMContainer from '/@/components/layout/HMContainer.vue'; import ColFilter from '/@/components/table/colFilter/ColFilter.vue'; import type { TableCol } from '/@/components/table/colFilter/types'; import LLMConnectDrawer from './components/LLMConnectDrawer.vue'; import { useUpdateData } from '/@/hooks/useUpdateData'; import LLMConfigDlg from './components/LLMConfigDlg.vue'; const columnList = ref<TableCol[]>([ { type: 'index', label: 'åºå·', width: 55, fixed: 'left', align: 'center' }, { prop: 'title', label: 'æ é¢', fixed: 'left' }, { prop: 'operate', label: 'æä½', width: 200, fixed: 'right' }, ]); //#region ====================== è¡¨æ ¼æ°æ®ï¼table init ====================== const tableLoading = ref(false); const tableData = ref(null); const isDragStatus = ref(false); const getTableData = async () => { const res = await GetLLMInfoList(); tableData.value = Object.keys(res.values || {}).map((key) => { return { id: key, ...res.values[key], }; }); }; //#endregion //#region ====================== è¡¨æ ¼æ¥è¯¢ãæåºï¼search form init ====================== const queryParams = ref({ title: '', }); const { resetQuery, handleQueryTable, displayTableData } = useQueryTable(tableData, queryParams, () => { displayTableData.value = tableData.value; }); const debounceQueryTable = debounce(handleQueryTable, 400); //#endregion //#region ====================== æ¥è¯¢å¿«æ·é® ====================== const queryFormRef = ref(null); const pressEnterSearch = (ev: KeyboardEvent) => { if (ev.key === 'Enter') { handleQueryTable(); } }; usePageDisplay( () => { queryFormRef.value?.$el?.addEventListener('keypress', pressEnterSearch); }, () => { queryFormRef.value?.$el?.removeEventListener('keypress', pressEnterSearch); } ); //#endregion //#region ====================== æ·»å ä¿®æ¹æä½ ====================== const optDlgIsShow = ref(false); const optDlgMapRow = ref(null); const openOptDlg = (row?: any) => { optDlgMapRow.value = row; optDlgIsShow.value = true; }; const updateOpt = (formValue) => { const foundIndex = tableData.value.findIndex((item) => item.id === formValue.id); if (foundIndex > -1) { tableData.value[foundIndex] = { ...tableData.value[foundIndex], ...formValue, }; } }; const insertOpt = (newData) => { tableData.value.unshift({ ...newData, published: SupervisorPublished.N }); }; //#endregion const updatePublishedById = (id: string, published: SupervisorPublished) => { const row = tableData.value.find((item) => item.id === id); if (row) { row.published = published; } }; //#region ====================== æ¹ååå¸ç¶æ ====================== const publishStatusChange = async (published: SupervisorPublished, id, index) => { const res = await updatePublishStatus( { id: id, publish: published, }, { loading: false, } ); const origin = published === SupervisorPublished.Y ? SupervisorPublished.N : SupervisorPublished.Y; const final = res.publish ?? origin; if (final === origin) { ElMessage.warning('æä½å¤±è´¥' + (res.fail_msg ? `ï¼${res.fail_msg}` : '')); return; } tableData.value[index].published = final; published === SupervisorPublished.Y ? ElMessage.success('å叿å') : ElMessage.info('已忶åå¸'); }; //#endregion //#region ====================== æ´æ°åå¸ç¶æ ====================== useUpdateData({ event: 'supervisor.publish', updateFun({ id, published }) { updatePublishedById(id, published); }, }); //#endregion //#region ====================== 大模åé ç½® ====================== const configDlgIsShow = ref(false); const configDlgMapRow = ref(null); const openConfigDlg = (row?: any) => { configDlgMapRow.value = row; configDlgIsShow.value = true; }; //#endregion //#region ====================== 大模åè¿æ¥ ====================== const connectDrawerIsShow = ref(false); const connectDrawerMapRow = ref(null); const openConnectDrawer = (row?: any) => { connectDrawerMapRow.value = row; connectDrawerIsShow.value = true; }; //#endregion onMounted(() => { getTableData(); }); </script> <style scoped lang="scss"></style> src/views/project/yw/systemManage/llmMgr/components/LLMConfigDlg.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,43 @@ <template> <yw-dialog v-model="isShow" :showFooter="false" width="500" :title="title"> <el-form label-width="76" v-if="item.config"> <el-form-item v-for="key in Object.keys(item.config)" :label="keyMapLabel[key]" :key="key"> <el-input v-model="item.config[key]" readonly /> </el-form-item> </el-form> </yw-dialog> </template> <script setup lang="ts" name="LLMConfigDlg"> import _ from 'lodash'; import { computed, ref, watch } from 'vue'; import ywDialog from '/@/components/dialog/yw-dialog.vue'; const props = defineProps(['item']); const isShow = defineModel({ type: Boolean, }); const keyMapLabel = { key: 'å¯é¥', base_url: 'åºç¡URL', proxy: '代ç', }; const title = computed(() => props.item?.title + 'ââé ç½®'); // è®¡ç®æé¿çlabel宽度 // const labelWidth = computed(() => { // const labels = Object.keys(props.item?.config ?? {}).map((key) => keyMapLabel[key]); // const maxLengthLabel = labels.reduce((prev, current) => { // return prev.length > current.length ? prev : current; // }, ''); // // æ¯ä¸ªä¸æå符æ16px计ç®,é¢å¤å 20pxçç½ // return `${maxLengthLabel.length * 16 + 20}px`; // }); </script> <style scoped lang="scss"> :deep(.el-card__body) { position: relative; } </style> src/views/project/yw/systemManage/llmMgr/components/LLMConnectDrawer.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,120 @@ <template> <div class="custom-drawer"> <el-drawer v-model="drawerIsShow" direction="rtl" size="40%"> <template #header> <div> <i class="ywifont ywicon-lizi !text-[15px] text-blue-400 cursor-pointer font-bold"></i> <!-- <SvgIcon name="ele-User" :size="16" style="margin-right: 3px; display: inline; vertical-align: middle" /> --> <span> {{ `ã${props.item?.title}ãæ¨¡å` }} </span> </div> </template> <div class="flex-column h-full"> <div class="flex-0 flex-col flex"> <el-form :inline="true" :model="queryParams"> <el-form-item label="æ é¢" prop="title"> <el-input v-model="queryParams.title" style="width: 226.4px" placeholder="æ é¢" clearable @input="debounceQueryTable" /> </el-form-item> </el-form> <!-- <span class="mt-[-12px] mb-[12px]">å ±æ {{ displayTableData.length }} æ¡æ°æ®</span> --> </div> <el-table class="flex-auto" size="small" v-loading="accountTableLoading" border :data="displayTableData" style="width: 100%"> <el-table-column label="åºå·" fixed="left" width="55" show-overflow-tooltip> <template #default="scope"> {{ scope.$index + 1 }} </template> </el-table-column> <el-table-column prop="title" width="120" label="æ é¢" fixed="left" show-overflow-tooltip /> <el-table-column prop="class" label="ç±»" show-overflow-tooltip /> <el-table-column label="æä½" width="80" fixed="right"> <template #default="scope"> <div class="space-x-3 items-center flex"> <el-tooltip effect="dark" content="æ¥çé ç½®" placement="top"> <i class="ywifont ywicon-shezhi !text-[19px] text-blue-400 cursor-pointer" @click="openModelConfigDlg(scope.row)" ></i> </el-tooltip> </div> </template> </el-table-column> </el-table> </div> </el-drawer> <teleport to="body"> <ModelConfigDlg v-model="modelConfigDlg" :item="modelConfigDlgItem" /> </teleport> </div> </template> <script setup lang="ts"> import { ref, watch } from 'vue'; import { getUserSampleListByPost } from '/@/api/sampleAdmin/index'; import { useQueryTable } from '/@/hooks/useQueryTable'; import { convertListToTree, debounce, travelTree } from '/@/utils/util'; import { onMounted } from 'vue'; import { getSceneGroupTreeByPost } from '/@/api/scene'; import ModelConfigDlg from './ModelConfigDlg.vue'; const props = defineProps(['item']); //#region ====================== ç¨æ·è´¦æ· ====================== const drawerIsShow = defineModel('modelValue', { type: Boolean, default: false, }); const accountTableData = ref([]); const accountTableLoading = ref(false); const getSystemAccountByUserID = async () => { accountTableData.value = Object.keys(props.item?.connects ?? {}).map((key) => { return { id: key, ...props.item?.connects[key], }; }); }; //#region ====================== æ¥è¯¢ ====================== const getEmptyParams = () => { return { title: '', }; }; const queryParams = ref(getEmptyParams()); const { resetQuery, handleQueryTable, displayTableData } = useQueryTable(accountTableData, queryParams, () => { displayTableData.value = accountTableData.value; }); const debounceQueryTable = debounce(handleQueryTable, 400); const groupChange = (val) => { handleQueryTable(); }; //#endregion const groupTree = ref(null); watch( () => drawerIsShow.value, (val) => { if (!val) { accountTableData.value = []; queryParams.value = getEmptyParams(); return; } getSystemAccountByUserID(); } ); //#endregion //#region ====================== æå¼æ¨¡åé ç½®å¯¹è¯æ¡ ====================== const modelConfigDlg = ref(false); const modelConfigDlgItem = ref(null); const openModelConfigDlg = (row) => { modelConfigDlg.value = true; modelConfigDlgItem.value = row; }; //#endregion </script> <style scoped lang="scss"></style> src/views/project/yw/systemManage/llmMgr/components/ModelConfigDlg.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,39 @@ <template> <yw-dialog v-model="isShow" :showFooter="false" width="500" :title="title"> <el-form label-width="56" v-if="item.config"> <el-form-item v-for="key in Object.keys(item.config)" :label="keyMapLabel[key]" :key="key"> <el-input v-model="item.config[key]" readonly /> </el-form-item> </el-form> </yw-dialog> </template> <script setup lang="ts" name="ModelConfigDlg"> import _ from 'lodash'; import { computed, ref, watch } from 'vue'; import ywDialog from '/@/components/dialog/yw-dialog.vue'; const props = defineProps(['item']); const isShow = defineModel({ type: Boolean, }); const keyMapLabel = { model: '模å', }; const title = computed(() => props.item?.title + 'ââé ç½®'); // è®¡ç®æé¿çlabel宽度 // const labelWidth = computed(() => { // const labels = ['模å']; // const maxLengthLabel = labels.reduce((prev, current) => { // return prev.length > current.length ? prev : current; // }, ''); // // æ¯ä¸ªä¸æå符æ16px计ç®,é¢å¤å 20pxçç½ // return `${maxLengthLabel.length * 16 + 20}px`; // }); </script> <style scoped lang="scss"> :deep(.el-card__body) { position: relative; } </style>