diff --git a/ui/src/assets/iconfont.js b/ui/src/assets/iconfont.js
index 63b33493f48..61442f80f52 100644
--- a/ui/src/assets/iconfont.js
+++ b/ui/src/assets/iconfont.js
@@ -1 +1 @@
-window._iconfont_svg_string_5200172='',(h=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,v,t,i,c,d=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_5200172,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?d(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),o()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=o,i=h.document,c=!1,e(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,z())})}function z(){c||(c=!0,t())}function e(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(e,50)}z()}})(window);
\ No newline at end of file
+window._iconfont_svg_string_5200172='',(h=>{var a=(l=(l=document.getElementsByTagName("script"))[l.length-1]).getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var o,v,t,i,c,d=function(a,l){l.parentNode.insertBefore(a,l)};if(a&&!h.__iconfont__svg__cssinject__){h.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,l=document.createElement("div");l.innerHTML=h._iconfont_svg_string_5200172,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(a=document.body).firstChild?d(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),o()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=o,i=h.document,c=!1,e(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,z())})}function z(){c||(c=!0,t())}function e(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(e,50)}z()}})(window);
\ No newline at end of file
diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md
index 919db027942..2f12372c979 100644
--- a/ui/src/components/COMPONENT_README.md
+++ b/ui/src/components/COMPONENT_README.md
@@ -320,6 +320,8 @@ Esc 或取消清理草稿;`loading` 默认为 false,为 true 时禁止创建
`maxTableHeight` 表示窗口中除表格外需要扣除的高度,默认为 `250`;组件会在窗口尺寸变化时
重新计算 `max-height`。传入 `resizable` 后启用列宽拖拽,并隐藏为拖拽借用的原生边框视觉。
+右侧固定列(`fixed="right"`,用于操作栏)统一禁止拖拽调整宽度,其他列保留原有配置。
+表格最右侧外边界统一禁止拖拽,即使最后一列不是固定操作列也不开放该边界。
仅开启 `resizable` 时,表头保持单行,拖拽下限按当前标题文字、排序/筛选图标、间距及内边距
计算;拖拽线与最终列宽均不能小于该宽度,原生 `header-dragend` 继续透传。
`resizable` 采用白名单式启用:只有需求明确指定的页面级表格才能开启;未明确指定的表格,以及
diff --git a/ui/src/components/global/mk-table/index.vue b/ui/src/components/global/mk-table/index.vue
index 6a0228f4475..999825b4724 100644
--- a/ui/src/components/global/mk-table/index.vue
+++ b/ui/src/components/global/mk-table/index.vue
@@ -117,7 +117,7 @@ const slots = defineSlots<{
'footer-batch-actions'?: () => VNode[]
}>()
-/** 表头排序统一交给调用方;在 Element Plus 排序前转换,避免重排当前页。 */
+/** 统一列配置:右侧固定操作列禁用调宽,表头排序交给调用方。 */
function normalizeColumn(column: VNode): VNode {
if (column.type === Fragment && Array.isArray(column.children)) {
return h(
@@ -129,7 +129,10 @@ function normalizeColumn(column: VNode): VNode {
if (column.type !== ElTableColumn) return column
const sortable = column.props?.sortable
- const normalizedColumn = cloneVNode(column, sortable === true || sortable === '' ? { sortable: 'custom' } : undefined)
+ const normalizedColumn = cloneVNode(column, {
+ ...(sortable === true || sortable === '' ? { sortable: 'custom' } : {}),
+ ...(column.props?.fixed === 'right' ? { resizable: false } : {}),
+ })
const columnSlots = column.children
if (columnSlots && !Array.isArray(columnSlots) && typeof columnSlots === 'object' && typeof columnSlots.default === 'function') {
const defaultSlot = columnSlots.default
@@ -270,6 +273,7 @@ defineExpose({ clearSelection, tableRef })
:row-key="props.rowKey"
v-bind="$attrs"
:border="props.resizable"
+ :allow-drag-last-column="false"
@select="handleSelect"
@selection-change="handleSelectionChange"
@pointerdown.capture="handlePointerDown"
diff --git a/ui/src/layout/sidebar/SystemSidebar.vue b/ui/src/layout/sidebar/SystemSidebar.vue
index 6623b2752cf..667e4df5890 100644
--- a/ui/src/layout/sidebar/SystemSidebar.vue
+++ b/ui/src/layout/sidebar/SystemSidebar.vue
@@ -28,7 +28,6 @@ const getSystemMenuIcon = (systemMenuItem: LayoutMenuItem) =>
:collapse-transition="false"
:default-active="systemActiveMenuPath"
router
- :persistent="false"
>
@@ -129,7 +128,6 @@ const getSystemMenuIcon = (systemMenuItem: LayoutMenuItem) =>
&__title {
border-radius: var(--el-border-radius-base);
- color: var(--el-text-color-primary);
height: auto;
line-height: 18px;
padding: 11px calc(var(--spacing) * 2) !important;
@@ -138,6 +136,12 @@ const getSystemMenuIcon = (systemMenuItem: LayoutMenuItem) =>
background-color: var(--mk-N900-transparent-10);
}
}
+ &.is-active {
+ .el-sub-menu__title {
+ color: var(--el-color-primary);
+ font-weight: 500;
+ }
+ }
.el-icon {
margin-right: calc(var(--spacing) * 2);
diff --git a/ui/src/router/admin/system/index.ts b/ui/src/router/admin/system/index.ts
index 9b7d30c567e..07938efc60d 100644
--- a/ui/src/router/admin/system/index.ts
+++ b/ui/src/router/admin/system/index.ts
@@ -30,6 +30,7 @@ export const systemRoutes: RouteRecordRaw = {
meta: {
title: '身份与权限',
icon: 'icon_account_outlined',
+ activeIcon: 'icon_account_filled',
order: 10,
permission: () => {
return (
@@ -148,6 +149,8 @@ export const systemRoutes: RouteRecordRaw = {
meta: {
title: '资源管理',
icon: 'icon_project-settings-outlined',
+ activeIcon: 'icon_project-settings-filled',
+
order: 20,
resourceScope: 'system-resource',
permission: () => {
@@ -190,6 +193,7 @@ export const systemRoutes: RouteRecordRaw = {
meta: {
title: '共享资源',
icon: 'icon_folder-share_outlined',
+ activeIcon: 'icon_folder-share_filled',
order: 30,
resourceScope: 'system-shared',
permission: () => {
@@ -228,6 +232,7 @@ export const systemRoutes: RouteRecordRaw = {
meta: {
title: '对话端管理',
icon: 'icon_contacts_outlined',
+ activeIcon: 'icon_contacts_filled',
order: 40,
permission: () => {
return perm.system.chatUser.read() || perm.system.chatUserGroup.read() || perm.system.chatAuth.read() || perm.system.portal.read()
@@ -268,6 +273,7 @@ export const systemRoutes: RouteRecordRaw = {
meta: {
title: '系统设置',
icon: 'icon_setting',
+ activeIcon: 'icon_setting_filled',
order: 50,
permission: () => {
return perm.system.loginAuth.read() || perm.system.appearance.read() || perm.system.email.read()