Skip to content

Commit ef0ebf7

Browse files
feat: change ai menu
1 parent 4b3f8a9 commit ef0ebf7

File tree

15 files changed

+232
-121
lines changed

15 files changed

+232
-121
lines changed

core/constant/common.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,14 @@ var WebUrlMap = map[string]struct{}{
5757
"/apps/upgrade": {},
5858
"/apps/setting": {},
5959

60-
"/ai": {},
61-
"/ai/model": {},
62-
"/ai/gpu": {},
63-
"/ai/gpu/current": {},
64-
"/ai/gpu/history": {},
65-
"/ai/mcp": {},
66-
"/ai/model/tensorrt": {},
67-
"/ai/model/vllm": {},
68-
"/ai/model/ollama": {},
69-
"/ai/agents/agent": {},
70-
"/ai/agents/model": {},
60+
"/ai": {},
61+
"/ai/model/account": {},
62+
"/ai/model/local": {},
63+
"/ai/gpu": {},
64+
"/ai/gpu/current": {},
65+
"/ai/gpu/history": {},
66+
"/ai/mcp": {},
67+
"/ai/agents/agent": {},
7168

7269
"/containers": {},
7370
"/containers/container/operate": {},

core/init/migration/helper/menu.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ func LoadMenus() string {
1414
item := []dto.ShowMenu{
1515
{ID: "1", Disabled: true, Title: "menu.home", IsShow: true, Label: "Home-Menu", Path: "/", Sort: 100},
1616
{ID: "2", Disabled: true, Title: "menu.apps", IsShow: true, Label: "App-Menu", Path: "/apps/all", Sort: 200},
17-
{ID: "3", Disabled: false, Title: "menu.aiTools", IsShow: true, Label: "AI-Menu", Path: "/ai/model", Sort: 300,
17+
{ID: "3", Disabled: false, Title: "menu.aiTools", IsShow: true, Label: "AI-Menu", Path: "/ai/model/account", Sort: 300,
1818
Children: []dto.ShowMenu{
1919
{ID: "44", Disabled: false, Title: "aiTools.agents.agent", IsShow: true, Label: "Agents", Path: "/ai/agents/agent", Sort: 50},
20-
{ID: "41", Disabled: false, Title: "aiTools.model.localModel", IsShow: true, Label: "OllamaModel", Path: "/ai/model", Sort: 100},
20+
{ID: "41", Disabled: false, Title: "aiTools.model.model", IsShow: true, Label: "AIModel", Path: "/ai/model/account", Sort: 100},
2121
{ID: "42", Disabled: false, Title: "menu.mcp", IsShow: true, Label: "MCPServer", Path: "/ai/mcp", Sort: 200},
2222
{ID: "43", Disabled: false, Title: "aiTools.gpu.gpu", IsShow: true, Label: "GPU", Path: "/ai/gpu", Sort: 300},
2323
}},
@@ -66,7 +66,7 @@ func MenuSort() []dto.MenuLabelSort {
6666
{Label: "App-Menu", Sort: 200},
6767
{Label: "AI-Menu", Sort: 300},
6868
{Label: "Agents", Sort: 50},
69-
{Label: "OllamaModel", Sort: 100},
69+
{Label: "AIModel", Sort: 100},
7070
{Label: "MCPServer", Sort: 200},
7171
{Label: "GPU", Sort: 300},
7272
{Label: "Website-Menu", Sort: 400},

core/init/migration/migrate.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func Init() {
3535
migrations.AddEditionSetting,
3636
migrations.UpdateAiLocalModelMenuTitle,
3737
migrations.UpdateAiAgentsHideMenuTitle,
38+
migrations.UpdateAiModelMenuStructure,
3839
migrations.AddDocSourceSetting,
3940
})
4041
if err := m.Migrate(); err != nil {

core/init/migration/migrations/init.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,3 +877,96 @@ var UpdateAiAgentsHideMenuTitle = &gormigrate.Migration{
877877
).Error
878878
},
879879
}
880+
881+
var UpdateAiModelMenuStructure = &gormigrate.Migration{
882+
ID: "20260403-update-ai-model-menu-structure",
883+
Migrate: func(tx *gorm.DB) error {
884+
var menuJSON string
885+
if err := tx.Model(&model.Setting{}).Where("key = ?", "HideMenu").Pluck("value", &menuJSON).Error; err != nil {
886+
return err
887+
}
888+
if menuJSON == "" {
889+
return tx.Model(&model.Setting{}).Where("key = ?", "HideMenu").Update("value", helper.LoadMenus()).Error
890+
}
891+
892+
var menus []dto.ShowMenu
893+
if err := json.Unmarshal([]byte(menuJSON), &menus); err != nil {
894+
return tx.Model(&model.Setting{}).Where("key = ?", "HideMenu").Update("value", helper.LoadMenus()).Error
895+
}
896+
897+
for i := range menus {
898+
if menus[i].Label != "AI-Menu" {
899+
continue
900+
}
901+
menus[i].Path = "/ai/model/account"
902+
menus[i].Children = buildAiMenuChildren(menus[i].Children)
903+
break
904+
}
905+
906+
updatedJSON, err := json.Marshal(menus)
907+
if err != nil {
908+
return tx.Model(&model.Setting{}).Where("key = ?", "HideMenu").Update("value", helper.LoadMenus()).Error
909+
}
910+
return tx.Model(&model.Setting{}).Where("key = ?", "HideMenu").Update("value", string(updatedJSON)).Error
911+
},
912+
}
913+
914+
func buildAiMenuChildren(children []dto.ShowMenu) []dto.ShowMenu {
915+
return []dto.ShowMenu{
916+
normalizeAiMenuChild(children, dto.ShowMenu{
917+
ID: "44",
918+
Label: "Agents",
919+
Disabled: false,
920+
IsShow: true,
921+
Title: "aiTools.agents.agent",
922+
Path: "/ai/agents/agent",
923+
Sort: 50,
924+
}, "Agents"),
925+
normalizeAiMenuChild(children, dto.ShowMenu{
926+
ID: "41",
927+
Label: "AIModel",
928+
Disabled: false,
929+
IsShow: true,
930+
Title: "aiTools.model.model",
931+
Path: "/ai/model/account",
932+
Sort: 100,
933+
}, "AIModel", "OllamaModel"),
934+
normalizeAiMenuChild(children, dto.ShowMenu{
935+
ID: "42",
936+
Label: "MCPServer",
937+
Disabled: false,
938+
IsShow: true,
939+
Title: "menu.mcp",
940+
Path: "/ai/mcp",
941+
Sort: 200,
942+
}, "MCPServer"),
943+
normalizeAiMenuChild(children, dto.ShowMenu{
944+
ID: "43",
945+
Label: "GPU",
946+
Disabled: false,
947+
IsShow: true,
948+
Title: "aiTools.gpu.gpu",
949+
Path: "/ai/gpu",
950+
Sort: 300,
951+
}, "GPU"),
952+
}
953+
}
954+
955+
func normalizeAiMenuChild(children []dto.ShowMenu, fallback dto.ShowMenu, labels ...string) dto.ShowMenu {
956+
for _, child := range children {
957+
for _, label := range labels {
958+
if child.Label != label {
959+
continue
960+
}
961+
child.ID = fallback.ID
962+
child.Label = fallback.Label
963+
child.Disabled = fallback.Disabled
964+
child.Title = fallback.Title
965+
child.Path = fallback.Path
966+
child.Sort = fallback.Sort
967+
child.Children = nil
968+
return child
969+
}
970+
}
971+
return fallback
972+
}

frontend/src/routers/modules/ai.ts

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
import { Layout } from '@/routers/constant';
22

3-
const vllmModules = import.meta.glob('@/xpack/views/vllm/index.vue');
4-
const loadVllmView = () => {
5-
const loader = vllmModules['/src/xpack/views/vllm/index.vue'];
6-
if (loader) {
7-
return loader();
8-
}
9-
return import('@/views/ai/model/vllm/index.vue');
10-
};
11-
123
const databaseRouter = {
134
sort: 4,
145
path: '/ai',
156
name: 'AI-Menu',
167
component: Layout,
17-
redirect: '/ai/model',
8+
redirect: '/ai/model/account',
189
meta: {
1910
icon: 'p-jiqiren2',
2011
title: 'menu.aiTools',
@@ -31,23 +22,23 @@ const databaseRouter = {
3122
},
3223
},
3324
{
34-
path: '/ai/agents/model',
35-
name: 'AgentsModel',
36-
component: () => import('@/views/ai/agents/model/index.vue'),
25+
path: '/ai/model/account',
26+
name: 'AIModel',
27+
component: () => import('@/views/ai/model/index.vue'),
3728
meta: {
38-
title: 'aiTools.agents.account',
39-
activeMenu: '/ai/agents/agent',
29+
icon: 'p-moxing-menu',
30+
title: 'aiTools.model.model',
4031
requiresAuth: true,
4132
},
4233
},
4334
{
44-
path: '/ai/model/ollama',
45-
name: 'OllamaModel',
46-
component: () => import('@/views/ai/model/ollama/index.vue'),
35+
path: '/ai/model/local',
36+
hidden: true,
37+
name: 'LocalModel',
38+
component: () => import('@/views/ai/model/index.vue'),
4739
meta: {
48-
icon: 'p-moxing-menu',
4940
title: 'aiTools.model.localModel',
50-
activeMenu: '/ai/model/ollama',
41+
activeMenu: '/ai/model/account',
5142
requiresAuth: true,
5243
},
5344
},
@@ -61,28 +52,6 @@ const databaseRouter = {
6152
requiresAuth: true,
6253
},
6354
},
64-
{
65-
path: '/ai/model/tensorrt',
66-
hidden: true,
67-
name: 'TensorRTLLm',
68-
component: () => import('@/views/ai/model/tensorrt/index.vue'),
69-
meta: {
70-
title: 'aiTools.tensorRT.llm',
71-
activeMenu: '/ai/model/ollama',
72-
requiresAuth: true,
73-
},
74-
},
75-
{
76-
path: '/ai/model/vllm',
77-
hidden: true,
78-
name: 'Vllm',
79-
component: loadVllmView,
80-
meta: {
81-
title: 'vLLM',
82-
activeMenu: '/ai/model/ollama',
83-
requiresAuth: true,
84-
},
85-
},
8655
{
8756
path: '/ai/gpu/current',
8857
name: 'GPU',

frontend/src/utils/app.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ export const jumpToInstall = (type: string, key: string) => {
3232
case 'vllm':
3333
if (globalStore.isProductPro) {
3434
router.push({
35-
path: '/ai/model/vllm',
35+
path: '/ai/model/local',
3636
query: {
37+
tab: 'vllm',
3738
uncached: 'true',
3839
open: 'create',
3940
},

frontend/src/views/ai/agents/agent/index.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div>
3-
<RouterMenu />
3+
<RouterButton :buttons="headerButtons" />
44
<DockerStatus v-model:isActive="isActive" v-model:isExist="isExist" />
55
<LayoutContent v-loading="loading" v-if="isExist" :class="{ mask: !isActive }">
66
<template #leftToolBar>
@@ -173,7 +173,6 @@ import { SearchWithPage } from '@/api/interface';
173173
import { dateFormat, newUUID } from '@/utils/util';
174174
import { MsgSuccess } from '@/utils/message';
175175
176-
import RouterMenu from '@/views/ai/agents/index.vue';
177176
import AddDialog from '@/views/ai/agents/agent/add/index.vue';
178177
import DeleteDialog from '@/views/ai/agents/agent/delete/index.vue';
179178
import ConfigDrawer from '@/views/ai/agents/agent/config/index.vue';
@@ -209,6 +208,13 @@ const isExist = ref(false);
209208
const noApp = ref(false);
210209
const searchName = ref('');
211210
211+
const headerButtons = [
212+
{
213+
label: i18n.global.t('aiTools.agents.agent'),
214+
path: '/ai/agents/agent',
215+
},
216+
];
217+
212218
const buttons = [
213219
{
214220
label: i18n.global.t('menu.config'),

frontend/src/views/ai/agents/index.vue

Lines changed: 0 additions & 23 deletions
This file was deleted.

frontend/src/views/ai/agents/model/index.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<template>
22
<div>
3-
<RouterMenu />
43
<LayoutContent>
54
<template #leftToolBar>
65
<el-button type="primary" @click="openCreate">{{ $t('commons.button.create') }}</el-button>
@@ -54,7 +53,6 @@
5453
import { onMounted, reactive, ref } from 'vue';
5554
import { deleteAgentAccount, pageAgentAccounts } from '@/api/modules/ai';
5655
import { AI } from '@/api/interface/ai';
57-
import RouterMenu from '@/views/ai/agents/index.vue';
5856
import AddDialog from '@/views/ai/agents/model/add/index.vue';
5957
import ModelPoolDialog from '@/views/ai/agents/model/pool/index.vue';
6058
import { ElMessageBox } from 'element-plus';
Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,31 @@
11
<template>
22
<div>
33
<RouterButton :buttons="buttons" />
4-
<LayoutContent>
5-
<router-view></router-view>
6-
</LayoutContent>
4+
<component :is="currentComponent" />
75
</div>
86
</template>
97

108
<script lang="ts" setup>
9+
import { computed } from 'vue';
10+
import { useRoute } from 'vue-router';
11+
import i18n from '@/lang';
12+
import AccountView from '@/views/ai/agents/model/index.vue';
13+
import LocalView from '@/views/ai/model/local/index.vue';
14+
15+
const route = useRoute();
16+
1117
const buttons = [
1218
{
13-
label: 'Ollama',
14-
path: '/ai/model/ollama',
19+
label: i18n.global.t('aiTools.agents.account'),
20+
path: '/ai/model/account',
1521
},
1622
{
17-
label: 'vLLM',
18-
path: '/ai/model/vllm',
19-
},
20-
{
21-
label: 'TensorRT LLM',
22-
path: '/ai/model/tensorrt',
23+
label: i18n.global.t('aiTools.model.localModel'),
24+
path: '/ai/model/local',
2325
},
2426
];
27+
28+
const currentComponent = computed(() => {
29+
return route.path === '/ai/model/local' ? LocalView : AccountView;
30+
});
2531
</script>

0 commit comments

Comments
 (0)