commit
a3652b7971
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -160,6 +160,7 @@
|
||||
"stylelint.enable": true,
|
||||
"stylelint.packageManager": "pnpm",
|
||||
"stylelint.validate": ["css", "less", "postcss", "scss", "vue"],
|
||||
"stylelint.customSyntax": "postcss-html",
|
||||
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
|
||||
|
||||
"typescript.inlayHints.enumMemberValues.enabled": true,
|
||||
|
@ -1,4 +1,8 @@
|
||||
# 1.0.1
|
||||
# 1.1.0
|
||||
|
||||
**FEATURES**
|
||||
|
||||
- 支持离线图标功能(全局可在内网环境中使用)
|
||||
|
||||
**BUG FIXES**
|
||||
|
||||
|
@ -8,6 +8,8 @@ v5版本采用分仓(包)目录结构, 具体开发路径为: `根目录/apps/we
|
||||
|
||||
目前对应后端版本: **5.2.3/2.2.3**
|
||||
|
||||
V1.1.0版本已支持离线图标
|
||||
|
||||
## 进度
|
||||
|
||||
**工作流相关模块等待后端重构后开发**
|
||||
@ -82,7 +84,7 @@ pnpm install
|
||||
|
||||
- 菜单图标替换
|
||||
|
||||
[根目录/scripts/菜单图标替换sql/update_icon.sql](https://gitee.com/dapppp/ruoyi-plus-vben5/blob/main/scripts/%E8%8F%9C%E5%8D%95%E5%9B%BE%E6%A0%87%E6%9B%BF%E6%8D%A2sql/update_icon.sql)
|
||||
参考 [菜单图标替换](https://dapdap.top/guide/quick-start.html#%E8%8F%9C%E5%8D%95%E5%9B%BE%E6%A0%87%E5%AF%BC%E5%85%A5)
|
||||
|
||||
- 关于代码生成
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/web-antd",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"homepage": "https://vben.pro",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -77,7 +77,7 @@ setupVbenVxeTable({
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderDefault(_renderOpts, params) {
|
||||
renderTableDefault(_renderOpts, params) {
|
||||
const { column, row } = params;
|
||||
return h(Image, { src: row[column.field] });
|
||||
},
|
||||
@ -85,7 +85,7 @@ setupVbenVxeTable({
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderDefault(renderOpts) {
|
||||
renderTableDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
Button,
|
||||
|
@ -1,12 +1,15 @@
|
||||
import { createApp } from 'vue';
|
||||
import { createApp, watchEffect } from 'vue';
|
||||
|
||||
import { registerAccessDirective } from '@vben/access';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { initStores } from '@vben/stores';
|
||||
import '@vben/styles';
|
||||
import '@vben/styles/antd';
|
||||
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { setupGlobalComponent } from '#/components/global';
|
||||
import { setupI18n } from '#/locales';
|
||||
import { $t, setupI18n } from '#/locales';
|
||||
|
||||
import { initComponentAdapter } from './adapter/component';
|
||||
import App from './app.vue';
|
||||
@ -33,6 +36,16 @@ async function bootstrap(namespace: string) {
|
||||
// 配置路由及路由守卫
|
||||
app.use(router);
|
||||
|
||||
// 动态更新标题
|
||||
watchEffect(() => {
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const routeTitle = router.currentRoute.value.meta?.title;
|
||||
const pageTitle =
|
||||
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||
useTitle(pageTitle);
|
||||
}
|
||||
});
|
||||
|
||||
app.mount('#app');
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,12 @@ import { useRouter } from 'vue-router';
|
||||
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
|
||||
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
|
||||
import { useWatermark } from '@vben/hooks';
|
||||
import { BookOpenText, CircleHelp, MdiGithub, ProfileIcon } from '@vben/icons';
|
||||
import {
|
||||
BookOpenText,
|
||||
CircleHelp,
|
||||
GitHubOutlined,
|
||||
UserOutlined,
|
||||
} from '@vben/icons';
|
||||
import {
|
||||
BasicLayout,
|
||||
LockScreen,
|
||||
@ -47,7 +52,7 @@ const menus = computed(() => {
|
||||
handler: () => {
|
||||
router.push('/profile');
|
||||
},
|
||||
icon: ProfileIcon,
|
||||
icon: UserOutlined,
|
||||
text: $t('ui.widgets.profile'),
|
||||
},
|
||||
{
|
||||
@ -56,7 +61,7 @@ const menus = computed(() => {
|
||||
target: '_blank',
|
||||
});
|
||||
},
|
||||
icon: MdiGithub,
|
||||
icon: GitHubOutlined,
|
||||
text: 'GitHub',
|
||||
},
|
||||
{
|
||||
|
@ -3,6 +3,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
||||
/**
|
||||
* @description 项目配置文件
|
||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||
*/
|
||||
export const overridesPreferences = defineOverridesPreferences({
|
||||
// overrides
|
||||
|
@ -5,9 +5,6 @@ import { preferences } from '@vben/preferences';
|
||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||
import { startProgress, stopProgress } from '@vben/utils';
|
||||
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
@ -40,13 +37,6 @@ function setupCommonGuard(router: Router) {
|
||||
if (preferences.transition.progress) {
|
||||
stopProgress();
|
||||
}
|
||||
|
||||
// 动态修改标题
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const { title } = to.meta;
|
||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ const profileRoute: RouteRecordStringComponent[] = [
|
||||
component: '/system/oss-config/index',
|
||||
meta: {
|
||||
activePath: '/system/oss',
|
||||
icon: 'mingcute:profile-line',
|
||||
icon: 'ant-design:setting-outlined',
|
||||
keepAlive: true,
|
||||
title: 'oss配置',
|
||||
},
|
||||
@ -57,7 +57,6 @@ const profileRoute: RouteRecordStringComponent[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
// TODO: 图标要改
|
||||
{
|
||||
component: 'BasicLayout',
|
||||
meta: {
|
||||
@ -73,7 +72,7 @@ const profileRoute: RouteRecordStringComponent[] = [
|
||||
component: '/tool/gen/edit-gen',
|
||||
meta: {
|
||||
activePath: '/tool/gen',
|
||||
icon: 'mingcute:profile-line',
|
||||
icon: 'tabler:code',
|
||||
keepAlive: true,
|
||||
title: '生成配置',
|
||||
},
|
||||
@ -97,7 +96,7 @@ const profileRoute: RouteRecordStringComponent[] = [
|
||||
component: '/system/role-assign/index',
|
||||
meta: {
|
||||
activePath: '/system/role',
|
||||
icon: 'mingcute:profile-line',
|
||||
icon: 'eos-icons:role-binding-outlined',
|
||||
keepAlive: true,
|
||||
title: '分配角色',
|
||||
},
|
||||
|
@ -28,7 +28,7 @@ const routes: RouteRecordRaw[] = [
|
||||
path: '/vben-admin/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:copyright',
|
||||
icon: 'lucide:copyright|offline',
|
||||
title: $t('demos.vben.about'),
|
||||
},
|
||||
},
|
||||
@ -37,7 +37,7 @@ const routes: RouteRecordRaw[] = [
|
||||
path: '/vben-admin/document',
|
||||
component: IFrameView,
|
||||
meta: {
|
||||
icon: 'lucide:book-open-text',
|
||||
icon: 'lucide:book-open-text|offline',
|
||||
link: VBEN_DOC_URL,
|
||||
title: $t('demos.vben.document'),
|
||||
},
|
||||
|
@ -1,7 +1,29 @@
|
||||
import type { DictData } from '#/api/system/dict/dict-data-model';
|
||||
|
||||
import { type Component as ComponentType, h } from 'vue';
|
||||
|
||||
import { JsonPreview } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import {
|
||||
AndroidIcon,
|
||||
BaiduIcon,
|
||||
ChromeIcon,
|
||||
DefaultBrowserIcon,
|
||||
DefaultOsIcon,
|
||||
DingtalkIcon,
|
||||
EdgeIcon,
|
||||
FirefoxIcon,
|
||||
IconifyIcon,
|
||||
IPhoneIcon,
|
||||
LinuxIcon,
|
||||
MicromessengerIcon,
|
||||
OperaIcon,
|
||||
OSXIcon,
|
||||
QQIcon,
|
||||
QuarkIcon,
|
||||
SafariIcon,
|
||||
UcIcon,
|
||||
WindowsIcon,
|
||||
} from '@vben/icons';
|
||||
|
||||
import { Tag } from 'ant-design-vue';
|
||||
|
||||
@ -129,28 +151,28 @@ export function renderDict(value: string, dictName: string) {
|
||||
const dictInfo = getDict(dictName);
|
||||
return renderDictTag(value, dictInfo);
|
||||
}
|
||||
|
||||
export function renderIconSpan(
|
||||
icon: string,
|
||||
icon: ComponentType,
|
||||
value: string,
|
||||
center = false,
|
||||
marginLeft = '2px',
|
||||
) {
|
||||
const justifyCenter = center ? 'justify-center' : '';
|
||||
|
||||
return (
|
||||
<span class={['flex', 'items-center', justifyCenter]}>
|
||||
{renderIcon(icon)}
|
||||
{h(icon)}
|
||||
<span style={{ marginLeft }}>{value}</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const osOptions = [
|
||||
{ icon: 'devicon:windows8', value: 'windows' },
|
||||
{ icon: 'devicon:linux', value: 'linux' },
|
||||
{ icon: 'wpf:macos', value: 'osx' },
|
||||
{ icon: 'flat-color-icons:android-os', value: 'android' },
|
||||
{ icon: 'majesticons:iphone-x-apps-line', value: 'iphone' },
|
||||
{ icon: WindowsIcon, value: 'windows' },
|
||||
{ icon: LinuxIcon, value: 'linux' },
|
||||
{ icon: OSXIcon, value: 'osx' },
|
||||
{ icon: AndroidIcon, value: 'android' },
|
||||
{ icon: IPhoneIcon, value: 'iphone' },
|
||||
];
|
||||
|
||||
/**
|
||||
@ -158,18 +180,18 @@ const osOptions = [
|
||||
* cn.hutool.http.useragent -> browers
|
||||
*/
|
||||
const browserOptions = [
|
||||
{ icon: 'logos:chrome', value: 'chrome' },
|
||||
{ icon: 'logos:microsoft-edge', value: 'edge' },
|
||||
{ icon: 'logos:firefox', value: 'firefox' },
|
||||
{ icon: 'logos:opera', value: 'opera' },
|
||||
{ icon: 'logos:safari', value: 'safari' },
|
||||
{ icon: 'mdi:wechat', value: 'micromessenger' },
|
||||
{ icon: 'logos:quarkus-icon', value: 'quark' },
|
||||
{ icon: 'mdi:wechat', value: 'wxwork' },
|
||||
{ icon: 'simple-icons:tencentqq', value: 'qq' },
|
||||
{ icon: 'ri:dingding-line', value: 'dingtalk' },
|
||||
{ icon: 'arcticons:uc-browser', value: 'uc' },
|
||||
{ icon: 'ri:baidu-fill', value: 'baidu' },
|
||||
{ icon: ChromeIcon, value: 'chrome' },
|
||||
{ icon: EdgeIcon, value: 'edge' },
|
||||
{ icon: FirefoxIcon, value: 'firefox' },
|
||||
{ icon: OperaIcon, value: 'opera' },
|
||||
{ icon: SafariIcon, value: 'safari' },
|
||||
{ icon: MicromessengerIcon, value: 'micromessenger' },
|
||||
{ icon: QuarkIcon, value: 'quark' },
|
||||
{ icon: MicromessengerIcon, value: 'wxwork' },
|
||||
{ icon: QQIcon, value: 'qq' },
|
||||
{ icon: DingtalkIcon, value: 'dingtalk' },
|
||||
{ icon: UcIcon, value: 'uc' },
|
||||
{ icon: BaiduIcon, value: 'baidu' },
|
||||
];
|
||||
|
||||
export function renderOsIcon(os: string, center = false) {
|
||||
@ -187,7 +209,7 @@ export function renderOsIcon(os: string, center = false) {
|
||||
return renderIconSpan(current.icon, os, center, '5px');
|
||||
}
|
||||
// 返回默认
|
||||
const defaultIcon = 'ic:outline-computer';
|
||||
const defaultIcon = DefaultOsIcon;
|
||||
return renderIconSpan(defaultIcon, os, center, '5px');
|
||||
}
|
||||
|
||||
@ -202,6 +224,6 @@ export function renderBrowserIcon(browser: string, center = false) {
|
||||
return renderIconSpan(current.icon, browser, center, '5px');
|
||||
}
|
||||
// 返回默认
|
||||
const defaultIcon = 'ph:browser-duotone';
|
||||
const defaultIcon = DefaultBrowserIcon;
|
||||
return renderIconSpan(defaultIcon, browser, center, '5px');
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import { createIconifyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { Col, Row, Tooltip } from 'ant-design-vue';
|
||||
@ -31,7 +30,7 @@ const clientList = accountBindList.filter((item) => item.action);
|
||||
<Tooltip :title="`${item.title}登录`">
|
||||
<span class="flex cursor-pointer items-center justify-center">
|
||||
<component
|
||||
:is="createIconifyIcon(item.avatar)"
|
||||
:is="item.avatar"
|
||||
v-if="item.avatar"
|
||||
:style="{ color: item.color }"
|
||||
class="size-[24px]"
|
||||
|
@ -1,3 +1,13 @@
|
||||
import type { Component } from 'vue';
|
||||
|
||||
import {
|
||||
AlipayIcon,
|
||||
DingdingIcon,
|
||||
GiteeIcon,
|
||||
GithubOAuthIcon,
|
||||
TaobaoIcon,
|
||||
} from '@vben/icons';
|
||||
|
||||
import { authBinding } from '#/api/core/auth';
|
||||
/**
|
||||
* @description: 菜单
|
||||
@ -13,7 +23,7 @@ export interface ListItem {
|
||||
title: string;
|
||||
description: string;
|
||||
extra?: string;
|
||||
avatar?: string;
|
||||
avatar?: Component;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
@ -50,7 +60,7 @@ async function handleAuthBinding(source: string) {
|
||||
*/
|
||||
export const accountBindList: BindItem[] = [
|
||||
{
|
||||
avatar: 'ri:taobao-fill',
|
||||
avatar: TaobaoIcon,
|
||||
color: '#ff4000',
|
||||
description: '绑定淘宝账号',
|
||||
key: '1',
|
||||
@ -58,7 +68,7 @@ export const accountBindList: BindItem[] = [
|
||||
title: '淘宝',
|
||||
},
|
||||
{
|
||||
avatar: 'fa-brands:alipay',
|
||||
avatar: AlipayIcon,
|
||||
color: '#2eabff',
|
||||
description: '绑定支付宝账号',
|
||||
key: '2',
|
||||
@ -66,7 +76,7 @@ export const accountBindList: BindItem[] = [
|
||||
title: '支付宝',
|
||||
},
|
||||
{
|
||||
avatar: 'ri:dingding-fill',
|
||||
avatar: DingdingIcon,
|
||||
color: '#2eabff',
|
||||
description: '绑定钉钉账号',
|
||||
key: '3',
|
||||
@ -75,7 +85,7 @@ export const accountBindList: BindItem[] = [
|
||||
},
|
||||
{
|
||||
action: () => handleAuthBinding('gitee'),
|
||||
avatar: 'simple-icons:gitee',
|
||||
avatar: GiteeIcon,
|
||||
color: '#c71d23',
|
||||
description: '绑定GITEE账号',
|
||||
key: '4',
|
||||
@ -84,7 +94,7 @@ export const accountBindList: BindItem[] = [
|
||||
},
|
||||
{
|
||||
action: () => handleAuthBinding('github'),
|
||||
avatar: 'uiw:github',
|
||||
avatar: GithubOAuthIcon,
|
||||
color: '',
|
||||
description: '绑定GITHUB账号',
|
||||
key: '5',
|
||||
|
@ -5,8 +5,6 @@ import type { SocialInfo } from '#/api/system/social/model';
|
||||
|
||||
import { computed, onMounted, ref, unref } from 'vue';
|
||||
|
||||
import { createIconifyIcon } from '@vben/icons';
|
||||
|
||||
import {
|
||||
Alert,
|
||||
Avatar,
|
||||
@ -127,7 +125,7 @@ onMounted(reload);
|
||||
<div class="flex w-full items-center gap-4">
|
||||
<div>
|
||||
<component
|
||||
:is="createIconifyIcon(item.avatar)"
|
||||
:is="item.avatar"
|
||||
v-if="item.avatar"
|
||||
:style="{ color: item.color }"
|
||||
class="size-[40px]"
|
||||
|
@ -1,12 +1,15 @@
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { h } from 'vue';
|
||||
|
||||
import { DictEnum } from '@vben/constants';
|
||||
import { FolderIcon, MenuIcon, OkButtonIcon, VbenIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { getPopupContainer } from '@vben/utils';
|
||||
|
||||
import { type FormSchemaGetter, z } from '#/adapter/form';
|
||||
import { getDictOptions } from '#/utils/dict';
|
||||
import { renderDict, renderIcon } from '#/utils/render';
|
||||
import { renderDict } from '#/utils/render';
|
||||
|
||||
export const querySchema: FormSchemaGetter = () => [
|
||||
{
|
||||
@ -48,11 +51,10 @@ export const yesNoOptions = [
|
||||
|
||||
// (M目录 C菜单 F按钮)
|
||||
const menuTypes = {
|
||||
M: { value: '目录', icon: 'fxemoji:folder' },
|
||||
C: { value: '菜单', icon: 'fluent-emoji-flat:open-book' },
|
||||
F: { value: '按钮', icon: 'fluent-emoji:ok-button' },
|
||||
C: { icon: MenuIcon, value: '菜单' },
|
||||
F: { icon: OkButtonIcon, value: '按钮' },
|
||||
M: { icon: FolderIcon, value: '目录' },
|
||||
};
|
||||
|
||||
export const columns: VxeGridProps['columns'] = [
|
||||
{
|
||||
title: '菜单名称',
|
||||
@ -74,7 +76,9 @@ export const columns: VxeGridProps['columns'] = [
|
||||
return '';
|
||||
}
|
||||
return (
|
||||
<span class={'flex justify-center'}>{renderIcon(row.icon)}</span>
|
||||
<span class={'flex justify-center'}>
|
||||
<VbenIcon icon={row.icon} />
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
@ -95,9 +99,9 @@ export const columns: VxeGridProps['columns'] = [
|
||||
return '未知';
|
||||
}
|
||||
return (
|
||||
<span class={['flex', 'items-center', 'justify-center']}>
|
||||
{renderIcon(current.icon)}
|
||||
<span style={{ marginLeft: '2px' }}>{current.value}</span>
|
||||
<span class="flex items-center justify-center gap-1">
|
||||
{h(current.icon, { class: 'size-[18px]' })}
|
||||
<span>{current.value}</span>
|
||||
</span>
|
||||
);
|
||||
},
|
||||
@ -189,7 +193,8 @@ export const drawerSchema: FormSchemaGetter = () => [
|
||||
show: (values) => values.menuType !== 'F',
|
||||
triggerFields: ['menuType'],
|
||||
},
|
||||
renderComponentContent: () => ({
|
||||
renderComponentContent: (model) => ({
|
||||
addonBefore: () => <VbenIcon icon={model.icon} />,
|
||||
addonAfter: () => (
|
||||
<a href="https://icon-sets.iconify.design/" target="_blank">
|
||||
搜索图标
|
||||
|
@ -2,14 +2,22 @@
|
||||
import type { Recordable } from '@vben/types';
|
||||
import type { Key } from 'ant-design-vue/es/vc-tree/interface';
|
||||
|
||||
import { ref } from 'vue';
|
||||
import { type Component, ref } from 'vue';
|
||||
|
||||
import {
|
||||
CodeMirror,
|
||||
type LanguageSupport,
|
||||
useVbenModal,
|
||||
} from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import {
|
||||
DefaultFileIcon,
|
||||
FolderIcon,
|
||||
JavaIcon,
|
||||
SqlIcon,
|
||||
TsIcon,
|
||||
VueIcon,
|
||||
XmlIcon,
|
||||
} from '@vben/icons';
|
||||
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { Skeleton, Tree } from 'ant-design-vue';
|
||||
@ -20,7 +28,7 @@ interface TreeNode {
|
||||
children: TreeNode[];
|
||||
title: string;
|
||||
key: string;
|
||||
icon: string; // 树左边图标
|
||||
icon: Component; // 树左边图标
|
||||
}
|
||||
|
||||
const treeData = ref<TreeNode[]>([]);
|
||||
@ -90,16 +98,16 @@ function convertToTree(paths: string[]): TreeNode[] {
|
||||
}
|
||||
|
||||
const iconMap = [
|
||||
{ key: 'java', value: 'skill-icons:java-light' },
|
||||
{ key: 'xml', value: 'tabler:file-type-xml' },
|
||||
{ key: 'sql', value: 'carbon:sql' },
|
||||
{ key: 'ts', value: 'skill-icons:typescript' },
|
||||
{ key: 'vue', value: 'logos:vue' },
|
||||
{ key: 'folder', value: 'flat-color-icons:folder' },
|
||||
{ key: 'java', value: JavaIcon },
|
||||
{ key: 'xml', value: XmlIcon },
|
||||
{ key: 'sql', value: SqlIcon },
|
||||
{ key: 'ts', value: TsIcon },
|
||||
{ key: 'vue', value: VueIcon },
|
||||
{ key: 'folder', value: FolderIcon },
|
||||
];
|
||||
function findIcon(path: string) {
|
||||
const defaultFileIcon = 'bx:file';
|
||||
const defaultFolderIcon = 'flat-color-icons:folder';
|
||||
const defaultFileIcon = DefaultFileIcon;
|
||||
const defaultFolderIcon = FolderIcon;
|
||||
if (path.endsWith('.vm')) {
|
||||
const realPath = path.slice(0, -3);
|
||||
// 是否为指定拓展名
|
||||
@ -172,7 +180,7 @@ const { copy } = useClipboard({ legacy: true });
|
||||
>
|
||||
<template #title="{ title, icon }">
|
||||
<div class="flex items-center gap-[16px]">
|
||||
<IconifyIcon :icon="icon" />
|
||||
<component :is="icon" />
|
||||
<span>{{ title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -10,10 +10,6 @@ export default defineConfig(async () => {
|
||||
vite: {
|
||||
optimizeDeps: {
|
||||
include: [
|
||||
'echarts/core',
|
||||
'echarts/charts',
|
||||
'echarts/components',
|
||||
'echarts/renderers',
|
||||
'ant-design-vue/es/locale/zh_CN',
|
||||
'ant-design-vue/es/locale/en_US',
|
||||
],
|
||||
|
@ -38,7 +38,7 @@ setupVbenVxeTable({
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderDefault(_renderOpts, params) {
|
||||
renderTableDefault(_renderOpts, params) {
|
||||
const { column, row } = params;
|
||||
const src = row[column.field];
|
||||
return h(ElImage, { src, previewSrcList: [src] });
|
||||
@ -47,7 +47,7 @@ setupVbenVxeTable({
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderDefault(renderOpts) {
|
||||
renderTableDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
ElButton,
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { createApp } from 'vue';
|
||||
import { createApp, watchEffect } from 'vue';
|
||||
|
||||
import { registerAccessDirective } from '@vben/access';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { initStores } from '@vben/stores';
|
||||
import '@vben/styles';
|
||||
import '@vben/styles/ele';
|
||||
|
||||
import { setupI18n } from '#/locales';
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { $t, setupI18n } from '#/locales';
|
||||
|
||||
import { initComponentAdapter } from './adapter/component';
|
||||
import App from './app.vue';
|
||||
@ -28,6 +31,16 @@ async function bootstrap(namespace: string) {
|
||||
// 配置路由及路由守卫
|
||||
app.use(router);
|
||||
|
||||
// 动态更新标题
|
||||
watchEffect(() => {
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const routeTitle = router.currentRoute.value.meta?.title;
|
||||
const pageTitle =
|
||||
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||
useTitle(pageTitle);
|
||||
}
|
||||
});
|
||||
|
||||
app.mount('#app');
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
||||
/**
|
||||
* @description 项目配置文件
|
||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||
*/
|
||||
export const overridesPreferences = defineOverridesPreferences({
|
||||
// overrides
|
||||
|
@ -5,9 +5,6 @@ import { preferences } from '@vben/preferences';
|
||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||
import { startProgress, stopProgress } from '@vben/utils';
|
||||
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
@ -40,13 +37,6 @@ function setupCommonGuard(router: Router) {
|
||||
if (preferences.transition.progress) {
|
||||
stopProgress();
|
||||
}
|
||||
|
||||
// 动态修改标题
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const { title } = to.meta;
|
||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ setupVbenVxeTable({
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderDefault(_renderOpts, params) {
|
||||
renderTableDefault(_renderOpts, params) {
|
||||
const { column, row } = params;
|
||||
return h(NImage, { src: row[column.field] });
|
||||
},
|
||||
@ -46,7 +46,7 @@ setupVbenVxeTable({
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderDefault(renderOpts) {
|
||||
renderTableDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
NButton,
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { createApp } from 'vue';
|
||||
import { createApp, watchEffect } from 'vue';
|
||||
|
||||
import { registerAccessDirective } from '@vben/access';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { initStores } from '@vben/stores';
|
||||
import '@vben/styles';
|
||||
|
||||
import { setupI18n } from '#/locales';
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { $t, setupI18n } from '#/locales';
|
||||
|
||||
import { initComponentAdapter } from './adapter/component';
|
||||
import App from './app.vue';
|
||||
@ -27,6 +30,16 @@ async function bootstrap(namespace: string) {
|
||||
// 配置路由及路由守卫
|
||||
app.use(router);
|
||||
|
||||
// 动态更新标题
|
||||
watchEffect(() => {
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const routeTitle = router.currentRoute.value.meta?.title;
|
||||
const pageTitle =
|
||||
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||
useTitle(pageTitle);
|
||||
}
|
||||
});
|
||||
|
||||
app.mount('#app');
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
||||
/**
|
||||
* @description 项目配置文件
|
||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||
*/
|
||||
export const overridesPreferences = defineOverridesPreferences({
|
||||
// overrides
|
||||
|
@ -5,9 +5,6 @@ import { preferences } from '@vben/preferences';
|
||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||
import { startProgress, stopProgress } from '@vben/utils';
|
||||
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
@ -40,13 +37,6 @@ function setupCommonGuard(router: Router) {
|
||||
if (preferences.transition.progress) {
|
||||
stopProgress();
|
||||
}
|
||||
|
||||
// 动态修改标题
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const { title } = to.meta;
|
||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,10 @@ import type { HeadConfig } from 'vitepress';
|
||||
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
import { viteArchiverPlugin } from '@vben/vite-config';
|
||||
import {
|
||||
viteArchiverPlugin,
|
||||
viteVxeTableImportsPlugin,
|
||||
} from '@vben/vite-config';
|
||||
|
||||
import {
|
||||
GitChangelog,
|
||||
@ -85,6 +88,7 @@ export const shared = defineConfig({
|
||||
GitChangelogMarkdownSection(),
|
||||
viteArchiverPlugin({ outputDir: '.vitepress' }),
|
||||
groupIconVitePlugin(),
|
||||
await viteVxeTableImportsPlugin(),
|
||||
],
|
||||
server: {
|
||||
fs: {
|
||||
@ -156,6 +160,7 @@ function pwa(): PwaOptions {
|
||||
registerType: 'autoUpdate',
|
||||
workbox: {
|
||||
globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'],
|
||||
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -15,11 +15,12 @@ import 'virtual:group-icons.css';
|
||||
import '@nolebase/vitepress-plugin-git-changelog/client/style.css';
|
||||
|
||||
export default {
|
||||
enhanceApp(ctx: EnhanceAppContext) {
|
||||
async enhanceApp(ctx: EnhanceAppContext) {
|
||||
const { app } = ctx;
|
||||
app.component('VbenContributors', VbenContributors);
|
||||
app.component('DemoPreview', DemoPreview);
|
||||
app.use(NolebaseGitChangelogPlugin);
|
||||
|
||||
// 百度统计
|
||||
initHmPlugin();
|
||||
},
|
||||
|
@ -8,12 +8,16 @@
|
||||
"docs:preview": "vitepress preview"
|
||||
},
|
||||
"imports": {
|
||||
"#/*": "./src/_env/*"
|
||||
"#/*": {
|
||||
"node": "./src/_env/node/*",
|
||||
"default": "./src/_env/*"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@vben-core/shadcn-ui": "workspace:*",
|
||||
"@vben/common-ui": "workspace:*",
|
||||
"@vben/locales": "workspace:*",
|
||||
"@vben/plugins": "workspace:*",
|
||||
"@vben/styles": "workspace:*",
|
||||
"ant-design-vue": "catalog:",
|
||||
"lucide-vue-next": "catalog:",
|
||||
|
@ -1 +0,0 @@
|
||||
export * from './form';
|
70
docs/src/_env/adapter/vxe-table.ts
Normal file
70
docs/src/_env/adapter/vxe-table.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { h } from 'vue';
|
||||
|
||||
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||
|
||||
import { Button, Image } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from './form';
|
||||
|
||||
if (!import.meta.env.SSR) {
|
||||
setupVbenVxeTable({
|
||||
configVxeTable: (vxeUI) => {
|
||||
vxeUI.setConfig({
|
||||
grid: {
|
||||
align: 'center',
|
||||
border: false,
|
||||
columnConfig: {
|
||||
resizable: true,
|
||||
},
|
||||
|
||||
formConfig: {
|
||||
// 全局禁用vxe-table的表单配置,使用formOptions
|
||||
enabled: false,
|
||||
},
|
||||
minHeight: 180,
|
||||
proxyConfig: {
|
||||
autoLoad: true,
|
||||
response: {
|
||||
result: 'items',
|
||||
total: 'total',
|
||||
list: 'items',
|
||||
},
|
||||
showActiveMsg: true,
|
||||
showResponseMsg: false,
|
||||
},
|
||||
round: true,
|
||||
showOverflow: true,
|
||||
size: 'small',
|
||||
},
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderTableDefault(_renderOpts, params) {
|
||||
const { column, row } = params;
|
||||
return h(Image, { src: row[column.field] });
|
||||
},
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderTableDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
Button,
|
||||
{ size: 'small', type: 'link' },
|
||||
{ default: () => props?.text },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
||||
// vxeUI.formats.add
|
||||
},
|
||||
useVbenForm,
|
||||
});
|
||||
}
|
||||
|
||||
export { useVbenVxeGrid };
|
||||
|
||||
export type * from '@vben/plugins/vxe-table';
|
4
docs/src/_env/node/adapter/form.ts
Normal file
4
docs/src/_env/node/adapter/form.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export const useVbenForm = () => {};
|
||||
export const z = {};
|
||||
export type VbenFormSchema = any;
|
||||
export type VbenFormProps = any;
|
3
docs/src/_env/node/adapter/vxe-table.ts
Normal file
3
docs/src/_env/node/adapter/vxe-table.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export type * from '@vben/plugins/vxe-table';
|
||||
|
||||
export const useVbenVxeGrid = () => {};
|
@ -4,4 +4,235 @@ outline: deep
|
||||
|
||||
# Vben Vxe Table 表格
|
||||
|
||||
文档待补充,如果需要使用,可先行查看 vxe-table 文档和 示例代码,内部有部分注释。
|
||||
框架提供的Table 列表组件基于 [vxe-table](https://vxetable.cn/v4/#/grid/api?apiKey=grid),结合`Vben Form 表单`进行了二次封装。
|
||||
|
||||
其中,表头的 **表单搜索** 部分采用了`Vben Form表单`,表格主体部分使用了`vxe-grid`组件,支持表格的分页、排序、筛选等功能。
|
||||
|
||||
> 如果文档内没有参数说明,可以尝试在在线示例或者在 [vxe-grid 官方API 文档](https://vxetable.cn/v4/#/grid/api?apiKey=grid) 内寻找
|
||||
|
||||
::: info 写在前面
|
||||
|
||||
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
|
||||
|
||||
:::
|
||||
|
||||
## 适配器
|
||||
|
||||
表格底层使用 [vxe-table](https://vxetable.cn/#/start/install) 进行实现,所以你可以使用 `vxe-table` 的所有功能。对于不同的 UI 框架,我们提供了适配器,以便更好的适配不同的 UI 框架。
|
||||
|
||||
### 适配器说明
|
||||
|
||||
每个应用都可以自己配置`vxe-table`的适配器,你可以根据自己的需求。下面是一个简单的配置示例:
|
||||
|
||||
::: details vxe-table 表格适配器
|
||||
|
||||
```ts
|
||||
import { h } from 'vue';
|
||||
|
||||
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||
|
||||
import { Button, Image } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from './form';
|
||||
|
||||
setupVbenVxeTable({
|
||||
configVxeTable: (vxeUI) => {
|
||||
vxeUI.setConfig({
|
||||
grid: {
|
||||
align: 'center',
|
||||
border: false,
|
||||
columnConfig: {
|
||||
resizable: true,
|
||||
},
|
||||
minHeight: 180,
|
||||
formConfig: {
|
||||
// 全局禁用vxe-table的表单配置,使用formOptions
|
||||
enabled: false,
|
||||
},
|
||||
proxyConfig: {
|
||||
autoLoad: true,
|
||||
response: {
|
||||
result: 'items',
|
||||
total: 'total',
|
||||
list: 'items',
|
||||
},
|
||||
showActiveMsg: true,
|
||||
showResponseMsg: false,
|
||||
},
|
||||
round: true,
|
||||
showOverflow: true,
|
||||
size: 'small',
|
||||
},
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderTableDefault(_renderOpts, params) {
|
||||
const { column, row } = params;
|
||||
return h(Image, { src: row[column.field] });
|
||||
},
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderTableDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
Button,
|
||||
{ size: 'small', type: 'link' },
|
||||
{ default: () => props?.text },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
||||
// vxeUI.formats.add
|
||||
},
|
||||
useVbenForm,
|
||||
});
|
||||
|
||||
export { useVbenVxeGrid };
|
||||
|
||||
export type * from '@vben/plugins/vxe-table';
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## 基础表格
|
||||
|
||||
使用 `useVbenVxeGrid` 创建最基础的表格。
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/basic" />
|
||||
|
||||
## 远程加载
|
||||
|
||||
通过指定 `proxyConfig.ajax` 的 `query` 方法,可以实现远程加载数据。
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/remote" />
|
||||
|
||||
## 树形表格
|
||||
|
||||
树形表格的数据源为扁平结构,可以指定`treeConfig`配置项,实现树形表格。
|
||||
|
||||
```typescript
|
||||
treeConfig: {
|
||||
transform: true, // 指定表格为树形表格
|
||||
parentField: 'parentId', // 父节点字段名
|
||||
rowField: 'id', // 行数据字段名
|
||||
},
|
||||
```
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/tree" />
|
||||
|
||||
## 固定表头/列
|
||||
|
||||
列固定可选参数: `'left' | 'right' | '' | null`
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/fixed" />
|
||||
|
||||
## 自定义单元格
|
||||
|
||||
自定义单元格有两种实现方式
|
||||
|
||||
- 通过 `slots` 插槽
|
||||
- 通过 `customCell` 自定义单元格,但是要先添加渲染器
|
||||
|
||||
```typescript
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderDefault(_renderOpts, params) {
|
||||
const { column, row } = params;
|
||||
return h(Image, { src: row[column.field] } as any); // 注意此处的Image 组件,来源于Antd,需要自行引入,否则会使用js的Image类
|
||||
},
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
Button,
|
||||
{ size: 'small', type: 'link' },
|
||||
{ default: () => props?.text },
|
||||
);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/custom-cell" />
|
||||
|
||||
## 搜索表单
|
||||
|
||||
**表单搜索** 部分采用了`Vben Form 表单`,参考 [Vben Form 表单文档](/components/common-ui/vben-form)。
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/form" />
|
||||
|
||||
## 单元格编辑
|
||||
|
||||
通过指定`editConfig.mode`为`cell`,可以实现单元格编辑。
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/edit-cell" />
|
||||
|
||||
## 行编辑
|
||||
|
||||
通过指定`editConfig.mode`为`row`,可以实现行编辑。
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/edit-row" />
|
||||
|
||||
## 虚拟滚动
|
||||
|
||||
通过 scroll-y.enabled 与 scroll-y.gt 组合开启,其中 enabled 为总开关,gt 是指当总行数大于指定行数时自动开启。
|
||||
|
||||
> 参考 [vxe-table 官方文档 - 虚拟滚动](https://vxetable.cn/v4/#/component/grid/scroll/vertical)。
|
||||
|
||||
<DemoPreview dir="demos/vben-vxe-table/virtual" />
|
||||
|
||||
## API
|
||||
|
||||
`useVbenVxeGrid` 返回一个数组,第一个元素是表格组件,第二个元素是表格的方法。
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
// Grid 为表格组件
|
||||
// gridApi 为表格的方法
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
gridOptions: {},
|
||||
formOptions: {},
|
||||
gridEvents: {},
|
||||
// 属性
|
||||
// 事件
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Grid />
|
||||
</template>
|
||||
```
|
||||
|
||||
### GridApi
|
||||
|
||||
useVbenVxeGrid 返回的第二个参数,是一个对象,包含了一些表单的方法。
|
||||
|
||||
| 方法名 | 描述 | 类型 |
|
||||
| --- | --- | --- |
|
||||
| setLoading | 设置loading状态 | `(loading)=>void` |
|
||||
| setGridOptions | 设置vxe-table grid组件参数 | `(options: Partial<VxeGridProps['gridOptions'])=>void` |
|
||||
| reload | 重载表格,会进行初始化 | `(params:any)=>void` |
|
||||
| query | 重载表格,会保留当前分页 | `(params:any)=>void` |
|
||||
| grid | vxe-table grid实例 | `VxeGridInstance` |
|
||||
| formApi | vbenForm api实例 | `FormApi` |
|
||||
|
||||
## Props
|
||||
|
||||
所有属性都可以传入 `useVbenVxeGrid` 的第一个参数中。
|
||||
|
||||
| 属性名 | 描述 | 类型 |
|
||||
| -------------- | ------------------ | ------------------- |
|
||||
| tableTitle | 表格标题 | `string` |
|
||||
| tableTitleHelp | 表格标题帮助信息 | `string` |
|
||||
| gridClass | grid组件的class | `string` |
|
||||
| gridOptions | grid组件的参数 | `VxeTableGridProps` |
|
||||
| gridEvents | grid组件的触发的⌚️ | `VxeGridListeners` |
|
||||
| formOptions | 表单参数 | `VbenFormProps` |
|
||||
|
85
docs/src/demos/vben-vxe-table/basic/index.vue
Normal file
85
docs/src/demos/vben-vxe-table/basic/index.vue
Normal file
@ -0,0 +1,85 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button, message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { MOCK_TABLE_DATA } from '../table-data';
|
||||
|
||||
interface RowType {
|
||||
address: string;
|
||||
age: number;
|
||||
id: number;
|
||||
name: string;
|
||||
nickname: string;
|
||||
role: string;
|
||||
}
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
columns: [
|
||||
{ title: '序号', type: 'seq', width: 50 },
|
||||
{ field: 'name', title: 'Name' },
|
||||
{ field: 'age', sortable: true, title: 'Age' },
|
||||
{ field: 'nickname', title: 'Nickname' },
|
||||
{ field: 'role', title: 'Role' },
|
||||
{ field: 'address', showOverflow: true, title: 'Address' },
|
||||
],
|
||||
data: MOCK_TABLE_DATA,
|
||||
pagerConfig: {
|
||||
enabled: false,
|
||||
},
|
||||
sortConfig: {
|
||||
multiple: true,
|
||||
},
|
||||
};
|
||||
|
||||
const gridEvents: VxeGridListeners<RowType> = {
|
||||
cellClick: ({ row }) => {
|
||||
message.info(`cell-click: ${row.name}`);
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({ gridEvents, gridOptions });
|
||||
|
||||
const showBorder = gridApi.useStore((state) => state.gridOptions?.border);
|
||||
const showStripe = gridApi.useStore((state) => state.gridOptions?.stripe);
|
||||
|
||||
function changeBorder() {
|
||||
gridApi.setGridOptions({
|
||||
border: !showBorder.value,
|
||||
});
|
||||
}
|
||||
|
||||
function changeStripe() {
|
||||
gridApi.setGridOptions({
|
||||
stripe: !showStripe.value,
|
||||
});
|
||||
}
|
||||
|
||||
function changeLoading() {
|
||||
gridApi.setLoading(true);
|
||||
setTimeout(() => {
|
||||
gridApi.setLoading(false);
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 此处的`vp-raw` 是为了适配文档的展示效果,实际使用时不需要 -->
|
||||
<div class="vp-raw w-full">
|
||||
<Grid>
|
||||
<template #toolbar-tools>
|
||||
<Button class="mr-2" type="primary" @click="changeBorder">
|
||||
{{ showBorder ? '隐藏' : '显示' }}边框
|
||||
</Button>
|
||||
<Button class="mr-2" type="primary" @click="changeLoading">
|
||||
显示loading
|
||||
</Button>
|
||||
<Button class="mr-2" type="primary" @click="changeStripe">
|
||||
{{ showStripe ? '隐藏' : '显示' }}斑马纹
|
||||
</Button>
|
||||
</template>
|
||||
</Grid>
|
||||
</div>
|
||||
</template>
|
105
docs/src/demos/vben-vxe-table/custom-cell/index.vue
Normal file
105
docs/src/demos/vben-vxe-table/custom-cell/index.vue
Normal file
@ -0,0 +1,105 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button, Image, Switch, Tag } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { getExampleTableApi } from '../mock-api';
|
||||
|
||||
interface RowType {
|
||||
category: string;
|
||||
color: string;
|
||||
id: string;
|
||||
imageUrl: string;
|
||||
open: boolean;
|
||||
price: string;
|
||||
productName: string;
|
||||
releaseDate: string;
|
||||
status: 'error' | 'success' | 'warning';
|
||||
}
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
checkboxConfig: {
|
||||
highlight: true,
|
||||
labelField: 'name',
|
||||
},
|
||||
columns: [
|
||||
{ title: '序号', type: 'seq', width: 50 },
|
||||
{ field: 'category', title: 'Category', width: 100 },
|
||||
{
|
||||
field: 'imageUrl',
|
||||
slots: { default: 'image-url' },
|
||||
title: 'Image',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
cellRender: { name: 'CellImage' },
|
||||
field: 'imageUrl2',
|
||||
title: 'Render Image',
|
||||
width: 130,
|
||||
},
|
||||
{
|
||||
field: 'open',
|
||||
slots: { default: 'open' },
|
||||
title: 'Open',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
slots: { default: 'status' },
|
||||
title: 'Status',
|
||||
width: 100,
|
||||
},
|
||||
{ field: 'color', title: 'Color', width: 100 },
|
||||
{ field: 'productName', title: 'Product Name', width: 200 },
|
||||
{ field: 'price', title: 'Price', width: 100 },
|
||||
{
|
||||
field: 'releaseDate',
|
||||
formatter: 'formatDateTime',
|
||||
title: 'Date',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
cellRender: { name: 'CellLink', props: { text: '编辑' } },
|
||||
field: 'action',
|
||||
fixed: 'right',
|
||||
title: '操作',
|
||||
width: 120,
|
||||
},
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
return await getExampleTableApi({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid] = useVbenVxeGrid({ gridOptions });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vp-raw w-full">
|
||||
<Grid>
|
||||
<template #image-url="{ row }">
|
||||
<Image :src="row.imageUrl" height="30" width="30" />
|
||||
</template>
|
||||
<template #open="{ row }">
|
||||
<Switch v-model:checked="row.open" />
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<Tag :color="row.color">{{ row.status }}</Tag>
|
||||
</template>
|
||||
<template #action>
|
||||
<Button type="link">编辑</Button>
|
||||
</template>
|
||||
</Grid>
|
||||
</div>
|
||||
</template>
|
55
docs/src/demos/vben-vxe-table/edit-cell/index.vue
Normal file
55
docs/src/demos/vben-vxe-table/edit-cell/index.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { getExampleTableApi } from '../mock-api';
|
||||
|
||||
interface RowType {
|
||||
category: string;
|
||||
color: string;
|
||||
id: string;
|
||||
price: string;
|
||||
productName: string;
|
||||
releaseDate: string;
|
||||
}
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
columns: [
|
||||
{ title: '序号', type: 'seq', width: 50 },
|
||||
{ editRender: { name: 'input' }, field: 'category', title: 'Category' },
|
||||
{ editRender: { name: 'input' }, field: 'color', title: 'Color' },
|
||||
{
|
||||
editRender: { name: 'input' },
|
||||
field: 'productName',
|
||||
title: 'Product Name',
|
||||
},
|
||||
{ field: 'price', title: 'Price' },
|
||||
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'Date' },
|
||||
],
|
||||
editConfig: {
|
||||
mode: 'cell',
|
||||
trigger: 'click',
|
||||
},
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
return await getExampleTableApi({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
showOverflow: true,
|
||||
};
|
||||
|
||||
const [Grid] = useVbenVxeGrid({ gridOptions });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vp-raw w-full">
|
||||
<Grid />
|
||||
</div>
|
||||
</template>
|
92
docs/src/demos/vben-vxe-table/edit-row/index.vue
Normal file
92
docs/src/demos/vben-vxe-table/edit-row/index.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button, message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { getExampleTableApi } from '../mock-api';
|
||||
|
||||
interface RowType {
|
||||
category: string;
|
||||
color: string;
|
||||
id: string;
|
||||
price: string;
|
||||
productName: string;
|
||||
releaseDate: string;
|
||||
}
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
columns: [
|
||||
{ title: '序号', type: 'seq', width: 50 },
|
||||
{ editRender: { name: 'input' }, field: 'category', title: 'Category' },
|
||||
{ editRender: { name: 'input' }, field: 'color', title: 'Color' },
|
||||
{
|
||||
editRender: { name: 'input' },
|
||||
field: 'productName',
|
||||
title: 'Product Name',
|
||||
},
|
||||
{ field: 'price', title: 'Price' },
|
||||
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'Date' },
|
||||
{ slots: { default: 'action' }, title: '操作' },
|
||||
],
|
||||
editConfig: {
|
||||
mode: 'row',
|
||||
trigger: 'click',
|
||||
},
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
return await getExampleTableApi({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
showOverflow: true,
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({ gridOptions });
|
||||
|
||||
function hasEditStatus(row: RowType) {
|
||||
return gridApi.grid?.isEditByRow(row);
|
||||
}
|
||||
|
||||
function editRowEvent(row: RowType) {
|
||||
gridApi.grid?.setEditRow(row);
|
||||
}
|
||||
|
||||
async function saveRowEvent(row: RowType) {
|
||||
await gridApi.grid?.clearEdit();
|
||||
|
||||
gridApi.setLoading(true);
|
||||
setTimeout(() => {
|
||||
gridApi.setLoading(false);
|
||||
message.success({
|
||||
content: `保存成功!category=${row.category}`,
|
||||
});
|
||||
}, 600);
|
||||
}
|
||||
|
||||
const cancelRowEvent = (_row: RowType) => {
|
||||
gridApi.grid?.clearEdit();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vp-raw w-full">
|
||||
<Grid>
|
||||
<template #action="{ row }">
|
||||
<template v-if="hasEditStatus(row)">
|
||||
<Button type="link" @click="saveRowEvent(row)">保存</Button>
|
||||
<Button type="link" @click="cancelRowEvent(row)">取消</Button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Button type="link" @click="editRowEvent(row)">编辑</Button>
|
||||
</template>
|
||||
</template>
|
||||
</Grid>
|
||||
</div>
|
||||
</template>
|
67
docs/src/demos/vben-vxe-table/fixed/index.vue
Normal file
67
docs/src/demos/vben-vxe-table/fixed/index.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { getExampleTableApi } from '../mock-api';
|
||||
|
||||
interface RowType {
|
||||
category: string;
|
||||
color: string;
|
||||
id: string;
|
||||
price: string;
|
||||
productName: string;
|
||||
releaseDate: string;
|
||||
}
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
columns: [
|
||||
{ fixed: 'left', title: '序号', type: 'seq', width: 50 },
|
||||
{ field: 'category', title: 'Category', width: 300 },
|
||||
{ field: 'color', title: 'Color', width: 300 },
|
||||
{ field: 'productName', title: 'Product Name', width: 300 },
|
||||
{ field: 'price', title: 'Price', width: 300 },
|
||||
{
|
||||
field: 'releaseDate',
|
||||
formatter: 'formatDateTime',
|
||||
title: 'DateTime',
|
||||
width: 500,
|
||||
},
|
||||
{
|
||||
field: 'action',
|
||||
fixed: 'right',
|
||||
slots: { default: 'action' },
|
||||
title: '操作',
|
||||
width: 120,
|
||||
},
|
||||
],
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
return await getExampleTableApi({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
rowConfig: {
|
||||
isHover: true,
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid] = useVbenVxeGrid({ gridOptions });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vp-raw w-full">
|
||||
<Grid>
|
||||
<template #action>
|
||||
<Button type="link">编辑</Button>
|
||||
</template>
|
||||
</Grid>
|
||||
</div>
|
||||
</template>
|
120
docs/src/demos/vben-vxe-table/form/index.vue
Normal file
120
docs/src/demos/vben-vxe-table/form/index.vue
Normal file
@ -0,0 +1,120 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VbenFormProps } from '#/adapter/form';
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { getExampleTableApi } from '../mock-api';
|
||||
|
||||
interface RowType {
|
||||
category: string;
|
||||
color: string;
|
||||
id: string;
|
||||
price: string;
|
||||
productName: string;
|
||||
releaseDate: string;
|
||||
}
|
||||
|
||||
const formOptions: VbenFormProps = {
|
||||
// 默认展开
|
||||
collapsed: false,
|
||||
schema: [
|
||||
{
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: 'Please enter category',
|
||||
},
|
||||
defaultValue: '1',
|
||||
fieldName: 'category',
|
||||
label: 'Category',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: 'Please enter productName',
|
||||
},
|
||||
fieldName: 'productName',
|
||||
label: 'ProductName',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: 'Please enter price',
|
||||
},
|
||||
fieldName: 'price',
|
||||
label: 'Price',
|
||||
},
|
||||
{
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
options: [
|
||||
{
|
||||
label: 'Color1',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: 'Color2',
|
||||
value: '2',
|
||||
},
|
||||
],
|
||||
placeholder: '请选择',
|
||||
},
|
||||
fieldName: 'color',
|
||||
label: 'Color',
|
||||
},
|
||||
{
|
||||
component: 'DatePicker',
|
||||
fieldName: 'datePicker',
|
||||
label: 'Date',
|
||||
},
|
||||
],
|
||||
// 控制表单是否显示折叠按钮
|
||||
showCollapseButton: true,
|
||||
submitButtonOptions: {
|
||||
content: '查询',
|
||||
},
|
||||
// 按下回车时是否提交表单
|
||||
submitOnEnter: false,
|
||||
};
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
checkboxConfig: {
|
||||
highlight: true,
|
||||
labelField: 'name',
|
||||
},
|
||||
columns: [
|
||||
{ title: '序号', type: 'seq', width: 50 },
|
||||
{ align: 'left', title: 'Name', type: 'checkbox', width: 100 },
|
||||
{ field: 'category', title: 'Category' },
|
||||
{ field: 'color', title: 'Color' },
|
||||
{ field: 'productName', title: 'Product Name' },
|
||||
{ field: 'price', title: 'Price' },
|
||||
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'Date' },
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues) => {
|
||||
message.success(`Query params: ${JSON.stringify(formValues)}`);
|
||||
return await getExampleTableApi({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid] = useVbenVxeGrid({ formOptions, gridOptions });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vp-raw w-full">
|
||||
<Grid />
|
||||
</div>
|
||||
</template>
|
36
docs/src/demos/vben-vxe-table/mock-api.ts
Normal file
36
docs/src/demos/vben-vxe-table/mock-api.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { MOCK_API_DATA } from './table-data';
|
||||
|
||||
export namespace DemoTableApi {
|
||||
export interface PageFetchParams {
|
||||
[key: string]: any;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}
|
||||
}
|
||||
|
||||
export function sleep(time = 1000) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(true);
|
||||
}, time);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取示例表格数据
|
||||
*/
|
||||
async function getExampleTableApi(params: DemoTableApi.PageFetchParams) {
|
||||
return new Promise<{ items: any; total: number }>((resolve) => {
|
||||
const { page, pageSize } = params;
|
||||
const items = MOCK_API_DATA.slice((page - 1) * pageSize, page * pageSize);
|
||||
|
||||
sleep(1000).then(() => {
|
||||
resolve({
|
||||
total: items.length,
|
||||
items,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export { getExampleTableApi };
|
112
docs/src/demos/vben-vxe-table/remote/index.vue
Normal file
112
docs/src/demos/vben-vxe-table/remote/index.vue
Normal file
@ -0,0 +1,112 @@
|
||||
<script lang="ts" setup>
|
||||
import type { DemoTableApi } from '../mock-api';
|
||||
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { MOCK_API_DATA } from '../table-data';
|
||||
|
||||
interface RowType {
|
||||
category: string;
|
||||
color: string;
|
||||
id: string;
|
||||
price: string;
|
||||
productName: string;
|
||||
releaseDate: string;
|
||||
}
|
||||
|
||||
// 数据实例
|
||||
// const MOCK_TREE_TABLE_DATA = [
|
||||
// {
|
||||
// date: '2020-08-01',
|
||||
// id: 10_000,
|
||||
// name: 'Test1',
|
||||
// parentId: null,
|
||||
// size: 1024,
|
||||
// type: 'mp3',
|
||||
// },
|
||||
// ]
|
||||
|
||||
const sleep = (time = 1000) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(true);
|
||||
}, time);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取示例表格数据
|
||||
*/
|
||||
async function getExampleTableApi(params: DemoTableApi.PageFetchParams) {
|
||||
return new Promise<{ items: any; total: number }>((resolve) => {
|
||||
const { page, pageSize } = params;
|
||||
const items = MOCK_API_DATA.slice((page - 1) * pageSize, page * pageSize);
|
||||
|
||||
sleep(1000).then(() => {
|
||||
resolve({
|
||||
total: items.length,
|
||||
items,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
checkboxConfig: {
|
||||
highlight: true,
|
||||
labelField: 'name',
|
||||
},
|
||||
columns: [
|
||||
{ title: '序号', type: 'seq', width: 50 },
|
||||
{ align: 'left', title: 'Name', type: 'checkbox', width: 100 },
|
||||
{ field: 'category', title: 'Category' },
|
||||
{ field: 'color', title: 'Color' },
|
||||
{ field: 'productName', title: 'Product Name' },
|
||||
{ field: 'price', title: 'Price' },
|
||||
{ field: 'releaseDate', formatter: 'formatDateTime', title: 'DateTime' },
|
||||
],
|
||||
exportConfig: {},
|
||||
// height: 'auto', // 如果设置为 auto,则必须确保存在父节点且不允许存在相邻元素,否则会出现高度闪动问题
|
||||
keepSource: true,
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
return await getExampleTableApi({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
toolbarConfig: {
|
||||
custom: true,
|
||||
export: true,
|
||||
// import: true,
|
||||
refresh: true,
|
||||
zoom: true,
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
gridOptions,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vp-raw w-full">
|
||||
<Grid>
|
||||
<template #toolbar-tools>
|
||||
<Button class="mr-2" type="primary" @click="() => gridApi.query()">
|
||||
刷新当前页面
|
||||
</Button>
|
||||
<Button type="primary" @click="() => gridApi.reload()">
|
||||
刷新并返回第一页
|
||||
</Button>
|
||||
</template>
|
||||
</Grid>
|
||||
</div>
|
||||
</template>
|
384
docs/src/demos/vben-vxe-table/table-data.ts
Normal file
384
docs/src/demos/vben-vxe-table/table-data.ts
Normal file
@ -0,0 +1,384 @@
|
||||
interface TableRowData {
|
||||
address: string;
|
||||
age: number;
|
||||
id: number;
|
||||
name: string;
|
||||
nickname: string;
|
||||
role: string;
|
||||
}
|
||||
|
||||
const roles = ['User', 'Admin', 'Manager', 'Guest'];
|
||||
|
||||
export const MOCK_TABLE_DATA: TableRowData[] = (() => {
|
||||
const data: TableRowData[] = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
data.push({
|
||||
address: `New York${i}`,
|
||||
age: i + 1,
|
||||
id: i,
|
||||
name: `Test${i}`,
|
||||
nickname: `Test${i}`,
|
||||
role: roles[Math.floor(Math.random() * roles.length)] as string,
|
||||
});
|
||||
}
|
||||
return data;
|
||||
})();
|
||||
|
||||
export const MOCK_TREE_TABLE_DATA = [
|
||||
{
|
||||
date: '2020-08-01',
|
||||
id: 10_000,
|
||||
name: 'Test1',
|
||||
parentId: null,
|
||||
size: 1024,
|
||||
type: 'mp3',
|
||||
},
|
||||
{
|
||||
date: '2021-04-01',
|
||||
id: 10_050,
|
||||
name: 'Test2',
|
||||
parentId: null,
|
||||
size: 0,
|
||||
type: 'mp4',
|
||||
},
|
||||
{
|
||||
date: '2020-03-01',
|
||||
id: 24_300,
|
||||
name: 'Test3',
|
||||
parentId: 10_050,
|
||||
size: 1024,
|
||||
type: 'avi',
|
||||
},
|
||||
{
|
||||
date: '2021-04-01',
|
||||
id: 20_045,
|
||||
name: 'Test4',
|
||||
parentId: 24_300,
|
||||
size: 600,
|
||||
type: 'html',
|
||||
},
|
||||
{
|
||||
date: '2021-04-01',
|
||||
id: 10_053,
|
||||
name: 'Test5',
|
||||
parentId: 24_300,
|
||||
size: 0,
|
||||
type: 'avi',
|
||||
},
|
||||
{
|
||||
date: '2021-10-01',
|
||||
id: 24_330,
|
||||
name: 'Test6',
|
||||
parentId: 10_053,
|
||||
size: 25,
|
||||
type: 'txt',
|
||||
},
|
||||
{
|
||||
date: '2020-01-01',
|
||||
id: 21_011,
|
||||
name: 'Test7',
|
||||
parentId: 10_053,
|
||||
size: 512,
|
||||
type: 'pdf',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 22_200,
|
||||
name: 'Test8',
|
||||
parentId: 10_053,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
{
|
||||
date: '2020-11-01',
|
||||
id: 23_666,
|
||||
name: 'Test9',
|
||||
parentId: null,
|
||||
size: 2048,
|
||||
type: 'xlsx',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 23_677,
|
||||
name: 'Test10',
|
||||
parentId: 23_666,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 23_671,
|
||||
name: 'Test11',
|
||||
parentId: 23_677,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 23_672,
|
||||
name: 'Test12',
|
||||
parentId: 23_677,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 23_688,
|
||||
name: 'Test13',
|
||||
parentId: 23_666,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 23_681,
|
||||
name: 'Test14',
|
||||
parentId: 23_688,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 23_682,
|
||||
name: 'Test15',
|
||||
parentId: 23_688,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
{
|
||||
date: '2020-10-01',
|
||||
id: 24_555,
|
||||
name: 'Test16',
|
||||
parentId: null,
|
||||
size: 224,
|
||||
type: 'avi',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 24_566,
|
||||
name: 'Test17',
|
||||
parentId: 24_555,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
{
|
||||
date: '2021-06-01',
|
||||
id: 24_577,
|
||||
name: 'Test18',
|
||||
parentId: 24_555,
|
||||
size: 1024,
|
||||
type: 'js',
|
||||
},
|
||||
];
|
||||
|
||||
export const MOCK_API_DATA = [
|
||||
{
|
||||
available: true,
|
||||
category: 'Computers',
|
||||
color: 'purple',
|
||||
currency: 'NAD',
|
||||
description:
|
||||
'Ergonomic executive chair upholstered in bonded black leather and PVC padded seat and back for all-day comfort and support',
|
||||
id: '45a613df-227a-4907-a89f-4a7f1252ca0c',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/62715097',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/75395683',
|
||||
inProduction: false,
|
||||
open: true,
|
||||
price: '48.89',
|
||||
productName: 'Handcrafted Steel Salad',
|
||||
quantity: 70,
|
||||
rating: 3.780_582_329_574_367,
|
||||
releaseDate: '2024-09-09T04:06:57.793Z',
|
||||
status: 'error',
|
||||
tags: ['Bespoke', 'Handmade', 'Luxurious'],
|
||||
weight: 1.031_015_671_912_002_5,
|
||||
},
|
||||
{
|
||||
available: true,
|
||||
category: 'Toys',
|
||||
color: 'green',
|
||||
currency: 'CZK',
|
||||
description:
|
||||
'The Nagasaki Lander is the trademarked name of several series of Nagasaki sport bikes, that started with the 1984 ABC800J',
|
||||
id: 'd02e5ee9-bc98-4de2-98fa-25a6567ecc19',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/51512330',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/58698113',
|
||||
inProduction: false,
|
||||
open: false,
|
||||
price: '68.15',
|
||||
productName: 'Generic Cotton Gloves',
|
||||
quantity: 3,
|
||||
rating: 1.681_749_367_682_703_3,
|
||||
releaseDate: '2024-06-16T09:00:36.806Z',
|
||||
status: 'warning',
|
||||
tags: ['Rustic', 'Handcrafted', 'Recycled'],
|
||||
weight: 9.601_076_149_300_575,
|
||||
},
|
||||
{
|
||||
available: true,
|
||||
category: 'Beauty',
|
||||
color: 'teal',
|
||||
currency: 'OMR',
|
||||
description:
|
||||
'The Apollotech B340 is an affordable wireless mouse with reliable connectivity, 12 months battery life and modern design',
|
||||
id: '2b72521c-225c-4e64-8030-611b76b10b37',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/50300075',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/36541691',
|
||||
inProduction: true,
|
||||
open: true,
|
||||
price: '696.94',
|
||||
productName: 'Gorgeous Soft Ball',
|
||||
quantity: 50,
|
||||
rating: 2.361_581_777_372_057_5,
|
||||
releaseDate: '2024-06-03T13:24:19.809Z',
|
||||
status: 'warning',
|
||||
tags: ['Gorgeous', 'Ergonomic', 'Licensed'],
|
||||
weight: 8.882_340_049_286_19,
|
||||
},
|
||||
{
|
||||
available: true,
|
||||
category: 'Games',
|
||||
color: 'silver',
|
||||
currency: 'SOS',
|
||||
description:
|
||||
'Carbonite web goalkeeper gloves are ergonomically designed to give easy fit',
|
||||
id: 'bafab694-3801-452c-b102-9eb519bd1143',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/89827115',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/55952747',
|
||||
inProduction: false,
|
||||
open: false,
|
||||
price: '553.84',
|
||||
productName: 'Bespoke Soft Computer',
|
||||
quantity: 29,
|
||||
rating: 2.176_412_873_760_271_7,
|
||||
releaseDate: '2024-09-17T12:16:27.034Z',
|
||||
status: 'error',
|
||||
tags: ['Elegant', 'Rustic', 'Recycled'],
|
||||
weight: 9.653_285_869_978_038,
|
||||
},
|
||||
{
|
||||
available: true,
|
||||
category: 'Toys',
|
||||
color: 'indigo',
|
||||
currency: 'BIF',
|
||||
description:
|
||||
'Andy shoes are designed to keeping in mind durability as well as trends, the most stylish range of shoes & sandals',
|
||||
id: 'bf6dea6b-2a55-441d-8773-937e03d99389',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/21431092',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/3771350',
|
||||
inProduction: true,
|
||||
open: true,
|
||||
price: '237.39',
|
||||
productName: 'Handcrafted Cotton Mouse',
|
||||
quantity: 54,
|
||||
rating: 4.363_265_388_265_461,
|
||||
releaseDate: '2023-10-23T13:42:34.947Z',
|
||||
status: 'error',
|
||||
tags: ['Unbranded', 'Handmade', 'Generic'],
|
||||
weight: 9.513_203_612_535_571,
|
||||
},
|
||||
{
|
||||
available: false,
|
||||
category: 'Tools',
|
||||
color: 'violet',
|
||||
currency: 'TZS',
|
||||
description:
|
||||
'New ABC 13 9370, 13.3, 5th Gen CoreA5-8250U, 8GB RAM, 256GB SSD, power UHD Graphics, OS 10 Home, OS Office A & J 2016',
|
||||
id: '135ba6ab-32ee-4989-8189-5cfa658ef970',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/29946092',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/23842994',
|
||||
inProduction: false,
|
||||
open: false,
|
||||
price: '825.25',
|
||||
productName: 'Awesome Bronze Ball',
|
||||
quantity: 94,
|
||||
rating: 4.251_159_804_726_753,
|
||||
releaseDate: '2023-12-30T07:31:43.464Z',
|
||||
status: 'warning',
|
||||
tags: ['Handmade', 'Elegant', 'Unbranded'],
|
||||
weight: 2.247_473_385_732_636_8,
|
||||
},
|
||||
{
|
||||
available: true,
|
||||
category: 'Automotive',
|
||||
color: 'teal',
|
||||
currency: 'BOB',
|
||||
description: 'The Football Is Good For Training And Recreational Purposes',
|
||||
id: '652ef256-7d4e-48b7-976c-7afaa781ea92',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/2531904',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/15215990',
|
||||
inProduction: false,
|
||||
open: false,
|
||||
price: '780.49',
|
||||
productName: 'Oriental Rubber Pants',
|
||||
quantity: 70,
|
||||
rating: 2.636_323_417_377_916,
|
||||
releaseDate: '2024-02-23T23:30:49.628Z',
|
||||
status: 'success',
|
||||
tags: ['Unbranded', 'Elegant', 'Unbranded'],
|
||||
weight: 4.812_965_858_018_838,
|
||||
},
|
||||
{
|
||||
available: false,
|
||||
category: 'Garden',
|
||||
color: 'plum',
|
||||
currency: 'LRD',
|
||||
description:
|
||||
'The slim & simple Maple Gaming Keyboard from Dev Byte comes with a sleek body and 7- Color RGB LED Back-lighting for smart functionality',
|
||||
id: '3ea24798-6589-40cc-85f0-ab78752244a0',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/23165285',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/14595665',
|
||||
inProduction: false,
|
||||
open: true,
|
||||
price: '583.85',
|
||||
productName: 'Handcrafted Concrete Hat',
|
||||
quantity: 15,
|
||||
rating: 1.371_600_527_752_802_7,
|
||||
releaseDate: '2024-03-02T19:40:50.255Z',
|
||||
status: 'error',
|
||||
tags: ['Rustic', 'Sleek', 'Ergonomic'],
|
||||
weight: 4.926_949_366_405_728_4,
|
||||
},
|
||||
{
|
||||
available: false,
|
||||
category: 'Industrial',
|
||||
color: 'salmon',
|
||||
currency: 'AUD',
|
||||
description:
|
||||
'The Apollotech B340 is an affordable wireless mouse with reliable connectivity, 12 months battery life and modern design',
|
||||
id: '997113dd-f6e4-4acc-9790-ef554c7498d1',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/49021914',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/4690621',
|
||||
inProduction: true,
|
||||
open: false,
|
||||
price: '67.99',
|
||||
productName: 'Generic Rubber Bacon',
|
||||
quantity: 68,
|
||||
rating: 4.129_840_682_128_08,
|
||||
releaseDate: '2023-12-17T01:40:25.415Z',
|
||||
status: 'error',
|
||||
tags: ['Oriental', 'Small', 'Handcrafted'],
|
||||
weight: 1.080_114_331_801_906_4,
|
||||
},
|
||||
{
|
||||
available: false,
|
||||
category: 'Tools',
|
||||
color: 'sky blue',
|
||||
currency: 'NOK',
|
||||
description:
|
||||
'The Nagasaki Lander is the trademarked name of several series of Nagasaki sport bikes, that started with the 1984 ABC800J',
|
||||
id: 'f697a250-6cb2-46c8-b0f7-871ab1f2fa8d',
|
||||
imageUrl: 'https://avatars.githubusercontent.com/u/95928385',
|
||||
imageUrl2: 'https://avatars.githubusercontent.com/u/47588244',
|
||||
inProduction: false,
|
||||
open: false,
|
||||
price: '613.89',
|
||||
productName: 'Gorgeous Frozen Ball',
|
||||
quantity: 55,
|
||||
rating: 1.646_947_205_998_534_6,
|
||||
releaseDate: '2024-10-13T12:31:04.929Z',
|
||||
status: 'warning',
|
||||
tags: ['Handmade', 'Unbranded', 'Unbranded'],
|
||||
weight: 9.430_690_557_758_114,
|
||||
},
|
||||
];
|
80
docs/src/demos/vben-vxe-table/tree/index.vue
Normal file
80
docs/src/demos/vben-vxe-table/tree/index.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { MOCK_TREE_TABLE_DATA } from '../table-data';
|
||||
|
||||
interface RowType {
|
||||
date: string;
|
||||
id: number;
|
||||
name: string;
|
||||
parentId: null | number;
|
||||
size: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
// 数据实例
|
||||
// const MOCK_TREE_TABLE_DATA = [
|
||||
// {
|
||||
// date: '2020-08-01',
|
||||
// id: 10_000,
|
||||
// name: 'Test1',
|
||||
// parentId: null,
|
||||
// size: 1024,
|
||||
// type: 'mp3',
|
||||
// },
|
||||
// {
|
||||
// date: '2021-04-01',
|
||||
// id: 10_050,
|
||||
// name: 'Test2',
|
||||
// parentId: 10_000,
|
||||
// size: 0,
|
||||
// type: 'mp4',
|
||||
// },
|
||||
// ];
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
columns: [
|
||||
{ type: 'seq', width: 70 },
|
||||
{ field: 'name', minWidth: 300, title: 'Name', treeNode: true },
|
||||
{ field: 'size', title: 'Size' },
|
||||
{ field: 'type', title: 'Type' },
|
||||
{ field: 'date', title: 'Date' },
|
||||
],
|
||||
data: MOCK_TREE_TABLE_DATA,
|
||||
pagerConfig: {
|
||||
enabled: false,
|
||||
},
|
||||
treeConfig: {
|
||||
parentField: 'parentId',
|
||||
rowField: 'id',
|
||||
transform: true,
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({ gridOptions });
|
||||
|
||||
const expandAll = () => {
|
||||
gridApi.grid?.setAllTreeExpand(true);
|
||||
};
|
||||
|
||||
const collapseAll = () => {
|
||||
gridApi.grid?.setAllTreeExpand(false);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vp-raw h-[300px] w-full">
|
||||
<Grid>
|
||||
<template #toolbar-tools>
|
||||
<Button class="mr-2" type="primary" @click="expandAll">
|
||||
展开全部
|
||||
</Button>
|
||||
<Button type="primary" @click="collapseAll"> 折叠全部 </Button>
|
||||
</template>
|
||||
</Grid>
|
||||
</div>
|
||||
</template>
|
64
docs/src/demos/vben-vxe-table/virtual/index.vue
Normal file
64
docs/src/demos/vben-vxe-table/virtual/index.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
interface RowType {
|
||||
id: number;
|
||||
name: string;
|
||||
role: string;
|
||||
sex: string;
|
||||
}
|
||||
|
||||
const gridOptions: VxeGridProps<RowType> = {
|
||||
columns: [
|
||||
{ type: 'seq', width: 70 },
|
||||
{ field: 'name', title: 'Name' },
|
||||
{ field: 'role', title: 'Role' },
|
||||
{ field: 'sex', title: 'Sex' },
|
||||
],
|
||||
data: [],
|
||||
height: 'auto',
|
||||
pagerConfig: {
|
||||
enabled: false,
|
||||
},
|
||||
scrollY: {
|
||||
enabled: true,
|
||||
gt: 0,
|
||||
},
|
||||
showOverflow: true,
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({ gridOptions });
|
||||
|
||||
// 模拟行数据
|
||||
const loadList = (size = 200) => {
|
||||
try {
|
||||
const dataList: RowType[] = [];
|
||||
for (let i = 0; i < size; i++) {
|
||||
dataList.push({
|
||||
id: 10_000 + i,
|
||||
name: `Test${i}`,
|
||||
role: 'Developer',
|
||||
sex: '男',
|
||||
});
|
||||
}
|
||||
gridApi.setGridOptions({ data: dataList });
|
||||
} catch (error) {
|
||||
console.error('Failed to load data:', error);
|
||||
// Implement user-friendly error handling
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadList(1000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="vp-raw h-[500px] w-full">
|
||||
<Grid />
|
||||
</div>
|
||||
</template>
|
@ -72,7 +72,7 @@ const { b, e, is } = useNamespace('menu');
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
// If you use it within the application, this line of code can be omitted as it has already been globally introduced in all applications
|
||||
@import '@vben/styles/global';
|
||||
@use '@vben/styles/global' as *;
|
||||
@include b('menu') {
|
||||
color: black;
|
||||
|
||||
|
@ -164,6 +164,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
||||
/**
|
||||
* @description 项目配置文件
|
||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||
*/
|
||||
export const overridesPreferences = defineOverridesPreferences({
|
||||
// overrides
|
||||
@ -536,5 +537,4 @@ interface Preferences {
|
||||
|
||||
- `overridesPreferences`方法只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置。
|
||||
- 任何配置项都可以覆盖,只需要在`overridesPreferences`方法内覆盖即可,不要修改默认配置文件。
|
||||
|
||||
:::
|
||||
- 更改配置后请清空缓存,否则可能不生效。:::
|
||||
|
@ -72,7 +72,7 @@ const { b, e, is } = useNamespace('menu');
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
// 如果你在应用内使用,这行代码可以省略,已经在所有的应用内全局引入了
|
||||
@import '@vben/styles/global';
|
||||
@use '@vben/styles/global' as *;
|
||||
@include b('menu') {
|
||||
color: black;
|
||||
|
||||
|
@ -66,7 +66,9 @@ pnpm install
|
||||
|
||||
::: tip 注意
|
||||
|
||||
项目只支持使用 `pnpm` 进行依赖安装,默认会使用 `corepack` 来安装指定版本的 `pnpm`。:
|
||||
- 项目只支持使用 `pnpm` 进行依赖安装,默认会使用 `corepack` 来安装指定版本的 `pnpm`。:
|
||||
- 如果你的网络环境无法访问npm源,你可以设置系统的环境变量`COREPACK_REGISTRY=https://registry.npmmirror.com`,然后再执行`pnpm install`。
|
||||
- 如果你不想使用`corepack`,你需要禁用`corepack`,然后使用你自己的`pnpm`进行安装。
|
||||
|
||||
:::
|
||||
|
||||
|
@ -109,7 +109,7 @@ function createCssOptions(injectGlobalScss = true) {
|
||||
const relativePath = relative(root, filepath);
|
||||
// apps下的包注入全局样式
|
||||
if (relativePath.startsWith(`apps${path.sep}`)) {
|
||||
return `@import "@vben/styles/global";\n${content}`;
|
||||
return `@use "@vben/styles/global" as *;\n${content}`;
|
||||
}
|
||||
return content;
|
||||
},
|
||||
|
@ -243,4 +243,5 @@ export {
|
||||
viteDtsPlugin,
|
||||
viteHtmlPlugin,
|
||||
viteVisualizerPlugin,
|
||||
viteVxeTableImportsPlugin,
|
||||
};
|
||||
|
@ -4,6 +4,35 @@ import { lazyImport, VxeResolver } from 'vite-plugin-lazy-import';
|
||||
|
||||
async function viteVxeTableImportsPlugin(): Promise<PluginOption> {
|
||||
return [
|
||||
// {
|
||||
// config() {
|
||||
// return {
|
||||
// optimizeDeps: {
|
||||
// include: [
|
||||
// 'vxe-pc-ui/es/vxe-button/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-checkbox/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-icon/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-input/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-loading/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-modal/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-pager/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-radio-group/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-select/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-tooltip/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-ui/index.js',
|
||||
// 'vxe-pc-ui/es/vxe-upload/index.js',
|
||||
// 'vxe-table/es/vxe-colgroup/index.js',
|
||||
// 'vxe-table/es/vxe-column/index.js',
|
||||
// 'vxe-table/es/vxe-grid/index.js',
|
||||
// 'vxe-table/es/vxe-table/index.js',
|
||||
// 'vxe-table/es/vxe-toolbar/index.js',
|
||||
// 'vxe-table/es/vxe-ui/index.js',
|
||||
// ],
|
||||
// },
|
||||
// };
|
||||
// },
|
||||
// name: 'vxe-table-adapter',
|
||||
// },
|
||||
lazyImport({
|
||||
resolvers: [
|
||||
VxeResolver({
|
||||
|
@ -97,7 +97,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.10.0",
|
||||
"pnpm": ">=9.5.0"
|
||||
"pnpm": ">=9.12.0"
|
||||
},
|
||||
"packageManager": "pnpm@9.12.3",
|
||||
"pnpm": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { defineComponent, h } from 'vue';
|
||||
|
||||
import { Icon } from '@iconify/vue';
|
||||
import { addIcon, Icon, type IconifyIcon } from '@iconify/vue';
|
||||
|
||||
function createIconifyIcon(icon: string) {
|
||||
return defineComponent({
|
||||
@ -11,4 +11,20 @@ function createIconifyIcon(icon: string) {
|
||||
});
|
||||
}
|
||||
|
||||
export { createIconifyIcon };
|
||||
/**
|
||||
* 创建离线图标
|
||||
* @param icon 图标名称 建议与iconify的名称保持一致
|
||||
* @param iconComponent 从@iconify/icon-xxx/xxx导入的图标
|
||||
* @returns IconComponent
|
||||
*/
|
||||
function createIconifyOfflineIcon(icon: string, iconComponent: IconifyIcon) {
|
||||
return defineComponent({
|
||||
name: `Icon-${icon}`,
|
||||
setup(props, { attrs }) {
|
||||
addIcon(icon, iconComponent);
|
||||
return () => h(Icon, { icon, ...props, ...attrs });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export { createIconifyIcon, createIconifyOfflineIcon };
|
||||
|
@ -5,3 +5,8 @@ export * from './lucide';
|
||||
|
||||
export type { IconifyIcon as IconifyIconStructure } from '@iconify/vue';
|
||||
export { addCollection, addIcon, Icon as IconifyIcon } from '@iconify/vue';
|
||||
|
||||
/**
|
||||
* 从@iconify/vue/dist/offline'导出的组件为离线ICON 不支持在线
|
||||
* 从@iconify/vue'导出的组件为在能找到本地图标为离线 否则会在线获取(适用性更强)
|
||||
*/
|
||||
|
@ -253,6 +253,7 @@ export class FormApi {
|
||||
}
|
||||
|
||||
unmount() {
|
||||
this.form?.resetForm?.();
|
||||
// this.state = null;
|
||||
this.isMounted = false;
|
||||
this.stateHandler.reset();
|
||||
|
@ -99,7 +99,7 @@ onBeforeUnmount(() => {
|
||||
>
|
||||
<template #trigger>
|
||||
<div :class="[nsMenu.be('tooltip', 'trigger')]">
|
||||
<VbenIcon :class="nsMenu.e('icon')" :icon="menuIcon" fallback />
|
||||
<VbenIcon :class="nsMenu.e('icon')" :icon="menuIcon" />
|
||||
<slot></slot>
|
||||
<span v-if="collapseShowTitle" :class="nsMenu.e('name')">
|
||||
<slot name="title"></slot>
|
||||
|
@ -144,7 +144,6 @@ const tabsView = computed(() => {
|
||||
:icon="tab.icon"
|
||||
class="mr-1 flex size-4 items-center overflow-hidden"
|
||||
/>
|
||||
|
||||
<span class="flex-1 overflow-hidden whitespace-nowrap text-sm">
|
||||
{{ tab.title }}
|
||||
</span>
|
||||
|
@ -38,9 +38,9 @@
|
||||
"@vben/types": "workspace:*",
|
||||
"@vueuse/core": "catalog:",
|
||||
"@vueuse/integrations": "catalog:",
|
||||
"codemirror": "^6.0.1",
|
||||
"codemirror": "6.0.1",
|
||||
"qrcode": "catalog:",
|
||||
"vditor": "^3.10.6",
|
||||
"vditor": "3.10.7",
|
||||
"vue": "catalog:",
|
||||
"vue-codemirror6": "1.3.4",
|
||||
"vue-json-pretty": "^2.4.0",
|
||||
|
@ -1,4 +1,4 @@
|
||||
:root {
|
||||
:root .vxe-grid {
|
||||
--vxe-ui-font-color: hsl(var(--foreground));
|
||||
--vxe-ui-font-primary-color: hsl(var(--primary));
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
/* layout */
|
||||
--vxe-ui-layout-background-color: hsl(var(--background));
|
||||
--vxe-ui-table-resizable-line-color: hsl(var(--border));
|
||||
--vxe-ui-table-resizable-line-color: hsl(var(--heavy));
|
||||
|
||||
/* --vxe-ui-table-fixed-left-scrolling-box-shadow: 8px 0px 10px -5px hsl(var(--accent));
|
||||
--vxe-ui-table-fixed-right-scrolling-box-shadow: -8px 0px 10px -5px hsl(var(--accent)); */
|
||||
@ -66,15 +66,13 @@
|
||||
box-shadow: 0 0 0 1px hsl(var(--border));
|
||||
}
|
||||
|
||||
.vxe-pager {
|
||||
&--wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.vxe-pager--wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&--sizes {
|
||||
margin-right: auto;
|
||||
}
|
||||
.vxe-pager--sizes {
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,3 +41,5 @@ export function useVbenVxeGrid(options: VxeGridProps) {
|
||||
|
||||
return [Grid, extendedApi] as const;
|
||||
}
|
||||
|
||||
export type UseVbenVxeGrid = typeof useVbenVxeGrid;
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
computed,
|
||||
nextTick,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
toRaw,
|
||||
useSlots,
|
||||
useTemplateRef,
|
||||
@ -261,6 +262,11 @@ onMounted(() => {
|
||||
props.api?.mount?.(gridRef.value, formApi);
|
||||
init();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
formApi?.unmount?.();
|
||||
props.api?.unmount?.();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -17,6 +17,44 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@vben-core/icons": "workspace:*"
|
||||
"@vben-core/icons": "workspace:*",
|
||||
"@vben-core/shadcn-ui": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify/icons-akar-icons": "^1.2.19",
|
||||
"@iconify/icons-ant-design": "^1.2.7",
|
||||
"@iconify/icons-arcticons": "^1.2.77",
|
||||
"@iconify/icons-bi": "^1.2.19",
|
||||
"@iconify/icons-bx": "^1.2.6",
|
||||
"@iconify/icons-carbon": "^1.2.20",
|
||||
"@iconify/icons-devicon": "^1.2.17",
|
||||
"@iconify/icons-emojione": "^1.2.6",
|
||||
"@iconify/icons-eos-icons": "^1.2.6",
|
||||
"@iconify/icons-fa-brands": "^1.2.4",
|
||||
"@iconify/icons-fe": "^1.2.5",
|
||||
"@iconify/icons-flat-color-icons": "^1.2.5",
|
||||
"@iconify/icons-fluent": "^1.2.38",
|
||||
"@iconify/icons-fluent-mdl2": "^1.2.1",
|
||||
"@iconify/icons-ic": "^1.2.13",
|
||||
"@iconify/icons-icon-park-outline": "^1.2.11",
|
||||
"@iconify/icons-icon-park-twotone": "^1.2.8",
|
||||
"@iconify/icons-la": "^1.2.3",
|
||||
"@iconify/icons-logos": "^1.2.36",
|
||||
"@iconify/icons-lucide": "^1.2.135",
|
||||
"@iconify/icons-majesticons": "^1.2.6",
|
||||
"@iconify/icons-material-symbols": "^1.2.58",
|
||||
"@iconify/icons-mdi": "^1.2.48",
|
||||
"@iconify/icons-mingcute": "^1.2.9",
|
||||
"@iconify/icons-noto": "^1.2.10",
|
||||
"@iconify/icons-ph": "^1.2.5",
|
||||
"@iconify/icons-ri": "^1.2.10",
|
||||
"@iconify/icons-simple-icons": "^1.2.74",
|
||||
"@iconify/icons-skill-icons": "^1.2.1",
|
||||
"@iconify/icons-solar": "^1.2.3",
|
||||
"@iconify/icons-streamline": "^1.2.3",
|
||||
"@iconify/icons-tabler": "^1.2.95",
|
||||
"@iconify/icons-uiw": "^1.2.6",
|
||||
"@iconify/icons-vscode-icons": "^1.2.29",
|
||||
"@iconify/icons-wpf": "^1.2.3"
|
||||
}
|
||||
}
|
||||
|
186
packages/icons/src/iconify-offline/index.ts
Normal file
186
packages/icons/src/iconify-offline/index.ts
Normal file
@ -0,0 +1,186 @@
|
||||
import { createIconifyOfflineIcon } from '@vben-core/icons';
|
||||
|
||||
import githubOutlined from '@iconify/icons-ant-design/github-outlined';
|
||||
import inboxIcon from '@iconify/icons-ant-design/inbox-outlined';
|
||||
import userOutlined from '@iconify/icons-ant-design/user-outlined';
|
||||
import ucIcon from '@iconify/icons-arcticons/uc-browser';
|
||||
import defaultFileIcon from '@iconify/icons-bx/file';
|
||||
import sqlIcon from '@iconify/icons-carbon/sql';
|
||||
import linuxIcon from '@iconify/icons-devicon/linux';
|
||||
import windowsIcon from '@iconify/icons-devicon/windows8';
|
||||
import alipayIcon from '@iconify/icons-fa-brands/alipay';
|
||||
import androidIcon from '@iconify/icons-flat-color-icons/android-os';
|
||||
import comandLine from '@iconify/icons-flat-color-icons/command-line';
|
||||
import folderIcon from '@iconify/icons-flat-color-icons/folder';
|
||||
import defaultOsIcon from '@iconify/icons-ic/outline-computer';
|
||||
import memoryIcon from '@iconify/icons-la/memory';
|
||||
import chromeIcon from '@iconify/icons-logos/chrome';
|
||||
import firefoxIcon from '@iconify/icons-logos/firefox';
|
||||
import edgeIcon from '@iconify/icons-logos/microsoft-edge';
|
||||
import operaIcon from '@iconify/icons-logos/opera';
|
||||
import quarkIcon from '@iconify/icons-logos/quarkus-icon';
|
||||
import redisIcon from '@iconify/icons-logos/redis';
|
||||
import safariIcon from '@iconify/icons-logos/safari';
|
||||
import vueIcon from '@iconify/icons-logos/vue';
|
||||
import iphoneIcon from '@iconify/icons-majesticons/iphone-x-apps-line';
|
||||
import menuIcon from '@iconify/icons-material-symbols/menu';
|
||||
import okButtonIcon from '@iconify/icons-mdi/button-pointer';
|
||||
import micromessengerIcon from '@iconify/icons-mdi/wechat';
|
||||
import defaultBrowserIcon from '@iconify/icons-ph/browser-duotone';
|
||||
import baiduIcon from '@iconify/icons-ri/baidu-fill';
|
||||
import dingdingFill from '@iconify/icons-ri/dingding-fill';
|
||||
import dingtalkIcon from '@iconify/icons-ri/dingding-line';
|
||||
import taobaoIconFill from '@iconify/icons-ri/taobao-fill';
|
||||
import giteeIcon from '@iconify/icons-simple-icons/gitee';
|
||||
import qqIcon from '@iconify/icons-simple-icons/tencentqq';
|
||||
import javaIcon from '@iconify/icons-skill-icons/java-light';
|
||||
import tsIcon from '@iconify/icons-skill-icons/typescript';
|
||||
import xmlIcon from '@iconify/icons-tabler/file-type-xml';
|
||||
import githubOAuthIcon from '@iconify/icons-uiw/github';
|
||||
import excelIcon from '@iconify/icons-vscode-icons/file-type-excel';
|
||||
import osxIcon from '@iconify/icons-wpf/macos';
|
||||
|
||||
import './menu-icons';
|
||||
|
||||
// 用户 下拉菜单
|
||||
export const GitHubOutlined = createIconifyOfflineIcon(
|
||||
'ant-design:github-outlined',
|
||||
githubOutlined,
|
||||
);
|
||||
|
||||
export const UserOutlined = createIconifyOfflineIcon(
|
||||
'ant-design:user-outlined',
|
||||
userOutlined,
|
||||
);
|
||||
|
||||
// 缓存监控使用
|
||||
export const RedisIcon = createIconifyOfflineIcon('logos:redis', redisIcon);
|
||||
export const CommandLineIcon = createIconifyOfflineIcon(
|
||||
'flat-color-icons:command-line',
|
||||
comandLine,
|
||||
);
|
||||
export const MemoryIcon = createIconifyOfflineIcon('la:memory', memoryIcon);
|
||||
|
||||
// 用户管理 导入
|
||||
// Excel图标
|
||||
export const ExcelIcon = createIconifyOfflineIcon(
|
||||
'vscode-icons:file-type-excel',
|
||||
excelIcon,
|
||||
);
|
||||
// 拖拽上传图标
|
||||
export const InBoxIcon = createIconifyOfflineIcon(
|
||||
'ant-design:inbox-outlined',
|
||||
inboxIcon,
|
||||
);
|
||||
|
||||
// 第三方登录相关图标
|
||||
export const TaobaoIcon = createIconifyOfflineIcon(
|
||||
'ri:taobao-fill',
|
||||
taobaoIconFill,
|
||||
);
|
||||
export const AlipayIcon = createIconifyOfflineIcon(
|
||||
'fa-brands:alipay',
|
||||
alipayIcon,
|
||||
);
|
||||
export const DingdingIcon = createIconifyOfflineIcon(
|
||||
'ri:dingding-fill',
|
||||
dingdingFill,
|
||||
);
|
||||
export const GiteeIcon = createIconifyOfflineIcon(
|
||||
'simple-icons:gitee',
|
||||
giteeIcon,
|
||||
);
|
||||
export const GithubOAuthIcon = createIconifyOfflineIcon(
|
||||
'uiw:github',
|
||||
githubOAuthIcon,
|
||||
);
|
||||
|
||||
// 系统相关图标
|
||||
export const WindowsIcon = createIconifyOfflineIcon(
|
||||
'devicon:windows8',
|
||||
windowsIcon,
|
||||
);
|
||||
export const LinuxIcon = createIconifyOfflineIcon('devicon:linux', linuxIcon);
|
||||
export const OSXIcon = createIconifyOfflineIcon('wpf:macos', osxIcon);
|
||||
export const AndroidIcon = createIconifyOfflineIcon(
|
||||
'flat-color-icons:android-os',
|
||||
androidIcon,
|
||||
);
|
||||
export const IPhoneIcon = createIconifyOfflineIcon(
|
||||
'majesticons:iphone-x-apps-line',
|
||||
iphoneIcon,
|
||||
);
|
||||
// 上面图标没找到 默认图标
|
||||
export const DefaultOsIcon = createIconifyOfflineIcon(
|
||||
'ic:outline-computer',
|
||||
defaultOsIcon,
|
||||
);
|
||||
|
||||
// 浏览器相关图标
|
||||
export const ChromeIcon = createIconifyOfflineIcon('logos:chrome', chromeIcon);
|
||||
export const EdgeIcon = createIconifyOfflineIcon(
|
||||
'logos:microsoft-edge',
|
||||
edgeIcon,
|
||||
);
|
||||
export const FirefoxIcon = createIconifyOfflineIcon(
|
||||
'logos:firefox',
|
||||
firefoxIcon,
|
||||
);
|
||||
export const OperaIcon = createIconifyOfflineIcon('logos:opera', operaIcon);
|
||||
export const SafariIcon = createIconifyOfflineIcon('logos:safari', safariIcon);
|
||||
export const MicromessengerIcon = createIconifyOfflineIcon(
|
||||
'mdi:wechat',
|
||||
micromessengerIcon,
|
||||
);
|
||||
export const QuarkIcon = createIconifyOfflineIcon(
|
||||
'logos:quarkus-icon',
|
||||
quarkIcon,
|
||||
);
|
||||
export const QQIcon = createIconifyOfflineIcon(
|
||||
'simple-icons:tencentqq',
|
||||
qqIcon,
|
||||
);
|
||||
export const DingtalkIcon = createIconifyOfflineIcon(
|
||||
'ri:dingding-line',
|
||||
dingtalkIcon,
|
||||
);
|
||||
export const UcIcon = createIconifyOfflineIcon('arcticons:uc-browser', ucIcon);
|
||||
export const BaiduIcon = createIconifyOfflineIcon('ri:baidu-fill', baiduIcon);
|
||||
// 未知浏览器图标
|
||||
export const DefaultBrowserIcon = createIconifyOfflineIcon(
|
||||
'ph:browser-duotone',
|
||||
defaultBrowserIcon,
|
||||
);
|
||||
|
||||
// 菜单类型 目录/按钮/菜单
|
||||
export const FolderIcon = createIconifyOfflineIcon(
|
||||
'flat-color-icons:folder',
|
||||
folderIcon,
|
||||
);
|
||||
export const OkButtonIcon = createIconifyOfflineIcon(
|
||||
'mdi:button-pointer',
|
||||
okButtonIcon,
|
||||
);
|
||||
export const MenuIcon = createIconifyOfflineIcon(
|
||||
'material-symbols:menu',
|
||||
menuIcon,
|
||||
);
|
||||
|
||||
export const JavaIcon = createIconifyOfflineIcon(
|
||||
'skill-icons:java-light',
|
||||
javaIcon,
|
||||
);
|
||||
export const XmlIcon = createIconifyOfflineIcon(
|
||||
'tabler:file-type-xml',
|
||||
xmlIcon,
|
||||
);
|
||||
export const SqlIcon = createIconifyOfflineIcon('carbon:sql', sqlIcon);
|
||||
export const TsIcon = createIconifyOfflineIcon(
|
||||
'skill-icons:typescript',
|
||||
tsIcon,
|
||||
);
|
||||
export const VueIcon = createIconifyOfflineIcon('logos:vue', vueIcon);
|
||||
export const DefaultFileIcon = createIconifyOfflineIcon(
|
||||
'flat-color-icons:folder',
|
||||
defaultFileIcon,
|
||||
);
|
102
packages/icons/src/iconify-offline/menu-icons.ts
Normal file
102
packages/icons/src/iconify-offline/menu-icons.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import { addIcon } from '@vben-core/icons';
|
||||
|
||||
import schedule from '@iconify/icons-akar-icons/schedule';
|
||||
import settingOutline from '@iconify/icons-ant-design/setting-outlined';
|
||||
import Operation from '@iconify/icons-arcticons/one-hand-operation';
|
||||
import BaseLineHousesFill from '@iconify/icons-bi/houses-fill';
|
||||
import BxPackage from '@iconify/icons-bx/package';
|
||||
import modelAlt from '@iconify/icons-carbon/model-alt';
|
||||
import taskApproved from '@iconify/icons-carbon/task-approved';
|
||||
import redisWordmark from '@iconify/icons-devicon/redis-wordmark';
|
||||
import springWordmark from '@iconify/icons-devicon/spring-wordmark';
|
||||
import vscode from '@iconify/icons-devicon/vscode';
|
||||
import evergreenTree from '@iconify/icons-emojione/evergreen-tree';
|
||||
import RoleBindingOutlined from '@iconify/icons-eos-icons/role-binding-outlined';
|
||||
import SystemGroup from '@iconify/icons-eos-icons/system-group';
|
||||
import NoticePush from '@iconify/icons-fe/notice-push';
|
||||
import plus from '@iconify/icons-flat-color-icons/plus';
|
||||
import from24 from '@iconify/icons-fluent/form-24-regular';
|
||||
import builDefinition from '@iconify/icons-fluent-mdl2/build-definition';
|
||||
import Dictionary from '@iconify/icons-fluent-mdl2/dictionary';
|
||||
import leaveUser from '@iconify/icons-fluent-mdl2/leave-user';
|
||||
import BaseLineHouse from '@iconify/icons-ic/baseline-house';
|
||||
import monitor from '@iconify/icons-ic/baseline-monitor';
|
||||
import roundLaunch from '@iconify/icons-ic/round-launch';
|
||||
import MenuSharp from '@iconify/icons-ic/sharp-menu';
|
||||
import Appointment from '@iconify/icons-icon-park-outline/appointment';
|
||||
import SettingTwo from '@iconify/icons-icon-park-twotone/setting-two';
|
||||
import boolOpenText from '@iconify/icons-lucide/book-open-text';
|
||||
import copyright from '@iconify/icons-lucide/copyright';
|
||||
import table from '@iconify/icons-lucide/table';
|
||||
import cloudDoneOutlineRounded from '@iconify/icons-material-symbols/cloud-done-outline-rounded';
|
||||
import generatingTokensOutline from '@iconify/icons-material-symbols/generating-tokens-outline';
|
||||
import LogoDevOutline from '@iconify/icons-material-symbols/logo-dev-outline';
|
||||
import ccOutline from '@iconify/icons-mdi/cc-outline';
|
||||
import tools from '@iconify/icons-mdi/tools';
|
||||
import workflowOutline from '@iconify/icons-mdi/workflow-outline';
|
||||
import DepartmentLine from '@iconify/icons-mingcute/department-line';
|
||||
import profileLine from '@iconify/icons-mingcute/profile-line';
|
||||
import UserDuotone from '@iconify/icons-ph/user-duotone';
|
||||
import insatnceLine from '@iconify/icons-ri/instance-line';
|
||||
import todoLine from '@iconify/icons-ri/todo-line';
|
||||
import Authy from '@iconify/icons-simple-icons/authy';
|
||||
import FolderWithFilesOutline from '@iconify/icons-solar/folder-with-files-outline';
|
||||
import monitorBoldDuotone from '@iconify/icons-solar/monitor-bold-duotone';
|
||||
import InterfaceLoginDialPadFingerPasswordDialPadDotFinger from '@iconify/icons-streamline/interface-login-dial-pad-finger-password-dial-pad-dot-finger';
|
||||
import categoryPlus from '@iconify/icons-tabler/category-plus';
|
||||
import code from '@iconify/icons-tabler/code';
|
||||
|
||||
/**
|
||||
* 这里添加菜单图标
|
||||
*/
|
||||
addIcon('eos-icons:system-group', SystemGroup);
|
||||
addIcon('ph:user-duotone', UserDuotone);
|
||||
addIcon('eos-icons:role-binding-outlined', RoleBindingOutlined);
|
||||
addIcon('ic:sharp-menu', MenuSharp);
|
||||
addIcon('mingcute:department-line', DepartmentLine);
|
||||
addIcon('icon-park-outline:appointment', Appointment);
|
||||
addIcon('fluent-mdl2:dictionary', Dictionary);
|
||||
addIcon('icon-park-twotone:setting-two', SettingTwo);
|
||||
addIcon('fe:notice-push', NoticePush);
|
||||
addIcon('material-symbols:logo-dev-outline', LogoDevOutline);
|
||||
addIcon('arcticons:one-hand-operation', Operation);
|
||||
addIcon(
|
||||
'streamline:interface-login-dial-pad-finger-password-dial-pad-dot-finger',
|
||||
InterfaceLoginDialPadFingerPasswordDialPadDotFinger,
|
||||
);
|
||||
addIcon('solar:folder-with-files-outline', FolderWithFilesOutline);
|
||||
addIcon('simple-icons:authy', Authy);
|
||||
addIcon('ic:baseline-house', BaseLineHouse);
|
||||
addIcon('bi:houses-fill', BaseLineHousesFill);
|
||||
addIcon('bx:package', BxPackage);
|
||||
addIcon('solar:monitor-bold-duotone', monitorBoldDuotone);
|
||||
addIcon('material-symbols:generating-tokens-outline', generatingTokensOutline);
|
||||
addIcon('devicon:redis-wordmark', redisWordmark);
|
||||
addIcon('devicon:spring-wordmark', springWordmark);
|
||||
addIcon('akar-icons:schedule', schedule);
|
||||
addIcon('mdi:tools', tools);
|
||||
addIcon('tabler:code', code);
|
||||
addIcon('flat-color-icons:plus', plus);
|
||||
addIcon('devicon:vscode', vscode);
|
||||
addIcon('lucide:table', table);
|
||||
addIcon('emojione:evergreen-tree', evergreenTree);
|
||||
addIcon('fluent-mdl2:leave-user', leaveUser);
|
||||
addIcon('mdi:workflow-outline', workflowOutline);
|
||||
addIcon('tabler:category-plus', categoryPlus);
|
||||
addIcon('carbon:model-alt', modelAlt);
|
||||
addIcon('fluent-mdl2:build-definition', builDefinition);
|
||||
addIcon('fluent-mdl2:build-definition', builDefinition);
|
||||
addIcon('icon-park-outline:monitor', monitor);
|
||||
addIcon('ri:instance-line', insatnceLine);
|
||||
addIcon('ri:todo-line', todoLine);
|
||||
addIcon('fluent:form-24-regular', from24);
|
||||
addIcon('carbon:task-approved', taskApproved);
|
||||
addIcon('ic:round-launch', roundLaunch);
|
||||
addIcon('material-symbols:cloud-done-outline-rounded', cloudDoneOutlineRounded);
|
||||
addIcon('mdi:cc-outline', ccOutline);
|
||||
addIcon('lucide:book-open-text', boolOpenText);
|
||||
addIcon('lucide:copyright', copyright);
|
||||
// 个人中心
|
||||
addIcon('mingcute:profile-line', profileLine);
|
||||
// oss配置
|
||||
addIcon('ant-design:setting-outlined', settingOutline);
|
@ -13,18 +13,6 @@ export const MdiGoogle = createIconifyIcon('mdi:google');
|
||||
export const MdiQqchat = createIconifyIcon('mdi:qqchat');
|
||||
|
||||
export const EosSystem = createIconifyIcon('eos-icons:system-group');
|
||||
// 缓存监控使用
|
||||
export const RedisIcon = createIconifyIcon('logos:redis');
|
||||
export const CommandLineIcon = createIconifyIcon(
|
||||
'flat-color-icons:command-line',
|
||||
);
|
||||
export const MemoryIcon = createIconifyIcon('la:memory');
|
||||
|
||||
export const GiteeIcon = createIconifyIcon('simple-icons:gitee');
|
||||
// 个人中心
|
||||
export const ProfileIcon = createIconifyIcon('mingcute:profile-line');
|
||||
|
||||
// Excel图标
|
||||
export const ExcelIcon = createIconifyIcon('vscode-icons:file-type-excel');
|
||||
// 拖拽上传图标
|
||||
export const InBoxIcon = createIconifyIcon('ant-design:inbox-outlined');
|
||||
|
@ -1,2 +1,4 @@
|
||||
export * from './iconify/index.js';
|
||||
export * from './iconify-offline/index.js';
|
||||
export * from './svg/index.js';
|
||||
export { VbenIcon } from '@vben-core/shadcn-ui';
|
||||
|
@ -1 +1 @@
|
||||
@import '@vben-core/design/bem';
|
||||
@use '@vben-core/design/bem' as *;
|
||||
|
@ -39,7 +39,7 @@ setupVbenVxeTable({
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderDefault(_renderOpts, params) {
|
||||
renderTableDefault(_renderOpts, params) {
|
||||
const { column, row } = params;
|
||||
return h(Image, { src: row[column.field] });
|
||||
},
|
||||
@ -47,7 +47,7 @@ setupVbenVxeTable({
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderDefault(renderOpts) {
|
||||
renderTableDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
Button,
|
||||
|
@ -1,17 +1,19 @@
|
||||
import { createApp } from 'vue';
|
||||
import { createApp, watchEffect } from 'vue';
|
||||
|
||||
import { registerAccessDirective } from '@vben/access';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { initStores } from '@vben/stores';
|
||||
import '@vben/styles';
|
||||
import '@vben/styles/antd';
|
||||
|
||||
import { VueQueryPlugin } from '@tanstack/vue-query';
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { setupI18n } from '#/locales';
|
||||
import { $t, setupI18n } from '#/locales';
|
||||
import { router } from '#/router';
|
||||
|
||||
import { initComponentAdapter } from './adapter/component';
|
||||
import App from './app.vue';
|
||||
import { router } from './router';
|
||||
|
||||
async function bootstrap(namespace: string) {
|
||||
// 初始化组件适配器
|
||||
@ -34,6 +36,16 @@ async function bootstrap(namespace: string) {
|
||||
// 配置@tanstack/vue-query
|
||||
app.use(VueQueryPlugin);
|
||||
|
||||
// 动态更新标题
|
||||
watchEffect(() => {
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const routeTitle = router.currentRoute.value.meta?.title;
|
||||
const pageTitle =
|
||||
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||
useTitle(pageTitle);
|
||||
}
|
||||
});
|
||||
|
||||
app.mount('#app');
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
||||
/**
|
||||
* @description 项目配置文件
|
||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||
* !!! 更改配置后请清空缓存,否则可能不生效
|
||||
*/
|
||||
export const overridesPreferences = defineOverridesPreferences({
|
||||
// overrides
|
||||
|
@ -5,9 +5,6 @@ import { preferences } from '@vben/preferences';
|
||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||
import { startProgress, stopProgress } from '@vben/utils';
|
||||
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import { $t } from '#/locales';
|
||||
import { accessRoutes, coreRouteNames } from '#/router/routes';
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
@ -39,13 +36,6 @@ function setupCommonGuard(router: Router) {
|
||||
if (preferences.transition.progress) {
|
||||
stopProgress();
|
||||
}
|
||||
|
||||
// 动态修改标题
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const { title } = to.meta;
|
||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ catalog:
|
||||
'@ctrl/tinycolor': ^4.1.0
|
||||
'@eslint/js': ^9.14.0
|
||||
'@faker-js/faker': ^9.2.0
|
||||
'@iconify/json': ^2.2.267
|
||||
'@iconify/json': ^2.2.269
|
||||
'@iconify/tailwind': ^1.1.3
|
||||
'@iconify/vue': ^4.1.2
|
||||
'@intlify/core-base': ^10.0.4
|
||||
@ -36,7 +36,7 @@ catalog:
|
||||
'@stylistic/stylelint-plugin': ^3.1.1
|
||||
'@tailwindcss/nesting': 0.0.0-insiders.565cd3e
|
||||
'@tailwindcss/typography': ^0.5.15
|
||||
'@tanstack/vue-query': ^5.59.17
|
||||
'@tanstack/vue-query': ^5.59.20
|
||||
'@tanstack/vue-store': ^0.5.6
|
||||
'@types/archiver': ^6.0.3
|
||||
'@types/eslint': ^9.6.1
|
||||
@ -44,13 +44,13 @@ catalog:
|
||||
'@types/jsonwebtoken': ^9.0.7
|
||||
'@types/lodash.clonedeep': ^4.5.9
|
||||
'@types/lodash.get': ^4.4.9
|
||||
'@types/node': ^22.8.7
|
||||
'@types/node': ^22.9.0
|
||||
'@types/nprogress': ^0.2.3
|
||||
'@types/postcss-import': ^14.0.3
|
||||
'@types/qrcode': ^1.5.5
|
||||
'@types/sortablejs': ^1.15.8
|
||||
'@typescript-eslint/eslint-plugin': ^8.12.2
|
||||
'@typescript-eslint/parser': ^8.12.2
|
||||
'@typescript-eslint/eslint-plugin': ^8.13.0
|
||||
'@typescript-eslint/parser': ^8.13.0
|
||||
'@vee-validate/zod': ^4.14.6
|
||||
'@vite-pwa/vitepress': ^0.5.3
|
||||
'@vitejs/plugin-vue': ^5.1.4
|
||||
@ -71,10 +71,10 @@ catalog:
|
||||
circular-dependency-scanner: ^2.3.0
|
||||
class-variance-authority: ^0.7.0
|
||||
clsx: ^2.1.1
|
||||
commitlint-plugin-function-rules: ^4.0.0
|
||||
commitlint-plugin-function-rules: ^4.0.1
|
||||
consola: ^3.2.3
|
||||
cross-env: ^7.0.3
|
||||
cspell: ^8.15.7
|
||||
cspell: ^8.16.0
|
||||
cssnano: ^7.0.6
|
||||
cz-git: ^1.10.1
|
||||
czg: ^1.10.1
|
||||
@ -91,7 +91,7 @@ catalog:
|
||||
eslint-plugin-import-x: ^4.4.0
|
||||
eslint-plugin-jsdoc: ^50.4.3
|
||||
eslint-plugin-jsonc: ^2.16.0
|
||||
eslint-plugin-n: ^17.12.0
|
||||
eslint-plugin-n: ^17.13.1
|
||||
eslint-plugin-no-only-tests: ^3.3.0
|
||||
eslint-plugin-perfectionist: ^3.9.1
|
||||
eslint-plugin-prettier: ^5.2.1
|
||||
@ -105,7 +105,7 @@ catalog:
|
||||
get-port: ^7.1.0
|
||||
globals: ^15.12.0
|
||||
h3: ^1.13.0
|
||||
happy-dom: ^15.8.3
|
||||
happy-dom: ^15.11.0
|
||||
html-minifier-terser: ^7.2.0
|
||||
husky: ^9.1.6
|
||||
is-ci: ^3.0.1
|
||||
@ -117,7 +117,7 @@ catalog:
|
||||
lucide-vue-next: ^0.454.0
|
||||
medium-zoom: ^1.1.0
|
||||
naive-ui: ^2.40.1
|
||||
nitropack: ^2.10.2
|
||||
nitropack: ^2.10.3
|
||||
nprogress: ^0.2.0
|
||||
ora: ^8.1.1
|
||||
pinia: 2.2.2
|
||||
@ -139,7 +139,7 @@ catalog:
|
||||
rimraf: ^6.0.1
|
||||
rollup: ^4.24.4
|
||||
rollup-plugin-visualizer: ^5.12.0
|
||||
sass: 1.79.5
|
||||
sass: 1.80.6
|
||||
sortablejs: ^1.15.3
|
||||
stylelint: ^16.10.0
|
||||
stylelint-config-recess-order: ^5.1.1
|
||||
@ -165,8 +165,8 @@ catalog:
|
||||
vite-plugin-html: ^3.2.2
|
||||
vite-plugin-lazy-import: ^1.0.7
|
||||
vite-plugin-pwa: ^0.20.5
|
||||
vite-plugin-vue-devtools: ^7.6.2
|
||||
vitepress: ^1.4.5
|
||||
vite-plugin-vue-devtools: ^7.6.3
|
||||
vitepress: ^1.5.0
|
||||
vitepress-plugin-group-icons: ^1.3.0
|
||||
vitest: ^2.1.4
|
||||
vue: ^3.5.12
|
||||
@ -174,8 +174,8 @@ catalog:
|
||||
vue-i18n: ^10.0.4
|
||||
vue-router: ^4.4.5
|
||||
vue-tsc: ^2.1.10
|
||||
vxe-pc-ui: ^4.2.40
|
||||
vxe-table: ^4.8.0
|
||||
vxe-pc-ui: ^4.2.45
|
||||
vxe-table: ^4.8.2
|
||||
watermark-js-plus: ^1.5.7
|
||||
zod: ^3.23.8
|
||||
zod-defaults: ^0.1.3
|
||||
|
@ -33,13 +33,13 @@ UPDATE sys_menu SET icon = 'emojione:evergreen-tree' WHERE menu_id = 1506;
|
||||
UPDATE sys_menu SET icon = 'mdi:workflow-outline' WHERE menu_id = 11616;
|
||||
UPDATE sys_menu SET icon = 'carbon:model-alt' WHERE menu_id = 11617;
|
||||
UPDATE sys_menu SET icon = 'carbon:task-approved' WHERE menu_id = 11618;
|
||||
UPDATE sys_menu SET icon = 'streamline:waiting-appointments-calendar' WHERE menu_id = 11619;
|
||||
UPDATE sys_menu SET icon = 'ri:todo-line' WHERE menu_id = 11619;
|
||||
UPDATE sys_menu SET icon = 'fluent-mdl2:build-definition' WHERE menu_id = 11620;
|
||||
UPDATE sys_menu SET icon = 'ri:instance-line' WHERE menu_id = 11621;
|
||||
UPDATE sys_menu SET icon = 'tabler:category-plus' WHERE menu_id = 11622;
|
||||
UPDATE sys_menu SET icon = 'ic:round-launch' WHERE menu_id = 11629;
|
||||
UPDATE sys_menu SET icon = 'icon-park-outline:monitor' WHERE menu_id = 11630;
|
||||
UPDATE sys_menu SET icon = 'streamline:waiting-appointments-calendar' WHERE menu_id = 11631;
|
||||
UPDATE sys_menu SET icon = 'ri:todo-line' WHERE menu_id = 11631;
|
||||
UPDATE sys_menu SET icon = 'material-symbols:cloud-done-outline-rounded' WHERE menu_id = 11632;
|
||||
UPDATE sys_menu SET icon = 'mdi:cc-outline' WHERE menu_id = 11633;
|
||||
UPDATE sys_menu SET icon = 'fluent-mdl2:leave-user' WHERE menu_id = 11638;
|
||||
|
Loading…
Reference in New Issue
Block a user