From 0f79df04250094686e92ba19fd8b4ce2fb14aa1c Mon Sep 17 00:00:00 2001 From: xueyinfei <1207092115@qq.com> Date: Mon, 24 Nov 2025 20:51:35 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=A4=A7=E6=A8=A1=E5=9E=8B=E5=8F=82=E6=95=B0=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module_admin/entity/do/menu_do.py | 3 + .../module_admin/entity/vo/menu_vo.py | 2 + vue-fastapi-frontend/src/api/aichat/aichat.js | 2 +- .../src/views/system/menu/index.vue | 126 +++++++++++++++++- 4 files changed, 127 insertions(+), 6 deletions(-) diff --git a/vue-fastapi-backend/module_admin/entity/do/menu_do.py b/vue-fastapi-backend/module_admin/entity/do/menu_do.py index d3ccffa..3b914f8 100644 --- a/vue-fastapi-backend/module_admin/entity/do/menu_do.py +++ b/vue-fastapi-backend/module_admin/entity/do/menu_do.py @@ -1,6 +1,7 @@ from datetime import datetime from sqlalchemy import Column, DateTime, Integer, String from config.database import Base +from sqlalchemy.dialects.mysql import LONGTEXT class SysMenu(Base): @@ -30,3 +31,5 @@ class SysMenu(Base): update_by = Column(String(64), nullable=True, default='', comment='更新者') update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') remark = Column(String(500), nullable=True, default='', comment='备注') + desc = Column(String(500), nullable=True, default='', comment='页面描述') + link_params = Column(LONGTEXT, nullable=True, default='', comment='跳转参数') diff --git a/vue-fastapi-backend/module_admin/entity/vo/menu_vo.py b/vue-fastapi-backend/module_admin/entity/vo/menu_vo.py index 9dc8d75..ef07503 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/menu_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/menu_vo.py @@ -33,6 +33,8 @@ class MenuModel(BaseModel): update_by: Optional[str] = Field(default=None, description='更新者') update_time: Optional[datetime] = Field(default=None, description='更新时间') remark: Optional[str] = Field(default=None, description='备注') + desc: Optional[str] = Field(default=None, description='页面描述') + link_params: Optional[str] = Field(default=None, description='跳转参数') @NotBlank(field_name='menu_name', message='菜单名称不能为空') @Size(field_name='menu_name', min_length=0, max_length=50, message='菜单名称长度不能超过50个字符') diff --git a/vue-fastapi-frontend/src/api/aichat/aichat.js b/vue-fastapi-frontend/src/api/aichat/aichat.js index e32ea4e..e340261 100644 --- a/vue-fastapi-frontend/src/api/aichat/aichat.js +++ b/vue-fastapi-frontend/src/api/aichat/aichat.js @@ -50,7 +50,7 @@ export async function addChat(data) { } export async function postDataQuery(data) { return request({ - url: '/dataquery-api/chat/nl2sql_client_chat', + url: '/dataquery-api/datachat', method: 'post', data: data }) diff --git a/vue-fastapi-frontend/src/views/system/menu/index.vue b/vue-fastapi-frontend/src/views/system/menu/index.vue index 729f1f5..01d6d2c 100644 --- a/vue-fastapi-frontend/src/views/system/menu/index.vue +++ b/vue-fastapi-frontend/src/views/system/menu/index.vue @@ -64,6 +64,21 @@ + + + + @@ -305,9 +372,11 @@ const menuOptions = ref([]); const isExpandAll = ref(false); const refreshTable = ref(true); const iconSelectRef = ref(null); +const linkParamsDialog = ref(null); const data = reactive({ form: {}, + linkParam:{}, queryParams: { menuName: undefined, visible: undefined @@ -319,8 +388,47 @@ const data = reactive({ }, }); -const { queryParams, form, rules } = toRefs(data); +const { queryParams, form, rules, linkParam } = toRefs(data); + +function openLinkParamsDialog(tag,index){ + linkParam.value = { + tagIndex : -1, + paramEnName: '', + paramCnName:'', + paramType: '', + desc:'' + } + if (tag){ + linkParam.value = { + tagIndex : index, + paramEnName: tag.paramEnName, + paramCnName: tag.paramCnName, + paramType: tag.paramType, + desc: tag.desc + } + } + linkParamsDialog.value = true +} +function saveLinkParam(){ + let obj = { + paramEnName: linkParam.value.paramEnName, + paramCnName:linkParam.value.paramCnName, + paramType: linkParam.value.paramType, + desc: linkParam.value.desc} + if (linkParam.value.tagIndex === -1){ + if (!form.value.linkParams){ + form.value.linkParams = [] + } + form.value.linkParams.push(obj) + }else{ + form.value.linkParams[linkParam.value.tagIndex] = obj + } + linkParamsDialog.value = false +} +function handleClose(tag,index){ + form.value.linkParams.splice(index,1) +} /** 查询菜单列表 */ function getList() { loading.value = true; @@ -356,7 +464,9 @@ function reset() { isFrame: 1, isCache: 0, visible: "0", - status: "0" + status: "0", + desc:'', + linkParams: undefined }; proxy.resetForm("menuRef"); } @@ -402,7 +512,11 @@ async function handleUpdate(row) { reset(); await getTreeselect(); getMenu(row.menuId).then(response => { - form.value = response.data; + let obj = response.data; + if (obj.linkParams && obj.linkParams.length > 0){ + obj.linkParams = JSON.parse(obj.linkParams) + } + form.value = obj open.value = true; title.value = "修改菜单"; }); @@ -411,14 +525,16 @@ async function handleUpdate(row) { function submitForm() { proxy.$refs["menuRef"].validate(valid => { if (valid) { + let obj = JSON.parse(JSON.stringify(form.value)) + obj.linkParams = JSON.stringify(obj.linkParams) if (form.value.menuId != undefined) { - updateMenu(form.value).then(response => { + updateMenu(obj).then(response => { proxy.$modal.msgSuccess("修改成功"); open.value = false; getList(); }); } else { - addMenu(form.value).then(response => { + addMenu(obj).then(response => { proxy.$modal.msgSuccess("新增成功"); open.value = false; getList(); From a0af31af75e92b779dd1284038f26256d2d53c98 Mon Sep 17 00:00:00 2001 From: xueyinfei <1207092115@qq.com> Date: Tue, 25 Nov 2025 18:53:42 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=B7=AF=E7=94=B1=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/meta/metaInfo/index.vue | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue b/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue index 6c0db76..68d348c 100644 --- a/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue +++ b/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue @@ -847,7 +847,7 @@ import {getToken} from "@/utils/auth.js"; import {getDirectoryTree} from "@/api/metadataConfig/directory.js"; import {EditPen} from "@element-plus/icons-vue"; - + import { useRoute } from 'vue-router'; const data = reactive({ queryParams:{ ssysId:'', @@ -873,6 +873,7 @@ tags:[] } }) + const route = useRoute(); const { queryParams, currentMetaData } = toRefs(data); const loading = ref(true); const drawer = ref(false); @@ -1505,7 +1506,7 @@ } function handleQuery(){ queryParams.value.pageNum = 1; - getList() + return getList() } function resetQuery(){ queryParams.value ={ @@ -1552,7 +1553,7 @@ } } function getList(){ - getMetaDataList(queryParams.value).then(res=>{ + return getMetaDataList(queryParams.value).then(res=>{ dataList.value = res.data.rows let dbList = databaseList.value[0].children if (dataList.value.length>0){ @@ -1768,8 +1769,46 @@ } onMounted(async () => { await getDatabaseList() - handleQuery() + if(route.query){ + if (route.query.ssysId){ + queryParams.value.ssysId = route.query.ssysId + } + if (route.query.mdlName){ + queryParams.value.mdlName = route.query.mdlName + } + if (route.query.tabName){ + queryParams.value.tabName = route.query.tabName + } + handleQuery().then(()=>{ + console.log(dataList.value.length) + if (dataList.value.length === 1){ + showColumnDialog(dataList.value[0]) + } + }) + }else{ + await handleQuery() + } }) + watch( + () => route.query, + (newId) => { + console.log(route.query) + if (route.query.ssysId){ + queryParams.value.ssysId = route.query.ssysId + } + if (route.query.mdlName){ + queryParams.value.mdlName = route.query.mdlName + } + if (route.query.tabName){ + queryParams.value.tabName = route.query.tabName + } + handleQuery().then(()=>{ + if (dataList.value.length === 1){ + showColumnDialog(dataList.value[0]) + } + }) + } + ); From ddf97ac242dd67dc652ea837cf28fdd73015c8c4 Mon Sep 17 00:00:00 2001 From: xueyinfei <1207092115@qq.com> Date: Tue, 25 Nov 2025 20:08:17 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=B7=AF=E7=94=B1=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module_admin/entity/vo/login_vo.py | 1 + .../module_admin/service/login_service.py | 5 +++- vue-fastapi-frontend/src/utils/request.js | 4 ++-- .../src/views/aichat/MdRenderer.vue | 23 +++++++++++++++++++ .../src/views/meta/metaInfo/index.vue | 8 ++++++- 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/vue-fastapi-backend/module_admin/entity/vo/login_vo.py b/vue-fastapi-backend/module_admin/entity/vo/login_vo.py index fbd6e07..8d45f1b 100644 --- a/vue-fastapi-backend/module_admin/entity/vo/login_vo.py +++ b/vue-fastapi-backend/module_admin/entity/vo/login_vo.py @@ -63,6 +63,7 @@ class MenuTreeModel(MenuModel): class MetaModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) + id: Optional[int] = Field(default=None, description='菜单ID') title: Optional[str] = Field(default=None, description='设置路由在侧边栏和面包屑中展示的名字') icon: Optional[str] = Field(default=None, description='设置路由的图标') no_cache: Optional[bool] = Field(default=None, description='设置为true,则不会被 缓存') diff --git a/vue-fastapi-backend/module_admin/service/login_service.py b/vue-fastapi-backend/module_admin/service/login_service.py index 4879311..ee9e5ef 100644 --- a/vue-fastapi-backend/module_admin/service/login_service.py +++ b/vue-fastapi-backend/module_admin/service/login_service.py @@ -319,6 +319,7 @@ class LoginService: component=RouterUtil.get_component(permission), query=permission.query, meta=MetaModel( + id=permission.menu_id, title=permission.menu_name, icon=permission.icon, noCache=True if permission.is_cache == 1 else False, @@ -338,6 +339,7 @@ class LoginService: component=permission.component, name=RouterUtil.get_route_name(permission.route_name, permission.path), meta=MetaModel( + id=permission.menu_id, title=permission.menu_name, icon=permission.icon, noCache=True if permission.is_cache == 1 else False, @@ -348,7 +350,7 @@ class LoginService: children_list.append(children) router.children = children_list elif permission.parent_id == 0 and RouterUtil.is_inner_link(permission): - router.meta = MetaModel(title=permission.menu_name, icon=permission.icon) + router.meta = MetaModel(id=permission.menu_id, title=permission.menu_name, icon=permission.icon) router.path = '/' children_list: List[RouterModel] = [] router_path = RouterUtil.inner_link_replace_each(permission.path) @@ -357,6 +359,7 @@ class LoginService: component=MenuConstant.INNER_LINK, name=RouterUtil.get_route_name(permission.route_name, permission.path), meta=MetaModel( + id=permission.menu_id, title=permission.menu_name, icon=permission.icon, link=permission.path if RouterUtil.is_http(permission.path) else None, diff --git a/vue-fastapi-frontend/src/utils/request.js b/vue-fastapi-frontend/src/utils/request.js index d08f010..3c2125d 100644 --- a/vue-fastapi-frontend/src/utils/request.js +++ b/vue-fastapi-frontend/src/utils/request.js @@ -17,11 +17,11 @@ const service = axios.create({ // axios中请求配置有baseURL选项,表示请求URL公共部分 // baseURL: import.meta.env.VITE_APP_BASE_API, // 超时 - timeout: 100000 + timeout: 180000 }) const rawAxios = axios.create({ baseURL: "/default-api", - timeout: 100000 + timeout: 180000 }); rawAxios.interceptors.request.use(config => { diff --git a/vue-fastapi-frontend/src/views/aichat/MdRenderer.vue b/vue-fastapi-frontend/src/views/aichat/MdRenderer.vue index c747797..dc4cd35 100644 --- a/vue-fastapi-frontend/src/views/aichat/MdRenderer.vue +++ b/vue-fastapi-frontend/src/views/aichat/MdRenderer.vue @@ -20,6 +20,9 @@ {{ doc.file_name }} +
+ {{'跳转到:'+ item.content.menuName}} +
@@ -34,7 +37,9 @@ import chatTable from './chatTable.vue' import htmlCharts from './htmlCharts.vue' import {Download, FullScreen} from "@element-plus/icons-vue"; import { ref, watch} from 'vue' +import { useRouter } from 'vue-router'; const { proxy } = getCurrentInstance(); +const router = useRouter() const props = defineProps({ source: Array, is_large: Boolean, @@ -46,6 +51,24 @@ function fullscreenG6(data){ emit('fullscreenG6',data) } +function jumpToPath(content){ + let routes = router.getRoutes() + let obj = routes.find(route =>{return route.meta?.id === content.id;}) + if (obj){ + let path = '?' + let params = content.params + for (const key of params.keys()){ + path += key+"="+params[key] + "&" + } + path = path.slice(0, -1); + path = obj.path + path + router.push(path) + }else { + proxy.$modal.msgWarning("该页面未授权,无法访问"); + } + +} + function downLoadFile(doc){ let data = {file:doc.file_name,bucket: doc.bucket,sessionId: doc.session_id} proxy.download("/default-api/aichat/file/download", { diff --git a/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue b/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue index 68d348c..4fa456e 100644 --- a/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue +++ b/vue-fastapi-frontend/src/views/meta/metaInfo/index.vue @@ -847,7 +847,7 @@ import {getToken} from "@/utils/auth.js"; import {getDirectoryTree} from "@/api/metadataConfig/directory.js"; import {EditPen} from "@element-plus/icons-vue"; - import { useRoute } from 'vue-router'; + import { useRoute} from 'vue-router'; const data = reactive({ queryParams:{ ssysId:'', @@ -874,6 +874,7 @@ } }) const route = useRoute(); + // const router = useRouter() const { queryParams, currentMetaData } = toRefs(data); const loading = ref(true); const drawer = ref(false); @@ -1769,6 +1770,11 @@ } onMounted(async () => { await getDatabaseList() + + +// 获取所有路由记录(包含动态添加的路由) +// const allRoutes = router.getRoutes() +// console.log(allRoutes) if(route.query){ if (route.query.ssysId){ queryParams.value.ssysId = route.query.ssysId From a754365fc1a3898e6e8d75eb33c2636c9652e090 Mon Sep 17 00:00:00 2001 From: xueyinfei <1207092115@qq.com> Date: Tue, 25 Nov 2025 20:08:57 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=B7=AF=E7=94=B1=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vue-fastapi-frontend/src/views/aichat/MdRenderer.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vue-fastapi-frontend/src/views/aichat/MdRenderer.vue b/vue-fastapi-frontend/src/views/aichat/MdRenderer.vue index dc4cd35..332262b 100644 --- a/vue-fastapi-frontend/src/views/aichat/MdRenderer.vue +++ b/vue-fastapi-frontend/src/views/aichat/MdRenderer.vue @@ -21,7 +21,7 @@
- {{'跳转到:'+ item.content.menuName}} + {{'跳转到:'+ item.content.menuName}}