Commit 9a1ba74920045a7d65f4dd802d244510aff5b3a9

Authored by Vben
1 parent f79cae63

wip: system management sample page

CHANGELOG.zh_CN.md
@@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
28 - 修复表格不能正确的获取选中行 28 - 修复表格不能正确的获取选中行
29 - 修复全屏状态下 modal 高度计算错误 29 - 修复全屏状态下 modal 高度计算错误
30 - 修复部分表格样式问题 30 - 修复部分表格样式问题
  31 +- 修复树形表格 `indentSize`设置失效
31 32
32 ## 2.0.1 (2021-02-21) 33 ## 2.0.1 (2021-02-21)
33 34
mock/demo/system.ts
@@ -18,6 +18,22 @@ const accountList = (() => { @@ -18,6 +18,22 @@ const accountList = (() => {
18 return result; 18 return result;
19 })(); 19 })();
20 20
  21 +const roleList = (() => {
  22 + const result: any[] = [];
  23 + for (let index = 0; index < 4; index++) {
  24 + result.push({
  25 + id: `${index}`,
  26 + orderNo: `${index + 1}`,
  27 + roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index],
  28 + roleValue: '@first',
  29 + createTime: '@datetime',
  30 + remark: '@cword(10,20)',
  31 + 'status|1': ['0', '1'],
  32 + });
  33 + }
  34 + return result;
  35 +})();
  36 +
