diff --git a/ui/src/assets/iconfont.js b/ui/src/assets/iconfont.js index 03897e75ce1..f3e5118851f 100644 --- a/ui/src/assets/iconfont.js +++ b/ui/src/assets/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_5200172='',(l=>{var a=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var o,v,t,i,c,d=function(a,h){h.parentNode.insertBefore(a,h)};if(a&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,h=document.createElement("div");h.innerHTML=l._iconfont_svg_string_5200172,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?d(h,a.firstChild):a.appendChild(h))},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=l.document,c=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())})}function e(){c||(c=!0,t())}function m(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}e()}})(window); \ No newline at end of file +window._iconfont_svg_string_5200172='',(l=>{var a=(h=(h=document.getElementsByTagName("script"))[h.length-1]).getAttribute("data-injectcss"),h=h.getAttribute("data-disable-injectsvg");if(!h){var o,v,t,i,c,d=function(a,h){h.parentNode.insertBefore(a,h)};if(a&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}o=function(){var a,h=document.createElement("div");h.innerHTML=l._iconfont_svg_string_5200172,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(a=document.body).firstChild?d(h,a.firstChild):a.appendChild(h))},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=l.document,c=!1,m(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,e())})}function e(){c||(c=!0,t())}function m(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(m,50)}e()}})(window); \ No newline at end of file diff --git a/ui/src/components.d.ts b/ui/src/components.d.ts index e7165ea46b7..554e9297c02 100644 --- a/ui/src/components.d.ts +++ b/ui/src/components.d.ts @@ -24,6 +24,7 @@ declare module 'vue' { MkFilterableDropdown: typeof import('./components/global/mk-filterable-dropdown/index.vue')['default'] MkIcon: typeof import('./components/global/mk-icon/index.vue')['default'] MkInfiniteScroll: typeof import('./components/global/mk-infinite-scroll/index.vue')['default'] + MkListItem: typeof import('./components/global/mk-list-item/index.vue')['default'] MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default'] MkStatusLabel: typeof import('./components/global/mk-status-label/index.vue')['default'] MkTable: typeof import('./components/global/mk-table/index.vue')['default'] @@ -49,6 +50,7 @@ declare global { const MkFilterableDropdown: typeof import('./components/global/mk-filterable-dropdown/index.vue')['default'] const MkIcon: typeof import('./components/global/mk-icon/index.vue')['default'] const MkInfiniteScroll: typeof import('./components/global/mk-infinite-scroll/index.vue')['default'] + const MkListItem: typeof import('./components/global/mk-list-item/index.vue')['default'] const MkSearchInput: typeof import('./components/global/mk-search-input/index.vue')['default'] const MkStatusLabel: typeof import('./components/global/mk-status-label/index.vue')['default'] const MkTable: typeof import('./components/global/mk-table/index.vue')['default'] diff --git a/ui/src/components/COMPONENT_README.md b/ui/src/components/COMPONENT_README.md index da49bba5990..58f8f48f3c2 100644 --- a/ui/src/components/COMPONENT_README.md +++ b/ui/src/components/COMPONENT_README.md @@ -67,6 +67,8 @@ src/components/ │ │ └── index.vue # SVG Symbol 与 Element Plus 图标统一入口 │ ├── mk-infinite-scroll/ │ │ └── index.vue # 分页列表滚动触底加载与结束状态 +│ ├── mk-list-item/ +│ │ └── index.vue # 列表与业务分组列表复用的行结构 │ ├── mk-view-layout/ │ │ ├── index.vue # 路由页面标题、操作区和内容区统一结构 │ │ └── layout-aside.vue # 页面可选左侧栏结构 @@ -79,8 +81,7 @@ src/components/ │ └── mk-tag-group/ │ └── index.vue # 标签折叠和剩余标签浮层 ├── mk-search-list/ -│ ├── index.vue # 搜索框与剩余空间滚动列表,手动导入 -│ └── mk-list-item.vue # 列表与业务分组列表复用的行结构 +│ └── index.vue # 搜索框与剩余空间滚动列表,手动导入 ├── mk-form-list/ │ └── index.vue # 可动态增删的表单行列表,手动导入 ├── codemirror-editor/ @@ -97,7 +98,6 @@ Vue 模板中使用,不需要手动导入。其他共享组件必须从具体 ```ts import MkSearchList from '@/components/mk-search-list/index.vue' -import MkListItem from '@/components/mk-search-list/mk-list-item.vue' import MkFormList from '@/components/mk-form-list/index.vue' import CodemirrorEditor from '@/components/codemirror-editor/index.vue' import MkSourceCard from '@/components/mk-source-card/index.vue' @@ -201,10 +201,11 @@ ID 和样式类渲染 `title`。内容区域超出最大高度后显示滚动条 ### MkDrawer -全局抽屉组件,统一使用 `el-scrollbar` 包裹内容并为默认插槽提供 `p-6` 内边距。默认显示关闭 -按钮、关闭时销毁内容,同时禁止点击遮罩或按 Escape 关闭;这些默认行为可以通过同名 Props -覆盖。Element Plus Drawer 的其他属性和事件通过 `$attrs` 透传,`header`、默认和 `footer` -插槽保持可用。 +全局抽屉组件,统一使用 `el-scrollbar` 包裹内容并为默认插槽提供 `p-6` 内边距。通过 +`content-class` 可以覆盖内容容器样式;全高布局可传入 `content-class="h-full p-0"`,再由 +`MkViewLayout` 管理内边距和滚动区域。默认显示关闭按钮、关闭时销毁内容,同时禁止点击遮罩或按 +Escape 关闭;这些默认行为可以通过同名 Props 覆盖。Element Plus Drawer 的其他属性和事件通过 +`$attrs` 透传,`header`、默认和 `footer` 插槽保持可用。 ```vue @@ -389,6 +390,26 @@ Element Plus 的 `v-infinite-scroll`。组件通过 `v-model` 管理已经加载 ``` +### MkListItem + +提供列表行的统一间距、悬停状态、选中状态和可选操作区。仅自定义默认插槽时,可以只传 +`active` 并监听 `click`;不需要补充无实际用途的 `row`、`label-field` 或 `index`。 + +```vue + + + 共享模型 + +``` + +数据驱动使用时传入 `row`。`label-field` 默认读取 `name`,`index` 默认为 `0`;未提供默认插槽时 +组件显示对应字段文本。`action` 和 `action-dropdown` 插槽需要配合 `row` 使用,并接收 `row`、 +`index`。 + +```vue + +``` + ### MkSearchInput 带默认搜索图标的输入框。`placeholder` 默认为“搜索”,组件固定支持清空;`v-model`、其他属性 @@ -580,26 +601,6 @@ const roleSettings = defineModel<{ roleId: string; workspaceIds: string[] }[]>({ `addText` 设置添加按钮文案。删除按钮及第一行与后续行的对齐由组件统一处理。 -### MkListItem - -提供列表行的统一间距、悬停状态、选中状态和可选操作区。仅自定义默认插槽时,可以只传 -`active` 并监听 `click`;不需要补充无实际用途的 `row`、`label-field` 或 `index`。 - -```vue - - - 共享模型 - -``` - -数据驱动使用时传入 `row`。`label-field` 默认读取 `name`,`index` 默认为 `0`;未提供默认插槽时 -组件显示对应字段文本。`action` 和 `action-dropdown` 插槽需要配合 `row` 使用,并接收 `row`、 -`index`。 - -```vue - -``` - ### MkSearchList 组合搜索框和占满剩余空间的滚动列表。传入 `data` 时,组件默认按 `name` 过滤并按 diff --git a/ui/src/components/business/folder-tree/VirtualizedTree.vue b/ui/src/components/business/folder-tree/VirtualizedTree.vue index 1bd36ca65b8..54d941d0c07 100644 --- a/ui/src/components/business/folder-tree/VirtualizedTree.vue +++ b/ui/src/components/business/folder-tree/VirtualizedTree.vue @@ -4,7 +4,6 @@ import { CaretBottom } from '@element-plus/icons-vue' import { Draggable, dragContext } from '@he-tree/vue' import '@he-tree/vue/style/default.css' import type { FolderItem } from '@/api/types' -import MkListItem from '@/components/mk-search-list/mk-list-item.vue' defineOptions({ name: 'FolderVirtualizedTree' }) interface FolderTreeNode extends Omit { diff --git a/ui/src/components/business/folder-tree/index.vue b/ui/src/components/business/folder-tree/index.vue index 238bf2f48b4..c0ed5328f22 100644 --- a/ui/src/components/business/folder-tree/index.vue +++ b/ui/src/components/business/folder-tree/index.vue @@ -6,7 +6,6 @@ import { FOLDER_SOURCE } from '@/api/enums' import { FOLDER_SORT, type FolderSort } from './types' import { FOLDER_ENTRIES, FOLDER_ENTRY_ID } from '@/constants' import { MsgSuccess, MsgConfirm } from '@/utils/message' -import MkListItem from '@/components/mk-search-list/mk-list-item.vue' import VirtualizedTree from './VirtualizedTree.vue' import FolderFormDialog from './FolderFormDialog.vue' import { useStore } from '@/stores' diff --git a/ui/src/components/global/mk-drawer/index.vue b/ui/src/components/global/mk-drawer/index.vue index 71d477c1658..ef747cbe877 100644 --- a/ui/src/components/global/mk-drawer/index.vue +++ b/ui/src/components/global/mk-drawer/index.vue @@ -1,6 +1,10 @@ - + diff --git a/ui/src/views/system/identity/roles/RoleListView.vue b/ui/src/views/system/identity/roles/RoleListView.vue index 6276d9c9f33..88daee49554 100644 --- a/ui/src/views/system/identity/roles/RoleListView.vue +++ b/ui/src/views/system/identity/roles/RoleListView.vue @@ -4,7 +4,6 @@ import RoleApi from '@/api/admin/system/role' import { ROLE_TYPE } from '@/api/enums' import type { RoleItem, RoleType } from '@/api/types' import { ROLE_TYPE_LABELS } from '@/constants' -import MkListItem from '@/components/mk-search-list/mk-list-item.vue' import { MsgConfirm, MsgSuccess } from '@/utils/message' import RoleMemberList from './components/RoleMemberList.vue' import RolePermissionConfiguration from './components/RolePermissionConfiguration.vue'