diff --git a/.eslintignore b/.eslintignore
index b1ee5549..8e5f2798 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,4 +1,5 @@
template
src/components/meKeepAlive
dist
-vite.config.ts.*
\ No newline at end of file
+vite.config.ts.*
+src/components/meVxeTable/vxe-table-plugin-element
\ No newline at end of file
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index b7259e5e..3c213c6f 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -46,16 +46,15 @@ module.exports = {
'vue/no-parsing-error': 'off',
'vue/require-default-prop': 'off',
'vue/no-v-html': 'off',
- 'no-unused-vars': [
+ '@typescript-eslint/no-non-null-assertion': 'off',
+ '@typescript-eslint/no-explicit-any': 'off',
+ '@typescript-eslint/ban-ts-comment': 'off',
+ '@typescript-eslint/no-unused-vars': [
'error',
// we are only using this rule to check for unused arguments since TS
// catches unused variables but not args.
{ varsIgnorePattern: '.*', args: 'none' },
],
- '@typescript-eslint/no-non-null-assertion': 'off',
- '@typescript-eslint/no-explicit-any': 'off',
- '@typescript-eslint/ban-ts-comment': 'off',
- '@typescript-eslint/no-unused-vars': 'off',
'no-undef': 'off', // ts(2304)
'@typescript-eslint/naming-convention': [
'error',
@@ -65,7 +64,7 @@ module.exports = {
leadingUnderscore: 'allow',
filter: {
// you can expand this regex to add more allowed names
- regex: '^__v_.*$',
+ regex: '^((__v_.*)|[0-9]+)$',
match: false,
},
},
@@ -81,7 +80,7 @@ module.exports = {
leadingUnderscore: 'allow',
filter: {
// you can expand this regex to add more allowed names
- regex: '^__v_.*$',
+ regex: '^((__v_.*)|[0-9]+)$',
match: false,
},
},
diff --git a/.husky/pre-commit b/.husky/pre-commit
index d24fdfc6..7b252062 100644
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -2,3 +2,4 @@
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
+npx vue-tsc --noEmit
diff --git a/README.md b/README.md
index d4182230..87817f93 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,6 @@ Me-admin template是一个免费开源的中后台模板,基于vue3、vite3、 p
- clone 代码
```
git clone https://github.com/meadmin-cn/meadmin-template.git
-
```
- 安装依赖
```
@@ -54,13 +53,43 @@ git clone https://github.com/meadmin-cn/meadmin-template.git
## 贡献代码
-规范文档正在整理中
+- 只允许向main分支贡献代码,template分支由作者自行维护,如果template分支有bug提issus,作者会及时跟进。
+- main分支只允许对不在template分支中的文件(不包括语言包文件)/新文件贡献代码
+- 贡献代码统一在github而非gitee
+### Pull Request:
+1.Fork 代码!
+
+2.创建自己的分支: `git checkout -b feat/xxxx`
+
+3.初始化:(`npm run i`) 或( `npm install` `npx husky install`)
+
+4.eslint检查:`npm run eslint`(husky 会自动运行eslint、prettier、type-check,但是不会自动修复eslint的warn,需要自己运行解决下warn)
+
+5.提交修改: git commit -am 'feat: add xxxxx'
+
+6.推送: `git push origin feat/xxxx`
+
+7.提交`pull request`
+
+## Git 贡献提交规范
+- 需符合 [commitlint](https://commitlint.js.org/#/concepts-commit-conventions)规范,建议安装`vscode`的`Conventional Commits`扩展
+ - `feat` 新功能
+ - `fix` Bug 修复
+ - `chore` 其他
+ - `docs` 文档更改
+ - `style` 样式更改
+ - `refactor` 重构
+ - `perf` 性能改进
+ - `test` 测试添加/更正
+ - `revert` 还原提交
+ - `ignore` 临时暂存可忽略
+ - `ci` CI发版
## 打赏作者
-作者还在为孩子奶粉钱苦苦挣扎,如果能帮到您欢迎打赏。
+作者还在为孩子奶粉钱苦苦挣扎,如果能帮到您欢迎打赏。打赏时请务必备注github name 后续会维护到打赏鸣谢列表
-
+
## License
diff --git a/TEMPLATE-CHANGELOG.md b/TEMPLATE-CHANGELOG.md
index e1f66260..7b381004 100644
--- a/TEMPLATE-CHANGELOG.md
+++ b/TEMPLATE-CHANGELOG.md
@@ -1,5 +1,54 @@
+## [1.0.7](https://github.com/meadmin-cn/meadmin-template/compare/template-1.0.6...template-1.0.7) (2022-09-23)
+
+
+### 新功能[feat]
+
+* 加上请求成功提示 ([683c69a](https://github.com/meadmin-cn/meadmin-template/commit/683c69af8716bfc3cb39212fdbcaaadab2268b40))
+* 加上全局popover-scrollbar-y 类 ([af84a4b](https://github.com/meadmin-cn/meadmin-template/commit/af84a4bc06b06ad09ab20eca6edcbdd227647744))
+* 全局语言包支持引入ts、json格式,支持子孙文件夹引入 ([b92081a](https://github.com/meadmin-cn/meadmin-template/commit/b92081a5c9f7a2b3970fd80fd0c4a8bf9fa9b2d6))
+* 自动生成加载组件类型 ([9d7f3d9](https://github.com/meadmin-cn/meadmin-template/commit/9d7f3d93906f8a63df376e9a97dd9bc30d452f16))
+* page 背景色更改 ([ecaa1d9](https://github.com/meadmin-cn/meadmin-template/commit/ecaa1d95ccef5f7eb7e066ef0c4103ac084511c2))
+
+
+### CI发版[ci]
+
+* 去掉无用eslint规则,加上提交自动vue-tsc ([32f2bfe](https://github.com/meadmin-cn/meadmin-template/commit/32f2bfec1710b97e5365d09ed1ff960e66a073e5))
+
+
+### 文档更改[docs]
+
+* 格式优化 ([e612861](https://github.com/meadmin-cn/meadmin-template/commit/e612861fe93491e637c1c320b39337c029565f02))
+* 加上贡献说明 ([2e8472b](https://github.com/meadmin-cn/meadmin-template/commit/2e8472b05d5f2e1bf108c2ef0dd1a684007b2e08))
+* 说明更改 ([99569c4](https://github.com/meadmin-cn/meadmin-template/commit/99569c4927b65e4f81b2fb8f46b472859fbadc43))
+
+
+### 其他[chore]
+
+* 加上element函数声明 ([a1b08a6](https://github.com/meadmin-cn/meadmin-template/commit/a1b08a6e3bda3da9e732c90ed318bf4e5b7998c7))
+
+
+### 性能改进[perf]
+
+* 加上element动态函数默认缓存 ([34da538](https://github.com/meadmin-cn/meadmin-template/commit/34da538019ddfa77ee65f15caf6af7d647305edc))
+* 强制依赖项扫描src,会导致首次启动变慢,但是不会每次第一次打开新页面都刷新 ([5635d36](https://github.com/meadmin-cn/meadmin-template/commit/5635d36df0c12dcdfa75a9a9130f09c6a697d570))
+
+
+### Bug 修复[fix]
+
+* 修复菜单收起时,感觉卡顿问题 ([81a18a3](https://github.com/meadmin-cn/meadmin-template/commit/81a18a31385dc84250e66dce55bf86b52201b4c8))
+* 修复跟字体不生效bug ([fe8c558](https://github.com/meadmin-cn/meadmin-template/commit/fe8c558f76378d1c9266016989713d34aabfcaf1))
+* 修复两个组件引入通一子组件热更新报错问题 ([add16a9](https://github.com/meadmin-cn/meadmin-template/commit/add16a923c320c8dce0ee82c38ba5ce64c47df1d))
+* a标签默认样式去除修复 ([f758914](https://github.com/meadmin-cn/meadmin-template/commit/f758914f340b0fd43dcbf5172bb21562740d2b58))
+* eslint检查支持数字属性 ([e0e5a4b](https://github.com/meadmin-cn/meadmin-template/commit/e0e5a4bc074759534b96744d06701d769fbec692))
+
+
+### 重构[refactor]
+
+* 移除vite-plugin-mock包改为@meadmin-cn/vite-plugin-mock ([8fd1bf6](https://github.com/meadmin-cn/meadmin-template/commit/8fd1bf65d3c4bd16ebae6311f621a7970ca54700))
+* logo ico添加,登录页背景色设为page color ([f292910](https://github.com/meadmin-cn/meadmin-template/commit/f2929100aaaa2fde01ba9db2a01f3326194f4bff))
+
## [1.0.6](https://github.com/meadmin-cn/meadmin-template/compare/template-1.0.5...template-1.0.6) (2022-09-16)
diff --git a/index.html b/index.html
index 361c8d43..961a82eb 100644
--- a/index.html
+++ b/index.html
@@ -2,7 +2,7 @@
-
+
me-admin
diff --git a/mock/apiDemo/admin.ts b/mock/apiDemo/admin.ts
new file mode 100644
index 00000000..e0dbba0c
--- /dev/null
+++ b/mock/apiDemo/admin.ts
@@ -0,0 +1,312 @@
+import { success, fail } from '../helper';
+
+let id = 10000;
+const group = [
+ {
+ id: 1,
+ name: '超级管理员',
+ status: 1,
+ parentId: 0,
+ rules: [
+ 'example',
+ 'permission',
+ 'componentLang',
+ 'example/request',
+ 'link',
+ 'pagePermission',
+ 'moreMenu',
+ 'moreMenu1',
+ 'moreMenu1-1',
+ 'moreMenu1-1-1',
+ 'moreMenu1-1-lang',
+ 'moreMenu1-2',
+ 'component',
+ 'meNumber',
+ 'editor',
+ 'wangEditor',
+ 'table',
+ 'vxeTable',
+ 'customComponent',
+ 'roleRule',
+ 'roleRuleIndex',
+ 'roleRuleAdd',
+ 'roleRuleEdit',
+ 'roleRuleDel',
+ ],
+ children: [
+ {
+ id: 2,
+ name: '一级管理员1',
+ status: 1,
+ parentId: 1,
+ rules: [
+ 'example',
+ 'permission',
+ 'componentLang',
+ 'example/request',
+ 'link',
+ 'pagePermission',
+ 'moreMenu',
+ 'moreMenu1',
+ 'moreMenu1-1',
+ 'moreMenu1-1-1',
+ 'moreMenu1-1-lang',
+ 'moreMenu1-2',
+ ],
+ children: [
+ {
+ id: 21,
+ name: '二级管理员1-1',
+ parentId: 2,
+ status: 1,
+ rules: ['example', 'permission', 'example/request'],
+ },
+ {
+ id: 22,
+ name: '二级管理员1-2',
+ parentId: 2,
+ status: 1,
+ rules: ['example', 'componentLang'],
+ },
+ {
+ id: 23,
+ name: '二级管理员1-3',
+ parentId: 2,
+ status: 0,
+ rules: [
+ 'example',
+ 'moreMenu',
+ 'moreMenu1',
+ 'moreMenu1-1',
+ 'moreMenu1-1-1',
+ 'moreMenu1-1-lang',
+ 'moreMenu1-2',
+ ],
+ children: [
+ {
+ id: 231,
+ name: '三级管理员1-3-1',
+ parentId: 23,
+ status: 1,
+ rules: ['example', 'moreMenu', 'moreMenu1', 'moreMenu1-1', 'moreMenu1-1-1'],
+ },
+ {
+ id: 232,
+ name: '三级管理员1-3-2',
+ parentId: 23,
+ status: 1,
+ rules: ['example', 'moreMenu', 'moreMenu1', 'moreMenu1-1', 'moreMenu1-1-lang'],
+ },
+ {
+ id: 233,
+ name: '三级管理员1-3-3',
+ parentId: 23,
+ status: 1,
+ rules: ['example', 'moreMenu', 'moreMenu1', 'moreMenu1-2'],
+ },
+ {
+ id: 234,
+ name: '三级管理员1-3-4',
+ parentId: 23,
+ status: 1,
+ rules: ['example', 'moreMenu', 'moreMenu1', 'moreMenu1-1', 'moreMenu1-1-1', 'moreMenu1-1-lang'],
+ children: [
+ {
+ id: 2341,
+ name: '四级管理员1-3-4-1',
+ parentId: 234,
+ status: 1,
+ rules: ['example', 'moreMenu', 'moreMenu1', 'moreMenu1-1', 'moreMenu1-1-1'],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ id: 24,
+ name: '二级管理员1-4',
+ parentId: 2,
+ status: 1,
+ rules: ['example', 'permission', 'componentLang', 'example/request', 'pagePermission'],
+ },
+ {
+ id: 25,
+ name: '二级管理员1-5',
+ parentId: 2,
+ status: 1,
+ rules: ['example', 'permission', 'componentLang', 'example/request', 'link', 'pagePermission'],
+ children: [
+ {
+ id: 251,
+ name: '三级管理员1-5-1',
+ parentId: 25,
+ status: 1,
+ rules: ['example', 'permission', 'componentLang'],
+ },
+ {
+ id: 252,
+ name: '三级管理员1-5-2',
+ parentId: 25,
+ status: 1,
+ rules: ['example', 'link', 'componentLang'],
+ },
+ {
+ id: 253,
+ name: '三级管理员1-5-3',
+ parentId: 25,
+ status: 1,
+ rules: ['example', 'pagePermission'],
+ },
+ ],
+ },
+ {
+ id: 26,
+ name: '二级管理员1-6',
+ parentId: 2,
+ status: 0,
+ rules: ['example', 'permission', 'componentLang', 'example/request'],
+ },
+ {
+ id: 27,
+ name: '二级管理员1-7',
+ parentId: 2,
+ status: 1,
+ rules: ['example', 'example/request'],
+ },
+ ],
+ },
+ {
+ id: 3,
+ parentId: 1,
+ name: '一级管理员2',
+ status: 1,
+ rules: ['component', 'meNumber', 'editor', 'wangEditor', 'table', 'vxeTable'],
+ children: [
+ {
+ id: 31,
+ parentId: 3,
+ name: '二级管理员2-1',
+ status: 1,
+ rules: ['component', 'meNumber'],
+ },
+ {
+ id: 32,
+ parentId: 3,
+ name: '二级管理员2-2',
+ status: 1,
+ rules: ['component', 'table'],
+ },
+ {
+ id: 33,
+ parentId: 3,
+ name: '二级管理员2-3',
+ status: 1,
+ rules: ['component', 'vxeTable'],
+ },
+ {
+ id: 34,
+ parentId: 3,
+ name: '二级管理员2-4',
+ status: 1,
+ rules: ['component', 'editor', 'wangEditor'],
+ },
+ {
+ id: 35,
+ parentId: 3,
+ name: '二级管理员2-5',
+ status: 1,
+ rules: ['component', 'table', 'vxeTable'],
+ },
+ ],
+ },
+ {
+ id: 4,
+ parentId: 1,
+ name: '一级管理员3',
+ status: 1,
+ rules: ['customComponent', 'roleRule', 'roleRuleIndex', 'roleRuleAdd', 'roleRuleEdit', 'roleRuleDel'],
+ },
+ ],
+ },
+];
+function getGroupItem(id: number, groupList?: typeof group) {
+ if (!groupList) {
+ return;
+ }
+ for (const key in groupList) {
+ if (groupList[key].id === id) {
+ return groupList[key];
+ }
+ const item = getGroupItem(id, groupList[key].children as any) as typeof group[number];
+ if (item) {
+ return item;
+ }
+ }
+}
+export default [
+ {
+ url: '/api/admin/group/index',
+ method: 'get',
+ timeout: 500 + Math.floor(Math.random() * 1000),
+ response: () => success(group),
+ },
+ {
+ url: '/api/admin/group/add',
+ method: 'post',
+ timeout: 500 + Math.floor(Math.random() * 1000),
+ response: (req: any) => {
+ const info = req.body;
+ delete info._X_ROW_KEY;
+ info.id = id++;
+ let item = group as any;
+ if (info.parentId) {
+ item = getGroupItem(info.parentId, group);
+ if (!item) {
+ return fail('错误的父级');
+ }
+ if (!item.children) {
+ item.children = [];
+ }
+ item = item.children;
+ }
+ item.push({ ...info });
+ return success('操作成功');
+ },
+ },
+ {
+ url: /\/api\/admin\/group\/[0-9]+/,
+ method: 'post',
+ timeout: 500 + Math.floor(Math.random() * 1000),
+ response: (req: any) => {
+ const info = req.body;
+ delete info._X_ROW_KEY;
+ const item = getGroupItem(+req.url.replace('/api/admin/group/', ''), group);
+ if (!item) {
+ return fail('错误的id');
+ }
+ Object.assign(item, info);
+ return success('操作成功');
+ },
+ },
+ {
+ url: /\/api\/admin\/group\/[0-9]+/,
+ method: 'DELETE',
+ timeout: 500 + Math.floor(Math.random() * 1000),
+ response: (req: any) => {
+ const id = +req.url.replace('/api/admin/group/', '');
+ const item = getGroupItem(id, group);
+ if (!item) {
+ return fail('错误的id');
+ }
+ let parent = group;
+ if (item.parentId) {
+ parent = getGroupItem(item.parentId, group)?.children as any;
+ }
+ parent.splice(
+ parent.findIndex((item) => item.id === id),
+ 1,
+ );
+ return success('操作成功');
+ },
+ },
+];
diff --git a/mock/apiDemo/menu.ts b/mock/apiDemo/menu.ts
new file mode 100644
index 00000000..f94456b5
--- /dev/null
+++ b/mock/apiDemo/menu.ts
@@ -0,0 +1,343 @@
+import { objectEach } from 'xe-utils';
+import { success, fail } from '../helper';
+let id = 100000;
+const menu = [
+ {
+ id: 1,
+ name: '示例',
+ rule: 'example',
+ type: 1,
+ sort: 1,
+ status: 1,
+ parentId: 0,
+ children: [
+ {
+ id: 11,
+ parentId: 1,
+ name: '权限',
+ rule: 'permission',
+ type: 1,
+ sort: 1,
+ status: 1,
+ },
+ {
+ id: 12,
+ parentId: 1,
+ name: '组件语言包',
+ rule: 'componentLang',
+ type: 1,
+ sort: 2,
+ status: 1,
+ },
+ {
+ id: 13,
+ parentId: 1,
+ name: '请求示例',
+ rule: 'example/request',
+ type: 1,
+ sort: 3,
+ status: 1,
+ },
+ {
+ id: 14,
+ parentId: 1,
+ name: '外链',
+ rule: 'link',
+ type: 1,
+ sort: 4,
+ status: 1,
+ },
+ {
+ id: 15,
+ parentId: 1,
+ name: '页面权限',
+ rule: 'pagePermission',
+ type: 1,
+ sort: 5,
+ status: 1,
+ },
+ {
+ id: 16,
+ parentId: 1,
+ name: '多级菜单',
+ rule: 'moreMenu',
+ type: 1,
+ sort: 6,
+ status: 1,
+ children: [
+ {
+ id: 161,
+ parentId: 16,
+ name: '多级菜单1',
+ rule: 'moreMenu1',
+ type: 1,
+ sort: 1,
+ status: 1,
+ children: [
+ {
+ id: 1611,
+ parentId: 161,
+ name: '多级菜单1-1',
+ rule: 'moreMenu1-1',
+ type: 1,
+ sort: 1,
+ status: 1,
+ children: [
+ {
+ id: 16111,
+ parentId: 1611,
+ name: '多级菜单1-1-1',
+ rule: 'moreMenu1-1-1',
+ type: 1,
+ sort: 1,
+ status: 1,
+ },
+ {
+ id: 16112,
+ parentId: 1611,
+ name: '组件语言包',
+ rule: 'moreMenu1-1-lang',
+ type: 1,
+ sort: 1,
+ status: 1,
+ },
+ ],
+ },
+ {
+ id: 1612,
+ parentId: 161,
+ name: '多级菜单1-2',
+ rule: 'moreMenu1-2',
+ type: 1,
+ sort: 1,
+ status: 1,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ id: 2,
+ parentId: 0,
+ name: '组件',
+ sort: 2,
+ status: 1,
+ rule: 'component',
+ type: 1,
+ children: [
+ {
+ id: 21,
+ parentId: 2,
+ name: '数字动画',
+ rule: 'meNumber',
+ type: 1,
+ sort: 1,
+ status: 1,
+ },
+ {
+ id: 22,
+ parentId: 2,
+ name: '编辑器',
+ sort: 2,
+ rule: 'editor',
+ type: 1,
+ status: 1,
+ children: [
+ {
+ id: 221,
+ parentId: 22,
+ name: 'WangEditor',
+ rule: 'wangEditor',
+ type: 1,
+ sort: 1,
+ status: 1,
+ },
+ ],
+ },
+ {
+ id: 23,
+ parentId: 2,
+ name: '表格',
+ sort: 3,
+ rule: 'table',
+ type: 1,
+ status: 1,
+ },
+ {
+ id: 24,
+ parentId: 2,
+ name: 'vxeTable',
+ sort: 4,
+ rule: 'vxeTable',
+ type: 1,
+ status: 1,
+ },
+ ],
+ },
+ {
+ id: 3,
+ parentId: 0,
+ name: '自定义组件',
+ sort: 3,
+ status: 1,
+ rule: 'customComponent',
+ type: 1,
+ },
+ {
+ id: 4,
+ parentId: 0,
+ name: '角色权限',
+ sort: 3,
+ status: 1,
+ rule: 'roleRule',
+ type: 1,
+ children: [
+ {
+ id: 41,
+ parentId: 4,
+ name: '查看',
+ sort: 3,
+ status: 1,
+ rule: 'roleRuleIndex',
+ type: 2,
+ },
+ {
+ id: 42,
+ parentId: 4,
+ name: '新增',
+ sort: 3,
+ status: 1,
+ rule: 'roleRuleAdd',
+ type: 3,
+ },
+ {
+ id: 43,
+ parentId: 4,
+ name: '编辑',
+ sort: 3,
+ status: 1,
+ rule: 'roleRuleEdit',
+ type: 3,
+ },
+ {
+ id: 44,
+ parentId: 4,
+ name: '删除',
+ sort: 3,
+ status: 1,
+ rule: 'roleRuleDel',
+ type: 3,
+ },
+ ],
+ },
+];
+function getMenuItem(id: number, menuList?: typeof menu) {
+ if (!menuList) {
+ return;
+ }
+ for (const key in menuList) {
+ if (menuList[key].id === id) {
+ return menuList[key];
+ }
+ const item = getMenuItem(id, menuList[key].children as any) as typeof menu[number];
+ if (item) {
+ return item;
+ }
+ }
+}
+function delMenu(id: number) {
+ const item = getMenuItem(id, menu);
+ if (!item) {
+ throw new Error('错误的id');
+ }
+ let parent = menu;
+ if (item.parentId) {
+ parent = getMenuItem(item.parentId, menu)?.children as any;
+ }
+ parent.splice(
+ parent.findIndex((item) => item.id === id),
+ 1,
+ );
+ return item;
+}
+function addMenu(info: any) {
+ let item = menu as any;
+ if (info.parentId) {
+ item = getMenuItem(info.parentId, menu);
+ if (!item) {
+ throw new Error('错误的父级');
+ }
+ if (!item.children) {
+ item.children = [];
+ }
+ item = item.children;
+ }
+ item.push({ ...info });
+ return true;
+}
+export default [
+ {
+ url: '/api/menu/index',
+ method: 'get',
+ timeout: 500 + Math.floor(Math.random() * 1000),
+ response: () => success(menu),
+ },
+ {
+ url: '/api/admin/menu/add',
+ method: 'post',
+ timeout: 500 + Math.floor(Math.random() * 1000),
+ response: (req: any) => {
+ try {
+ const info = req.body;
+ delete info._X_ROW_KEY;
+ info.id = id++;
+ addMenu(info);
+ return success('操作成功');
+ } catch (e) {
+ return fail('' + e);
+ }
+ },
+ },
+ {
+ url: /\/api\/admin\/menu\/[0-9]+/,
+ method: 'post',
+ timeout: 500 + Math.floor(Math.random() * 1000),
+ response: (req: any) => {
+ const id = +req.url.replace('/api/admin/menu/', '');
+ const info = req.body;
+ delete info._X_ROW_KEY;
+ const item = getMenuItem(id, menu);
+ if (!item) {
+ return fail('错误的id');
+ }
+ if (item?.parentId === info.parentId) {
+ Object.assign(item, info);
+ return success('操作成功');
+ }
+ try {
+ const item = delMenu(id);
+ Object.assign(item, info);
+ addMenu(item);
+ return success('操作成功');
+ } catch (e) {
+ return fail('' + e);
+ }
+ },
+ },
+ {
+ url: /\/api\/admin\/menu\/[0-9]+/,
+ method: 'DELETE',
+ timeout: 500 + Math.floor(Math.random() * 1000),
+ response: (req: any) => {
+ const id = +req.url.replace('/api/admin/menu/', '');
+ try {
+ delMenu(id);
+ return success('操作成功');
+ } catch (e) {
+ return fail('' + e);
+ }
+ },
+ },
+];
diff --git a/mock/index.ts b/mock/index.ts
index 44908e3f..071c72b8 100644
--- a/mock/index.ts
+++ b/mock/index.ts
@@ -1,5 +1,5 @@
// mockProdServer.ts
-import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
+import { createProdMockServer } from '@meadmin-cn/vite-plugin-mock/es/createProdMockServer';
export function setupProdMockServer() {
const modules = import.meta.glob('./apiDemo/*.ts', {
diff --git a/package.json b/package.json
index f23c0f02..57a71139 100644
--- a/package.json
+++ b/package.json
@@ -1,17 +1,17 @@
{
"name": "meadmin-template",
"private": true,
- "version": "1.0.6",
+ "version": "1.0.7",
"type": "module",
"scripts": {
"format": "prettier --write --cache .",
"dev": "vite",
"build": "vite build -m prod && npm run type-check",
"build-github": "vite build -m prod --base=/meadmin-template/ && npm run type-check",
- "type-check": "vue-tsc --noEmit",
+ "type-check": "vue-tsc --noEmit --skipLibCheck",
"preview": "vite preview",
- "release-main": "vue-tsc --noEmit & release-it -c .release-it-main.json",
- "release-template": "vue-tsc --noEmit & release-it",
+ "release-main": "release-it -c .release-it-main.json",
+ "release-template": "release-it",
"eslint": "eslint . --cache --ext .vue,.ts,.tsx",
"eslint:fix": "eslint . --ext .vue,.ts,.tsx --fix",
"prettier": "prettier --cache -l \"./**/*\"",
@@ -19,6 +19,7 @@
"i": "npm install --registry=https://registry.npm.taobao.org && npx husky install"
},
"dependencies": {
+ "@meadmin-cn/vite-plugin-mock": "^2.9.7",
"@vueuse/core": "^9.1.0",
"@wangeditor/editor": "^5.1.15",
"@wangeditor/editor-for-vue": "^5.1.12",
@@ -39,7 +40,8 @@
"vue-form-create": "^1.2.10",
"vue-i18n": "^9.1.10",
"vue-request": "^2.0.0-rc.2",
- "vue-router": "^4.1.1"
+ "vue-router": "^4.1.1",
+ "vxe-table": "^4.3.5"
},
"devDependencies": {
"@babel/core": "^7.18.10",
@@ -75,7 +77,6 @@
"vite": "^3.0.0",
"vite-plugin-autogeneration-import-file": "^2.1.0",
"vite-plugin-compression": "^0.5.1",
- "vite-plugin-mock": "^2.9.6",
"vite-svg-loader": "^3.4.0",
"vue-eslint-parser": "^9.0.3",
"vue-tsc": "^0.34.7",
diff --git a/plugin/vueSetupExtend.ts b/plugin/vueSetupExtend.ts
index 3528679c..c5f3cd40 100644
--- a/plugin/vueSetupExtend.ts
+++ b/plugin/vueSetupExtend.ts
@@ -83,10 +83,10 @@ export function supportScript(code: string, options: ExtendOptions) {
attrs.langImport = `{{${langImport}}}`;
}
}
- if (options.setComponents) {
+ if (options.setComponents && !attrs.getComponents) {
const components = getComponent(descriptor);
if (components.length) {
- attrs.components = `{{[${components}]}}`;
+ attrs.getComponents = `{{()=>[${components}]}}`;
}
}
let scriptStr = '';
diff --git a/public/favicon.ico b/public/favicon.ico
index df36fcfb..a4d91736 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/public/logo.png b/public/logo.png
new file mode 100644
index 00000000..4067c90b
Binary files /dev/null and b/public/logo.png differ
diff --git a/src/api/admin.ts b/src/api/admin.ts
new file mode 100644
index 00000000..8d7db454
--- /dev/null
+++ b/src/api/admin.ts
@@ -0,0 +1,62 @@
+import request from '@/utils/request';
+
+const enum Api {
+ GROUP = '/api/admin/group/index',
+ ADD_GROUP = '/api/admin/group/add',
+ EDIT_GROUP = '/api/admin/group/{id}',
+ DEL_GROUP = '/api/admin/group/{id}',
+}
+
+// 管理员组
+export class GroupInfo {
+ id?: number;
+ parentId?: number;
+ name = ''; //名称
+ rules = [] as string[]; //权限数组
+ status = 1 as 0 | 1; //状态
+}
+export function addGroupApi() {
+ return request(
+ (info) => ({
+ url: Api.ADD_GROUP,
+ method: 'POST',
+ data: info,
+ }),
+ { success: true },
+ );
+}
+
+export function editGroupApi() {
+ return request]>(
+ (id, info) => ({
+ url: Api.EDIT_GROUP.replace('{id}', id + ''),
+ method: 'POST',
+ data: info,
+ }),
+ { success: true },
+ );
+}
+
+export function delGroupApi() {
+ return request(
+ (id) => ({
+ url: Api.DEL_GROUP.replace('{id}', id + ''),
+ method: 'DELETE',
+ }),
+ { success: true },
+ );
+}
+
+export type GroupListResult = (Required & {
+ children: GroupListResult;
+})[];
+
+export function groupListApi() {
+ return request(
+ () => ({
+ url: Api.GROUP,
+ method: 'get',
+ }),
+ { noLoading: true, cacheKey: 'groupList', cacheTime: 5 * 60 * 1000 },
+ );
+}
diff --git a/src/api/menu.ts b/src/api/menu.ts
new file mode 100644
index 00000000..cf358e98
--- /dev/null
+++ b/src/api/menu.ts
@@ -0,0 +1,65 @@
+import request from '@/utils/request';
+
+const enum Api {
+ LIST = '/api/menu/index',
+ ADD = '/api/admin/menu/add',
+ EDIT = '/api/admin/menu/{id}',
+ DEL = '/api/admin/menu/{id}',
+}
+
+// 菜单列表
+export class MenuInfo {
+ id?: number;
+ parentId?: number; //父级id
+ name = ''; //名称
+ rule = ''; //规则
+ sort = 0; //排序
+ status = 1 as 0 | 1; //状态0停用1启用
+ type = 1 as 1 | 2 | 3; //1菜单2页面3按钮
+}
+
+export function addMenuApi() {
+ return request(
+ (info) => ({
+ url: Api.ADD,
+ method: 'POST',
+ data: info,
+ }),
+ { success: true },
+ );
+}
+
+export function editMenuApi() {
+ return request]>(
+ (id, info) => ({
+ url: Api.EDIT.replace('{id}', id + ''),
+ method: 'POST',
+ data: info,
+ }),
+ { success: true },
+ );
+}
+
+export function delMenuApi() {
+ return request(
+ (id) => ({
+ url: Api.DEL.replace('{id}', id + ''),
+ method: 'DELETE',
+ }),
+ { success: true },
+ );
+}
+
+export type MenuListResult = (Required & {
+ children: MenuListResult;
+})[];
+
+export function menuListApi() {
+ return request(
+ () => ({
+ url: Api.LIST,
+ method: 'get',
+ }),
+ { noLoading: true, cacheKey: 'menuList', cacheTime: 5 * 60 * 1000 },
+ );
+}
diff --git a/src/components/meTable/hooks/exportTable.ts b/src/components/meTable/hooks/exportTable.ts
index 177c4898..050b5356 100644
--- a/src/components/meTable/hooks/exportTable.ts
+++ b/src/components/meTable/hooks/exportTable.ts
@@ -1,6 +1,6 @@
import { Defaults, TableExport } from 'tableexport';
type ExportType = 'csv' | 'txt' | 'xlsx';
-export default (elTable: ELTable, type: ExportType, filename?: string, options?: Defaults) => {
+export default (elTable: ELTableInstance, type: ExportType, filename?: string, options?: Defaults) => {
const selectionIndexs = elTable.getSelectionIndexs();
const ignoreRows = [] as number[];
if (selectionIndexs.length) {
diff --git a/src/components/meTable/hooks/print.ts b/src/components/meTable/hooks/print.ts
index a2fd82e3..0b1bce64 100644
--- a/src/components/meTable/hooks/print.ts
+++ b/src/components/meTable/hooks/print.ts
@@ -56,7 +56,7 @@ export function handlePrint(content: string, title = '', head: string[] = [], ty
printFrame.src = URL.createObjectURL(blob);
}
-export default async (elTable: ELTable, title = '', head: string[] = []) => {
+export default async (elTable: ELTableInstance, title = '', head: string[] = []) => {
head.unshift(`
diff --git a/src/components/meVxeTable/install.ts b/src/components/meVxeTable/install.ts
new file mode 100644
index 00000000..bfb95bf5
--- /dev/null
+++ b/src/components/meVxeTable/install.ts
@@ -0,0 +1,14 @@
+import { app } from '@/app';
+import VXETable from 'vxe-table';
+import VXETablePluginElement from './vxe-table-plugin-element';
+import './style.scss';
+import './vxe-table-plugin-element/style.scss';
+VXETable.use(VXETablePluginElement);
+if (app.config.globalProperties.$t) {
+ //为了兼容热更新重新拉取
+ VXETable.setup({
+ // 对组件内置的提示语进行国际化翻译
+ i18n: app.config.globalProperties.$t,
+ });
+ app.use(VXETable);
+}
diff --git a/src/components/meVxeTable/style.scss b/src/components/meVxeTable/style.scss
new file mode 100644
index 00000000..a53cd2db
--- /dev/null
+++ b/src/components/meVxeTable/style.scss
@@ -0,0 +1,155 @@
+@import 'vxe-table/lib/style.min.css';
+
+.vxe-table--render-default .vxe-cell--checkbox .vxe-checkbox--icon {
+ font-weight: 500 !important;
+ font-size: 1em !important;
+}
+
+.vxe-table {
+ ::-webkit-scrollbar-corner {
+ background: unset;
+ }
+
+ ::-webkit-scrollbar {
+ z-index: 1;
+ border-radius: 4px;
+ width: 6px;
+ }
+
+ ::-webkit-scrollbar:horizontal {
+ height: 5px;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ background-color: rgba(144, 147, 153, 0.3);
+ opacity: 0.3;
+ border-radius: 4px;
+ }
+}
+[class*='vxe-'] .el-checkbox__inner::after {
+ box-sizing: content-box !important;
+}
+.vxe-table--body-wrapper,
+.vxe-table--fixed-left-body-wrapper,
+.vxe-table--fixed-right-body-wrapper {
+ overflow-y: overlay !important;
+ overflow-x: overlay !important;
+}
+
+.vxe-table--render-default .vxe-table--footer-wrapper,
+.vxe-table--render-default .vxe-table--header-wrapper {
+ overflow-x: hidden !important;
+ overflow-y: hidden !important;
+}
+
+.vxe-table--footer-wrapper.body--wrapper {
+ overflow-x: overlay !important;
+}
+
+.dark .wxe-table ::-webkit-scrollbar-thumb {
+ background-color: rgba(163, 166, 173, 0.3);
+}
+
+//暗黑模式暂时只加上table相关,vxetable不支持css变量 只能写死,后续vxetable升级支持css变量后会更新一版完整的暗黑样式。
+.dark {
+ /*font*/
+ $vxe-font-color: #cfd3dc !default;
+
+ /*color*/
+ $vxe-primary-color: #409eff !default;
+ $vxe-success-color: #67c23a !default;
+ $vxe-info-color: #909399 !default;
+ $vxe-warning-color: #e6a23c !default;
+ $vxe-danger-color: #f56c6c !default;
+ $vxe-disabled-color: #2b2b2c !default;
+ $vxe-primary-disabled-color: #6c6e72 !default;
+
+ /*input/radio/checkbox*/
+ $vxe-input-border-color: #4c4d4f !default;
+ $vxe-input-disabled-color: #4c4d4f !default;
+ $vxe-input-disabled-background-color: #262727 !default;
+ $vxe-input-placeholder-color: #8d9095 !default;
+
+ /*table*/
+ $vxe-table-font-color: #cfd3dc !default;
+ $vxe-table-header-font-color: #a3a6ad !default;
+ $vxe-table-footer-font-color: #cfd3dc !default;
+ // $vxe-table-border-radius: $vxe-border-radius !default;
+ $vxe-table-border-width: 1px !default;
+ $vxe-table-border-color: #414243 !default;
+ $vxe-table-resizable-line-color: #363637 !default;
+ $vxe-table-resizable-drag-line-color: #363637 !default;
+ $vxe-table-header-background-color: #262727 !default;
+ $vxe-table-body-background-color: transparent !default;
+ $vxe-table-footer-background-color: transparent !default;
+ $vxe-table-tree-node-line-color: #414243 !default;
+ $vxe-table-tree-node-line-style: dotted !default;
+ $vxe-table-header-font-weight: bold !default;
+
+ $vxe-table-row-height-default: 48px !default;
+ $vxe-table-row-height-medium: 44px !default;
+ $vxe-table-row-height-small: 40px !default;
+ $vxe-table-row-height-mini: 36px !default;
+ $vxe-table-row-line-height: 22px !default;
+ $vxe-table-row-hover-background-color: #262727 !default;
+ $vxe-table-row-striped-background-color: #1d1d1d !default;
+ $vxe-table-row-hover-striped-background-color: #262727 !default;
+ $vxe-table-row-radio-checked-background-color: #7d5b28 !default;
+ $vxe-table-row-hover-radio-checked-background-color: #e6a23c !default;
+ $vxe-table-row-checkbox-checked-background-color: #7d5b28 !default;
+ $vxe-table-row-hover-checkbox-checked-background-color: #e6a23c !default;
+ $vxe-table-row-current-background-color: #18222c !default;
+ $vxe-table-row-hover-current-background-color: #213d5b !default;
+
+ $vxe-table-column-padding-default: 13px 0 !default;
+ $vxe-table-column-padding-medium: 11px 0 !default;
+ $vxe-table-column-padding-small: 9px 0 !default;
+ $vxe-table-column-padding-mini: 7px 0 !default;
+ $vxe-table-column-hover-background-color: #213d5b !default;
+ $vxe-table-column-current-background-color: #18222c !default;
+ $vxe-table-column-icon-border-color: #6c6e72 !default;
+ $vxe-table-column-icon-border-hover-color: #a3a6ad !default;
+
+ $vxe-table-cell-placeholder-color: #8d9095 !default;
+ $vxe-table-cell-padding-left: 10px !default;
+ $vxe-table-cell-padding-right: 10px !default;
+ $vxe-table-cell-input-height-default: $vxe-table-row-height-default - 6 !default;
+ $vxe-table-cell-input-height-medium: $vxe-table-row-height-medium - 6 !default;
+ $vxe-table-cell-input-height-small: $vxe-table-row-height-small - 6 !default;
+ $vxe-table-cell-input-height-mini: $vxe-table-row-height-mini - 6 !default;
+ $vxe-table-cell-dirty-width: 5px !default;
+ $vxe-table-cell-dirty-update-color: #f56c6c !default;
+ $vxe-table-cell-dirty-insert-color: #67c23a !default;
+ $vxe-table-cell-area-border-color: $vxe-primary-color !default;
+ $vxe-table-cell-area-border-width: 1px !default;
+ $vxe-table-cell-main-area-extension-border-color: #141414;
+ $vxe-table-cell-main-area-extension-background-color: $vxe-primary-color !default;
+ $vxe-table-cell-extend-area-border-width: 2px !default;
+ $vxe-table-cell-copy-area-border-width: 3px !default;
+ $vxe-table-cell-active-area-border-width: 2px !default;
+ $vxe-table-cell-copy-area-border-color: $vxe-table-cell-area-border-color !default;
+ $vxe-table-cell-extend-area-border-color: $vxe-table-cell-area-border-color !default;
+ $vxe-table-cell-active-area-border-color: $vxe-table-cell-area-border-color !default;
+ $vxe-table-cell-area-background-color: rgba(64, 158, 255, 0.2) !default;
+
+ $vxe-table-checkbox-range-border-width: 1px !default;
+ $vxe-table-checkbox-range-border-color: #006af1 !default;
+ $vxe-table-checkbox-range-background-color: rgba(50, 128, 252, 0.2) !default;
+
+ $vxe-table-fixed-left-scrolling-box-shadow: 4px 3px 4px 0px rgba(0, 0, 0, 0.12) !default;
+ $vxe-table-fixed-right-scrolling-box-shadow: -4px 3px 4px 0px rgba(0, 0, 0, 0.12) !default;
+
+ /*toolbar*/
+ $vxe-toolbar-background-color: #141414 !default;
+ $vxe-toolbar-custom-active-background-color: #262727 !default;
+ $vxe-toolbar-panel-background-color: #141414 !default;
+
+ /*tooltip*/
+ $vxe-tooltip-dark-color: #141414 !default;
+ $vxe-tooltip-dark-background-color: #e5eaf3 !default;
+ $vxe-tooltip-light-background-color: #141414 !default;
+ $vxe-tooltip-validate-error-color: #fff !default;
+ $vxe-tooltip-validate-error-background-color: #f56c6c !default;
+
+ @import 'vxe-table/styles/index.scss';
+}
diff --git a/src/components/meVxeTable/vxe-table-plugin-element/index.ts b/src/components/meVxeTable/vxe-table-plugin-element/index.ts
new file mode 100644
index 00000000..19666d63
--- /dev/null
+++ b/src/components/meVxeTable/vxe-table-plugin-element/index.ts
@@ -0,0 +1,990 @@
+//vxe-table-plugin-element插件过不去vue-tsc检查,提bug没人理无奈只能自己copy下来改一下
+import { h, resolveComponent, ComponentOptions } from 'vue';
+import XEUtils from 'xe-utils';
+import {
+ VXETableCore,
+ VxeTableDefines,
+ VxeColumnPropTypes,
+ VxeGlobalRendererHandles,
+ VxeGlobalInterceptorHandles,
+ FormItemRenderOptions,
+ FormItemContentRenderParams,
+} from 'vxe-table';
+import dayjs from 'dayjs';
+
+let vxetable: VXETableCore;
+
+function isEmptyValue(cellValue: any) {
+ return cellValue === null || cellValue === undefined || cellValue === '';
+}
+
+function getOnName(type: string) {
+ return 'on' + type.substring(0, 1).toLocaleUpperCase() + type.substring(1);
+}
+
+function getModelProp(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
+ return 'modelValue';
+}
+
+function getModelEvent(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
+ return 'update:modelValue';
+}
+
+function getChangeEvent(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
+ let type = 'change';
+ switch (renderOpts.name) {
+ case 'ElAutocomplete':
+ type = 'select';
+ break;
+ case 'ElInput':
+ case 'ElInputNumber':
+ type = 'input';
+ break;
+ }
+ return type;
+}
+
+function toDayStringDate(value: any, format: string) {
+ return dayjs(value, format).date;
+}
+
+function toDayDateString(date: any, format: string) {
+ return dayjs(date).format(format);
+}
+
+function parseDate(value: any, props: { [key: string]: any }) {
+ return value && props.valueFormat ? toDayStringDate(value, props.valueFormat) : value;
+}
+
+function getFormatDate(value: any, props: { [key: string]: any }, defaultFormat: string) {
+ return value ? toDayDateString(parseDate(value, props), props.format || defaultFormat) : value;
+}
+
+function getFormatDates(values: any[], props: { [key: string]: any }, separator: string, defaultFormat: string) {
+ return XEUtils.map(values, (date: any) => getFormatDate(date, props, defaultFormat)).join(separator);
+}
+
+function equalDaterange(cellValue: any, data: any, props: { [key: string]: any }, defaultFormat: string) {
+ cellValue = getFormatDate(cellValue, props, defaultFormat);
+ return (
+ cellValue >= getFormatDate(data[0], props, defaultFormat) &&
+ cellValue <= getFormatDate(data[1], props, defaultFormat)
+ );
+}
+
+function getCellEditFilterProps(
+ renderOpts: VxeGlobalRendererHandles.RenderOptions,
+ params: VxeGlobalRendererHandles.RenderEditParams | VxeGlobalRendererHandles.RenderFilterParams,
+ value: any,
+ defaultProps?: { [prop: string]: any },
+) {
+ return XEUtils.assign({}, defaultProps, renderOpts.props, { [getModelProp(renderOpts)]: value });
+}
+
+function getItemProps(
+ renderOpts: VxeGlobalRendererHandles.RenderOptions,
+ params: FormItemContentRenderParams,
+ value: any,
+ defaultProps?: { [prop: string]: any },
+) {
+ return XEUtils.assign({}, defaultProps, renderOpts.props, { [getModelProp(renderOpts)]: value });
+}
+
+function formatText(cellValue: any) {
+ return '' + (isEmptyValue(cellValue) ? '' : cellValue);
+}
+
+function getCellLabelVNs(
+ renderOpts: VxeColumnPropTypes.EditRender,
+ params: VxeGlobalRendererHandles.RenderCellParams,
+ cellLabel: any,
+) {
+ const { placeholder } = renderOpts;
+ return [
+ h(
+ 'span',
+ {
+ class: 'vxe-cell--label',
+ },
+ placeholder && isEmptyValue(cellLabel)
+ ? [
+ h(
+ 'span',
+ {
+ class: 'vxe-cell--placeholder',
+ },
+ formatText(vxetable._t(placeholder)),
+ ),
+ ]
+ : formatText(cellLabel),
+ ),
+ ];
+}
+
+function getOns(
+ renderOpts: VxeGlobalRendererHandles.RenderOptions,
+ params: VxeGlobalRendererHandles.RenderParams,
+ inputFunc?: Function,
+ changeFunc?: Function,
+) {
+ const { events } = renderOpts;
+ const modelEvent = getModelEvent(renderOpts);
+ const changeEvent = getChangeEvent(renderOpts);
+ const isSameEvent = changeEvent === modelEvent;
+ const ons: { [type: string]: Function } = {};
+ XEUtils.objectEach(events, (func: Function, key: string) => {
+ ons[getOnName(key)] = function (...args: any[]) {
+ func(params, ...args);
+ };
+ });
+ if (inputFunc) {
+ ons[getOnName(modelEvent)] = function (targetEvnt: any) {
+ inputFunc(targetEvnt);
+ if (events && events[modelEvent]) {
+ events[modelEvent](params, targetEvnt);
+ }
+ if (isSameEvent && changeFunc) {
+ changeFunc(targetEvnt);
+ }
+ };
+ }
+ if (!isSameEvent && changeFunc) {
+ ons[getOnName(changeEvent)] = function (...args: any[]) {
+ changeFunc(...args);
+ if (events && events[changeEvent]) {
+ events[changeEvent](params, ...args);
+ }
+ };
+ }
+ return ons;
+}
+
+function getEditOns(
+ renderOpts: VxeGlobalRendererHandles.RenderOptions,
+ params: VxeGlobalRendererHandles.RenderEditParams,
+) {
+ const { $table, row, column } = params;
+ return getOns(
+ renderOpts,
+ params,
+ (value: any) => {
+ // 处理 model 值双向绑定
+ XEUtils.set(row, column.property, value);
+ },
+ () => {
+ // 处理 change 事件相关逻辑
+ $table.updateStatus(params);
+ },
+ );
+}
+
+function getFilterOns(
+ renderOpts: VxeGlobalRendererHandles.RenderOptions,
+ params: VxeGlobalRendererHandles.RenderFilterParams,
+ option: VxeTableDefines.FilterOption,
+ changeFunc: Function,
+) {
+ return getOns(
+ renderOpts,
+ params,
+ (value: any) => {
+ // 处理 model 值双向绑定
+ option.data = value;
+ },
+ changeFunc,
+ );
+}
+
+function getItemOns(renderOpts: VxeGlobalRendererHandles.RenderOptions, params: FormItemContentRenderParams) {
+ const { $form, data, property } = params;
+ return getOns(
+ renderOpts,
+ params,
+ (value: any) => {
+ // 处理 model 值双向绑定
+ XEUtils.set(data, property, value);
+ },
+ () => {
+ // 处理 change 事件相关逻辑
+ $form.updateStatus(params);
+ },
+ );
+}
+
+function matchCascaderData(index: number, list: any[], values: any[], labels: any[]) {
+ const val = values[index];
+ if (list && values.length > index) {
+ XEUtils.each(list, (item) => {
+ if (item.value === val) {
+ labels.push(item.label);
+ matchCascaderData(++index, item.children, values, labels);
+ }
+ });
+ }
+}
+
+function getSelectCellValue(
+ renderOpts: VxeColumnPropTypes.EditRender,
+ params: VxeGlobalRendererHandles.RenderCellParams,
+) {
+ const { options = [], optionGroups, props = {}, optionProps = {}, optionGroupProps = {} } = renderOpts;
+ const { $table, rowid, row, column } = params;
+ const { filterable, multiple } = props;
+ const labelProp = optionProps.label || 'label';
+ const valueProp = optionProps.value || 'value';
+ const groupOptions = optionGroupProps.options || 'options';
+ const cellValue = XEUtils.get(row, column.property);
+ const colid = column.id;
+ let cellData: any;
+ if (filterable) {
+ const { internalData } = $table;
+ const { fullAllDataRowIdData } = internalData;
+ const rest: any = fullAllDataRowIdData[rowid];
+ if (rest) {
+ cellData = rest.cellData;
+ if (!cellData) {
+ cellData = rest.cellData = {};
+ }
+ }
+ if (rest && cellData[colid] && cellData[colid].value === cellValue) {
+ return cellData[colid].label;
+ }
+ }
+ if (!isEmptyValue(cellValue)) {
+ const selectlabel = XEUtils.map(
+ multiple ? cellValue : [cellValue],
+ optionGroups
+ ? (value) => {
+ let selectItem: any;
+ for (let index = 0; index < optionGroups.length; index++) {
+ selectItem = XEUtils.find(optionGroups[index][groupOptions], (item) => item[valueProp] === value);
+ if (selectItem) {
+ break;
+ }
+ }
+ return selectItem ? selectItem[labelProp] : value;
+ }
+ : (value) => {
+ const selectItem = XEUtils.find(options, (item) => item[valueProp] === value);
+ return selectItem ? selectItem[labelProp] : value;
+ },
+ ).join(', ');
+ if (cellData && options && options.length) {
+ cellData[colid] = { value: cellValue, label: selectlabel };
+ }
+ return selectlabel;
+ }
+ return '';
+}
+
+function getCascaderCellValue(
+ renderOpts: VxeGlobalRendererHandles.RenderOptions,
+ params: VxeGlobalRendererHandles.RenderCellParams,
+) {
+ const { props = {} } = renderOpts;
+ const { row, column } = params;
+ const cellValue = XEUtils.get(row, column.property);
+ const values: any[] = cellValue || [];
+ const labels: any[] = [];
+ matchCascaderData(0, props.options, values, labels);
+ return (props.showAllLevels === false ? labels.slice(labels.length - 1, labels.length) : labels).join(
+ ` ${props.separator || '/'} `,
+ );
+}
+
+function getDatePickerCellValue(
+ renderOpts: VxeGlobalRendererHandles.RenderOptions,
+ params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.ExportMethodParams,
+) {
+ const { props = {} } = renderOpts;
+ const { row, column } = params;
+ const { rangeSeparator = '-' } = props;
+ let cellValue = XEUtils.get(row, column.property);
+ switch (props.type) {
+ case 'week':
+ cellValue = getFormatDate(cellValue, props, 'YYYYwWW');
+ break;
+ case 'month':
+ cellValue = getFormatDate(cellValue, props, 'YYYY-MM');
+ break;
+ case 'year':
+ cellValue = getFormatDate(cellValue, props, 'YYYY');
+ break;
+ case 'dates':
+ cellValue = getFormatDates(cellValue, props, ', ', 'YYYY-MM-DD');
+ break;
+ case 'daterange':
+ cellValue = getFormatDates(cellValue, props, ` ${rangeSeparator} `, 'YYYY-MM-DD');
+ break;
+ case 'datetimerange':
+ cellValue = getFormatDates(cellValue, props, ` ${rangeSeparator} `, 'YYYY-MM-DD HH:ss:mm');
+ break;
+ case 'monthrange':
+ cellValue = getFormatDates(cellValue, props, ` ${rangeSeparator} `, 'YYYY-MM');
+ break;
+ default:
+ cellValue = getFormatDate(cellValue, props, 'YYYY-MM-DD');
+ }
+ return cellValue;
+}
+
+function getTimePickerCellValue(
+ renderOpts: VxeGlobalRendererHandles.RenderOptions,
+ params: VxeGlobalRendererHandles.RenderCellParams | VxeGlobalRendererHandles.RenderEditParams,
+) {
+ const { props = {} } = renderOpts;
+ const { row, column } = params;
+ const { isRange, format = 'hh:mm:ss', rangeSeparator = '-' } = props;
+ let cellValue = XEUtils.get(row, column.property);
+ if (cellValue && isRange) {
+ cellValue = XEUtils.map(cellValue, (date) => toDayDateString(parseDate(date, props), format)).join(
+ ` ${rangeSeparator} `,
+ );
+ }
+ return toDayDateString(parseDate(cellValue, props), format);
+}
+
+function createEditRender(defaultProps?: { [key: string]: any }) {
+ return function (renderOpts: VxeColumnPropTypes.EditRender, params: VxeGlobalRendererHandles.RenderEditParams) {
+ const { row, column } = params;
+ const { name, attrs } = renderOpts;
+ const cellValue = XEUtils.get(row, column.property);
+ return [
+ h(resolveComponent(name!), {
+ ...attrs,
+ ...getCellEditFilterProps(renderOpts, params, cellValue, defaultProps),
+ ...getEditOns(renderOpts, params),
+ }),
+ ];
+ };
+}
+
+function defaultButtonEditRender(
+ renderOpts: VxeColumnPropTypes.EditRender,
+ params: VxeGlobalRendererHandles.RenderEditParams,
+) {
+ const { attrs } = renderOpts;
+ return [
+ h(
+ resolveComponent('el-button'),
+ {
+ ...attrs,
+ ...getCellEditFilterProps(renderOpts, params, null),
+ ...getOns(renderOpts, params),
+ },
+ cellText(renderOpts.content),
+ ),
+ ];
+}
+
+function defaultButtonsEditRender(
+ renderOpts: VxeColumnPropTypes.EditRender,
+ params: VxeGlobalRendererHandles.RenderEditParams,
+) {
+ const { children } = renderOpts;
+ if (children) {
+ return children.map(
+ (childRenderOpts: VxeColumnPropTypes.EditRender) => defaultButtonEditRender(childRenderOpts, params)[0],
+ );
+ }
+ return [];
+}
+
+function createFilterRender(defaultProps?: { [key: string]: any }) {
+ return function (renderOpts: VxeColumnPropTypes.FilterRender, params: VxeGlobalRendererHandles.RenderFilterParams) {
+ const { column } = params;
+ const { name, attrs } = renderOpts;
+ return [
+ h(
+ 'div',
+ {
+ class: 'vxe-table--filter-element-wrapper',
+ },
+ column.filters.map((option, oIndex) => {
+ const optionValue = option.data;
+ return h(resolveComponent(name!), {
+ key: oIndex,
+ ...attrs,
+ ...getCellEditFilterProps(renderOpts, params, optionValue, defaultProps),
+ ...getFilterOns(renderOpts, params, option, () => {
+ // 处理 change 事件相关逻辑
+ handleConfirmFilter(params, !!option.data, option);
+ }),
+ });
+ }),
+ ),
+ ];
+ };
+}
+
+function handleConfirmFilter(
+ params: VxeGlobalRendererHandles.RenderFilterParams,
+ checked: boolean,
+ option: VxeTableDefines.FilterOption,
+) {
+ const { $panel } = params;
+ $panel.changeOption(null, checked, option);
+}
+
+/**
+ * 模糊匹配
+ * @param params
+ */
+function defaultFuzzyFilterMethod(params: VxeGlobalRendererHandles.FilterMethodParams) {
+ const { option, row, column } = params;
+ const { data } = option;
+ const cellValue = XEUtils.get(row, column.property);
+ return XEUtils.toValueString(cellValue).indexOf(data) > -1;
+}
+
+/**
+ * 精确匹配
+ * @param params
+ */
+function defaultExactFilterMethod(params: VxeGlobalRendererHandles.FilterMethodParams) {
+ const { option, row, column } = params;
+ const { data } = option;
+ const cellValue = XEUtils.get(row, column.property);
+ /* eslint-disable eqeqeq */
+ return cellValue === data;
+}
+
+function renderOptions(options: any[], optionProps: VxeGlobalRendererHandles.RenderOptionProps) {
+ const labelProp = optionProps.label || 'label';
+ const valueProp = optionProps.value || 'value';
+ return XEUtils.map(options, (item, oIndex) => {
+ return h(resolveComponent('el-option'), {
+ key: oIndex,
+ value: item[valueProp],
+ label: item[labelProp],
+ disabled: item.disabled,
+ });
+ });
+}
+
+function cellText(cellValue: any): string[] {
+ return [formatText(cellValue)];
+}
+
+function createFormItemRender(defaultProps?: { [key: string]: any }) {
+ return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
+ const { data, property } = params;
+ const { name } = renderOpts;
+ const { attrs } = renderOpts;
+ const itemValue = XEUtils.get(data, property);
+ return [
+ h(resolveComponent(name!), {
+ ...attrs,
+ ...getItemProps(renderOpts, params, itemValue, defaultProps),
+ ...getItemOns(renderOpts, params),
+ }),
+ ];
+ };
+}
+
+function defaultButtonItemRender(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
+ const { attrs } = renderOpts;
+ const props = getItemProps(renderOpts, params, null);
+ return [
+ h(
+ resolveComponent('el-button') as ComponentOptions,
+ {
+ ...attrs,
+ ...props,
+ ...getOns(renderOpts, params),
+ },
+ {
+ default: () => cellText(renderOpts.content || props.content),
+ },
+ ),
+ ];
+}
+
+function defaultButtonsItemRender(renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
+ const { children } = renderOpts;
+ if (children) {
+ return children.map(
+ (childRenderOpts: FormItemRenderOptions) => defaultButtonItemRender(childRenderOpts, params)[0],
+ );
+ }
+ return [];
+}
+
+function createExportMethod(getExportCellValue: Function) {
+ return function (params: VxeGlobalRendererHandles.ExportMethodParams) {
+ const { row, column, options } = params;
+ return options && options.original
+ ? XEUtils.get(row, column.property)
+ : getExportCellValue(column.editRender || column.cellRender, params);
+ };
+}
+
+function createFormItemRadioAndCheckboxRender() {
+ return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
+ const { name, options = [], optionProps = {}, attrs } = renderOpts;
+ const { data, property } = params;
+ const labelProp = optionProps.label || 'label';
+ const valueProp = optionProps.value || 'value';
+ const itemValue = XEUtils.get(data, property);
+ return [
+ h(
+ resolveComponent(`${name}Group`) as ComponentOptions,
+ {
+ ...attrs,
+ ...getItemProps(renderOpts, params, itemValue),
+ ...getItemOns(renderOpts, params),
+ },
+ {
+ default: () => {
+ return options.map((option, oIndex) => {
+ return h(
+ resolveComponent(name!) as ComponentOptions,
+ {
+ key: oIndex,
+ label: option[valueProp],
+ disabled: option.disabled,
+ },
+ {
+ default: () => cellText(option[labelProp]),
+ },
+ );
+ });
+ },
+ },
+ ),
+ ];
+ };
+}
+
+/**
+ * 检查触发源是否属于目标节点
+ */
+function getEventTargetNode(evnt: any, container: HTMLElement, className: string) {
+ let targetElem;
+ let target = evnt.target;
+ while (target && target.nodeType && target !== document) {
+ if (
+ className &&
+ target.className &&
+ target.className.split &&
+ target.className.split(' ').indexOf(className) > -1
+ ) {
+ targetElem = target;
+ } else if (target === container) {
+ return { flag: className ? !!targetElem : true, container, targetElem: targetElem };
+ }
+ target = target.parentNode;
+ }
+ return { flag: false };
+}
+
+/**
+ * 事件兼容性处理
+ */
+function handleClearEvent(
+ params:
+ | VxeGlobalInterceptorHandles.InterceptorClearFilterParams
+ | VxeGlobalInterceptorHandles.InterceptorClearActivedParams
+ | VxeGlobalInterceptorHandles.InterceptorClearAreasParams,
+) {
+ const { $event } = params;
+ const bodyElem = document.body;
+ if (
+ // 远程搜索
+ getEventTargetNode($event, bodyElem, 'el-autocomplete-suggestion').flag ||
+ // 下拉框
+ getEventTargetNode($event, bodyElem, 'el-select-dropdown').flag ||
+ // 级联
+ getEventTargetNode($event, bodyElem, 'el-cascader__dropdown').flag ||
+ getEventTargetNode($event, bodyElem, 'el-cascader-menus').flag ||
+ // 日期
+ getEventTargetNode($event, bodyElem, 'el-time-panel').flag ||
+ getEventTargetNode($event, bodyElem, 'el-picker-panel').flag ||
+ // 颜色
+ getEventTargetNode($event, bodyElem, 'el-color-dropdown').flag
+ ) {
+ return false;
+ }
+}
+
+declare module 'vxe-table' {
+ interface DefineRendererOption {
+ defaultFilterMethod?(params: VxeGlobalRendererHandles.FilterMethodParams): boolean;
+ }
+}
+
+/**
+ * 基于 vxe-table 表格的适配插件,用于兼容 element-ui 组件库
+ */
+export const VXETablePluginElement = {
+ install(vxetablecore: VXETableCore) {
+ const { interceptor, renderer } = vxetablecore;
+
+ vxetable = vxetablecore;
+
+ renderer.mixin({
+ ElAutocomplete: {
+ autofocus: 'input.el-input__inner',
+ renderDefault: createEditRender(),
+ renderEdit: createEditRender(),
+ renderFilter: createFilterRender(),
+ defaultFilterMethod: defaultExactFilterMethod,
+ renderItemContent: createFormItemRender(),
+ },
+ ElInput: {
+ autofocus: 'input.el-input__inner',
+ renderDefault: createEditRender(),
+ renderEdit: createEditRender(),
+ renderFilter: createFilterRender(),
+ defaultFilterMethod: defaultFuzzyFilterMethod,
+ renderItemContent: createFormItemRender(),
+ },
+ ElInputNumber: {
+ autofocus: 'input.el-input__inner',
+ renderDefault: createEditRender(),
+ renderEdit: createEditRender(),
+ renderFilter: createFilterRender(),
+ defaultFilterMethod: defaultFuzzyFilterMethod,
+ renderItemContent: createFormItemRender(),
+ },
+ ElSelect: {
+ renderEdit(renderOpts, params) {
+ const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
+ const { row, column } = params;
+ const { attrs } = renderOpts;
+ const cellValue = XEUtils.get(row, column.property);
+ const props = getCellEditFilterProps(renderOpts, params, cellValue);
+ const ons = getEditOns(renderOpts, params);
+ if (optionGroups) {
+ const groupOptions = optionGroupProps.options || 'options';
+ const groupLabel = optionGroupProps.label || 'label';
+ return [
+ h(
+ resolveComponent('el-select') as ComponentOptions,
+ {
+ ...attrs,
+ ...props,
+ ...ons,
+ },
+ {
+ default: () => {
+ return XEUtils.map(optionGroups, (group, gIndex) => {
+ return h(
+ resolveComponent('el-option-group') as ComponentOptions,
+ {
+ key: gIndex,
+ label: group[groupLabel],
+ },
+ {
+ default: () => renderOptions(group[groupOptions], optionProps),
+ },
+ );
+ });
+ },
+ },
+ ),
+ ];
+ }
+ return [
+ h(
+ resolveComponent('el-select') as ComponentOptions,
+ {
+ ...props,
+ ...attrs,
+ ...ons,
+ },
+ {
+ default: () => renderOptions(options, optionProps),
+ },
+ ),
+ ];
+ },
+ renderCell(renderOpts, params) {
+ return getCellLabelVNs(renderOpts, params, getSelectCellValue(renderOpts, params));
+ },
+ renderFilter(renderOpts, params) {
+ const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
+ const groupOptions = optionGroupProps.options || 'options';
+ const groupLabel = optionGroupProps.label || 'label';
+ const { column } = params;
+ const { attrs } = renderOpts;
+ return [
+ h(
+ 'div',
+ {
+ class: 'vxe-table--filter-element-wrapper',
+ },
+ optionGroups
+ ? column.filters.map((option, oIndex) => {
+ const optionValue = option.data;
+ const props = getCellEditFilterProps(renderOpts, params, optionValue);
+ return h(
+ resolveComponent('el-select') as ComponentOptions,
+ {
+ key: oIndex,
+ ...attrs,
+ ...props,
+ ...getFilterOns(renderOpts, params, option, () => {
+ // 处理 change 事件相关逻辑
+ handleConfirmFilter(
+ params,
+ props.multiple ? option.data && option.data.length > 0 : !XEUtils.eqNull(option.data),
+ option,
+ );
+ }),
+ },
+ {
+ default: () => {
+ return XEUtils.map(optionGroups, (group, gIndex) => {
+ return h(
+ resolveComponent('el-option-group') as ComponentOptions,
+ {
+ key: gIndex,
+ label: group[groupLabel],
+ },
+ {
+ default: () => renderOptions(group[groupOptions], optionProps),
+ },
+ );
+ });
+ },
+ },
+ );
+ })
+ : column.filters.map((option, oIndex) => {
+ const optionValue = option.data;
+ const props = getCellEditFilterProps(renderOpts, params, optionValue);
+ return h(
+ resolveComponent('el-select') as ComponentOptions,
+ {
+ key: oIndex,
+ ...attrs,
+ ...props,
+ ...getFilterOns(renderOpts, params, option, () => {
+ // 处理 change 事件相关逻辑
+ handleConfirmFilter(
+ params,
+ props.multiple ? option.data && option.data.length > 0 : !XEUtils.eqNull(option.data),
+ option,
+ );
+ }),
+ },
+ {
+ default: () => renderOptions(options, optionProps),
+ },
+ );
+ }),
+ ),
+ ];
+ },
+ defaultFilterMethod(params) {
+ const { option, row, column } = params;
+ const { data } = option;
+ const { property, filterRender: renderOpts } = column;
+ const { props = {} } = renderOpts;
+ const cellValue = XEUtils.get(row, property);
+ if (props.multiple) {
+ if (XEUtils.isArray(cellValue)) {
+ return XEUtils.includeArrays(cellValue, data);
+ }
+ return data.indexOf(cellValue) > -1;
+ }
+ /* eslint-disable eqeqeq */
+ return cellValue == data;
+ },
+ renderItemContent(renderOpts, params) {
+ const { options = [], optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts;
+ const { data, property } = params;
+ const { attrs } = renderOpts;
+ const itemValue = XEUtils.get(data, property);
+ const props = getItemProps(renderOpts, params, itemValue);
+ const ons = getItemOns(renderOpts, params);
+ if (optionGroups) {
+ const groupOptions = optionGroupProps.options || 'options';
+ const groupLabel = optionGroupProps.label || 'label';
+ return [
+ h(
+ resolveComponent('el-select') as ComponentOptions,
+ {
+ ...attrs,
+ ...props,
+ ...ons,
+ },
+ {
+ default: () => {
+ return XEUtils.map(optionGroups, (group, gIndex) => {
+ return h(
+ resolveComponent('el-option-group') as ComponentOptions,
+ {
+ label: group[groupLabel],
+ key: gIndex,
+ },
+ {
+ default: () => renderOptions(group[groupOptions], optionProps),
+ },
+ );
+ });
+ },
+ },
+ ),
+ ];
+ }
+ return [
+ h(
+ resolveComponent('el-select') as ComponentOptions,
+ {
+ ...attrs,
+ ...props,
+ ...ons,
+ },
+ {
+ default: () => renderOptions(options, optionProps),
+ },
+ ),
+ ];
+ },
+ exportMethod: createExportMethod(getSelectCellValue),
+ },
+ ElCascader: {
+ renderEdit: createEditRender(),
+ renderCell(renderOpts, params) {
+ return getCellLabelVNs(renderOpts, params, getCascaderCellValue(renderOpts, params));
+ },
+ renderItemContent: createFormItemRender(),
+ exportMethod: createExportMethod(getCascaderCellValue),
+ },
+ ElDatePicker: {
+ renderEdit: createEditRender(),
+ renderCell(renderOpts, params) {
+ return getCellLabelVNs(renderOpts, params, getDatePickerCellValue(renderOpts, params));
+ },
+ renderFilter(renderOpts, params) {
+ const { column } = params;
+ const { name, attrs } = renderOpts;
+ return [
+ h(
+ 'div',
+ {
+ class: 'vxe-table--filter-element-wrapper',
+ },
+ column.filters.map((option, oIndex) => {
+ const optionValue = option.data;
+ return h(resolveComponent(name!), {
+ key: oIndex,
+ ...attrs,
+ ...getCellEditFilterProps(renderOpts, params, optionValue),
+ ...getFilterOns(renderOpts, params, option, () => {
+ // 处理 change 事件相关逻辑
+ handleConfirmFilter(params, !!option.data, option);
+ }),
+ });
+ }),
+ ),
+ ];
+ },
+ defaultFilterMethod(params) {
+ const { option, row, column } = params;
+ const { data } = option;
+ const { filterRender: renderOpts } = column;
+ const { props = {} } = renderOpts;
+ const cellValue = XEUtils.get(row, column.property);
+ if (data) {
+ switch (props.type) {
+ case 'daterange':
+ return equalDaterange(cellValue, data, props, 'YYYY-MM-DD');
+ case 'datetimerange':
+ return equalDaterange(cellValue, data, props, 'YYYY-MM-DD HH:ss:mm');
+ case 'monthrange':
+ return equalDaterange(cellValue, data, props, 'YYYY-MM');
+ default:
+ return cellValue === data;
+ }
+ }
+ return false;
+ },
+ renderItemContent: createFormItemRender(),
+ exportMethod: createExportMethod(getDatePickerCellValue),
+ },
+ ElTimePicker: {
+ renderEdit: createEditRender(),
+ renderCell(renderOpts, params) {
+ return getCellLabelVNs(renderOpts, params, getTimePickerCellValue(renderOpts, params));
+ },
+ renderItemContent: createFormItemRender(),
+ exportMethod: createExportMethod(getTimePickerCellValue),
+ },
+ ElTimeSelect: {
+ renderEdit: createEditRender(),
+ renderItemContent: createFormItemRender(),
+ },
+ ElRate: {
+ renderDefault: createEditRender(),
+ renderEdit: createEditRender(),
+ renderFilter: createFilterRender(),
+ defaultFilterMethod: defaultExactFilterMethod,
+ renderItemContent: createFormItemRender(),
+ },
+ ElSwitch: {
+ renderDefault: createEditRender(),
+ renderEdit: createEditRender(),
+ renderFilter(renderOpts, params) {
+ const { column } = params;
+ const { name, attrs } = renderOpts;
+ return [
+ h(
+ 'div',
+ {
+ class: 'vxe-table--filter-element-wrapper',
+ },
+ column.filters.map((option, oIndex) => {
+ const optionValue = option.data;
+ return h(resolveComponent(name!), {
+ key: oIndex,
+ ...attrs,
+ ...getCellEditFilterProps(renderOpts, params, optionValue),
+ ...getFilterOns(renderOpts, params, option, () => {
+ // 处理 change 事件相关逻辑
+ handleConfirmFilter(params, XEUtils.isBoolean(option.data), option);
+ }),
+ });
+ }),
+ ),
+ ];
+ },
+ defaultFilterMethod: defaultExactFilterMethod,
+ renderItemContent: createFormItemRender(),
+ },
+ ElSlider: {
+ renderDefault: createEditRender(),
+ renderEdit: createEditRender(),
+ renderFilter: createFilterRender(),
+ defaultFilterMethod: defaultExactFilterMethod,
+ renderItemContent: createFormItemRender(),
+ },
+ ElRadio: {
+ renderItemContent: createFormItemRadioAndCheckboxRender(),
+ },
+ ElCheckbox: {
+ renderItemContent: createFormItemRadioAndCheckboxRender(),
+ },
+ ElButton: {
+ renderDefault: defaultButtonEditRender,
+ renderItemContent: defaultButtonItemRender,
+ },
+ ElButtons: {
+ renderDefault: defaultButtonsEditRender,
+ renderItemContent: defaultButtonsItemRender,
+ },
+ });
+
+ interceptor.add('event.clearFilter', handleClearEvent);
+ interceptor.add('event.clearActived', handleClearEvent);
+ interceptor.add('event.clearAreas', handleClearEvent);
+ },
+};
+
+if (typeof window !== 'undefined' && window.VXETable && window.VXETable.use) {
+ window.VXETable.use(VXETablePluginElement);
+}
+
+export default VXETablePluginElement;
diff --git a/src/components/meVxeTable/vxe-table-plugin-element/style.scss b/src/components/meVxeTable/vxe-table-plugin-element/style.scss
new file mode 100644
index 00000000..5e8d9b62
--- /dev/null
+++ b/src/components/meVxeTable/vxe-table-plugin-element/style.scss
@@ -0,0 +1,98 @@
+$vxe-table-validate-error-color: #f56c6c;
+
+%ResetBorder {
+ border: 0;
+}
+
+%SliderStyle {
+ .el-slider__runway {
+ margin: 8px 0;
+ .el-slider__button-wrapper {
+ z-index: auto;
+ }
+ }
+}
+
+%CompWidth {
+ & > .el-input,
+ & > .el-autocomplete,
+ & > .el-input-number,
+ & > .el-select,
+ & > .el-cascader,
+ & > .el-date-editor,
+ & > .el-slider {
+ width: 100%;
+ }
+ & > .el-color-picker {
+ vertical-align: middle;
+ }
+}
+.vxe-form {
+ .vxe-form--item-content {
+ @extend %CompWidth;
+ }
+}
+.vxe-table--filter-element-wrapper {
+ padding: 0.8em 1em;
+ & > .el-input,
+ & > .el-input-number,
+ & > .el-autocomplete,
+ & > .el-select,
+ & > .el-rate,
+ & > .el-slider {
+ width: 180px;
+ }
+ & > .el-slider {
+ @extend %SliderStyle;
+ }
+}
+.vxe-table {
+ .vxe-cell,
+ .vxe-tree-cell {
+ @extend %CompWidth;
+ & > .el-slider {
+ @extend %SliderStyle;
+ }
+ }
+}
+.col--valid-error {
+ & > .vxe-cell,
+ & > .vxe-tree-cell {
+ & > .el-input .el-input__inner,
+ & > .el-autocomplete .el-input__inner,
+ & > .el-input-number .el-input__inner,
+ & > .el-select .el-input__inner,
+ & > .el-cascader .el-input__inner,
+ & > .el-date-picker .el-input__inner {
+ border-color: $vxe-table-validate-error-color;
+ }
+ }
+}
+.vxe-table.cell--highlight {
+ .vxe-cell,
+ .vxe-tree-cell {
+ & > .el-input:not(.el-date-editor),
+ & > .el-autocomplete,
+ & > .el-select,
+ & > .el-cascader {
+ .el-input__inner {
+ padding: 0;
+ @extend %ResetBorder;
+ }
+ }
+ & > .el-input-number {
+ .el-input-number__decrease,
+ .el-input-number__increase {
+ @extend %ResetBorder;
+ }
+ .el-input__inner {
+ @extend %ResetBorder;
+ }
+ }
+ & > .el-date-editor {
+ .el-input__inner {
+ @extend %ResetBorder;
+ }
+ }
+ }
+}
diff --git a/src/event/modules/core.ts b/src/event/modules/core.ts
index 8b6ec480..f5fba227 100644
--- a/src/event/modules/core.ts
+++ b/src/event/modules/core.ts
@@ -1,8 +1,6 @@
import { installRoute } from '@/router';
import { installStore } from '@/store';
import { event, mitter } from '../index';
-import 'element-plus/dist/index.css';
-import 'element-plus/theme-chalk/dark/css-vars.css';
import { installIcon } from '@/icons';
import { installI18n } from '@/locales/i18n';
import nProgress from 'nprogress';
diff --git a/src/layout/components/header/components/topBar/components/right/index.vue b/src/layout/components/header/components/topBar/components/right/index.vue
index 0744a1af..294186b9 100644
--- a/src/layout/components/header/components/topBar/components/right/index.vue
+++ b/src/layout/components/header/components/topBar/components/right/index.vue
@@ -11,9 +11,6 @@
+
diff --git a/src/views/customForm.vue b/src/views/customForm.vue
index 8cc6874a..41c19e46 100644
--- a/src/views/customForm.vue
+++ b/src/views/customForm.vue
@@ -130,27 +130,12 @@ if (app && !app.config.globalProperties.$initCreate) {
}
}
//为了兼容暗黑模式对create-form样式做的覆盖
-:global(#app) {
+:global(body #app) {
color: unset;
font-family: unset;
min-height: unset;
}
-:global(::-webkit-scrollbar) {
- width: unset;
- height: unset;
-}
-:global(::-webkit-scrollbar-thumb) {
- border-radius: unset;
- background-color: unset;
-}
-:global(::-webkit-scrollbar-track) {
- border-radius: unset;
- background-color: unset;
-}
-:global(.fc-style ::-webkit-scrollbar) {
- width: 5px;
- height: 5px;
-}
+
:global(.fc-style ::-webkit-scrollbar-thumb) {
border-radius: 1rem;
background-color: rgba(144, 147, 153, 0.3);
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
index 21998307..edff2024 100644
--- a/src/views/login/index.vue
+++ b/src/views/login/index.vue
@@ -99,14 +99,8 @@ const login = async () => {
};
diff --git a/src/views/rolePermissions/components/group/group.vue b/src/views/rolePermissions/components/group/group.vue
new file mode 100644
index 00000000..7c0e1ad8
--- /dev/null
+++ b/src/views/rolePermissions/components/group/group.vue
@@ -0,0 +1,120 @@
+
+
+
+
+
diff --git a/src/views/rolePermissions/components/menu/components/add.vue b/src/views/rolePermissions/components/menu/components/add.vue
new file mode 100644
index 00000000..b116c474
--- /dev/null
+++ b/src/views/rolePermissions/components/menu/components/add.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+ {{ item }}
+
+
+
+ 提交
+ 重置
+
+
+
+
+
+
diff --git a/src/views/rolePermissions/components/menu/dict.ts b/src/views/rolePermissions/components/menu/dict.ts
new file mode 100644
index 00000000..67e077b4
--- /dev/null
+++ b/src/views/rolePermissions/components/menu/dict.ts
@@ -0,0 +1,9 @@
+export const type = {
+ '1': '菜单',
+ '2': '页面',
+ '3': '按钮',
+};
+export const status = {
+ '0': '关闭',
+ '1': '开启',
+};
diff --git a/src/views/rolePermissions/components/menu/menu.vue b/src/views/rolePermissions/components/menu/menu.vue
new file mode 100644
index 00000000..c69d4c71
--- /dev/null
+++ b/src/views/rolePermissions/components/menu/menu.vue
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ item.rule),
+ )
+ "
+ >保存
+
+
+
+
+
+
+
diff --git a/src/views/rolePermissions/rolePermissions.vue b/src/views/rolePermissions/rolePermissions.vue
new file mode 100644
index 00000000..64d306da
--- /dev/null
+++ b/src/views/rolePermissions/rolePermissions.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/template/components.d.ts b/template/components.d.ts
index ceec6cbb..dc6fc9ab 100644
--- a/template/components.d.ts
+++ b/template/components.d.ts
@@ -3,4 +3,7 @@ declare module '@vue/runtime-core' {
//code
}
}
+declare global {
+ //typeCode
+}
export {};
diff --git a/types/global.d.ts b/types/global.d.ts
index 1095d10a..3d2a2460 100644
--- a/types/global.d.ts
+++ b/types/global.d.ts
@@ -2,6 +2,11 @@ import { Component, AllowedComponentProps, DefineComponent, VNodeProps } from 'v
import { ElTable } from 'element-plus';
export {};
declare global {
+ //unplugin-auto-import的Element是在页面加载到的时候才生成类型,这里全局声明一下
+ const ElLoading: typeof import('element-plus/es')['ElLoading'];
+ const ElMessage: typeof import('element-plus/es')['ElMessage'];
+ const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'];
+ const ElNotification: typeof import('element-plus/es')['ElNotification'];
// svg-icon /el-cion-*组件定义
type Icon = DefineComponent<{
size: (StringConstructor | NumberConstructor)[];
@@ -24,7 +29,7 @@ declare global {
>]: InstanceType['$props'][K];
};
- type ELTable = InstanceType & {
+ type ELTableInstance = InstanceType & {
getSelectionIndexs: () => number[]; //获取选中行的索引
};
}
diff --git a/vite.config.ts b/vite.config.ts
index e78364b9..aebee153 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -4,7 +4,7 @@ import { resolve } from 'path';
import * as fs from 'fs';
import { autoImport, resolver } from 'vite-plugin-autogeneration-import-file';
import vueSetUpExtend from './plugin/vueSetupExtend';
-import { viteMockServe } from 'vite-plugin-mock';
+import { viteMockServe } from '@meadmin-cn/vite-plugin-mock';
import { ConfigEnv, UserConfigExport } from 'vite';
import { visualizer } from 'rollup-plugin-visualizer'; //打包大小分析(stats.html)
import AutoImport from 'unplugin-auto-import/vite';
@@ -89,7 +89,7 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
toFile: 'types/meIconComments.d.ts',
name: 'MeIcon_{{name}}',
template: fs.readFileSync('./template/meIconComments.d.ts', 'utf-8'),
- codeTemplates: [{ key: '//code', template: '{{name}}: Icon;\n ' }],
+ codeTemplates: [{ key: '//code', template: '{{name}}: Icon;\n ' }],
},
{
// pinia module
@@ -123,6 +123,10 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
key: '//code',
template: '{{name}}: typeof import("{{path}}")["default"];\n ',
},
+ {
+ key: '//typeCode',
+ template: 'type {{name}}Instance = InstanceType;\n ',
+ },
],
name: '_{{name}}',
},
@@ -184,5 +188,15 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
},
},
},
+ optimizeDeps: {
+ //因为项目中很多用到了自动引入和动态加载,所以vite首次扫描依赖项会扫描不全,这里强制扫描全局。
+ entries: ['./src/**/*.{ts,tsx,vue}'],
+ include: [
+ 'element-plus/es/components/loading/style/css',
+ 'element-plus/es/components/message/style/css',
+ 'element-plus/es/components/message-box/style/css',
+ 'element-plus/es/components/notification/style/css',
+ ],
+ },
};
};