21 const deptList = (() => { 37 const deptList = (() => {
22 const result: any[] = []; 38 const result: any[] = [];
23 for (let index = 0; index < 3; index++) { 39 for (let index = 0; index < 3; index++) {
@@ -49,6 +65,46 @@ const deptList = (() =&gt; { @@ -49,6 +65,46 @@ const deptList = (() =&gt; {
49 return result; 65 return result;
50 })(); 66 })();
51 67
  68 +const menuList = (() => {
  69 + const result: any[] = [];
  70 + for (let index = 0; index < 3; index++) {
  71 + result.push({
  72 + id: `${index}`,
  73 + icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index],
  74 + component: 'LAYOUT',
  75 + menuName: ['Dashboard', '权限管理', '功能'][index],
  76 + permission: '',
  77 + orderNo: index + 1,
  78 + createTime: '@datetime',
  79 + 'status|1': ['0', '0', '1'],
  80 + children: (() => {
  81 + const children: any[] = [];
  82 + for (let j = 0; j < 4; j++) {
  83 + children.push({
  84 + id: `${index}-${j}`,
  85 + menuName: ['菜单1', '菜单2', '菜单3', '菜单4'][j],
  86 + icon: 'ion:document',
  87 + permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index],
  88 + component: [
  89 + '/dashboard/welcome/index',
  90 + '/dashboard/analysis/index',
  91 + '/dashboard/workbench/index',
  92 + '/dashboard/test/index',
  93 + ][j],
  94 + orderNo: j + 1,
  95 + createTime: '@datetime',
  96 + 'status|1': ['0', '1'],
  97 + parentMenu: `${index}`,
  98 + children: undefined,
  99 + });
  100 + }
  101 + return children;
  102 + })(),
  103 + });
  104 + }
  105 + return result;
  106 +})();
  107 +
52 export default [ 108 export default [
53 { 109 {
54 url: '/api/system/getAccountList', 110 url: '/api/system/getAccountList',
@@ -60,6 +116,15 @@ export default [ @@ -60,6 +116,15 @@ export default [
60 }, 116 },
61 }, 117 },
62 { 118 {
  119 + url: '/api/system/getRoleList',
  120 + timeout: 100,
  121 + method: 'get',
  122 + response: ({ query }) => {
  123 + const { page = 1, pageSize = 20 } = query;
  124 + return resultPageSuccess(page, pageSize, roleList);
  125 + },
  126 + },
  127 + {
63 url: '/api/system/getDeptList', 128 url: '/api/system/getDeptList',
64 timeout: 100, 129 timeout: 100,
65 method: 'get', 130 method: 'get',
@@ -67,4 +132,12 @@ export default [ @@ -67,4 +132,12 @@ export default [
67 return resultSuccess(deptList); 132 return resultSuccess(deptList);
68 }, 133 },
69 }, 134 },
  135 + {
  136 + url: '/api/system/getMenuList',
  137 + timeout: 100,
  138 + method: 'get',
  139 + response: () => {
  140 + return resultSuccess(menuList);
  141 + },
  142 + },
70 ] as MockMethod[]; 143 ] as MockMethod[];
package.json
@@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
53 "devDependencies": { 53 "devDependencies": {
54 "@commitlint/cli": "^12.0.1", 54 "@commitlint/cli": "^12.0.1",
55 "@commitlint/config-conventional": "^12.0.1", 55 "@commitlint/config-conventional": "^12.0.1",
56 - "@iconify/json": "^1.1.310", 56 + "@iconify/json": "^1.1.311",
57 "@ls-lint/ls-lint": "^1.9.2", 57 "@ls-lint/ls-lint": "^1.9.2",
58 "@purge-icons/generated": "^0.7.0", 58 "@purge-icons/generated": "^0.7.0",
59 "@types/crypto-js": "^4.0.1", 59 "@types/crypto-js": "^4.0.1",
@@ -110,7 +110,7 @@ @@ -110,7 +110,7 @@
110 "vite-plugin-pwa": "^0.5.6", 110 "vite-plugin-pwa": "^0.5.6",
111 "vite-plugin-style-import": "^0.7.6", 111 "vite-plugin-style-import": "^0.7.6",
112 "vite-plugin-theme": "^0.4.8", 112 "vite-plugin-theme": "^0.4.8",
113 - "vite-plugin-windicss": "0.6.2", 113 + "vite-plugin-windicss": "0.6.4",
114 "vue-eslint-parser": "^7.6.0", 114 "vue-eslint-parser": "^7.6.0",
115 "yargs": "^16.2.0" 115 "yargs": "^16.2.0"
116 }, 116 },
src/api/demo/model/systemModel.ts
@@ -4,12 +4,21 @@ export type AccountParams = BasicPageParams &amp; { @@ -4,12 +4,21 @@ export type AccountParams = BasicPageParams &amp; {
4 account?: string; 4 account?: string;
5 nickname?: string; 5 nickname?: string;
6 }; 6 };
  7 +export type RoleParams = BasicPageParams & {
  8 + roleName?: string;
  9 + status?: string;
  10 +};
7 11
8 export type DeptParams = { 12 export type DeptParams = {
9 deptName?: string; 13 deptName?: string;
10 status?: string; 14 status?: string;
11 }; 15 };
12 16
  17 +export type MenuParams = {
  18 + menuName?: string;
  19 + status?: string;
  20 +};
  21 +
13 export interface AccountListItem { 22 export interface AccountListItem {
14 id: string; 23 id: string;
15 account: string; 24 account: string;
@@ -29,9 +38,32 @@ export interface DeptListItem { @@ -29,9 +38,32 @@ export interface DeptListItem {
29 status: number; 38 status: number;
30 } 39 }
31 40
  41 +export interface MenuListItem {
  42 + id: string;
  43 + orderNo: string;
  44 + createTime: string;
  45 + status: number;
  46 + icon: string;
  47 + component: string;
  48 + permission: string;
  49 +}
  50 +
  51 +export interface RoleListItem {
  52 + id: string;
  53 + roleName: string;
  54 + roleValue: string;
  55 + status: number;
  56 + orderNo: string;
  57 + createTime: string;
  58 +}
  59 +
32 /** 60 /**
33 * @description: Request list return value 61 * @description: Request list return value
34 */ 62 */
35 export type AccountListGetResultModel = BasicFetchResult<AccountListItem>; 63 export type AccountListGetResultModel = BasicFetchResult<AccountListItem>;
36 64
37 export type DeptListGetResultModel = BasicFetchResult<DeptListItem>; 65 export type DeptListGetResultModel = BasicFetchResult<DeptListItem>;
  66 +
  67 +export type MenuListGetResultModel = BasicFetchResult<MenuListItem>;
  68 +
  69 +export type RoleListGetResultModel = BasicFetchResult<RoleListItem>;
src/api/demo/system.ts
1 import { 1 import {
2 AccountParams, 2 AccountParams,
3 DeptListItem, 3 DeptListItem,
  4 + MenuParams,
  5 + RoleParams,
  6 + MenuListGetResultModel,
4 DeptListGetResultModel, 7 DeptListGetResultModel,
5 AccountListGetResultModel, 8 AccountListGetResultModel,
  9 + RoleListGetResultModel,
6 } from './model/systemModel'; 10 } from './model/systemModel';
7 import { defHttp } from '/@/utils/http/axios'; 11 import { defHttp } from '/@/utils/http/axios';
8 12
9 enum Api { 13 enum Api {
10 - // The address does not exist  
11 AccountList = '/system/getAccountList', 14 AccountList = '/system/getAccountList',
12 DeptList = '/system/getDeptList', 15 DeptList = '/system/getDeptList',
  16 + MenuList = '/system/getMenuList',
  17 + RoleList = '/system/getRoleList',
13 } 18 }
14 19
15 export const getAccountList = (params: AccountParams) => 20 export const getAccountList = (params: AccountParams) =>
@@ -17,3 +22,9 @@ export const getAccountList = (params: AccountParams) =&gt; @@ -17,3 +22,9 @@ export const getAccountList = (params: AccountParams) =&gt;
17 22
18 export const getDeptList = (params?: DeptListItem) => 23 export const getDeptList = (params?: DeptListItem) =>
19 defHttp.get<DeptListGetResultModel>({ url: Api.DeptList, params }); 24 defHttp.get<DeptListGetResultModel>({ url: Api.DeptList, params });
  25 +
  26 +export const getMenuList = (params?: MenuParams) =>
  27 + defHttp.get<MenuListGetResultModel>({ url: Api.MenuList, params });
  28 +
  29 +export const getRoleList = (params?: RoleParams) =>
  30 + defHttp.get<RoleListGetResultModel>({ url: Api.RoleList, params });
src/components/Form/src/componentMap.ts
@@ -22,6 +22,7 @@ import RadioButtonGroup from &#39;./components/RadioButtonGroup.vue&#39;; @@ -22,6 +22,7 @@ import RadioButtonGroup from &#39;./components/RadioButtonGroup.vue&#39;;
22 import ApiSelect from './components/ApiSelect.vue'; 22 import ApiSelect from './components/ApiSelect.vue';
23 import { BasicUpload } from '/@/components/Upload'; 23 import { BasicUpload } from '/@/components/Upload';
24 import { StrengthMeter } from '/@/components/StrengthMeter'; 24 import { StrengthMeter } from '/@/components/StrengthMeter';
  25 +import { IconPicker } from '/@/components/Icon';
25 26
26 const componentMap = new Map<ComponentType, Component>(); 27 const componentMap = new Map<ComponentType, Component>();
27 28
@@ -53,6 +54,7 @@ componentMap.set(&#39;RangePicker&#39;, DatePicker.RangePicker); @@ -53,6 +54,7 @@ componentMap.set(&#39;RangePicker&#39;, DatePicker.RangePicker);
53 componentMap.set('WeekPicker', DatePicker.WeekPicker); 54 componentMap.set('WeekPicker', DatePicker.WeekPicker);
54 componentMap.set('TimePicker', TimePicker); 55 componentMap.set('TimePicker', TimePicker);
55 componentMap.set('StrengthMeter', StrengthMeter); 56 componentMap.set('StrengthMeter', StrengthMeter);
  57 +componentMap.set('IconPicker', IconPicker);
56 58
57 componentMap.set('Upload', BasicUpload); 59 componentMap.set('Upload', BasicUpload);
58 60
src/components/Form/src/types/index.ts
@@ -107,4 +107,5 @@ export type ComponentType = @@ -107,4 +107,5 @@ export type ComponentType =
107 | 'Switch' 107 | 'Switch'
108 | 'StrengthMeter' 108 | 'StrengthMeter'
109 | 'Upload' 109 | 'Upload'
  110 + | 'IconPicker'
110 | 'Render'; 111 | 'Render';
src/components/Icon/src/IconPicker.vue
@@ -3,8 +3,8 @@ @@ -3,8 +3,8 @@
3 disabled 3 disabled
4 :style="{ width }" 4 :style="{ width }"
5 :placeholder="t('component.icon.placeholder')" 5 :placeholder="t('component.icon.placeholder')"
6 - v-model:value="currentSelect"  
7 :class="prefixCls" 6 :class="prefixCls"
  7 + v-model:value="currentSelect"
8 > 8 >
9 <template #addonAfter> 9 <template #addonAfter>
10 <Popover 10 <Popover
@@ -91,6 +91,7 @@ @@ -91,6 +91,7 @@
91 const icons = getIcons(); 91 const icons = getIcons();
92 export default defineComponent({ 92 export default defineComponent({
93 name: 'IconPicker', 93 name: 'IconPicker',
  94 + inheritAttrs: false,
94 components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty }, 95 components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty },
95 props: { 96 props: {
96 value: propTypes.string, 97 value: propTypes.string,
src/components/Page/index.ts
1 -import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';  
2 -export const PageFooter = createAsyncComponent(() => import('./src/PageFooter.vue'));  
3 - 1 +export { default as PageFooter } from './src/PageFooter.vue';
4 export { default as PageWrapper } from './src/PageWrapper.vue'; 2 export { default as PageWrapper } from './src/PageWrapper.vue';
src/components/Qrcode/index.ts
1 -import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';  
2 -export const QrCode = createAsyncComponent(() => import('./src/index.vue')); 1 +export { default as QrCode } from './src/index.vue';
3 2
4 export * from './src/types'; 3 export * from './src/types';
src/components/StrengthMeter/index.ts
1 -import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';  
2 -  
3 -export const StrengthMeter = createAsyncComponent(() => import('./src/index.vue')); 1 +export { default as StrengthMeter } from './src/index.vue';
src/components/Table/src/components/ExpandIcon.tsx
@@ -3,7 +3,7 @@ import { BasicArrow } from &#39;/@/components/Basic&#39;; @@ -3,7 +3,7 @@ import { BasicArrow } from &#39;/@/components/Basic&#39;;
3 export default () => { 3 export default () => {
4 return (props: Recordable) => { 4 return (props: Recordable) => {
5 if (!props.expandable) { 5 if (!props.expandable) {
6 - return null; 6 + return <span />;
7 } 7 }
8 return ( 8 return (
9 <BasicArrow 9 <BasicArrow
src/components/Table/src/components/settings/ColumnSetting.vue
@@ -3,8 +3,8 @@ @@ -3,8 +3,8 @@
3 <template #title> 3 <template #title>
4 <span>{{ t('component.table.settingColumn') }}</span> 4 <span>{{ t('component.table.settingColumn') }}</span>
5 </template> 5 </template>
  6 + <!-- :getPopupContainer="getPopupContainer" -->
6 <Popover 7 <Popover
7 - :getPopupContainer="getPopupContainer"  
8 placement="bottomLeft" 8 placement="bottomLeft"
9 trigger="click" 9 trigger="click"
10 @visibleChange="handleVisibleChange" 10 @visibleChange="handleVisibleChange"
src/components/Table/src/props.ts
@@ -49,6 +49,8 @@ export const basicProps = { @@ -49,6 +49,8 @@ export const basicProps = {
49 default: null, 49 default: null,
50 }, 50 },
51 51
  52 + indentSize: propTypes.number.def(24),
  53 +
52 canColDrag: propTypes.bool.def(true), 54 canColDrag: propTypes.bool.def(true),
53 api: { 55 api: {
54 type: Function as PropType<(...arg: any[]) => Promise<any>>, 56 type: Function as PropType<(...arg: any[]) => Promise<any>>,
src/design/ant/input.less
@@ -14,3 +14,11 @@ @@ -14,3 +14,11 @@
14 .ant-input-clear-icon { 14 .ant-input-clear-icon {
15 margin-right: 5px; 15 margin-right: 5px;
16 } 16 }
  17 +
  18 +.ant-input-affix-wrapper-textarea-with-clear-btn {
  19 + padding: 0 !important;
  20 +
  21 + textarea.ant-input {
  22 + padding: 4px;
  23 + }
  24 +}
src/locales/lang/en/routes/demo/system.ts
@@ -6,4 +6,7 @@ export default { @@ -6,4 +6,7 @@ export default {
6 password: 'Change password', 6 password: 'Change password',
7 7
8 dept: 'Department management', 8 dept: 'Department management',
  9 +
  10 + menu: 'Menu management',
  11 + role: 'Role management',
9 }; 12 };
src/locales/lang/zh_CN/routes/demo/system.ts
@@ -6,4 +6,7 @@ export default { @@ -6,4 +6,7 @@ export default {
6 password: '修改密码', 6 password: '修改密码',
7 7
8 dept: '部门管理', 8 dept: '部门管理',
  9 +
  10 + menu: '菜单管理',
  11 + role: '角色管理',
9 }; 12 };
src/locales/useLocale.ts
@@ -3,13 +3,11 @@ @@ -3,13 +3,11 @@
3 */ 3 */
4 import type { LocaleType } from '/#/config'; 4 import type { LocaleType } from '/#/config';
5 5
6 -import { ref } from 'vue';  
7 import moment from 'moment'; 6 import moment from 'moment';
8 -import { computed } from 'vue';  
9 7
10 import { i18n } from './setupI18n'; 8 import { i18n } from './setupI18n';
11 import { localeStore } from '/@/store/modules/locale'; 9 import { localeStore } from '/@/store/modules/locale';
12 -import { unref } from 'vue'; 10 +import { unref, computed } from 'vue';
13 11
14 interface LangModule { 12 interface LangModule {
15 message: Recordable; 13 message: Recordable;
@@ -17,8 +15,6 @@ interface LangModule { @@ -17,8 +15,6 @@ interface LangModule {
17 momentLocaleName: string; 15 momentLocaleName: string;
18 } 16 }
19 17
20 -const antConfigLocale = ref<Nullable<Recordable>>(null);  
21 -  
22 const loadLocalePool: LocaleType[] = []; 18 const loadLocalePool: LocaleType[] = [];
23 19
24 function setI18nLanguage(locale: LocaleType) { 20 function setI18nLanguage(locale: LocaleType) {
@@ -67,7 +63,6 @@ export function useLocale() { @@ -67,7 +63,6 @@ export function useLocale() {
67 getLocale, 63 getLocale,
68 getShowLocalePicker, 64 getShowLocalePicker,
69 changeLocale, 65 changeLocale,
70 - antConfigLocale,  
71 getAntdLocale, 66 getAntdLocale,
72 }; 67 };
73 } 68 }
src/router/menus/modules/demo/system.ts
@@ -18,7 +18,20 @@ const menu: MenuModule = { @@ -18,7 +18,20 @@ const menu: MenuModule = {
18 type: 'warn', 18 type: 'warn',
19 }, 19 },
20 }, 20 },
21 - 21 + {
  22 + path: 'role',
  23 + name: t('routes.demo.system.role'),
  24 + tag: {
  25 + content: 'new',
  26 + },
  27 + },
  28 + {
  29 + path: 'menu',
  30 + name: t('routes.demo.system.menu'),
  31 + tag: {
  32 + content: 'new',
  33 + },
  34 + },
22 { 35 {
23 path: 'dept', 36 path: 'dept',
24 name: t('routes.demo.system.dept'), 37 name: t('routes.demo.system.dept'),
src/router/routes/modules/demo/system.ts
@@ -23,6 +23,25 @@ const system: AppRouteModule = { @@ -23,6 +23,25 @@ const system: AppRouteModule = {
23 component: () => import('/@/views/demo/system/account/index.vue'), 23 component: () => import('/@/views/demo/system/account/index.vue'),
24 }, 24 },
25 { 25 {
  26 + path: 'role',
  27 + name: 'RoleManagement',
  28 + meta: {
  29 + title: t('routes.demo.system.role'),
  30 + ignoreKeepAlive: true,
  31 + },
  32 + component: () => import('/@/views/demo/system/role/index.vue'),
  33 + },
  34 +
  35 + {
  36 + path: 'menu',
  37 + name: 'MenuManagement',
  38 + meta: {
  39 + title: t('routes.demo.system.menu'),
  40 + ignoreKeepAlive: true,
  41 + },
  42 + component: () => import('/@/views/demo/system/menu/index.vue'),
  43 + },
  44 + {
26 path: 'dept', 45 path: 'dept',
27 name: 'DeptManagement', 46 name: 'DeptManagement',
28 meta: { 47 meta: {
src/views/demo/system/dept/DeptModal.vue
@@ -21,9 +21,6 @@ @@ -21,9 +21,6 @@
21 labelWidth: 100, 21 labelWidth: 100,
22 schemas: formSchema, 22 schemas: formSchema,
23 showActionButtonGroup: false, 23 showActionButtonGroup: false,
24 - actionColOptions: {  
25 - span: 23,  
26 - },  
27 }); 24 });
28 25
29 const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { 26 const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
src/views/demo/system/dept/dept.data.ts
@@ -7,22 +7,23 @@ export const columns: BasicColumn[] = [ @@ -7,22 +7,23 @@ export const columns: BasicColumn[] = [
7 { 7 {
8 title: '部门名称', 8 title: '部门名称',
9 dataIndex: 'deptName', 9 dataIndex: 'deptName',
10 - width: 300, 10 + width: 160,
  11 + align: 'left',
11 }, 12 },
12 { 13 {
13 title: '排序', 14 title: '排序',
14 dataIndex: 'orderNo', 15 dataIndex: 'orderNo',
15 - width: 80, 16 + width: 50,
16 }, 17 },
17 { 18 {
18 title: '状态', 19 title: '状态',
19 dataIndex: 'status', 20 dataIndex: 'status',
20 - width: 120, 21 + width: 80,
21 customRender: ({ record }) => { 22 customRender: ({ record }) => {
22 const status = record.status; 23 const status = record.status;
23 const enable = ~~status === 0; 24 const enable = ~~status === 0;
24 const color = enable ? 'green' : 'red'; 25 const color = enable ? 'green' : 'red';
25 - const text = enable ? '正常' : '停用'; 26 + const text = enable ? '启用' : '停用';
26 return h(Tag, { color: color }, () => text); 27 return h(Tag, { color: color }, () => text);
27 }, 28 },
28 }, 29 },
@@ -69,6 +70,7 @@ export const formSchema: FormSchema[] = [ @@ -69,6 +70,7 @@ export const formSchema: FormSchema[] = [
69 field: 'parentDept', 70 field: 'parentDept',
70 label: '上级部门', 71 label: '上级部门',
71 component: 'TreeSelect', 72 component: 'TreeSelect',
  73 +
72 componentProps: { 74 componentProps: {
73 replaceFields: { 75 replaceFields: {
74 title: 'deptName', 76 title: 'deptName',
@@ -89,10 +91,11 @@ export const formSchema: FormSchema[] = [ @@ -89,10 +91,11 @@ export const formSchema: FormSchema[] = [
89 field: 'status', 91 field: 'status',
90 label: '状态', 92 label: '状态',
91 component: 'RadioButtonGroup', 93 component: 'RadioButtonGroup',
  94 + defaultValue: '0',
92 componentProps: { 95 componentProps: {
93 options: [ 96 options: [
94 - { label: '正常', value: '0' },  
95 - { label: '禁用', value: '1' }, 97 + { label: '启用', value: '0' },
  98 + { label: '停用', value: '1' },
96 ], 99 ],
97 }, 100 },
98 required: true, 101 required: true,
src/views/demo/system/dept/index.vue
@@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
56 showTableSetting: true, 56 showTableSetting: true,
57 bordered: true, 57 bordered: true,
58 showIndexColumn: false, 58 showIndexColumn: false,
59 - indentSize: 20, 59 + canResize: false,
60 actionColumn: { 60 actionColumn: {
61 width: 80, 61 width: 80,
62 title: '操作', 62 title: '操作',
src/views/demo/system/menu/MenuDrawer.vue 0 → 100644
  1 +<template>
  2 + <BasicDrawer
  3 + v-bind="$attrs"
  4 + @register="registerDrawer"
  5 + showFooter
  6 + :title="getTitle"
  7 + width="50%"
  8 + @ok="handleSubmit"
  9 + >
  10 + <BasicForm @register="registerForm" />
  11 + </BasicDrawer>
  12 +</template>
  13 +<script lang="ts">
  14 + import { defineComponent, ref, computed, unref } from 'vue';
  15 + import { BasicForm, useForm } from '/@/components/Form/index';
  16 + import { formSchema } from './menu.data';
  17 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  18 +
  19 + import { getMenuList } from '/@/api/demo/system';
  20 +
  21 + export default defineComponent({
  22 + name: 'MenuDrawer',
  23 + components: { BasicDrawer, BasicForm },
  24 + emits: ['success', 'register'],
  25 + setup(_, { emit }) {
  26 + const isUpdate = ref(true);
  27 +
  28 + const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
  29 + labelWidth: 100,
  30 + schemas: formSchema,
  31 + showActionButtonGroup: false,
  32 + baseColProps: { lg: 12, md: 24 },
  33 + });
  34 +
  35 + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
  36 + resetFields();
  37 + setDrawerProps({ confirmLoading: false });
  38 + isUpdate.value = !!data?.isUpdate;
  39 +
  40 + if (unref(isUpdate)) {
  41 + setFieldsValue({
  42 + ...data.record,
  43 + });
  44 + }
  45 + const treeData = await getMenuList();
  46 + updateSchema({
  47 + field: 'parentMenu',
  48 + componentProps: { treeData },
  49 + });
  50 + });
  51 +
  52 + const getTitle = computed(() => (!unref(isUpdate) ? '新增菜单' : '编辑菜单'));
  53 +
  54 + async function handleSubmit() {
  55 + try {
  56 + const values = await validate();
  57 + setDrawerProps({ confirmLoading: true });
  58 + // TODO custom api
  59 + console.log(values);
  60 + closeDrawer();
  61 + emit('success');
  62 + } finally {
  63 + setDrawerProps({ confirmLoading: false });
  64 + }
  65 + }
  66 +
  67 + return { registerDrawer, registerForm, getTitle, handleSubmit };
  68 + },
  69 + });
  70 +</script>
src/views/demo/system/menu/index.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <BasicTable @register="registerTable">
  4 + <template #toolbar>
  5 + <a-button type="primary" @click="handleCreate"> 新增菜单 </a-button>
  6 + </template>
  7 + <template #action="{ record }">
  8 + <TableAction
  9 + :actions="[
  10 + {
  11 + icon: 'clarity:note-edit-line',
  12 + onClick: handleEdit.bind(null, record),
  13 + },
  14 + {
  15 + icon: 'ant-design:delete-outlined',
  16 + color: 'error',
  17 + popConfirm: {
  18 + title: '是否确认删除',
  19 + confirm: handleDelete.bind(null, record),
  20 + },
  21 + },
  22 + ]"
  23 + />
  24 + </template>
  25 + </BasicTable>
  26 + <MenuDrawer @register="registerDrawer" @success="handleSuccess" />
  27 + </div>
  28 +</template>
  29 +<script lang="ts">
  30 + import { defineComponent } from 'vue';
  31 +
  32 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  33 + import { getMenuList } from '/@/api/demo/system';
  34 +
  35 + import { useDrawer } from '/@/components/Drawer';
  36 + import MenuDrawer from './MenuDrawer.vue';
  37 +
  38 + import { columns, searchFormSchema } from './menu.data';
  39 +
  40 + export default defineComponent({
  41 + name: 'MenuManagement',
  42 + components: { BasicTable, MenuDrawer, TableAction },
  43 + setup() {
  44 + const [registerDrawer, { openDrawer }] = useDrawer();
  45 + const [registerTable, { reload }] = useTable({
  46 + title: '菜单列表',
  47 + api: getMenuList,
  48 + columns,
  49 + formConfig: {
  50 + labelWidth: 120,
  51 + schemas: searchFormSchema,
  52 + },
  53 + pagination: false,
  54 + striped: false,
  55 + useSearchForm: true,
  56 + showTableSetting: true,
  57 + bordered: true,
  58 + showIndexColumn: false,
  59 + canResize: false,
  60 + actionColumn: {
  61 + width: 80,
  62 + title: '操作',
  63 + dataIndex: 'action',
  64 + slots: { customRender: 'action' },
  65 + fixed: undefined,
  66 + },
  67 + });
  68 +
  69 + function handleCreate() {
  70 + openDrawer(true, {
  71 + isUpdate: false,
  72 + });
  73 + }
  74 +
  75 + function handleEdit(record: Recordable) {
  76 + openDrawer(true, {
  77 + record,
  78 + isUpdate: true,
  79 + });
  80 + }
  81 +
  82 + function handleDelete(record: Recordable) {
  83 + console.log(record);
  84 + }
  85 +
  86 + function handleSuccess() {
  87 + reload();
  88 + }
  89 +
  90 + return {
  91 + registerTable,
  92 + registerDrawer,
  93 + handleCreate,
  94 + handleEdit,
  95 + handleDelete,
  96 + handleSuccess,
  97 + };
  98 + },
  99 + });
  100 +</script>
src/views/demo/system/menu/menu.data.ts 0 → 100644
  1 +import { BasicColumn } from '/@/components/Table';
  2 +import { FormSchema } from '/@/components/Table';
  3 +import { h } from 'vue';
  4 +import { Tag } from 'ant-design-vue';
  5 +import { Icon } from '/@/components/Icon';
  6 +
  7 +export const columns: BasicColumn[] = [
  8 + {
  9 + title: '菜单名称',
  10 + dataIndex: 'menuName',
  11 + width: 200,
  12 + align: 'left',
  13 + },
  14 + {
  15 + title: '图标',
  16 + dataIndex: 'icon',
  17 + width: 50,
  18 + customRender: ({ record }) => {
  19 + return h(Icon, { icon: record.icon });
  20 + },
  21 + },
  22 + {
  23 + title: '权限标识',
  24 + dataIndex: 'permission',
  25 + width: 180,
  26 + },
  27 + {
  28 + title: '组件',
  29 + dataIndex: 'component',
  30 + },
  31 + {
  32 + title: '排序',
  33 + dataIndex: 'orderNo',
  34 + width: 50,
  35 + },
  36 + {
  37 + title: '状态',
  38 + dataIndex: 'status',
  39 + width: 80,
  40 + customRender: ({ record }) => {
  41 + const status = record.status;
  42 + const enable = ~~status === 0;
  43 + const color = enable ? 'green' : 'red';
  44 + const text = enable ? '启用' : '停用';
  45 + return h(Tag, { color: color }, () => text);
  46 + },
  47 + },
  48 + {
  49 + title: '创建时间',
  50 + dataIndex: 'createTime',
  51 + width: 180,
  52 + },
  53 +];
  54 +
  55 +const isDir = (type: string) => type === '0';
  56 +const isMenu = (type: string) => type === '1';
  57 +const isButton = (type: string) => type === '2';
  58 +
  59 +export const searchFormSchema: FormSchema[] = [
  60 + {
  61 + field: 'menuName',
  62 + label: '菜单名称',
  63 + component: 'Input',
  64 + colProps: { span: 8 },
  65 + },
  66 + {
  67 + field: 'status',
  68 + label: '状态',
  69 + component: 'Select',
  70 + componentProps: {
  71 + options: [
  72 + { label: '启用', value: '0' },
  73 + { label: '停用', value: '1' },
  74 + ],
  75 + },
  76 + colProps: { span: 8 },
  77 + },
  78 +];
  79 +
  80 +export const formSchema: FormSchema[] = [
  81 + {
  82 + field: 'type',
  83 + label: '菜单类型',
  84 + component: 'RadioButtonGroup',
  85 + defaultValue: '0',
  86 + componentProps: {
  87 + options: [
  88 + { label: '目录', value: '0' },
  89 + { label: '菜单', value: '1' },
  90 + { label: '按钮', value: '2' },
  91 + ],
  92 + },
  93 + colProps: { lg: 24, md: 24 },
  94 + },
  95 + {
  96 + field: 'menuName',
  97 + label: '菜单名称',
  98 + component: 'Input',
  99 + required: true,
  100 + },
  101 +
  102 + {
  103 + field: 'parentMenu',
  104 + label: '上级菜单',
  105 + component: 'TreeSelect',
  106 + componentProps: {
  107 + replaceFields: {
  108 + title: 'menuName',
  109 + key: 'id',
  110 + value: 'id',
  111 + },
  112 + getPopupContainer: () => document.body,
  113 + },
  114 + },
  115 +
  116 + {
  117 + field: 'orderNo',
  118 + label: '排序',
  119 + component: 'InputNumber',
  120 + required: true,
  121 + },
  122 + {
  123 + field: 'icon',
  124 + label: '图标',
  125 + component: 'IconPicker',
  126 + required: true,
  127 + show: ({ values }) => !isButton(values.type),
  128 + },
  129 +
  130 + {
  131 + field: 'routePath',
  132 + label: '路由地址',
  133 + component: 'Input',
  134 + required: true,
  135 + show: ({ values }) => !isButton(values.type),
  136 + },
  137 + {
  138 + field: 'component',
  139 + label: '组件路径',
  140 + component: 'Input',
  141 + show: ({ values }) => isMenu(values.type),
  142 + },
  143 + {
  144 + field: 'permission',
  145 + label: '权限标识',
  146 + component: 'Input',
  147 + show: ({ values }) => !isDir(values.type),
  148 + },
  149 + {
  150 + field: 'status',
  151 + label: '状态',
  152 + component: 'RadioButtonGroup',
  153 + defaultValue: '0',
  154 + componentProps: {
  155 + options: [
  156 + { label: '启用', value: '0' },
  157 + { label: '禁用', value: '1' },
  158 + ],
  159 + },
  160 + },
  161 + {
  162 + field: 'isExt',
  163 + label: '是否外链',
  164 + component: 'RadioButtonGroup',
  165 + defaultValue: '0',
  166 + componentProps: {
  167 + options: [
  168 + { label: '否', value: '0' },
  169 + { label: '是', value: '1' },
  170 + ],
  171 + },
  172 + show: ({ values }) => !isButton(values.type),
  173 + },
  174 +
  175 + {
  176 + field: 'keepalive',
  177 + label: '是否缓存',
  178 + component: 'RadioButtonGroup',
  179 + defaultValue: '0',
  180 + componentProps: {
  181 + options: [
  182 + { label: '否', value: '0' },
  183 + { label: '是', value: '1' },
  184 + ],
  185 + },
  186 + show: ({ values }) => isMenu(values.type),
  187 + },
  188 +
  189 + {
  190 + field: 'show',
  191 + label: '是否显示',
  192 + component: 'RadioButtonGroup',
  193 + defaultValue: '0',
  194 + componentProps: {
  195 + options: [
  196 + { label: '是', value: '0' },
  197 + { label: '否', value: '1' },
  198 + ],
  199 + },
  200 + show: ({ values }) => !isButton(values.type),
  201 + },
  202 +];
src/views/demo/system/role/RoleDrawer.vue 0 → 100644
  1 +<template>
  2 + <BasicDrawer
  3 + v-bind="$attrs"
  4 + @register="registerDrawer"
  5 + showFooter
  6 + :title="getTitle"
  7 + width="500px"
  8 + @ok="handleSubmit"
  9 + >
  10 + <BasicForm @register="registerForm" />
  11 + </BasicDrawer>
  12 +</template>
  13 +<script lang="ts">
  14 + import { defineComponent, ref, computed, unref } from 'vue';
  15 + import { BasicForm, useForm } from '/@/components/Form/index';
  16 + import { formSchema } from './role.data';
  17 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  18 +
  19 + import { getMenuList } from '/@/api/demo/system';
  20 +
  21 + export default defineComponent({
  22 + name: 'RoleDrawer',
  23 + components: { BasicDrawer, BasicForm },
  24 + emits: ['success', 'register'],
  25 + setup(_, { emit }) {
  26 + const isUpdate = ref(true);
  27 +
  28 + const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
  29 + labelWidth: 90,
  30 + schemas: formSchema,
  31 + showActionButtonGroup: false,
  32 + });
  33 +
  34 + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
  35 + resetFields();
  36 + setDrawerProps({ confirmLoading: false });
  37 + isUpdate.value = !!data?.isUpdate;
  38 +
  39 + if (unref(isUpdate)) {
  40 + setFieldsValue({
  41 + ...data.record,
  42 + });
  43 + }
  44 + const treeData = await getMenuList();
  45 + updateSchema({
  46 + field: 'parentMenu',
  47 + componentProps: { treeData },
  48 + });
  49 + });
  50 +
  51 + const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));
  52 +
  53 + async function handleSubmit() {
  54 + try {
  55 + const values = await validate();
  56 + setDrawerProps({ confirmLoading: true });
  57 + // TODO custom api
  58 + console.log(values);
  59 + closeDrawer();
  60 + emit('success');
  61 + } finally {
  62 + setDrawerProps({ confirmLoading: false });
  63 + }
  64 + }
  65 +
  66 + return { registerDrawer, registerForm, getTitle, handleSubmit };
  67 + },
  68 + });
  69 +</script>
src/views/demo/system/role/index.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <BasicTable @register="registerTable">
  4 + <template #toolbar>
  5 + <a-button type="primary" @click="handleCreate"> 新增角色 </a-button>
  6 + </template>
  7 + <template #action="{ record }">
  8 + <TableAction
  9 + :actions="[
  10 + {
  11 + icon: 'clarity:note-edit-line',
  12 + onClick: handleEdit.bind(null, record),
  13 + },
  14 + {
  15 + icon: 'ant-design:delete-outlined',
  16 + color: 'error',
  17 + popConfirm: {
  18 + title: '是否确认删除',
  19 + confirm: handleDelete.bind(null, record),
  20 + },
  21 + },
  22 + ]"
  23 + />
  24 + </template>
  25 + </BasicTable>
  26 + <RoleDrawer @register="registerDrawer" @success="handleSuccess" />
  27 + </div>
  28 +</template>
  29 +<script lang="ts">
  30 + import { defineComponent } from 'vue';
  31 +
  32 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  33 + import { getRoleList } from '/@/api/demo/system';
  34 +
  35 + import { useDrawer } from '/@/components/Drawer';
  36 + import RoleDrawer from './RoleDrawer.vue';
  37 +
  38 + import { columns, searchFormSchema } from './role.data';
  39 +
  40 + export default defineComponent({
  41 + name: 'RoleManagement',
  42 + components: { BasicTable, RoleDrawer, TableAction },
  43 + setup() {
  44 + const [registerDrawer, { openDrawer }] = useDrawer();
  45 + const [registerTable, { reload }] = useTable({
  46 + title: '角色列表',
  47 + api: getRoleList,
  48 + columns,
  49 + formConfig: {
  50 + labelWidth: 120,
  51 + schemas: searchFormSchema,
  52 + },
  53 + useSearchForm: true,
  54 + showTableSetting: true,
  55 + bordered: true,
  56 + showIndexColumn: false,
  57 + actionColumn: {
  58 + width: 80,
  59 + title: '操作',
  60 + dataIndex: 'action',
  61 + slots: { customRender: 'action' },
  62 + fixed: undefined,
  63 + },
  64 + });
  65 +
  66 + function handleCreate() {
  67 + openDrawer(true, {
  68 + isUpdate: false,
  69 + });
  70 + }
  71 +
  72 + function handleEdit(record: Recordable) {
  73 + openDrawer(true, {
  74 + record,
  75 + isUpdate: true,
  76 + });
  77 + }
  78 +
  79 + function handleDelete(record: Recordable) {
  80 + console.log(record);
  81 + }
  82 +
  83 + function handleSuccess() {
  84 + reload();
  85 + }
  86 +
  87 + return {
  88 + registerTable,
  89 + registerDrawer,
  90 + handleCreate,
  91 + handleEdit,
  92 + handleDelete,
  93 + handleSuccess,
  94 + };
  95 + },
  96 + });
  97 +</script>
src/views/demo/system/role/role.data.ts 0 → 100644
  1 +import { BasicColumn } from '/@/components/Table';
  2 +import { FormSchema } from '/@/components/Table';
  3 +import { h } from 'vue';
  4 +import { Tag } from 'ant-design-vue';
  5 +
  6 +export const columns: BasicColumn[] = [
  7 + {
  8 + title: '角色名称',
  9 + dataIndex: 'roleName',
  10 + width: 200,
  11 + },
  12 + {
  13 + title: '角色值',
  14 + dataIndex: 'roleValue',
  15 + width: 180,
  16 + },
  17 + {
  18 + title: '排序',
  19 + dataIndex: 'orderNo',
  20 + width: 50,
  21 + },
  22 + {
  23 + title: '状态',
  24 + dataIndex: 'status',
  25 + width: 80,
  26 + customRender: ({ record }) => {
  27 + const status = record.status;
  28 + const enable = ~~status === 0;
  29 + const color = enable ? 'green' : 'red';
  30 + const text = enable ? '启用' : '停用';
  31 + return h(Tag, { color: color }, () => text);
  32 + },
  33 + },
  34 + {
  35 + title: '创建时间',
  36 + dataIndex: 'createTime',
  37 + width: 180,
  38 + },
  39 + {
  40 + title: '备注',
  41 + dataIndex: 'remark',
  42 + },
  43 +];
  44 +
  45 +export const searchFormSchema: FormSchema[] = [
  46 + {
  47 + field: 'roleNme',
  48 + label: '角色名称',
  49 + component: 'Input',
  50 + colProps: { span: 8 },
  51 + },
  52 + {
  53 + field: 'status',
  54 + label: '状态',
  55 + component: 'Select',
  56 + componentProps: {
  57 + options: [
  58 + { label: '启用', value: '0' },
  59 + { label: '停用', value: '1' },
  60 + ],
  61 + },
  62 + colProps: { span: 8 },
  63 + },
  64 +];
  65 +
  66 +export const formSchema: FormSchema[] = [
  67 + {
  68 + field: 'roleName',
  69 + label: '角色名称',
  70 + required: true,
  71 + component: 'Input',
  72 + },
  73 + {
  74 + field: 'roleValue',
  75 + label: '角色值',
  76 + required: true,
  77 + component: 'Input',
  78 + },
  79 + {
  80 + field: 'status',
  81 + label: '状态',
  82 + component: 'RadioButtonGroup',
  83 + defaultValue: '0',
  84 + componentProps: {
  85 + options: [
  86 + { label: '启用', value: '0' },
  87 + { label: '停用', value: '1' },
  88 + ],
  89 + },
  90 + },
  91 + {
  92 + label: '备注',
  93 + field: 'remark',
  94 + component: 'InputTextArea',
  95 + },
  96 + {
  97 + label: '菜单分配',
  98 + field: 'menu',
  99 + slot: 'menu',
  100 + component: 'Render',
  101 + },
  102 +];
vite.config.ts
@@ -36,7 +36,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig =&gt; { @@ -36,7 +36,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig =&gt; {
36 replacement: pathResolve('src') + '/', 36 replacement: pathResolve('src') + '/',
37 }, 37 },
38 { 38 {
39 - // /@/xxxx => src/xxx 39 + // /#/xxxx => types/xxx
40 find: /^\/#\//, 40 find: /^\/#\//,
41 replacement: pathResolve('types') + '/', 41 replacement: pathResolve('types') + '/',
42 }, 42 },
@@ -52,6 +52,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig =&gt; { @@ -52,6 +52,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig =&gt; {
52 }, 52 },
53 53
54 build: { 54 build: {
  55 + cssCodeSplit: false,
55 // minify: 'esbuild', 56 // minify: 'esbuild',
56 outDir: OUTPUT_DIR, 57 outDir: OUTPUT_DIR,
57 polyfillDynamicImport: VITE_LEGACY, 58 polyfillDynamicImport: VITE_LEGACY,
yarn.lock
@@ -1117,10 +1117,10 @@ @@ -1117,10 +1117,10 @@
1117 dependencies: 1117 dependencies:
1118 cross-fetch "^3.0.6" 1118 cross-fetch "^3.0.6"
1119 1119
1120 -"@iconify/json@^1.1.310":  
1121 - version "1.1.310"  
1122 - resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.310.tgz#4180cfdafbf4e218b8f78abae3434089bcb6ccf6"  
1123 - integrity sha512-gLCuqulJPC2ly3upqPILOA1nV2fYfb99Dx64hLvneUb0r22opL+TfMfl352AjSZTFMGKV6ve8pNSAOS5gvY3vg== 1120 +"@iconify/json@^1.1.311":
  1121 + version "1.1.311"
  1122 + resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.311.tgz#cafa09c427fdacce8198e787f87c194eaa7e3e38"
  1123 + integrity sha512-ghm5JynA3aft0goTlEt6w2aYZCTaOO4IE59Cf99ip81NDs0qw4OJ/JSoR09jIrcVDSVZJdp3jf0Tni1iRV1j+w==
1124 1124
1125 "@intlify/core-base@9.0.0": 1125 "@intlify/core-base@9.0.0":
1126 version "9.0.0" 1126 version "9.0.0"
@@ -1780,16 +1780,16 @@ @@ -1780,16 +1780,16 @@
1780 dependencies: 1780 dependencies:
1781 vue-demi latest 1781 vue-demi latest
1782 1782
1783 -"@windicss/plugin-utils@0.6.2":  
1784 - version "0.6.2"  
1785 - resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.6.2.tgz#8fc76d9f2a1e3de123ffd54fdd9d1583801bb087"  
1786 - integrity sha512-qR2h/vDn3LZtL0cC3id9nxPwhYqCtkcwASs63sHTUOzLhxz+zkG4xR+odndbR6PTjrlTgBC7n5hLjpq0lxRksg== 1783 +"@windicss/plugin-utils@0.6.4":
  1784 + version "0.6.4"
  1785 + resolved "https://registry.npmjs.org/@windicss/plugin-utils/-/plugin-utils-0.6.4.tgz#854f411b156fea61b2e6724799e91f0f9407a637"
  1786 + integrity sha512-5RZQ71snmoKmZEXHyCByOohUM/SsWIX856+geMwOfbMOGL0guv/1TVg2PalFrZh3k/HfqQnO2ft5YSWKtrW32A==
1787 dependencies: 1787 dependencies:
1788 - esbuild "^0.8.52" 1788 + esbuild "^0.8.54"
1789 esbuild-register "^2.0.0" 1789 esbuild-register "^2.0.0"
1790 fast-glob "^3.2.5" 1790 fast-glob "^3.2.5"
1791 micromatch "^4.0.2" 1791 micromatch "^4.0.2"
1792 - windicss "^2.2.0" 1792 + windicss "^2.2.3"
1793 1793
1794 "@zxcvbn-ts/core@^0.2.0": 1794 "@zxcvbn-ts/core@^0.2.0":
1795 version "0.2.0" 1795 version "0.2.0"
@@ -8957,13 +8957,13 @@ vite-plugin-theme@^0.4.8: @@ -8957,13 +8957,13 @@ vite-plugin-theme@^0.4.8:
8957 es-module-lexer "^0.3.26" 8957 es-module-lexer "^0.3.26"
8958 tinycolor2 "^1.4.2" 8958 tinycolor2 "^1.4.2"
8959 8959
8960 -vite-plugin-windicss@0.6.2:  
8961 - version "0.6.2"  
8962 - resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.6.2.tgz#2b406c65768ce7df22451dc7b47c0026abd4bb24"  
8963 - integrity sha512-V4WnjkxvriJSVQjswY+SrDKogOLNq1eG6dQw1wWcJRV+0QUz9pAGrMolSwed4d4MwSSbJrCA7If8xa+EFLUigw== 8960 +vite-plugin-windicss@0.6.4:
  8961 + version "0.6.4"
  8962 + resolved "https://registry.npmjs.org/vite-plugin-windicss/-/vite-plugin-windicss-0.6.4.tgz#2d2bc7831dddff129d597959efaff616c6408a01"
  8963 + integrity sha512-4BuUglBXeNIrIDfSKyg7rvqKEmxvyja2aKJxgHdOCICV8jIz2MvrZaRS9a74gUihz+OohBYqLnkOlfD+sCIQBg==
8964 dependencies: 8964 dependencies:
8965 - "@windicss/plugin-utils" "0.6.2"  
8966 - windicss "^2.2.0" 8965 + "@windicss/plugin-utils" "0.6.4"
  8966 + windicss "^2.2.3"
8967 8967
8968 vite@^2.0.5: 8968 vite@^2.0.5:
8969 version "2.0.5" 8969 version "2.0.5"
@@ -9090,10 +9090,10 @@ which@^2.0.1: @@ -9090,10 +9090,10 @@ which@^2.0.1:
9090 dependencies: 9090 dependencies:
9091 isexe "^2.0.0" 9091 isexe "^2.0.0"
9092 9092
9093 -windicss@^2.2.0:  
9094 - version "2.2.0"  
9095 - resolved "https://registry.npmjs.org/windicss/-/windicss-2.2.0.tgz#42fe83b9bff6d4fc9caf85272fb6c6ddb990fbc1"  
9096 - integrity sha512-UuPhwe/NMgGOmUMnaTR+64eMeoiRCYb/zKJfo4pm9XUb4BRFlaFMm1x0KF1RF8EtK/8jKvDlXMc/J6UPBj8/OA== 9093 +windicss@^2.2.3:
  9094 + version "2.2.3"
  9095 + resolved "https://registry.npmjs.org/windicss/-/windicss-2.2.3.tgz#5d25cab4b397d64f74660cac9b947b29cda240e9"
  9096 + integrity sha512-rDaHpCgF3nq6tt21KC3691vhNZcbDHo0DJN+fgY5OmNCqd8muvZ9N4Zp9eqjWaJetg+ulz++MBM/pG9D70sj2w==
9097 9097
9098 wmf@~1.0.1: 9098 wmf@~1.0.1:
9099 version "1.0.2" 9099 version "1.0.2"