Compare commits

..

541 Commits

Author SHA1 Message Date
sanmen359
de231901a6 main代码合并到electron-main (#1834)
* upgrade electron version:11->18.

upgrade electron version:11->18.
Packaging failed because the original electronic version was too old.
将electron 11 改成18.因为11太老导致打包错误。

* main->electron-main合并代码

* main->electron-main合并代码

* main->electron-main合并代码
2022-04-21 13:34:29 +08:00
vben
006d93229c chore: delete workflows 2021-09-14 00:17:19 +08:00
vben
563f2b470e chore: merge branch 'main' of github.com:anncwb/vue-vben-admin into main 2021-09-14 00:13:51 +08:00
vben
2aa5e5da76 chore: release 2.7.2 2021-09-14 00:05:45 +08:00
vben
44b21bfc6c chore: update deps 2021-09-14 00:03:34 +08:00
vben
2820d5a627 fix: improve type introduction, fix #1196 2021-09-13 23:46:31 +08:00
无木
9640484895 fix: fixed token clear error
修复将token设置为undefined时可能失败的问题
2021-09-13 19:04:02 +08:00
无木
f87b0f2f5e fix(api-select): fixed value prop define
修复ApiSelect的value属性定义问题

fixed: #1175
2021-09-11 22:52:52 +08:00
无木
656ee4e5c9 fix(upload): accept not work as expected
修复basicUpload的accept属性未按预期工作的问题
2021-09-11 21:47:04 +08:00
无木
7593ef6a4f fix(table-action): divider not work as expected
修复tableAction中的divider未按预期工作
2021-09-11 20:26:27 +08:00
无木
b3307fe283 fix: warning in logout action
修复退出登录相关代码中的警告
2021-09-11 11:08:34 +08:00
无木
73dc492b2a feat(markdown-viewer): add new component
新增MarkdownViewer组件用于显示Markdown格式的富文本

close: #1181
2021-09-10 11:24:53 +08:00
无木
0bb9c035f7 fix(markdown): value not worked on init
修复Markdown组件的value属性初始值不起作用的问题
2021-09-10 11:22:40 +08:00
Francis Zuo
9e9ea3f43d fix: 修复弹窗全屏按钮异常关闭的问题(#1177) (#1182) 2021-09-09 22:59:53 +08:00
vben
996f2f3c22 chore: update deps 2021-09-09 22:59:10 +08:00
vben
b90a9557a3 chore: update deps 2021-09-09 22:58:29 +08:00
love-life
7df9b51344 fix: 修改axios 中 urlPrefix 字段不生效问题 (#1170)
* fix(样式污染): 会污染其他带有srcollbar的组件样式

* fix(axios): urlPrefix 字段传递不生问题效
2021-09-09 09:41:34 +08:00
handsomeFu
c753d945e0 fix: 修复 apiSelect 绑定值 attrs 的问题 (#1172)
* chore(permission): fix func name typo

* fix(apiSelect): fix `v-bind` value  `attrs` to `$attrs`
2021-09-09 09:40:53 +08:00
无木
83c1683bfd feat(demo): add JsonPreview demo
添加JsonPreview组件的使用演示

close: #1146
2021-09-06 20:36:19 +08:00
无木
044e2e4e86 fix(table): rowClassName not worked with striped
修复rowClassName属性无法和striped同时生效的问题

fixed: #1167
2021-09-06 20:13:13 +08:00
frezs
59a9087728 feat(table): 添加和支持动态删除和插入数据 (#1152) 2021-09-06 09:14:12 +08:00
Lan
3b6b4f7303 perf(tree): 优化Tree搜索功能,添加搜索高亮功能,优化样式表现 (#1153)
1. 修复expandOnSearch与checkOnSearch功能
2. 添加selectOnSearch功能
3. 添加搜索高亮title功能
4. 优化TreeHeader的样式表现: searchInput自动扩充
2021-09-06 09:13:53 +08:00
songweionline
5fa730c49a fix(table): Solve the bug of setting ifshow to false in table column (#1166)
表格列设置ifshow为false,表格的列设置里依然会渲染该列的checkBox,实际应该不渲染。如果需要隐藏应该是设置defaultHidden。
2021-09-06 09:13:35 +08:00
vben
6cadcf087d chore: update deps 2021-09-05 18:11:59 +08:00
江麻妞
95aca2ab8d fix (modal): 修复对话框 hook 不设置 loaded问题 (#1143)
fix (modal):  修复对话框 hook 不设置 loaded问题
2021-08-30 09:05:15 +08:00
Lan
e00578c40a feat(tree): 1. 添加自定义数据过滤判断方法 2. 添加搜索完成自动展开结果选项 3. 添加搜索完成自动选中结果选项 4. 树节点数据变化时强制搜索(同步searchData避免展示错误) (#1132) 2021-08-30 09:04:59 +08:00
Lan
6717fe654e fix: Improve content height calculation (#1136)
* feat(useContentHeight): 为useContentHeight 添加 向上递归 移除差值 的功能。

* feat(useContentHeight): 为useContentHeight 添加 向上递归 移除差值 的功能。 pagewrapper添加 upwardSpace以支持向上递归功能。
2021-08-30 09:04:32 +08:00
无木
ee7c31db44 feat(table): add onValid for editRow
为table的可编辑行添加校验方法
2021-08-27 22:23:39 +08:00
无木
a36825a6d4 fix: add loss action for userStore 2021-08-27 11:24:36 +08:00
无木
628e820684 fix(card-list): fixed build error
修复CardList组件造成的build错误
2021-08-27 08:55:38 +08:00
JinMao
0f5ddbf1ec feat: add CardList component 2021-08-27 05:51:58 +08:00
无木
1ddfc31c3c fix: getUserinfo is compatible with empty roles data
修复getUserinfo接口数据未携带roles字段时登录失败的问题
2021-08-26 21:20:26 +08:00
无木
d27633fb31 fix: fixed build warning for style of intro.js
修复intro.js的样式文件造成的build警告

fixed: #1130
2021-08-26 20:50:25 +08:00
江麻妞
30fa4cfa2a fix(table): 修复表格背景颜色再深色模式下会被穿透问题 (#1133) 2021-08-26 20:01:25 +08:00
love-life
6e7f6f82ed fix(modal): avoid style pollution to the whole world (#1128) 2021-08-26 20:01:05 +08:00
vben
466d4edcd0 perf: optimize css volume 2021-08-25 23:04:15 +08:00
vben
0b0a7ceef9 Revert "Revert "feat: support setup name""
This reverts commit 99daecdb60.
2021-08-25 22:57:00 +08:00
vben
99daecdb60 Revert "feat: support setup name"
This reverts commit d8362f084f.
2021-08-25 22:44:56 +08:00
vben
c8017b1365 fix(markdown): the hierarchy of markDown components after full screen 2021-08-25 22:42:39 +08:00
vben
d8362f084f feat: support setup name 2021-08-25 22:39:28 +08:00
无木
9f6822991c fix: name of vite mode support more characters
修复vite模式名称不支持下划线的问题

fixed: #1115
2021-08-24 22:54:31 +08:00
vben
56a966cfbf chore: format code 2021-08-24 22:41:48 +08:00
vben
2884e863ce perf: not waiting for router.isReady 2021-08-24 22:32:43 +08:00
无木
1235978ab2 fix: useRedo called duplicate may cause exception
修复useRedo的不当调用可能导致异常的问题

fixed: #1121
2021-08-24 21:01:28 +08:00
vben
9dd9fcd334 chore: adjust the windicss reference 2021-08-24 00:29:22 +08:00
无木
a426b9027e fix(table): fix table footer style
修复表尾合计行可能与主体部分的列没有对齐的问题

fixed: #1112
2021-08-23 16:36:26 +08:00
vben
455d109f71 chore: update deps 2021-08-22 12:22:56 +08:00
vben
6e85795737 chore: update vite-plugin-html 2021-08-21 00:13:43 +08:00
vben
d1f59b493d chore: update deps 2021-08-20 21:46:51 +08:00
无木
edc3096565 fix(table): editable icon not show with empty cell
修复可编辑单元格当内容为空时不会显示编辑图标的问题

fixed: #1103
2021-08-20 17:07:42 +08:00
无木
3a5d1a5757 fix: refresh failed while token invalid
修复当token失效时,刷新页面可能出现异常的问题

fixed: #1101
2021-08-20 16:55:42 +08:00
无木
2c867b3d63 feat(table): add beforeEditSubmit for editable cell
单元格编辑功能新增提交回调
2021-08-19 23:57:42 +08:00
无木
fb43fad555 fix(tinymce): fixed tinymce destory method
修复tinymce销毁方法可能出现异常的问题
2021-08-19 19:51:55 +08:00
无木
8e01377481 fix(tinymce): fixed inline mode
修复Tinymce的inline模式在一些场景下会出现异常的问题

fixed: #1092
2021-08-18 22:55:36 +08:00
无木
e7c96363a1 fix(code-editor): fixed formatting error
修复JSON编辑器在格式化无效JSON文本时会抛出异常的问题
2021-08-18 20:52:34 +08:00
无木
93812f734e fix(echarts): theme setting supported
修复useECharts的theme参数不起作用的问题

fixed: #1095
2021-08-18 20:05:40 +08:00
vben
e15b4f14db fix: fix all types of errors, compatible with volar plugin 2021-08-17 23:04:29 +08:00
无木
a5ff59237f feat(form): component Divider support helpMessage
Divider表单组件支持helpMessage配置
2021-08-17 22:59:36 +08:00
vben
65735926d4 chore: update deps 2021-08-17 22:15:27 +08:00
无木
47a448b8ae feat(form): add Divider for schema component type
新增Divider用于较长表单的区域分割
2021-08-17 17:50:54 +08:00
无木
5138e447e7 fix: slots worked in basicTable and basicModal
修复basicTable和basicModal的插槽传递异常的问题
2021-08-17 17:09:48 +08:00
matevip
837a365885 docs: Readme增加后台整合示例 (#1087) 2021-08-17 15:07:22 +08:00
vben
43658e2fb3 chore: release 2.7.1 2021-08-16 23:44:29 +08:00
vben
8fa6015b1a chore: change to setup syntax 2021-08-16 23:43:09 +08:00
handsomeFu
91cbe0a03b chore(permission): fix func name typo (#1082) 2021-08-16 23:15:19 +08:00
CXM
72634ffe6e fix: add axios error info from response (#1083)
* fix(type): fix ant-design-vue  ->

* fix: add axios error info from response
2021-08-16 23:14:40 +08:00
无木
c420174c1d style: fix basicButton style 2021-08-16 20:18:53 +08:00
无木
b7487675ce chore: downgrade vue-json-pretty to 1.8.1 2021-08-16 13:33:20 +08:00
无木
1b577922e7 fix: fixed basicButton primary style
修正BasicButton primary类型的样式
2021-08-16 09:12:48 +08:00
无木
3ba8a67647 fix: fixed basicButton ghost style
修正BasicButton幽灵状态的样式
2021-08-16 08:47:45 +08:00
无木
beb4ae92c1 fix: fixed basicButton style
修正BasicButton的样式
2021-08-16 07:35:47 +08:00
无木
cc46935a82 feat: always refresh userinfo when page reload
每次刷新整个页面时都从接口更新用户信息
2021-08-16 06:04:12 +08:00
无木
53e79a2d94 fix(table): fix injection not found warning
修复injection警告
2021-08-16 05:52:04 +08:00
vben
8ff5c03d53 ci: remove cache 2021-08-15 23:05:00 +08:00
vben
c69996d073 chore: use node16 2021-08-15 22:49:03 +08:00
RemMai
b07003e184 添加v-model:value双向绑定的支持 (#1073)
无需在Change事件中修改绑定的Value。
仅需在属性中设置 v-model:value,选择图标后,value值自动修改。
2021-08-15 22:37:21 +08:00
vben
45a8eb974a refactor(dashboard): change to setup syntax 2021-08-15 22:36:46 +08:00
无木
2dd3d85448 fix: fixed useRedo may loss route params
修复useRedo会丢失当前路由的params数据问题

fixed: #1079
2021-08-15 16:45:13 +08:00
无木
da12da9d8c perf(table): fixed code style
修复一些代码检查警告,并且为table的canResize属性添加不兼容场景警告

close: #1070
2021-08-15 08:54:42 +08:00
无木
30c5fc63c8 fix(demo): fix form style in modal
修复演示页面中Modal内的Form样式问题

closed: #1076
2021-08-14 23:21:05 +08:00
无木
7971896383 fix(table): size not worked in editComponentProps
修复无法设置basicTable编辑组件的size属性的问题

fixed: #1074
2021-08-14 22:31:25 +08:00
无木
a8b18c2697 style: fix selected background color of tr
修复表格选中行的背景颜色与固定列的冲突

fixed: #1069
2021-08-14 21:12:30 +08:00
无木
5ae894a5c7 style: restore default border-color
恢复antd默认的基础边框色
2021-08-14 20:53:52 +08:00
无木
bcfa338227 feat: add updatePath for useTabs
添加更新标签path的方法

close: #1068
2021-08-13 15:13:35 +08:00
无木
b1f31762e3 fix: slots working in components
修复vue新版本改动导致组件传递slots可能出现错误的问题
2021-08-13 15:06:06 +08:00
无木
93f9a19aa1 feat(form): add alwaysShowLines prop
允许设置Form折叠时始终保持显示状态的行数

close: #1051
2021-08-13 11:51:23 +08:00
无木
61d853e6a5 style(types): fix some type statement 2021-08-13 11:13:29 +08:00
无木
1f55c4180f fix(i18n): add i18n translate data
添加部分缺失的翻译文案
2021-08-13 11:11:35 +08:00
无木
4b6025cb9a fix(table): getSelectRows support multi-page
getSelectRows支持跨页选择

close: #914
2021-08-13 08:50:28 +08:00
vben
2f6d133b96 refactor(application): change to setup syntax 2021-08-13 07:29:33 +08:00
vben
9035fd191e fix(types): fix some type errors 2021-08-13 00:12:51 +08:00
vben
bb89c5059c refactor(sys): change to setup syntax 2021-08-12 23:54:12 +08:00
CXM
66feb779a8 fix: fix build handler & misc (#1060)
* fix(type): fix ant-design-vue  ->

* fix: fix build handler & misc
2021-08-12 23:23:44 +08:00
vben
948219c576 chore: update deps 2021-08-12 23:19:28 +08:00
无木
60577d6720 feat(tree): add searchable function
添加搜索功能相关属性和方法

close: #1057
2021-08-11 17:59:07 +08:00
无木
953bfc6f1a fix(modal): helpMessage doesn't work
修复`helpMessage`属性不起作用的问题
2021-08-10 23:02:59 +08:00
无木
2052eb5a65 fix(table): wrong bg-color in fullscreen mode
修复浅色主题下的table在全屏状态时背景颜色不正确的问题
2021-08-10 22:34:41 +08:00
无木
019555be0c fix(table): selection-change not triggered in unchecking
修复selection-change事件在取消勾选时未能正确触发的问题

fixed: #1053
2021-08-10 14:36:29 +08:00
无木
33a335a3f5 fix(table): 0 is not shown in editable cell
修复可编辑单元格中未能正确显示零值的问题

fixed: #1039
2021-08-09 21:49:11 +08:00
vben
9d2231b1cd chore: update deps 2021-08-08 23:05:44 +08:00
CXM
6d5388aaf1 fix(type): fix ant-design-vue -> (#1043) 2021-08-08 10:16:37 +08:00
spking11
b2d49cbbf8 fix(locales): fix that vscode extension i18n-Ally detect zh-CN as zh (#1044) 2021-08-08 10:16:19 +08:00
Leo Caan (陈栋)
1bb5156923 fix(route): the whitelist should include basicRoutes (#1048)
* fix(table): recursive updateTableDataRecord

无刷新更新表格数据时,支持递归查找,用于树状数据时。同时新增 findTableDataRecord 函数,用于支持无刷新新增数据到树状表格中

* fix(router): whitelist include basicRoutes

白名单应包含不在菜单上出现的静态路由,否则在动态切换菜单 resetRouter 时会丢失这些,如在usePermission.resume中

* fix: get basicRoutes whitelist bad code
2021-08-08 10:15:34 +08:00
Vben
62f8468775 chore: add windi.config.ts 2021-08-04 23:26:08 +08:00
Vben
8e5740e715 chore: update deps 2021-08-04 23:21:43 +08:00
JasonYHZ
f3cf162af1 feat(table): add getRawDataSource() function (#1029) 2021-08-04 08:59:21 +08:00
无木
381943078f fix(cropper): cropper not destroy in time
图片剪裁组件未能及时销毁资源

fixed: #1027
2021-08-03 21:17:38 +08:00
无木
26f251e1ed fix(qrcode): qrcode not displayed properly
fixed: #1026
2021-08-03 20:55:40 +08:00
无木
1214b7c32c fix(table): cellFormat support Map
close: #1031
2021-08-03 20:37:02 +08:00
Vben
c82040425d chore: release 2.7.0 2021-08-03 07:41:23 +08:00
Vben
5e17cc8802 refactor: refactor tailwindcss to windicss 2021-08-03 07:40:29 +08:00
Dack Wang
02e7756062 fix(): The Style of tableTitle slot (#1023)
Co-authored-by: 王英琦 <wangyingqi@91bihu.com>
2021-08-03 07:36:40 +08:00
Leo Caan (陈栋)
72f953c8d3 fix(table): recursive updateTableDataRecord (#1024)
无刷新更新表格数据时,支持递归查找,用于树状数据时。同时新增 findTableDataRecord 函数,用于支持无刷新新增数据到树状表格中
2021-08-03 07:36:15 +08:00
yanzhuang
d76cfd7f80 fix: fix iframe heigth error (#1012) 2021-08-01 08:51:52 +08:00
Lowell
2fd0fd281e fix: the position of tinymce upload image is wrong (#1015) 2021-08-01 08:51:01 +08:00
Li Li
be2d11d5d3 fix: Fix the invalid hot update of BasicButton when changing style outside (#1016)
* chore: ignore bak dir

Signed-off-by: LiLi <urfreespace@gmail.com>

* fix: 修复BasicButton在外部改变样式热更新无效问题

Signed-off-by: LiLi <urfreespace@gmail.com>

* chore: remove extra ignore

Signed-off-by: LiLi <urfreespace@gmail.com>

* chore: ignore fix

Signed-off-by: LiLi <urfreespace@gmail.com>
2021-08-01 08:50:21 +08:00
vben
88451565db chore: update deps 2021-08-01 08:46:27 +08:00
无木
26d9476caf feat(use-loading): add setTip method
为useLoading添加setTip方法
2021-07-30 16:59:52 +08:00
无木
ddd1893b11 fix(tree): fix checkAll effects disabled node 2021-07-30 15:25:13 +08:00
Wang Weitao
e8eefd1bca fix: typo for utils/env (#1004) 2021-07-29 22:43:04 +08:00
无木
8879ae8d77 fix(page-wrapper): fix class not working 2021-07-29 20:12:54 +08:00
无木
f2b8bb43a0 fix(table): fix getSelectRows for treeTable
修复getSelectRows不支持树形表格子级数据的问题

fixed: #1003
2021-07-29 18:37:19 +08:00
vben
d2c361803b chore: update .env 2021-07-29 00:09:20 +08:00
vben
e2664f6002 perf: improve legacy compatibility 2021-07-29 00:06:35 +08:00
Lowell
225bd4c39d fix: style property of actionColOpt is invalid (#997) 2021-07-28 23:09:25 +08:00
江麻妞
7e6a89ffeb fix: typo (#980) 2021-07-28 23:08:54 +08:00
周旭
189bc6feb3 feat: Added support for tailwindcss night mode mechanism (#998)
* feat: 新增支持 tailwindcss 的夜间模式支持

(cherry picked from commit 1de8704b61c38c92bc6877d0bec9e6f67766b3c8)

* docs: update changelog
2021-07-28 23:08:41 +08:00
无木
a544dd3e58 fix: auto remove script dom in useScript
修复useScript未能自动移除script节点的问题
2021-07-28 11:24:26 +08:00
无木
0065ab0b2d style(header): fix notify icon color in dark
修复暗色header中的通知图标的颜色问题
2021-07-28 11:09:53 +08:00
无木
e32789373e fix(table): fix pagination props working
修复table的pagination属性无法动态设置数据的问题
2021-07-27 17:10:06 +08:00
无木
c375e32305 fix(demo): fix roles mock data 2021-07-27 12:05:14 +08:00
无木
4c9e8564bd chore: add chinese issue template 2021-07-26 23:11:10 +08:00
无木
bdf0be81b0 type(preview): fix type definition
修复Preview组件的事件参数类型定义
2021-07-26 21:18:55 +08:00
无木
e23bd2696d feat(preview): add more features
为Preview组件添加新的属性及事件
2021-07-26 20:58:18 +08:00
vben
98749ec6fe chore: update deps 2021-07-25 09:07:53 +08:00
Lowell
98c206d9c9 fix: expandIcon slot of BasicTable component is invalid (#975) 2021-07-25 09:01:39 +08:00
江麻妞
fe4eae3714 fix(qrcode): Fix the problem that the QR code cannot be dynamically generated (#974)
* fix: Fix the problem that the QR code cannot be dynamically generated

* Fix the problem that the size of the QR code is automatically changed when dynamically generated
2021-07-25 09:01:09 +08:00
无木
14fb21d0b7 fix(table): fix expand style
修复启用expandRowByClick展开图标样式问题

fixed: #969
2021-07-24 20:09:10 +08:00
无木
dce3fb0f20 fix(table): fix tableSettings popup in fullscreen mode
修复全屏模式下的表格设置组件的弹出层配置
2021-07-24 16:11:17 +08:00
无木
a5a9b3fb34 fix(table): fix dataPicker show in fullscreen mode
修复basicTable编辑组件的校验提示以及日期选择框的弹出层在全屏模式下的显示问题
2021-07-24 14:48:09 +08:00
无木
a07ab6d7aa fix(table): component shown in fullscreen mode
修复表格在全屏模式下编辑组件弹出层的显示问题
2021-07-24 14:36:16 +08:00
无木
9b8f165a36 fix(table-action): stopButtonPropagation not working
修复TableAction组件的stopButtonPropagation属性无效的问题
2021-07-24 13:27:10 +08:00
无木
e1c47233ed fix(demo): multi-modal used with dynamic component
修复以动态组件的方式使用多个modal的演示
2021-07-23 15:55:15 +08:00
loujohn
956ed2e3f7 fix(): Fix vite profile hot update error reporting (#968)
修复vite修改配置文件热更新报错Error: Must provide a proper URL as target

Co-authored-by: lou <825681860@qq.com>
2021-07-23 11:58:02 +08:00
无木
8702965057 fix(demo): account page form validation
修复账号管理页面对不可见表单域的验证问题
2021-07-23 09:57:42 +08:00
无木
cebc6a590e fix(login): fix auto fill style in dark-theme
修复黑暗主题下的自动填充表单域样式
2021-07-23 09:33:14 +08:00
SUPER_AI
525484e7a4 fix(echarts): fix graphic config cannot be used in echarts options (#959) 2021-07-23 07:29:53 +08:00
wl19
350c85accf fix(utils): The date function gets a non-date when the parameter is null (#954)
Co-authored-by: “weilin <“784742294@qq.com>
2021-07-23 07:29:39 +08:00
无木
202aa42b8d fix(table): editable cell display with validation
修复带验证的可编辑表格的组件意外失焦的问题

fixed: #953
2021-07-23 01:18:55 +08:00
无木
8d185bb584 fix(form): remove console error for setFieldsValue
移除setFieldsValue方法输出的控制台错误

fixed: #952
2021-07-23 01:13:10 +08:00
无木
27207a78ca fix: fixed moment locale config
修复moment的英文语言配置
2021-07-23 01:02:05 +08:00
无木
d1e0e8bcea fix(dark-theme): fixed TreeSelect & DatePicker theme
修复黑暗主题下的组件样式

fixed: #955
2021-07-23 00:35:40 +08:00
M69w
d3f08e37c5 fix(style): fix checkbox-checked css in dark mode 2021-07-22 20:52:55 +08:00
vben
ee44d99c74 chore: update deps 2021-07-21 23:45:04 +08:00
Lan
9c4889f085 fix(perm-guard): Fix the problem that the routing query is lost after refreshing the page (#941) 2021-07-21 23:27:24 +08:00
无木
59cf860564 style(alert): fix alert border color
修复Alert组件的默认边框颜色不正确的问题
2021-07-21 23:19:44 +08:00
无木
662b576ac2 fix(dark-theme): style for checked tree nodes
修复黑暗主题下已勾选的Tree的复选框的样式问题
2021-07-21 22:43:47 +08:00
无木
42812162c4 fix(dark-theme): disabled link button color
修复黑暗主题下禁用状态的link类型按钮的颜色
2021-07-21 21:51:48 +08:00
无木
9b7ede09b9 fix(dark-theme): alert color in dark-theme
修复Alert组件在Dark主题下的颜色问题
2021-07-21 21:39:23 +08:00
无木
8cf004a5f5 fix(dark-theme): bgcolor of selected tree node in dark theme
修复tree的被选中节点的背景颜色在黑暗模式下不正确的问题

fixed: #949
2021-07-21 20:34:00 +08:00
无木
32d64dbe81 fix(img-rotate-drag-verify): fix resume method support
修复ImgRotateDragVerify组件的resume方法无效的问题

fixed: #946
2021-07-21 17:52:07 +08:00
无木
8b4b767f4c feat(demo): add async-validator demo
添加表单使用后端接口异步验证的例子
2021-07-21 15:44:46 +08:00
无木
341bd633d8 fix(demo): menu error-log link to 404 page
修复演示菜单的错误日志页面指向了404的问题
2021-07-21 11:20:40 +08:00
无木
571f28138f fix(form): fix validate promise catch
修复自动校验时没有捕获promise catch的错误提示
2021-07-21 11:18:10 +08:00
无木
4bb506fb1f fix(table): fix editable cell not support ellipsis
修复可编辑单元格不支持ellipsis配置的问题

fixed: #944
2021-07-21 00:43:37 +08:00
无木
c734f6858d fix(api-tree-select): auto reload while params changed
修复ApiTreeSelect组件没有正确监听params变化的问题
2021-07-20 18:01:18 +08:00
vben
596670dc88 chore: release 2.6.1 2021-07-19 23:56:14 +08:00
vben
680ad0763c chore: restore vite to version 2.3.6 2021-07-19 23:54:47 +08:00
无木
7a7dab0c4b feat(demo): multi-modal in one page usage
添加使用is动态组件来在页面内使用多个modal的演示
2021-07-19 18:40:02 +08:00
无木
59eb828d4d style: fixed line break style
修正换行符
2021-07-19 16:37:47 +08:00
无木
52af1dd0d4 feat(basic-table): add ApiTreeSelect edit component
为表格添加ApiTreeSelect编辑组件,修复一些其它的已知问题
2021-07-19 16:25:56 +08:00
无木
897bed9729 fix(api-select): fix options-change event data
修复options-change事件参数不是select所使用的标准options数据的问题
2021-07-19 16:19:51 +08:00
无木
a764a95ae9 fix(countdown-input): add slots support
为CountdownInput组件添加Input的插槽支持
2021-07-19 15:27:05 +08:00
无木
535bdddf91 fix(demo): fix display problem of editable table with apiSelect
修复ApiSelect在可编辑表格中的显示问题
2021-07-19 00:51:02 +08:00
vben
18567e13a6 chore: update deps 2021-07-19 00:14:53 +08:00
lzdjack
03b17a8f8b fix(formItem): Fix labelcol type mismatch (#903)
*修复antdv升级后formItem中labelCol没有类型style的bug
2021-07-18 23:25:51 +08:00
无木
8832a074dc fix(code-editor): value not support use as v-model
修复value不支持v-model用法的问题

fixed: #933
2021-07-17 18:01:23 +08:00
无木
61ce25be1b fix(table): value show problem in editable cell
修复可编辑单元格的值不能直接通过修改dataSource来更新显示的问题。

fixed: #922
2021-07-16 13:59:55 +08:00
无木
d9d0071401 fix(api-tree-select): fix event checked in form
修复ApiTreeSelect在BasicForm内使用时可能出现的onChange类型检查失败的警告
2021-07-16 13:17:25 +08:00
无木
f8440175f3 fix(model): auto validate on value change
修复BasicModel的表单值发生变化时未能自动校验

fixed: #920
2021-07-16 13:14:24 +08:00
无木
5baaa58581 fix(modal): fixed fullscreen not worked
修复全屏功能异常的问题

fixed: #918
2021-07-16 11:22:12 +08:00
无木
f707541dda fix(tree): fixed checkedKeys with search mode
修复搜索状态的切换导致的勾选值可能不正确的问题
2021-07-16 10:56:37 +08:00
无木
b06a7ab77b fix(basic-tree): checkedKeys not worked with search
修复搜索功能可能导致`checkedKeys`丢失的问题

fixed: #915
2021-07-15 23:17:31 +08:00
无木
1b3058f825 fix(api-tree-select): auto load data if necessary
修正ApiTreeSelect的数据加载时机
2021-07-15 18:39:54 +08:00
无木
d81db890df feat(api-tree-select): add api options to tree-select
添加ApiTreeSelect组件
2021-07-15 18:05:13 +08:00
无木
c1178027f0 fix: fix homePage affix error
修复当没有通过接口为用户指定首页时,如果默认的首页是一个带有重定向的路由,则可能出现双首页Tab的问题
2021-07-15 17:15:15 +08:00
无木
db7254a5e0 fix(table-action): fix circle button style
修复table-action组件内的圆形按钮内容没有居中的问题
2021-07-15 15:42:47 +08:00
无木
dc51e6a8d4 fix(table-action): fixed icon margin without label
修复当没有label时,icon没有在按钮内居中的问题
2021-07-15 14:36:40 +08:00
无木
4b46a84c2b fix: infinite redirect in BACK mode
修复后端权限模式下的路由无限重定向的问题
2021-07-15 01:59:23 +08:00
无木
87583c8b54 fix: ensure PAGE_NOT_FOUND_ROUTE exist
修复某些情况下404路由可能白屏的问题
2021-07-14 21:37:10 +08:00
无木
1e63379088 fix(multiple-tab): ignore login page
修复标签页可能会创建登录页面标签的问题
2021-07-14 20:44:52 +08:00
无木
237e65eac9 fix: resolving Vue Router warn
移除因为动态加载路由而产生的vue-router警告
2021-07-14 20:32:58 +08:00
无木
6350224a1b style(basic-table): remove scroller patcher
移除table滚动条样式覆盖
2021-07-14 16:37:53 +08:00
Vben
ae7821e296 fix(modal): ensure that props are passed correctly,fix #897 2021-07-13 22:46:01 +08:00
yanzhuang
a1d956d369 fix(useWatermark): fix func call createWatermark call clear to resizeEvent removed (#901) 2021-07-13 22:23:11 +08:00
无木
35e1347029 fix(markdown): set value error
修复markdown组件在完成初始化之前动态设置value可能导致异常的问题
2021-07-13 18:04:42 +08:00
无木
d95815b503 fix(markdown): resolving markdown exceptions
修复markdown组件的异常以及不能正确设置value的问题
2021-07-13 15:28:10 +08:00
无木
0a3683a186 feat: customized user home page
新增自定义的用户首页(可以每个用户都不相同)
2021-07-13 14:10:31 +08:00
无木
f5e31febbd fix(breadcrumb): redirect not worked
修复面包屑组件的重定向菜单不能工作以及eslint警告
2021-07-13 11:09:00 +08:00
周旭
6f830703a2 perf(menu): Optimize the style of the bottom collapse button in the Mix menu layout (#896) 2021-07-13 09:25:46 +08:00
shisan
bfb5ebd7b8 chore: update deps 2021-07-13 00:07:10 +08:00
无木
012020e51c style(notice-list): adjust style
去除通知列表组件标题和内容部分多余的margin-bottom,禁止自动隐藏不可用的翻页按钮
2021-07-12 22:33:28 +08:00
无木
aeebfc4d3d style(notice-list): fix margin-bottom value
去除通知列表组件标题和内容部分多余的margin-bottom
2021-07-12 22:22:33 +08:00
无木
c16be2c499 feat(notice-list): add pagination support
为通知列表组件添加分页、超长自动省略、标题点击响应、标题删除线等功能

fixed: #894
2021-07-12 22:12:16 +08:00
无木
0f28e803d0 fix(table-action): incorrect button color of disabled state
修复表格操作列的按钮在disabled状态下的颜色显示

fixed: #891
2021-07-12 16:46:27 +08:00
无木
cad021c34b fix(menu): fix mix-menu incorrect jumping in hover mode
修复悬停触发模式下左侧混合菜单会在没有子菜单且被激活时直接跳转路由
2021-07-09 19:20:05 +08:00
无木
5ceeefd17d fix(menu): display error when contains hidden items
修复顶栏菜单在包含隐藏项目时的显示问题
2021-07-09 17:25:38 +08:00
无木
a9bbed1973 fix(form): fix suffix slot style
修复suffix插槽的样式问题
2021-07-09 16:39:50 +08:00
无木
0595a72da9 fix(mix-sider): fix mix-sider hover logic
修复左侧混合菜单的悬停处理逻辑
2021-07-09 13:56:33 +08:00
无木
c7c0a7e4c8 fix(table): fix index column style
修复序号列的样式问题
2021-07-09 13:37:13 +08:00
无木
05329ce950 fix(upload): ensure the value type is correct
修复BasicUpload组件在设置null值时的问题
2021-07-09 00:22:00 +08:00
周旭
7b76945bff chore: perf TableAction.vue、build/utils.ts、prettier.config.js (#868)
* perf: 优化 build 时 vite 模式判断

* perf: 优化 TableAction, 仅在 action.tooltip 存在的情况下 才使用 Tooltip 组件

* docs: 仅在 action.tooltip 存在的情况下 才使用 Tooltip 组件

* fix: 在 window 上,拉取代码后 eslint 因 endOfLine 而保错问题

* docs: 修复在 window 上,拉取代码后 eslint 因 endOfLine 而保错问题
2021-07-08 23:20:49 +08:00
无木
540423ecf7 feat(table): add headerTop slot
为表格添加`headerTop`插槽(表格头部的标题之上),以及相关演示

close: #881
2021-07-08 20:16:22 +08:00
无木
9cf070dd63 feat(api-select): clear options before fetch
ApiSelect组件在发起新的请求之前先清空已有的options
2021-07-08 02:50:33 +08:00
无木
41e6d94b3b feat(demo): add search demo for apiSelect
添加ApiSelect的本地搜索和远程搜索例子
2021-07-08 02:46:15 +08:00
Vben
17e47e074e chore: add a multi-environment configuration example 2021-07-07 23:47:47 +08:00
Vben
dafcdd898c fix: ensure that safari is running properly, fix #875 2021-07-07 23:40:29 +08:00
Vben
5bce6528ba chore: update deps 2021-07-07 22:59:35 +08:00
无木
1e61da644f fix(table): fix tree node align
修复树形表格的带有展开图标的单元格的内容对齐问题

fixed: #829
2021-07-07 22:38:00 +08:00
无木
9228282ae2 fix(demo): form pages support keepAlive
修复表单演示页面不支持keepAlive的问题
2021-07-07 21:33:08 +08:00
无木
45a94e41c1 fix(demo): resolve key not exist warnings
修复角色编辑页面可能会出现tree组件报key not exist警告的问题
2021-07-07 21:26:20 +08:00
无木
542121129e feat(demo): add basicTree with async data expand all
演示basicTree使用异步数据并自动展开
2021-07-06 17:10:19 +08:00
Vben
cf840e3e73 perf: image compression configuration optimization 2021-07-06 00:30:16 +08:00
MARVIN
82eb72bbce fix(CountTo): Fix displaying empty string when the value is 0 (#864) 2021-07-05 22:45:13 +08:00
无木
5f1a6cdc59 feat(demo): demo default expanded tree table
演示默认展开树形表格数据
2021-07-05 16:23:58 +08:00
无木
02d3dca57e fix(app-search): exclude items by hideChildrenInMenu
修复菜单搜索组件可能会显示被隐藏的子菜单的问题
2021-07-05 14:50:41 +08:00
无木
faf5c9fd7e fix(app-search): exclude hidden items
修复菜单搜索组件可能会显示被隐藏的菜单的问题
2021-07-05 14:34:49 +08:00
无木
d5d5c4b4bf fix(demo): setup page route config
修复引导页的相关路由配置
2021-07-05 12:18:05 +08:00
无木
993e19dcc3 fix(demo): add mock data account detail route
添加mock数据中缺失的账号详情路由

fixed: #858
2021-07-05 12:04:36 +08:00
无木
808291b503 fix: menuSetting can not set collapsed to false as default
修复无法通过将菜单配置为默认折叠的问题.
2021-07-05 11:07:27 +08:00
无木
d8c38207c0 fix(table): scrollbar style 2021-07-05 00:34:23 +08:00
vben
f4778431de chore: release 2.6.0 2021-07-04 22:12:26 +08:00
vben
acacb32bb5 fix(tailwindcss): remove console warnings 2021-07-04 22:09:25 +08:00
zhangfugui
186b274faa refactor: tree component empty state display (#853) 2021-07-04 21:08:15 +08:00
无木
f1c0e0c52b types: fix CropperAvatar props define 2021-07-04 09:29:57 +08:00
无木
735028c430 fix(table): auto hide unnecessary scrollbar
隐藏无需显示的滚动条时
2021-07-04 02:41:55 +08:00
无木
c8c7615569 docs: update CHANGELOG.zh_CN 2021-07-04 00:10:14 +08:00
无木
c3b907656a feat(modal): add tooltip for action buttons
为最大化、全屏、还原等操作按钮添加工具提示
2021-07-03 23:25:01 +08:00
无木
b96ea0753b feat(avatar-cropper): more props added
为头像剪裁组件添加value属性、onChange事件以及用于自定义上传按钮的属性;更新个人设置页的头像设置
2021-07-03 23:12:54 +08:00
无木
6cbac4b7ec feat(avatar-cropper): add action tooltip
为头像剪裁组件的操作按钮添加工具提示
2021-07-03 20:14:58 +08:00
vben
81cf441373 chore: npm script adjustment 2021-07-03 17:22:51 +08:00
Lan
48fcd7684c feat(param-menu): feature: menu with params (#845) 2021-07-03 17:13:59 +08:00
无木
791b323dbd fix(table): param of handleSearchInfoFn
修复`handleSearchInfoFn`的参数会有多余的空白键
2021-07-03 14:32:38 +08:00
无木
49f39de7b4 feat(axios): use defHttp like axios
当非GET请求并且同时存在data和params,不再忽略data。使defHttp的用法习惯接近axios原生配置

fixed: #850
2021-07-03 14:01:18 +08:00
无木
8819af083c types(action-item): set label optional 2021-07-02 15:45:22 +08:00
无木
73654b7862 fix(popconfirm-button): remove button excess title
移除PopconfirmButton组件多余的title;修改TableAction的tooltip默认位置
2021-07-02 12:17:07 +08:00
无木
5fab267a69 feat(table-action): support tooltip option
为tableAction组件中的操作按钮增加tooltip配置

close: #848
2021-07-02 11:55:13 +08:00
无木
5637588fce fix(demo): fix async tree demo, fixed: #823 2021-07-02 02:27:33 +08:00
无木
5a20df45ad feat(tree): add insertNodesByKey method 2021-07-02 02:26:13 +08:00
无木
d52b0de83e feat(route): add hidePathForChildren in meta
添加`hidePathForChildren`选项用于在子菜单中隐藏本级path
2021-07-02 00:30:48 +08:00
无木
72ac240f28 feat: routers support ignoreRoute option
为路由配置添加`meta`.`ignoreRoute`配置,允许在`ROUTE_MAPPING`及`BACK`模式下配置纯菜单数据

fixed:
2021-07-01 23:54:10 +08:00
无木
b5046f07a2 fix(form): fix some prop declaration
修复`submitButtonOptions`、'resetButtonOptions'的类型定义
2021-07-01 14:42:29 +08:00
无木
ddf116da14 style(demo): replace account page detail icon 2021-07-01 11:36:45 +08:00
无木
5005e6e56b fix(sider): custom trigger does not take effect
修复侧边菜单底部的自定义折叠按钮不起作用的问题
2021-07-01 10:45:59 +08:00
Eric
3871204d08 fix: routes filter can't effective when permission mode set to ROUTE_MAPPING (#836) 2021-06-30 22:27:26 +08:00
无木
b4a3f936cd fix(table): global configuration accidentally modified
修复table的全局配置可能被意外修改的问题
2021-06-30 18:40:33 +08:00
无木
16c5d327f1 feat(basic-upload): value support v-model 2021-06-30 17:02:50 +08:00
无木
76a5f87c0c fix: hasPermission not work in ROLE Mode 2021-06-30 16:52:13 +08:00
无木
49e72a8e76 feat(basic-upload): add preview-delete event
添加预览Modal中删除文件的事件

close: #835
2021-06-30 16:35:00 +08:00
无木
6f845b53bd fix(table): selection-change not triggered on row click
修复selection-change事件在点击行来改变勾选时不会被触发的问题
2021-06-30 15:43:32 +08:00
无木
d509e897be fix(axios): option withToken not work 2021-06-30 01:07:27 +08:00
无木
424b171e0d fix(demo): account list fetch loss param
修复账号管理列表发起请求时可能缺少当前选中的部门ID参数的问题

fixed: #830
2021-06-30 00:50:49 +08:00
Lan
9de6ac1119 refactor(contentHeight): 重构,将PageWrapper的useContentHeight抽象为公共hook,满足自定义扩展组件时的自动高度计算需求。 同时优化高度计算算法。 (#826) 2021-06-30 00:50:19 +08:00
周旭
95c16a5d26 fix: support various vite modes of build, not just production (#832)
(cherry picked from commit bcc4773fbfc3dd1b7a24655bc731be830ad6d72d)
2021-06-30 00:49:19 +08:00
Vben
cdb10cc4ac fix(menu): make sure the menu is activated correctly 2021-06-30 00:47:59 +08:00
SUPER_AI
749ba5c1da feat(table): support asynchrony in beforeFetch and afterFetch (#827) 2021-06-29 23:53:10 +08:00
无木
d38ff6670a fix(lock-screen): ensure lock info is saved
确保打开多个窗口锁屏时,其它窗口不会误覆盖锁屏状态
2021-06-29 20:23:47 +08:00
无木
e5f37885ff fix: multi windows token sharing
修复同时打开多个窗口时令牌没能同步共享的问题

fixed: #761
2021-06-29 19:41:06 +08:00
无木
d7b84c7874 fix(lock-screen): fix lock-screen can skip on new window
修复锁屏功能可以通过刷新页面或复制 URL 打开新的浏览器标签来跳过锁定状态的问题
2021-06-29 18:34:51 +08:00
无木
c99cf5e53f feat(axios): add withToken option
添加withToken配置,用于控制request是否提交token
2021-06-29 17:31:30 +08:00
无木
df0f00085c fix(table): fix rowSelection.onChange not work
修复为table提供rowSelection.onChange时,无法手动变更table的选中项的问题

fixed: #825
2021-06-29 16:39:47 +08:00
无木
99829c79ab fix(svg-icon): fix SvgIcon style 2021-06-29 15:16:21 +08:00
Vben
bdae33e34a chore: revert scrollbar 2021-06-28 23:40:03 +08:00
Vben
e9e51b2fdc perf(scrollbar): scrollbar update when slot changed 2021-06-28 22:45:40 +08:00
无木
1bde404121 fix(sider): bottom trigger not work
修复侧边栏底部的折叠按钮不工作的问题

fixed: #820
2021-06-28 21:16:04 +08:00
无木
c7de65ebba fix(modal): setModalProps support defaultFullscreen
修复setModalProps不支持设置defaultFullscreen的问题
2021-06-28 18:10:26 +08:00
无木
829b366cb2 fix(table): editComponentProps support onChange
修复editComponentProps不支持onChange的问题
2021-06-28 16:27:53 +08:00
无木
3dbbde2662 fix(modal): remove console log 2021-06-28 11:12:52 +08:00
无木
f750ff435f fix(modal): maskClosable not work
修复BasicModal点击遮罩不能关闭的问题
2021-06-28 11:10:58 +08:00
vben
f9cda2e8c0 chore: release 2.5.2 2021-06-28 00:22:34 +08:00
vben
913c22c84f feat(menu): the route is automatically mapped to the menu 2021-06-27 23:58:14 +08:00
vben
327d71b8fb perf(router): reduce the number of guard files 2021-06-27 22:59:59 +08:00
无木
941ad59759 fix(drawer): openDrawer is not normal in some cases
修复BasicDrawer在设置其它属性时可能会影响visible状态的问题
2021-06-27 19:13:57 +08:00
无木
d0b6c496d6 style: remove tailwind lightBlue renamed warning 2021-06-27 16:38:40 +08:00
无木
20d7a25eb8 fix: user drop-down event key loss
修复顶部的用户操作下拉菜单点击事件丢失key参数的问题
2021-06-27 15:33:30 +08:00
vben
59d3e8c80f perf(icon): remove Icon component global registration 2021-06-27 13:56:09 +08:00
无木
c73694ab8b fix: user dropdown event response failure
修正顶部用户下拉菜单不响应点击事件的问题
2021-06-27 02:32:18 +08:00
vben
81a0f478af chore: release 2.5.1 2021-06-27 00:04:01 +08:00
bbkkkk8
d97aa92741 fix(comp-tree): support comp-tree-foreach stop,add insertNodesByKey (#818)
Co-authored-by: git <lixiaokang215@163.com>
2021-06-27 00:01:38 +08:00
vben
480cfb914e fix: fix antdv console warning 2021-06-26 23:56:57 +08:00
无木
0e414ba3c1 feat(demo): add route multi tabs show
添加同一路由演示多个不同参数的tab

close: #817
2021-06-26 21:25:11 +08:00
无木
61d4efd55a revert(axios): remove baseUrl config
无需 baseUrl 配置,已有apiUrl 替代
2021-06-26 12:14:06 +08:00
JinMao
d5f9919b60 fix: fix defHttp baseUrl work 2021-06-26 04:47:17 +08:00
Vben
aed622bd09 chore: update deps 2021-06-26 00:31:21 +08:00
无木
e78af6f228 fix(table): getDataSource not worked on empty data
修复getDataSource获取的数据源在表格为空时返回值错误的问题。

fixed: #752
2021-06-25 15:08:43 +08:00
无木
4ae39c53b4 fix(table): treeTable editable error
修复树表格的编辑问题

fixed: #811
2021-06-25 14:51:58 +08:00
Vben
fa64fc8a62 fix(api-select): ensure that the onchange function parameters are correct 2021-06-24 23:51:14 +08:00
Vben
a2a75a097f fix(demo-form): add fieldMapToTime example,fix #807 2021-06-24 23:17:56 +08:00
Vben
a2d8be3ab2 fix(demo): style error,fix #806 2021-06-24 23:10:43 +08:00
Vben
aec230ca19 fix(design): correct tailwind configuration,fix #800 2021-06-24 22:57:36 +08:00
无木
a6ef771fcc fix(pop-confirm): fix event working unexpected 2021-06-24 18:55:38 +08:00
Lan
4d8e39857e perf(pagewrapper): 优化PageWrapper的高度自适应表现使用getViewportOffset替代useContentViewHeight (#792)
Co-authored-by: NorthLan <lan6995@gmail.com>
2021-06-23 23:16:47 +08:00
Vben
c4b22a225d fix(upload): make sure to carry custom parameters, fix #802 2021-06-23 22:37:30 +08:00
无木
60b80c96e8 fix(dropdown): icon and trigger work unexpected
修复Dropdown中popconfirm的事件响应区域以及icon不正常的问题

fix: #796,#787
2021-06-23 21:56:43 +08:00
JinMao
9298b3c988 feat: add Tree LoadData demo 2021-06-23 15:53:31 +08:00
无木
8d22231a5f fix(table): event editCancel loss params
修复table的editCancel事件缺少部分参数的问题
2021-06-23 00:27:11 +08:00
vben
8eba7fb527 fix(table): fix table jitter problem 2021-06-22 22:46:03 +08:00
Vben
99cabf048d chore: merge main 2021-06-20 21:50:38 +08:00
Vben
c1525252e8 chore: release 2.5.0 2021-06-20 21:39:59 +08:00
Vben
893f3c79e7 refactor(css): refactored windicss to tailwindcss 2021-06-20 21:36:52 +08:00
vben
e8d6f8851e fix(store): fix type error after pinia version upgrade 2021-06-19 23:17:44 +08:00
Vben
7dce50cb1f chore: typo 2021-06-19 22:38:29 +08:00
Vben
d3d620f4fc perf(utils): mitt default export is changed from Class to Function 2021-06-19 22:38:29 +08:00
无木
ea6834aeec feat: optimize error message for api failure
优化request并发请求失败时的错误提示(同种类型的失败只提示一个message)
2021-06-18 17:14:31 +08:00
Vben
4c89ea7474 fix(menu): fix the jitter problem of menu folding animation,fix #732 2021-06-18 00:39:33 +08:00
Vben
0d0708409c feat(project-setting): added sessionTimeoutProcessing project configuration item,fix #772 2021-06-17 23:39:55 +08:00
Vben
b6d5b0796d feat(axios): added authenticationScheme configuration,fix #774 2021-06-17 23:25:31 +08:00
Vben
f6fe1dd62d feat(test): add jest test suite 2021-06-17 23:00:12 +08:00
无木
154ebc3d96 fix(use-message): content not support vNode
修复封装的`useMessage`部分函数中`content`不支持vNode类型以及`createConfirm`不支持html的问题
2021-06-17 22:38:22 +08:00
Vben
0acc4ab2dd perf(locale): reduce the number of multilingual files 2021-06-17 21:43:53 +08:00
Vben
d196340d27 feat(demo): added guide page example 2021-06-17 21:43:53 +08:00
Vben
4f20d45f9d chore: type optimization 2021-06-17 21:43:53 +08:00
Vben
e9064631c7 chore: update deps 2021-06-17 21:43:52 +08:00
无木
513823bfbd fix(form): loss args on component change event
修复部分组件的change事件不止一个参数时,componentProps中配置的onChange只能接收到第一个参数的问题
2021-06-17 17:34:11 +08:00
JinMao
d683b0f1e8 fix: fix Login Page LocalePicker showLocale condition 2021-06-17 12:41:18 +08:00
JinMao
21c771b59c fix: fix if getDropdownList.length==0 show Dropdown component 2021-06-17 12:40:10 +08:00
xlaoyu
49b66e83ac refactor(axios): control the display of common errors in the request cycle (#758)
Co-authored-by: frankylli <frankylli@tencent.com>
2021-06-16 22:34:32 +08:00
Lan
ab2c7efe69 perf(PageWrapper): fix the height calculation problem when footer and global footer are opened at the same time (#760)
* perf(PageWrapper): 优化PageWrapper在page的footer与全局页脚同时开启时的高度计算表现。

* docs(PageWrapper): 修复footer与全局页脚同时开启时的高度计算问题

Co-authored-by: NorthLan <lan6995@gmail.com>
2021-06-16 22:23:39 +08:00
Vben
655b743236 fix(modal): ensure that the shutdown event is not triggered multiple times 2021-06-14 23:15:30 +08:00
M69W
a03d3cc60c fix(ApiSelect demo): add demo about ApiSelect's use (#757)
* fix(ApiSelect demo): add demo about ApiSelect's use

* fix(ApiSelect demo): typo

* revert(ApiSelect): remove console

Co-authored-by: M69W <M69W@M69W>
2021-06-14 22:10:41 +08:00
bOtalkin
bbce002be1 fix(layout): props warn (#756) 2021-06-14 22:06:20 +08:00
Vben
29b2d344ae chore: typo 2021-06-11 23:35:30 +08:00
Vben
305630e3fd feat(preview): added createImgPreview picture preview function 2021-06-11 23:26:30 +08:00
Vben
3f6920f7a9 perf(component): optimize tree and upload components 2021-06-11 23:19:03 +08:00
Vben
fa828fd972 fix(flow-chart): fix drag and drop menu loss 2021-06-11 23:09:03 +08:00
Vben
bd2039accb refactor: remove useExpose 2021-06-11 22:45:02 +08:00
Vben
3b2c40bec8 refactor(virtual-scroll): refactor virtualScroll component 2021-06-11 22:39:02 +08:00
Vben
1c1755cf5b fix(modal): ensure that the full screen height is calculated correctly 2021-06-11 22:29:02 +08:00
Vben
639520ad5d feat(use-drawer): add closeDrawer function 2021-06-11 22:19:02 +08:00
Vben
c7c95dd2af chore: type Descrition,Drawer,Excel,Dropdown 2021-06-11 22:09:02 +08:00
Vben
6dbbdbac76 perf(cropper-avatar): code optimization 2021-06-11 21:49:02 +08:00
jinmao88
b7c7c46853 perf: add createImgPreview func (#713) 2021-06-11 16:08:39 +08:00
Lan
33cd8fe653 fix(useViewHeight): Fix the problem that useContentViewHeight does not calculate the footer (#747)
Co-authored-by: NorthLan <lan6995@gmail.com>
2021-06-11 09:37:17 +08:00
无木
c6b766d8ea fix(route): dynamically introduce components error
修复后台权限模式下,加载IFrame类型的路由时会丢失component的问题
2021-06-11 00:29:39 +08:00
Vben
a222ec8553 fix(mock): make sure ignore matches the file correctly, fix #745 2021-06-10 22:16:15 +08:00
Vben
8e410fc640 feat: add CropperAvatar component 2021-06-10 21:46:46 +08:00
无木
de12babd31 fix(modal): add v-model support for visible 2021-06-10 19:48:43 +08:00
无木
b387681c00 fix(api): select api type error 2021-06-10 15:43:28 +08:00
Vben
2c5351f9f4 chore: release 2.4.2 2021-06-10 00:36:54 +08:00
Vben
40008bc235 refactor: refactor CountTo component 2021-06-10 00:32:15 +08:00
Vben
00fca0fe6c chore: prettier code 2021-06-09 22:36:30 +08:00
Vben
34a80542de fix: fix darkModeSwitch switch failure 2021-06-09 22:36:30 +08:00
无木
c5f2577f51 fix(api-select): loss option data on event callback
close #733
2021-06-09 18:31:01 +08:00
无木
7c1ffa3d23 fix(mock): type error 2021-06-09 12:13:13 +08:00
Vben
7b9cd09ad8 fix(demo): make sure the map https resource is correct 2021-06-09 00:25:45 +08:00
Vben
55e9d9fc29 perf: optimize components and add comments 2021-06-09 00:22:29 +08:00
无木
84d9300e52 fix(demo): breadcrumb route invalid redirect 2021-06-08 16:45:42 +08:00
无木
df8cd86051 fix(router): loss directory route
修复"目录"路由丢失的问题

fix: #722
2021-06-08 15:14:05 +08:00
无木
448a4c2809 feat(table): updateTableDataRecord support functional rowKey 2021-06-08 15:14:05 +08:00
Leo Caan (陈栋)
f62f378f42 chore: add util for install component (#707) 2021-06-08 14:28:19 +08:00
无木
6d5f9aa699 feat(modal): add closeModal for useModal 2021-06-08 10:55:33 +08:00
Vben
941f0cc96c feat: support electron 2021-06-08 02:18:02 +08:00
vben
8dfa1778e8 wip: support electron 2021-06-08 01:26:18 +08:00
无木
21f7a854fe fix(demo): account list page validate and save 2021-06-08 01:13:22 +08:00
无木
8e4f486fcf feat(table): add updateTableDataRecord method
添加updateTableDataRecord以便可以根据指定的rowKey来直接更新行数据而无需reload
2021-06-08 01:08:04 +08:00
vben
5212ea79b4 fix: build error 2021-06-08 00:15:34 +08:00
Vben
9a2577465e chore: merge main 2021-06-07 22:38:40 +08:00
Gavin Chain
d4c4215b08 wip: support electron 2021-06-07 22:33:38 +08:00
Vben
cda0f9c10a chore: add some notes 2021-06-07 21:30:27 +08:00
liuzhidong
efce482b32 feat(Tinymce): add dynamics to the read-only state of the rich text editor (#725)
*富文本目前只支持初始化配置,本次增加了只读状态动态设置,只需更改readonly的值
2021-06-07 21:28:26 +08:00
无木
bcad95d32a fix(form): fix form update problem
修复表单组件在特定情况下的卡顿、崩溃问题
fix: #720
2021-06-07 14:52:03 +08:00
无木
125a7d1483 feat(table): support columns-change event
添加列改变事件(含排序、可见性、固定列)。该事件仅由表格设置组件中人为触发。
2021-06-07 12:37:21 +08:00
liuzhidong
966571bdcb fix(Tinymce): Read only status upload button can also be used (#718)
*修复富文本组件在只读状态下上传图片按钮也能点击的bug
2021-06-07 12:23:34 +08:00
无木
aee613034f refactor(mock): remove third-party images 2021-06-07 01:14:07 +08:00
Vben
d677729acb perf(i18n): improve circular dependencies 2021-06-06 23:36:22 +08:00
Vben
d81481c521 fix(table): try to get close to the form stuck 2021-06-06 22:54:25 +08:00
无木
19d8e01e11 feat(table-img): support simple show mode and more props
改进TableImg组件,支持简单显示模式以及更多可配置的属性。
2021-06-06 16:27:19 +08:00
Vben
50f94bfee4 chore(axios): remove useless code 2021-06-06 15:12:15 +08:00
无木
ee384b1fa7 fix(radio-button): fix RadioButton disabled support
fix #710
2021-06-06 13:24:32 +08:00
无木
4fd2051bc0 fix(table): settings indeterminate state effect
修复存在操作列的情况下,表格设置组件中的半选状态显示不正确的问题
2021-06-06 12:03:53 +08:00
Vben
a96cb2509c refactor(test-server): improve test service code 2021-06-05 22:29:56 +08:00
无木
8b6e07b768 fix(demo): fix basic form page style
修复表单基础示例页面,远程下拉的弹出层有时显示不完整的问题。
2021-06-05 22:17:17 +08:00
无木
50207ad702 feat(api-select): auto refetch after params changed
ApiSelect 组件在params改变后自动重新获取远程数据
2021-06-05 22:15:51 +08:00
无木
4805ca2626 chore: vite server options adjustment 2021-06-05 20:14:55 +08:00
无木
437692869a fix(upload): ensure preview items valid 2021-06-05 18:10:58 +08:00
无木
495b1da385 fix(table): wrong indeterminate state
修复table在包含默认不显示的列时,settings的[列展示]复选框的初始indeterminate状态不正确的问题
2021-06-05 16:22:26 +08:00
无木
fe2bcfc6f7 feat(table): support custom update on row editing
在表格进入行编辑状态时,在某一列数据发生修改时,允许获取或同步修改其它列的当前编辑数据。

close #646
2021-06-05 14:11:00 +08:00
无木
808012b544 feat(table-action): add stopButtonPropagation prop
为TableAction组件添加stopButtonPropagation来配置是否要阻止操作列的按钮的点击事件冒泡。

close #699
2021-06-05 12:58:07 +08:00
无木
40e3cb043c fix(lock): fix lock modal height
fixed #701
2021-06-05 12:25:39 +08:00
无木
6c4f947386 fix(page): basic form action btns should be in line
修正基础表单页面的提交和重置按钮没有处于一行的问题
2021-06-04 19:22:30 +08:00
无木
fb6c76db53 feat(echarts): add getInstance for useECharts
为useECharts添加getInstance以便绑定事件或执行更多自定义动作
2021-06-04 17:22:06 +08:00
无木
46899aa3cd feat(demo): switch use in table
演示在table中渲染switch列并响应修改switch的动作
2021-06-04 16:11:18 +08:00
无木
41854121f3 fix(mock): menu list api loss type field 2021-06-04 16:08:41 +08:00
无木
b69dcd79d7 fix(axios): transformRequestHook logic error 2021-06-04 14:18:22 +08:00
Vben
4da3d2c534 chore: vscode configuration adjustment 2021-06-03 23:45:01 +08:00
无木
d62d0ca08c fix(keep-alive): tablist cache updating effect
修复 updateCacheTab 逻辑问题造成的KeepAlive配置可能失效的问题

close: #695
2021-06-03 16:28:48 +08:00
无木
808328dc7e fix(form): schemas update problem
修复某些情况下重设schemas数据不会生效的问题

fixed #688
2021-06-03 10:54:58 +08:00
无木
5d554f184f fix(modal): redoModalHeight not work as expected
修复redoModalHeight根据内容重设高度时,只会增大而不能减少Modal高度的问题
2021-06-03 10:52:17 +08:00
无木
f732b56904 feat(modal): add redoModalHeight for useModalInner
允许在Modal内部动态加载内容后重新调整高度
2021-06-02 23:31:15 +08:00
zuihou
9e2aa20daa fix(form): radioButtonGroup value support boolean 2021-06-02 08:59:39 +08:00
vben
1a429dd4d1 chore: release v2.4.1 2021-06-01 23:43:49 +08:00
vben
d73d43ed91 fix(table): make sure the table width is correct, fix #593 2021-06-01 23:21:04 +08:00
vben
8a3f47d6b8 chore: adjust setting 2021-06-01 21:38:16 +08:00
江麻妞
eca8907a11 fix: Fix the problem that the lang attribute of HTML will not be set when it is first loaded (#682)
* refactor:  Encapsulate the function of changing the page language

* fix(lang): Fix the problem that the `lang` attribute of `HTML` will not be set when it is first loaded
2021-06-01 21:37:59 +08:00
liuzhidong
e1123a2ccb fix(codeMirror): fix the JsonEditor embedded in the bullet frame causing the style to be disordered (#668) 2021-06-01 21:37:25 +08:00
无木
bbddf30e96 fix(form): radioButtonGroup value support number 2021-06-01 17:07:50 +08:00
Netfan
5ddccf6ba2 feat(tabs): add setTabTitle method (#680)
添加设置标签页标题的方法和演示
2021-06-01 01:13:19 +08:00
Vben
644dbe315b fix: fix node12 version data mock error 2021-06-01 01:08:57 +08:00
vben
aebad61b3d fix: ensure that roleList is not empty 2021-05-30 22:30:26 +08:00
vben
b1cb863502 fix(table-action): fix the split line style is missing,fix #674 2021-05-30 20:46:20 +08:00
Netfan
132c7fb944 fix: session timeout login logic error (#678)
修复超时重新登录的页面在某些逻辑下未能正确刷新数据的问题。

fix: #673
2021-05-31 09:23:19 +08:00
无木
9f5085c9f9 fix(table): useTable support onChange
修复useTable无法直接通过设置onChange来注册change事件响应的问题
2021-05-30 18:10:16 +08:00
无木
9f4d1719ca fix(table): support change event
修复表格不支持change事件的问题。

fix #677
2021-05-30 17:52:16 +08:00
vben
035f55af97 fix: login failed 2021-05-29 23:35:07 +08:00
Netfan
9e5e630987 refactor(api): remove unnecessary userId param (#675)
* refactor(api): remove unnecessary userId param

移除getUserInfo、getPermCode、getMenuList接口的userId参数。
这些接口应当始终与当前登录用户相关而无需传递userId。

* fix: fix auth header key case error
2021-05-29 23:11:38 +08:00
vben
70dcd60beb chore: update deps 2021-05-29 23:10:07 +08:00
无木
3ed2339a6d fix(tree): support defaultExpandAll prop
defaultExpandLevel已去除-1的行为定义,由defaultExpandAll代替。
2021-05-29 23:08:10 +08:00
无木
6edca1c19c feat(tree): add defaultExpandLevel prop
新增defaultExpandLevel属性,指定默认要展开的层级数。-1为默认全部展开(等同于ATree的defaultExpandAll),大于0则展开到指定层级。注意:该属性仅在首次渲染时起作用

close: #672
2021-05-29 00:48:56 +08:00
无木
1ae636296d feat(app-search): auto focus on show
菜单搜索组件在显示后input自动获得焦点
2021-05-28 17:58:32 +08:00
Netfan
b218f10e25 fix(login): login page modal style fixed: #662 (#666)
* fix: catch axios error data on request

* fix(login): login page modal style fixed: #662
2021-05-28 00:07:28 +08:00
vben
834fa7eb9c fix(axios): make sure that the parameter is an object before processing, fix #660 2021-05-27 23:58:21 +08:00
vben
566280422d fix(code-editor): fix CodeEditor style problem, fix #655 2021-05-27 23:06:41 +08:00
vben
3a16f2b80a chore: adjust component file name 2021-05-27 22:58:54 +08:00
无木
83c9cd7742 feat(tinymce): support dark theme and I18n
支持暗黑主题和中英文(暂不支持动态切换)
2021-05-27 22:16:40 +08:00
无木
ba2bebb406 fix(codeeditor): empty value set failed.fixed:#659 2021-05-27 19:14:31 +08:00
vben
7e2ca79ece fix: theme switching fails 2021-05-27 00:17:11 +08:00
无木
8eaf575626 feat(table): editable component text align
使可编辑单元格显示的input中的文字对齐方式与列自身的align属性相匹配
2021-05-26 23:06:07 +08:00
vben
d018363ddc fix(layout): fix class loss 2021-05-26 22:03:54 +08:00
无木
2066f66971 fix(avatar): mock data and Account center style
头像链接使用https,修正个人中心头像部分的位置
2021-05-26 21:58:14 +08:00
Netfan
93006c7dc7 feat(table): add editable DatePicker & TimePicker (#654)
为表格的可编辑单元格添加日期选择框和时间选择框组件
2021-05-26 21:47:31 +08:00
江麻妞
4f0d45f1df fix(log): fix Wrong version number (#653)
* fix(log): fix Wrong version number
2021-05-26 21:47:04 +08:00
vben
905e5b714b fix(layout): fix style compatibility issues 2021-05-26 21:45:32 +08:00
vben
6ef62ba6ea perf(i18n): improve warning prompt 2021-05-26 21:30:44 +08:00
vben
afa0eae829 chore: release 2.4.0 2021-05-25 23:47:27 +08:00
vben
5465f058ce feat(user): add user login expiration example 2021-05-25 23:14:05 +08:00
vben
d5b768929e fix(lock): automatic screen lock does not work 2021-05-25 22:35:52 +08:00
liuzhidong
785732f438 feat(form): add 'layout', 'labelAlign', 'rowProps' option (#651)
* feat(form):  add 'layout', 'labelAlign', 'rowProps' option

1.添加Form布局方式,当layout: 'vertical',labelWidth可以控制col间距
2.添加Form的全局label对齐方式, labelAlign: left | right
3.添加Form的Row组件所支持属性,控制Col间的间距,对齐方式,布局方式

* feat(Rate): add 'Rate' module

*添加评分组件,并添加了dome例子
2021-05-25 22:25:13 +08:00
vben
94a826d028 perf: let svg-icon support ssr 2021-05-25 22:10:56 +08:00
无木
6d626d5f00 chore: update deps 2021-05-25 15:17:45 +08:00
vben
cd4b5e14c2 fix(types): fix store types 2021-05-25 01:24:26 +08:00
Mikasa33
765064a190 feat(form): requires Increase function type value (#649)
* feat(form): requires Increase function type value

* feat(form): requires Increase function type value

* fix(form): 修复 rules 赋值错误的问题
2021-05-25 01:17:32 +08:00
vben
bbf178f64b fix(store): fix pinia typo 2021-05-23 23:45:21 +08:00
vben
8e3f84c3b7 fix(style): fix layout style, fix #633 2021-05-23 22:46:22 +08:00
Vben
e3569b81b1 fix: typo, ifx #637 2021-05-23 00:12:17 +08:00
Netfan
7519a00ada fix(avatar): show current user's avatar (#640)
在显示头像的地方正确显示当前登录用户的头像,已补充mock接口返回的avatar字段。
2021-05-23 09:02:47 +08:00
Netfan
d8ff30d9ec fix(tree): onCheck event lose origin param (#636)
修复Tree的onCheck事件缺少节点参数的问题
2021-05-22 22:36:19 +08:00
zuihou
3ef5087be6 style: formatting code 2021-05-22 18:08:53 +08:00
Netfan
2d3d04f547 fix(form): placeholder setting in componentProps (#634)
修复为RangePicker组件设置的placeholder属性无效的BUG
2021-05-21 09:36:41 +08:00
Netfan
bb0d2e1c71 fix(login): incorrect enter event bind (#625)
登录页面的回车事件绑定不正确,导致可能会意外提交登录表单:想按按下Enter关闭错误Modal时、在注册表单或其它表单按下Enter时等等。现已将Enter事件绑定在登录Form上
2021-05-20 22:51:51 +08:00
Netfan
5eee0ceb6e fix(theme): wrong color when RadioButtonGroup checked (#626) 2021-05-20 22:51:02 +08:00
Netfan
9b2d41ea44 feat(form): add prop autoSubmitOnEnter (#620)
为Form添加autoSubmitOnEnter属性,当设置为true时,可以在input组件上按下回车时自动提交表单
2021-05-20 09:19:46 +08:00
Vben
3bb6d11ed1 fix(layout): fix useLockPage not work, fix #611 2021-05-18 23:23:15 +08:00
Vben
d7d6039876 chore: update deps 2021-05-18 23:18:19 +08:00
Netfan
bc82d1a397 fix(tree): typo(#615)
* perf(form): schema required prop support array and strictly tree

* fix(tree): event 'change' triggered correctly
2021-05-18 23:05:33 +08:00
Mikasa33
f455fb97f9 feat(form): helpMessage Increase function type value (#616)
* feat(form): helpMessage

* feat(form): helpMessage
2021-05-18 23:04:31 +08:00
M69W
0e440f0793 style: fix the background color of table striped is lose (#618)
Co-authored-by: ljh <ljh>
2021-05-18 23:03:48 +08:00
Netfan
0112d6b313 fix(tree): value prop type (#613) 2021-05-17 13:32:43 +08:00
Vben
e4c3d0918a chore: update deps 2021-05-17 00:54:45 +08:00
江麻妞
c26dd03416 fix(theme generate): Fix #604 (#605)
fix(theme generate): Fix #604
2021-05-17 09:31:15 +08:00
HUCHAOQI
336be680d3 fix(store): addTab fx (#607)
在更新tabList的时候也能同时更新cacheTab
2021-05-17 09:31:03 +08:00
Netfan
adff788de5 perf(tree): improve the beforeRightClick callback to support more configuration of the menu (#608) 2021-05-17 09:29:24 +08:00
江麻妞
d34467d3f4 fix(cipher): fix #587 (#588) 2021-05-12 20:35:52 +08:00
HUCHAOQI
ec3d51d69b feat(form): add form field nested support (#591)
* feat(form): add form field nested support

* refactor(form): use lodash set replace
2021-05-12 20:35:28 +08:00
zuihou
4c16ffa383 Merge remote-tracking branch 'origin/main' 2021-05-12 13:19:23 +08:00
zuihou
56d8af147e feat(axios): Do you want to return the original response header? For example, use this property when you need to get the response header 2021-05-12 13:19:14 +08:00
江麻妞
a7c8c67c83 chore: typo (#584)
* fix: 变量名错误

* fix: 修复正则可以匹配纯数字问题
2021-05-11 18:56:38 +08:00
江麻妞
ae3f8329c2 perf: optimize i18n to add the initial locale to the locale pool during initialization (#577) 2021-05-11 09:24:03 +08:00
Netfan
2b76b88481 feat(qrcode): custom drawing support (#580) 2021-05-11 09:23:24 +08:00
Vben
9d19546272 chore: update deps 2021-05-10 00:32:37 +08:00
Vben
78191d6658 chore: update deps 2021-05-09 15:46:10 +08:00
Netfan
a579b8456a fix(modal): proptype conflict with ant design modal(fixed: #545) (#575) 2021-05-09 15:21:31 +08:00
Netfan
43e4c21950 fix(table): columns ref fixed(#564) (#573) 2021-05-07 21:01:11 +08:00
Mikasa33
9cd293c283 fix(CodeEditor): add readonly prop (#572) 2021-05-07 21:00:40 +08:00
啝裳
2f8b2183ec fix(tree): basicTree设置blockNode=false后,显示异常 (#567) 2021-05-06 21:11:12 +08:00
Netfan
1ff13bf459 fix:searching with replaceFields fix #548,#557 (#569)
* fix: update selected before row-click event(#548)

* fix(tree): searching with replaceFields(#557)
2021-05-06 21:10:29 +08:00
Yirius
5724bc5b3b perf: set header can use For Qs (#562)
set header can use For Qs
2021-05-05 21:19:12 +08:00
Mikasa33
bf365e26e5 fix(style): add table title min-height (#547) 2021-04-28 20:42:46 +08:00
木头锤纸
e80280fb81 feat(form): add Slider demo (#555)
* feat(function): add 增加Slider滑动输入条组件

* feat(function): add 增加Slider滑动输入条组件demo

* feat(function): add 增加Slider滑动输入条组件demo
2021-04-28 20:33:44 +08:00
zuihou
f4c9703ab9 docs(CHANGELOG): improve documentation 2021-04-27 00:25:54 +08:00
zuihou
9e208411a2 feat(demo): add permission table demo 2021-04-27 00:22:05 +08:00
zuihou
5a3861b9cf feat(table): 表格的数据列和操作列的字段可以根据权限和业务来控制是否显示 2021-04-27 00:20:20 +08:00
Vben
7c41c8673c fix(form): expose formModel,fix #533 2021-04-26 21:02:50 +08:00
M69W
5fae2b02ea perf: add Coordinating the selection of provinces and cities (#534)
Co-authored-by: M69W <M69W@M69W>
2021-04-26 20:53:33 +08:00
Vben
3ff70bb56f fix(form): improve warning prompt, fix #538 2021-04-26 20:52:31 +08:00
zuihou
6afee415a3 feat(table): Table operation columns support permission codes 2021-04-26 16:18:53 +08:00
Vben
8b2e0f665f fix: fix the default value of props 2021-04-25 23:39:56 +08:00
Vben
6a8820597f fix: ensure that the 401 jumps to the login page correctly, fix #512 2021-04-24 20:31:05 +08:00
Vben
b7ea68e6f8 fix(form): improve form props acquisition,fix #527 2021-04-24 20:27:01 +08:00
Vben
ccae5cd924 fix(style): fix icon style, fix #496 2021-04-24 20:19:41 +08:00
Vben
cb35341b8f fix(form): ensure that the DateTime component checked properly,fix #511 2021-04-24 20:10:31 +08:00
Vben
16ecf71850 fix(table): submitButtonOptions not work,fix #531 2021-04-24 18:27:48 +08:00
Vben
ca717602a6 fix: trigger resize in full screen to ensure that the height of other components is normal,fix #508 2021-04-24 11:23:28 +08:00
Vben
6b7f688eaf fix(menu): ensure that the external link jumps correctly, fix #516 2021-04-24 11:11:59 +08:00
Vben
7f6f8eefe9 fix(style): fix build style errors,fix #528 2021-04-24 10:59:45 +08:00
Mikasa33
e2ddf43699 fix(style): fix layout header style, basic arrow style and table search form style (#525)
* style: cursor pointer

* style: light mode, hover background-color

* fix(style): fix form border-radius style
2021-04-23 22:04:27 +08:00
Vben
090c76ba20 chore: vite version downgrade 2021-04-22 23:29:32 +08:00
Vben
f0ae146ca0 chore: update workflow 2021-04-22 22:59:53 +08:00
zuihou
c639e493a5 feat(form): adding resetSchema method 2021-04-22 22:51:00 +08:00
Vben
7e2668f667 chore: update deps 2021-04-22 22:13:03 +08:00
最后
e689ee5fa6 Update useFormEvents.ts (#514)
fix: 修复 表单回显时,参数为null或者''时, 报Invalid date的错
2021-04-22 21:14:42 +08:00
Vben
f4af231172 fix(button): ghost style 2021-04-19 23:53:12 +08:00
Vben
38f5072695 fix(form): remove field binding when deleting schema #471 2021-04-19 23:53:11 +08:00
Vben
b92b8a3c6a fix(tabs): fix the problem that other functions are invalid when the tab is closed, close #376 2021-04-19 23:53:11 +08:00
Vben
4f0c6fbcc7 chore: update stylelint 2021-04-19 23:53:11 +08:00
jinmao88
8c2491fcb6 fix: fix AppendFormDemo (#505)
Co-authored-by: haha <admin@qq.com>
2021-04-19 23:52:37 +08:00
jinmao88
85b92a9add perf: add AppendFormDemo (#503)
Co-authored-by: haha <admin@qq.com>
2021-04-19 18:42:31 +08:00
Li yao
bd83eccdc5 fix: password icon dislocation (#501)
修复登录页密码显示icon不同分辨率下错位
2021-04-19 18:36:44 +08:00
啝裳
94b2222c08 perf: improve countTo (#499) 2021-04-19 13:22:33 +08:00
最后
502cc2701b feat:icon name can be displayed(#498)
feat: 鼠标移上去,能显示图标名
2021-04-19 01:11:38 +08:00
Vben
4a035478ca fix(flow-chart): dark style not work 2021-04-17 23:20:39 +08:00
啝裳
5e36a8b575 perf: improve cropper example (#491) 2021-04-17 22:39:05 +08:00
最后
e1b30a5075 fix: update Axios.ts (#492)
1. 应该使用传递进来的 请求头
2. 针对有数组类型的参数,应该用brackets 或者 repeat 。  最好将arrayFormat参数改成可以让使用者通过入参来改的。  参考: https://blog.csdn.net/pifutan/article/details/86320705
2021-04-17 22:30:53 +08:00
Vben
0649011eba feat: add JsonPreview component 2021-04-17 18:51:19 +08:00
Vben
a812685084 feat: add codeEditor component 2021-04-17 18:42:14 +08:00
Vben
c04e8943bc perf: merge locale file 2021-04-17 18:39:18 +08:00
Vben
e1bc33f5c5 perf: improve flowChart logic 2021-04-17 18:36:49 +08:00
啝裳
2576735ade feat: add flowChart Component (#488) 2021-04-17 06:06:08 +08:00
Vben
a863ad46b4 fix(tinymce): ensure that the public resource path is correct,fix #487 2021-04-17 00:01:31 +08:00
Vben
7db37eedcc chore: update deps 2021-04-16 23:54:53 +08:00
Vben
6b47a8b930 chore: update deps 2021-04-14 21:15:50 +08:00
Vben
2cdf2c28c4 style: background to background-color 2021-04-13 21:43:10 +08:00
Vben
c9089c3243 chore: typo 2021-04-13 21:42:10 +08:00
LiuYa
6dd7d0f928 feat: add spin prop for Icon (#477)
Co-authored-by: 刘亚 <liuya54892@outlook.com>
2021-04-13 21:42:50 +08:00
Vben
021c6364fa chore: update deps 2021-04-13 00:19:36 +08:00
Vben
3c441a05da style(eslint): fix eslint error 2021-04-12 23:02:48 +08:00
Vben
26adbc92be fix: fix dark theme refreshing flashing white screen 2021-04-12 23:00:35 +08:00
Liu Ya
9a21b8b6a4 fix(form): Improve form error handling
* 自定义组件 Array 的元素可能为 null

* 自定义组件时没有抛出错误
2021-04-12 20:50:45 +08:00
Vben
663d13a67f fix: fix case errors 2021-04-10 23:57:50 +08:00
Vben
7e43d88f9c fix: echart import path 2021-04-10 23:49:39 +08:00
Vben
51a9f6b3da chore: bump 2.3.0 2021-04-10 23:30:00 +08:00
Vben
c77f7e62ab fix(theme): make sure the menu style is correct, fix #382 2021-04-10 23:20:29 +08:00
Vben
640a2c1798 fix(theme): make sure the steps style is correct, fix #414 2021-04-10 22:16:06 +08:00
Vben
37c5741601 fix(api-select): make sure the type is correct, fix #468 2021-04-10 21:41:22 +08:00
Vben
967b28c4c0 feat: persistent save tab, fix #359 2021-04-10 21:41:22 +08:00
Vben
2037293aa3 refactor: refactor hooks 2021-04-10 21:41:22 +08:00
Vben
215d8bab38 refactor: refactor store 2021-04-10 21:41:22 +08:00
啝裳
700306bb45 fix: Improve the picture cropping component (#463)
* fix: Improve the picture cropping component

* fix: component /verify/rotate text show problem
2021-04-10 21:19:28 +08:00
Vben
ee1c349858 fix(menu): improve menu logic, fix #461 2021-04-08 23:04:16 +08:00
Vben
780a8a67b8 fix: improve login page style 2021-04-08 22:08:55 +08:00
Vben
96a49ba116 chore: update deps 2021-04-08 22:08:12 +08:00
啝裳
af6d58eb26 fix: login page overflow show problem (#455) 2021-04-08 18:02:38 +08:00
792 changed files with 33286 additions and 17866 deletions

View File

@@ -1,5 +1,3 @@
VITE_PORT = 3100
# Whether to open mock # Whether to open mock
VITE_USE_MOCK = true VITE_USE_MOCK = true
@@ -8,7 +6,7 @@ VITE_PUBLIC_PATH = /
# Cross-domain proxy, you can configure multiple # Cross-domain proxy, you can configure multiple
# Please note that no line breaks # Please note that no line breaks
VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3001/upload"]] VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]]
# VITE_PROXY=[["/api","https://vvbin.cn/test"]] # VITE_PROXY=[["/api","https://vvbin.cn/test"]]
# Delete console # Delete console

View File

@@ -2,7 +2,7 @@
VITE_USE_MOCK = true VITE_USE_MOCK = true
# public path # public path
VITE_PUBLIC_PATH = / VITE_PUBLIC_PATH = ./
# Delete console # Delete console
VITE_DROP_CONSOLE = true VITE_DROP_CONSOLE = true

36
.env.test Normal file
View File

@@ -0,0 +1,36 @@
NODE_ENV=production
# Whether to open mock
VITE_USE_MOCK = true
# public path
VITE_PUBLIC_PATH = /
# Delete console
VITE_DROP_CONSOLE = true
# Whether to enable gzip or brotli compression
# Optional: gzip | brotli | none
# If you need multiple forms, you can use `,` to separate
VITE_BUILD_COMPRESS = 'none'
# Whether to delete origin files when using compress, default false
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
# Basic interface address SPA
VITE_GLOB_API_URL=/basic-api
# File upload address optional
# It can be forwarded by nginx or write the actual address directly
VITE_GLOB_UPLOAD_URL=/upload
# Interface prefix
VITE_GLOB_API_URL_PREFIX=
# Whether to enable image compression
VITE_USE_IMAGEMIN= true
# use pwa
VITE_USE_PWA = false
# Is it compatible with older browsers
VITE_LEGACY = false

View File

@@ -1,6 +1,4 @@
// @ts-check module.exports = {
const { defineConfig } = require('eslint-define-config');
module.exports = defineConfig({
root: true, root: true,
env: { env: {
browser: true, browser: true,
@@ -20,10 +18,10 @@ module.exports = defineConfig({
extends: [ extends: [
'plugin:vue/vue3-recommended', 'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:prettier/recommended', 'plugin:prettier/recommended',
], ],
rules: { rules: {
'vue/script-setup-uses-vars': 'error',
'@typescript-eslint/ban-ts-ignore': 'off', '@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-explicit-any': 'off',
@@ -60,6 +58,7 @@ module.exports = defineConfig({
'vue/singleline-html-element-content-newline': 'off', 'vue/singleline-html-element-content-newline': 'off',
'vue/attribute-hyphenation': 'off', 'vue/attribute-hyphenation': 'off',
'vue/require-default-prop': 'off', 'vue/require-default-prop': 'off',
'vue/require-explicit-emits': 'off',
'vue/html-self-closing': [ 'vue/html-self-closing': [
'error', 'error',
{ {
@@ -72,5 +71,6 @@ module.exports = defineConfig({
math: 'always', math: 'always',
}, },
], ],
'vue/multi-word-component-names': 'off',
}, },
}); };

28
.github/ISSUE_TEMPLATE/3-bug-cn.md vendored Normal file
View File

@@ -0,0 +1,28 @@
---
name: 🐛 Bug 报告
about: 向我们报告一个Bug以帮助我们改进
title: ''
labels: 'bug: pending triage'
assignees: ''
---
**⚠️ 重要 ⚠️ 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭**
- [ ] 已阅读 [文档](https://anncwb.github.io/vue-vben-admin-doc/).
- [ ] 确保您的代码已是最新或者所报告的 Bug 在最新版本中可以重现. (部分 Bug 可能已经在最近的代码中修复)
- [ ] 已在 Issues 中搜索了相关的关键词
- [ ] 不是 ant design vue 组件库的 Bug
### 描述 Bug
请清晰地描述此 Bug 的具体表现。
### 复现 Bug
请描述在演示页面中复现 Bug 的详细步骤,以确保我们可以理解并定位问题。部分 Bug 如果未在 Demo 中涉及,请务必提供关键代码
## 系统信息
- 操作系统:
- Node 版本:
- 包管理器 (npm/yarn/pnpm) 及其版本:

View File

@@ -1,118 +0,0 @@
name: deploy
on:
push:
branches:
- main
jobs:
# push-to-ftp:
# if: "contains(github.event.head_commit.message, '[deploy]')"
# runs-on: ubuntu-latest
# steps:
# - name: Checkout
# uses: actions/checkout@v2
# - name: Sed Config Base
# shell: bash
# run: |
# sed -i 's#VITE_PUBLIC_PATH\s*=.*#VITE_PUBLIC_PATH = /next/#g' ./.env.production
# sed -i "s#VITE_BUILD_COMPRESS\s*=.*#VITE_BUILD_COMPRESS = 'gzip'#g" ./.env.production
# cat ./.env.production
# - name: use Node.js 14
# uses: actions/setup-node@v2.1.2
# with:
# node-version: '14.x'
# - name: Get yarn cache
# id: yarn-cache
# run: echo "::set-output name=dir::$(yarn cache dir)"
# - name: Cache dependencies
# uses: actions/cache@v2
# with:
# path: ${{ steps.yarn-cache.outputs.dir }}
# key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
# restore-keys: |
# ${{ runner.os }}-yarn-
# - name: Build
# run: |
# yarn install
# yarn run build
# - name: Deploy
# uses: SamKirkland/FTP-Deploy-Action@2.0.0
# env:
# FTP_SERVER: ${{ secrets.FTP_SERVER }}
# FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
# FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
# METHOD: sftp
# PORT: ${{ secrets.FTP_PORT }}
# LOCAL_DIR: dist
# REMOTE_DIR: /srv/www/vben-admin
# ARGS: --delete --verbose --parallel=80
push-to-gh-pages:
if: "contains(github.event.head_commit.message, '[release]')"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Sed Config Base
shell: bash
run: |
sed -i 's#VITE_PUBLIC_PATH\s*=.*#VITE_PUBLIC_PATH = /vue-vben-admin/#g' ./.env.production
sed -i "s#VITE_BUILD_COMPRESS\s*=.*#VITE_BUILD_COMPRESS = 'gzip'#g" ./.env.production
cat ./.env.production
- name: use Node.js 14
uses: actions/setup-node@v2.1.2
with:
node-version: '14.x'
- name: Get yarn cache
id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Set SSH Environment
env:
DOCS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }}
run: |
mkdir -p ~/.ssh/
echo "$ACTIONS_DEPLOY_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com > ~/.ssh/known_hosts
chmod 700 ~/.ssh && chmod 600 ~/.ssh/*
git config --local user.email "vbenadmin@163.com"
git config --local user.name "vbenAdmin"
- name: Delete gh-pages branch
run: |
git push origin --delete gh-pages
- name: Build
run: |
yarn install
yarn run build
touch dist/.nojekyll
cp dist/index.html dist/404.html
- name: Deploy
uses: peaceiris/actions-gh-pages@v2.5.0
env:
ACTIONS_DEPLOY_KEY: ${{secrets.ACTIONS_DEPLOY_KEY}}
PUBLISH_BRANCH: gh-pages
PUBLISH_DIR: ./dist
with:
forceOrphan: true

View File

@@ -1,55 +0,0 @@
name: schedule-push-to-ftp
# Timed deployment project
on:
push:
schedule:
- cron: '0 20 * * *'
jobs:
schedule-push-to-ftp:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Sed Config Base
shell: bash
run: |
sed -i 's#VITE_PUBLIC_PATH\s*=.*#VITE_PUBLIC_PATH = /next/#g' ./.env.production
sed -i "s#VITE_BUILD_COMPRESS\s*=.*#VITE_BUILD_COMPRESS = 'gzip'#g" ./.env.production
cat ./.env.production
- name: use Node.js 14
uses: actions/setup-node@v2.1.2
with:
node-version: '14.x'
- name: Get yarn cache
id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Build
run: |
yarn install
yarn run build
- name: Deploy
uses: SamKirkland/FTP-Deploy-Action@2.0.0
env:
FTP_SERVER: ${{ secrets.FTP_SERVER }}
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
METHOD: sftp
PORT: ${{ secrets.FTP_PORT }}
LOCAL_DIR: dist
REMOTE_DIR: /srv/www/vben-admin
ARGS: --delete --verbose --parallel=80

4
.gitignore vendored
View File

@@ -4,12 +4,14 @@ dist
.npmrc .npmrc
.cache .cache
test/upload-server/static tests/server/static
tests/server/static/upload
.local .local
# local env files # local env files
.env.local .env.local
.env.*.local .env.*.local
.eslintcache
# Log files # Log files
npm-debug.log* npm-debug.log*

View File

@@ -2,5 +2,5 @@ ports:
- port: 3344 - port: 3344
onOpen: open-preview onOpen: open-preview
tasks: tasks:
- init: yarn - init: pnpm install
command: yarn dev command: pnpm run dev

1
.husky/.gitignore vendored
View File

@@ -1 +0,0 @@
_

View File

@@ -1,8 +0,0 @@
module.exports = {
'*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
'package.json': ['prettier --write'],
'*.vue': ['eslint --fix', 'prettier --write', 'stylelint --fix'],
'*.{scss,less,styl,html}': ['stylelint --fix', 'prettier --write'],
'*.md': ['prettier --write'],
};

View File

@@ -6,5 +6,3 @@
# Format and submit code according to lintstagedrc.js configuration # Format and submit code according to lintstagedrc.js configuration
npm run lint:lint-staged npm run lint:lint-staged
npm run lint:pretty

View File

@@ -1,6 +1,6 @@
{ {
"recommendations": [ "recommendations": [
"octref.vetur", "johnsoncodehk.volar",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"stylelint.vscode-stylelint", "stylelint.vscode-stylelint",
"esbenp.prettier-vscode", "esbenp.prettier-vscode",

4
.vscode/launch.json vendored
View File

@@ -5,9 +5,9 @@
"type": "chrome", "type": "chrome",
"request": "launch", "request": "launch",
"name": "Launch Chrome", "name": "Launch Chrome",
"url": "http://localhost:3100", "url": "https://localhost:3100",
"webRoot": "${workspaceFolder}/src", "webRoot": "${workspaceFolder}/src",
"sourceMaps": true "sourceMaps": true
}, }
] ]
} }

145
.vscode/settings.json vendored
View File

@@ -2,55 +2,9 @@
"typescript.tsdk": "./node_modules/typescript/lib", "typescript.tsdk": "./node_modules/typescript/lib",
"volar.tsPlugin": true, "volar.tsPlugin": true,
"volar.tsPluginStatus": false, "volar.tsPluginStatus": false,
//=========================================== "npm.packageManager": "pnpm",
//============= Editor ======================
//===========================================
"explorer.openEditors.visible": 0,
"editor.tabSize": 2, "editor.tabSize": 2,
"editor.renderControlCharacters": true,
"editor.minimap.renderCharacters": false,
"editor.minimap.maxColumn": 300,
"editor.minimap.showSlider": "always",
"editor.cursorBlinking": "phase",
"editor.cursorSmoothCaretAnimation": true,
"editor.detectIndentation": false,
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"diffEditor.ignoreTrimWhitespace": false,
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
"editor.suggestSelection": "first",
"editor.trimAutoWhitespace": true,
"editor.quickSuggestions": {
"other": true,
"comments": true,
"strings": true
},
//===========================================
//============= Other =======================
//===========================================
"breadcrumbs.enabled": true,
"open-in-browser.default": "chrome",
//===========================================
//============= emmet =======================
//===========================================
"emmet.triggerExpansionOnTab": true,
"emmet.showAbbreviationSuggestions": true,
"emmet.showExpandedAbbreviation": "always",
"emmet.syntaxProfiles": {
"vue-html": "html",
"vue": "html",
"xml": {
"attr_quotes": "single"
}
},
"emmet.includeLanguages": {
"jsx-sublime-babel-tags": "javascriptreact"
},
//===========================================
//============= files =======================
//===========================================
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"files.eol": "\n", "files.eol": "\n",
"search.exclude": { "search.exclude": {
"**/node_modules": true, "**/node_modules": true,
@@ -73,9 +27,14 @@
"CHANGELOG.md": true, "CHANGELOG.md": true,
"examples": true, "examples": true,
"res": true, "res": true,
"screenshots": true "screenshots": true,
"yarn-error.log": true,
"**/.yarn": true
}, },
"files.exclude": { "files.exclude": {
"**/.cache": true,
"**/.editorconfig": true,
"**/.eslintcache": true,
"**/bower_components": true, "**/bower_components": true,
"**/.idea": true, "**/.idea": true,
"**/tmp": true, "**/tmp": true,
@@ -96,57 +55,10 @@
"**/yarn.lock": true "**/yarn.lock": true
}, },
"stylelint.enable": true, "stylelint.enable": true,
"stylelint.packageManager": "yarn", "stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// ===========================================
// ================ Eslint ===================
// ===========================================
"eslint.alwaysShowStatus": true,
"eslint.options": {
"plugins": ["html", "vue", "javascript", "jsx", "typescript"],
"extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"]
},
"eslint.validate": [
"javascript",
"typescript",
"reacttypescript",
"reactjavascript",
"html",
"vue"
],
// ===========================================
// ================ Vetur ====================
// ===========================================
"vetur.experimental.templateInterpolationService": true,
"vetur.format.options.tabSize": 2,
"vetur.format.defaultFormatter.html": "js-beautify-html",
"vetur.format.defaultFormatter.scss": "prettier",
"vetur.format.defaultFormatter.css": "prettier",
"vetur.format.defaultFormatter.ts": "prettier-tslint",
"vetur.format.defaultFormatter.js": "prettier",
"vetur.languageFeatures.codeActions": false,
"vetur.format.defaultFormatterOptions": {
"js-beautify-html": {
"wrap_attributes": "force-expand-multiline"
},
"prettier": {
"eslintIntegration": true,
"arrowParens": "always",
"semi": false,
"singleQuote": true
}
},
"liveServer.settings.donotShowInfoMsg": true,
"terminal.integrated.rendererType": "dom",
"telemetry.enableCrashReporter": false,
"telemetry.enableTelemetry": false,
"workbench.settings.enableNaturalLanguageSearch": false,
"path-intellisense.mappings": { "path-intellisense.mappings": {
"/@/": "${workspaceRoot}/src" "/@/": "${workspaceRoot}/src"
}, },
"prettier.requireConfig": true,
"typescript.updateImportsOnFileMove.enabled": "always",
"workbench.sideBar.location": "left",
"[javascriptreact]": { "[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
}, },
@@ -176,7 +88,8 @@
}, },
"[vue]": { "[vue]": {
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": false "source.fixAll.eslint": true,
"source.fixAll.stylelint": true
} }
}, },
"i18n-ally.localesPaths": ["src/locales/lang"], "i18n-ally.localesPaths": ["src/locales/lang"],
@@ -186,5 +99,41 @@
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}", "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
"i18n-ally.enabledParsers": ["ts"], "i18n-ally.enabledParsers": ["ts"],
"i18n-ally.sourceLanguage": "en", "i18n-ally.sourceLanguage": "en",
"i18n-ally.enabledFrameworks": ["vue", "react"] "i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.enabledFrameworks": ["vue", "react"],
"cSpell.words": [
"vben",
"windi",
"browserslist",
"tailwindcss",
"esnext",
"antv",
"tinymce",
"qrcode",
"sider",
"pinia",
"sider",
"nprogress",
"INTLIFY",
"stylelint",
"esno",
"vitejs",
"sortablejs",
"mockjs",
"codemirror",
"iconify",
"commitlint",
"vditor",
"echarts",
"cropperjs",
"logicflow",
"vueuse",
"zxcvbn",
"lintstagedrc",
"brotli",
"tailwindcss",
"sider",
"pnpm",
"antd"
]
} }

View File

@@ -1,48 +0,0 @@
# test directories
__tests__
test
tests
powered-test
# asset directories
docs
doc
website
images
assets
# examples
example
examples
# code coverage directories
coverage
.nyc_output
# build scripts
Makefile
Gulpfile.js
Gruntfile.js
# configs
appveyor.yml
circle.yml
codeship-services.yml
codeship-steps.yml
wercker.yml
.tern-project
.gitattributes
.editorconfig
.*ignore
.eslintrc
.jshintrc
.flowconfig
.documentup.json
.yarn-metadata.json
.travis.yml
# misc
*.md
!istanbul-reports/lib/html/assets
!istanbul-api/node_modules/istanbul-reports/lib/html/assets

View File

@@ -1,3 +1,382 @@
## 2.8.0(2021-11.03)
### Upgrade Instructions
- Package manager changed from `yarn` to `pnpm`
- Delete `node_modules` and `yarn.lock`, install `pnpm` globally
- Execute `pnpm install`
### ✨ Features
- **Others**
- The `VITE_PROXY` configuration in the `.env` file supports single quotes
- Remove warnings during build
### 🐛 Bug Fixes
- **BasicTable**
- Fix the issue that editable cells cannot be submitted in some cases
- Fix the problem that the `inset` attribute does not work
- Fix the problem that the performance of `useTable` and `reload` method `await` of `BasicTable` instance are inconsistent
- Fix the issue that `clickToRowSelect` would ignore the disabled state of the row selection box
- Fix the problem that the page of `BasicTable` will be reset in some cases
- Modify the `deleteTableDataRecord` method
- **BasicModal**
- Fixed the problem that `Modal` could not be closed even when clicking on the mask and pressing the `Esc` key
- Fixed the issue that clicking the close button and the blank area next to the maximize button would also cause `Modal` to close
- **BasicTree** Fix the problem that the node slot does not work
- **CodeEditor** Fix the problem that may cause `Build` failure
- **BasicForm** Fix the problem that the content width of the custom FormItem component may be out of range
- **ApiTreeSelect** Fix the problem that the change of `params` failed to trigger the re-request of api data
- **Others** -Fixed an issue where multiple tabs would not jump to routing when closing tabs in some cases
- Fix the issue that some components may cause abnormal hot update
- Fix the problem that some sub-components of `antdv` will be reported in the build process when directly `import` part of the `antdv`, such as: TabPane, RadioGroup
## 2.7.2(2021-09-14)
### ✨ Features
- **BasicForm** New `Divider` in the form component for dividing the area of longer forms
- **BasicTable**
- Cell editor adds submit callback, which will decide whether to submit data to the form based on the result returned by the callback function
- Add check method for row editing, allowing only check but not submit value, so asynchronously save data successfully before submit to table
- Fix the problem that the `rowClassName` property cannot be used at the same time as `striped`.
- New component **MarkdownViewer** for displaying rich text in Markdown format
### 🐛 Bug Fixes
- **CodeEditor** Fix JSON editor throwing exception when formatting invalid JSON text
- **Tinymce** fixes an issue where inline mode throws an exception in some scenarios
- **BasicTable**
- Repair the problem that the editing icon is not displayed when the content of editable cell is empty
- Repair the problem that the total row at the end of the table sometimes fails to align with the columns in the main part of the table.
- **MarkDown** Repair the problem that the value of initial value property does not work.
- **BasicUpload** Repair the problem that `accept` property does not support `MIME` and suffix name starting with dot.
- **ApiSelect** Fix the problem of type definition of `value` property.
- **Other**
- Repair the problem that some wrapper components give error when using slots.
- Repair the problem that `theme` parameter of `useECharts` does not work.
- Repair the problem that when `Token` is invalid, pressing F5 to refresh the page may cause abnormal page loading.
- Repair the problem that the improper call of `useRedo` may lead to `path` redirection abnormality.
- Repair the problem that `vite` custom mode name does not support underscore.
## 2.7.1(2021-08-16)
- Upgrade vue 3.2, if the operation fails, delete node_modules and reinstall it
### ✨ Features
- **BasicTree** Add search function related properties and methods
- **BasicForm** added `alwaysShowLines` to set the number of lines kept displayed when folding
### 🐛 Bug Fixes
- **Cropper** Fix the problem of failure to destroy in time
- **BasicTable**
- Fix the problem that `CellFormat` cannot use `Map` type data
- Fixed an issue where the editable cell failed to display the `0` value correctly
- Fixed the issue that selection-change event failed to trigger correctly when unchecked
- Fix the problem that the background color of the full screen state under the light theme is incorrect
- Fix the problem of obtaining complete data when `getSelectRows` does not support remote data cross-page selection
- Fix the issue that the `size` property provided for editing components in `editComponentProps` is invalid
- **Qrcode** Fixed the problem that the QR code component could not be drawn in time when it was created
- **BasicModal** Fix the problem that the `helpMessage` property does not work
- **BasicButton** Fix the problem that the button style performance is inconsistent with the official antd
- **Others** Fix the problem that `useRedo` (reload the current route) will lose route `params` data
## 2.7.0(2021-08-03)
## (Breaking changes) Breaking changes
- Restore the project `tailwindcss` back to `windicss`, tried `tailwindcss`, there may be a lot of problems, first switch back to `windicss` to improve development efficiency and lower switching costs.
- There are currently incompatible areas of the project
- The wording of `xl:!m-4` needs to be changed to `!xl:m-4`, note that only `!` is incompatible. If you dont use it, you dont need to change it.
- The memory overflow problem may still exist (low frequency, just restart, restart vite faster)
### ✨ Features
- **Preview** Add new properties and events
- **Dark Theme** added support for tailwindcss night mode
- **Others** add setTip method for useLoading
### 🐛 Bug Fixes
- **ApiTreeSelect** Fixed the problem of failing to monitor `params` changes correctly
- **ImgRotateDragVerify** Fix the problem that the component `resume` method cannot be called
- **TableAction** Fix the problem that the stopButtonPropagation property does not work in some cases
- **PageWrapper** Fix the problem of invalid `class` attribute
- **BasicTree** Fix the problem that the `checkAll` method will affect the `disabled` state node
- **BasicTable**
- Fix the issue that editable cells do not support `ellipsis` configuration
- Fixed the problem that the pop-up layer of sub-components (popconfirm and edit components such as select and treeSelect) cannot be seen in full-screen mode
- Fixed an issue where when `expandRowByClick` is enabled, clicking non-expandable rows may cause style errors
- Fix the problem that the dynamic change of `pagination` property does not take effect
- Fix the problem that `getSelectRows` does not support the child data of the tree table -**Dark Theme** Fix the color matching problem under the dark theme
- Fix the background color of the selected node of the `Tree` component
- Fix the color configuration of the `Alert` component
- Fix the problem of the button color of `link` type in the disabled state
- Fix the style problem of checked checkboxes in `Tree` -**Others** Fix the problem that useScript failed to automatically remove the script node
## 2.6.1(2021-07-19)
### ✨ Features
- **NoticeList** Add pagination, auto omit for overlength, title click event, title strikethrough, etc.
- **MixSider** Optimize the style of the bottom collapse button in the Mix menu layout to be consistent with the style of other menu layouts
- **ApiTreeSelect** Extend `TreeSelect` component of `antdv` to support remote data source, similar to `ApiSelect`.
- **BasicTable** New `ApiTreeSelect` editing component
- Different backend home pages can be specified for different users.
- Add `homePath` field (optional) to the user information returned by the `getUserInfo` interface to customize the home page path for the current user
### 🐛 Bug Fixes
- **BasicTable**
- Fix scrollbar style issue (removed scroll style patch)
- Fix the alignment problem of cells with expanded icons in tree tables
- Add `headerTop` slot.
- Fix the color display of the operation column button in disabled state.
- Repair the problem that the values of editable cells cannot be updated by modifying `dataSource` directly.
- Repair the problem of data replay when using `ApiSelect` to edit components.
- Repair the problem that editing components may report `onXXX` type error in some scenarios.
- **TableAction**
- Create Tooltip component only if `action.tooltip` exists.
- Fix the problem that the content of the round button inside the component is not centered
- **AppSearch** Fix the problem that the hidden menu may be searched.
- **BasicUpload** Repair the problem of error when handling non-`array` values.
- **Form** Repair the `suffix` slot style problem of `FormItem`.
- **Menu**
- Repair the hovering trigger logic of the left mixed menu
- Repair the problem that the top bar menu is wrong when displaying menu items that need to be hidden.
- Fix the left mixed menu in hover trigger mode will jump to route directly when there is no submenu and it is activated
- **Breadcrumb** Repair the problem that the menu with redirection cannot be jumped when clicked
- **Markdown** fixes an initialization exception and an issue where value was not set dynamically correctly
- **Modal** Make sure props are passed correctly
- **MultipleTab** fixes an issue that could accidentally create login route tabs
- **BasicTree** Fix the problem that the search function may cause `checkedKeys` to be lost
- **CodeEditor** Fix the problem that value does not support v-model usage.
- **CountdownInput** Fix the problem that `input` slot is not supported.
- **ApiSelect** Fix the problem that the `options-change` event parameter is not the standard `options` data used by `select
- **Other**
- Fix the problem that the configuration of default menu collapse does not work
- Repair the problem that `safari` browser reports an error and the website cannot be opened.
- Repair the problem that eslint keeps error due to endOfLine after pulling the code on window.
- Fix `Vue Router warn` caused by dynamic routing
### 🎫 Chores
- Add test environment test command
## 2.6.0(2021-07-04)
### ✨ Features
- **Axios** New `withToken` configuration to control whether the request carries a token or not
- **BasicUpload**
- New `preview-delete` event triggered when deleting a file in preview `Modal`.
- `value` supports `v-model` usage
- **Route configuration**
- Add `ignoreRoute` to generate menu only in `ROUTE_MAPPING` or `BACK` permission mode
- Add `hidePathForChildren` configuration to ignore this level `path` when generating menus for child items
- **TableAction** Add `tooltip` configuration to add tooltip hint for button
- **CropperAvatar**
- Added `value` to set the current avatar
- Added `onChange` to accept avatar cropping and upload success event
- New `btnText`, `btnProps` for customizing the text and properties of the upload button
- Add tooltips to the action buttons in `Modal` for cropping
- **Modal** Add tooltip for action button in top right corner
### 🐛 Bug Fixes
- **Modal**
- Fix the problem that the mask cannot be closed by clicking on it.
- Fix `setModalProps` does not support setting `defaultFullscreen`.
- **Table**
- Fix the problem that `editComponentProps` doesn't support `onChange`.
- Fix the problem that `selection-change` event is not triggered when `clickToRowSelect` is enabled.
- Fix the problem that global configuration `fetchSetting` may be accidentally modified by local configuration.
- Fix the problem that the parameter of `handleSearchInfoFn` contains redundant blank keys.
- Repair the problem that when rowSelection.onChange is provided for table, the selected items of table cannot be changed manually.
- Fix the problem that the scrollbar continues to be displayed even when it is not needed to be displayed.
- **Icon** Repair the problem that SvgIcon is missing some styles.
- **Menu**
- Repair the problem that single-level menu refreshing will not be activated in route mapping mode.
- Repair the problem that the collapse customization at the bottom of the side menu is invalid.
- **Form** Repair the type definition of `submitButtonOptions` and `resetButtonOptions`.
- **PopConfirmButton** Remove the redundant `title` on `Button`.
- **Axios** Fix the problem that `params` and `data` data cannot be submitted at the same time when non-`GET` requests are made
- **Other**
- Repair the problem that the lock screen function can skip the lock state by refreshing the page or copying the URL to open a new browser tab
- Repair the problem that `Token` won't be synchronized when multiple windows open pages at the same time.
- Repair the problem that `hasPermission` does not work in `ROLE` permission mode.
- **Table** Repair the problem that the parameter of `handleSearchInfoFn` contains extra blank keys.
- **Tailwindcss** Remove console warning
## 2.5.2(2021-06-27)
### ⚡ Performance Improvements
- **Icon** Remove the global registration of Icon components to prevent hot update issues under certain circumstances
### ✨ Features
- **Menu** Added `permissionMode=PermissionModeEnum.ROUTE_MAPPING` mode
- The project is changed to this mode by default, and the original menu file is deleted
- If you have written the menu before, you can change to `PermissionModeEnum.ROLE` mode
## 2.5.1(2021-06-26)
### ⚡ Performance Improvements
- Upgrade `vue` and `ant-design-vue` versions to solve compatibility issues
- **Tree** Performance optimization
### 🐛 Bug Fixes
- **Table** Fix page jitter problem
- **Upload** Make sure to carry custom parameters
- **Dropdown** Fix the icon display problem of popConfirm
- **Table** Fix the problem that the editing event of the tree table is abnormal
- **Table** Fix the problem that when the table data is empty, the value returned by getDataSource is not the data source used by the table
## 2.5.0(2021-06-20)
## (Breaking changes) Breaking changes
- Change the project `windicss` to `tailwindcss` to solve the memory overflow problem
- There are currently incompatible areas of the project
- The wording of `!xl:m-4` needs to be changed to `xl:!m-4`, note that only `!` is incompatible. If you dont use it, you dont need to change it.
- The new features of `windicss` itself need to be adjusted, for example, `Attribute` mode is not compatible
### ✨ Refactor
- Remove `useExpose` and use `expose` provided by the component itself instead
### ⚡ Performance Improvements
- **Locale** merge multi-language files to reduce the number of files
- **Utils** Mitt default export is changed from `Class` to `Function`
- **Axios** `isTransformRequestResult` is renamed to `isTransformResponse`
### ✨ Features
- **CropperImage** `Cropper` Avatar cropping adds circular cropping function
- **CropperAvatar** Added avatar upload component
- **Drawer** `useDrawer` added `closeDrawer` function
- **Preview** Added `createImgPreview` picture preview function
- **Setup** New guide page example
- **Tests** Add jest test suite, Vue component single test is not currently supported
- **Axios** Added `authenticationScheme` configuration to specify the authentication scheme
- **Setting** Added `sessionTimeoutProcessing` project configuration item, used to configure how to deal with session timeout
### 🐛 Bug Fixes
- **Modal** fix full screen height calculation error
- **Modal** Fix the problem that the shutdown event is triggered multiple times
- **PageWrapper** fix the height calculation problem
- **FlowChart** Repair drag and drop menu missing
- Fixed Iframe routing error in background mode
- **PageWrapper** Fix the height calculation problem when footer and global footer are opened at the same time
- **Menu** Fix the jitter problem of menu folding animation
- **Store** fixed type error after pinia version upgrade
## 2.4.2(2021-06-10)
### ✨ Refactor
- `CountTo` component refactoring
### ✨ Features
- `radioButtonGroup` supports `boolean` value
- `useModalInner` added `redoModalHeight` to reset the height of `Modal` inside Modal
- `useECharts` added `getInstance` to obtain instances of `echart`
- `TableAction` added `stopButtonPropagation` to prevent the action button click event from bubbling
- `BasicTable` in the row edit mode, you can get or set the value of other editing components in the column
- The `ApiSelect` component will automatically re-fetch the data after the `params` is changed
- `TableImg` component improvement
- `BasicTable` added `columns-change` event to monitor the user to change the sorting, display, and fixed status of columns
- `Tinymce` supports dynamic modification readonly
- `BasicTable` added `updateTableDataRecord` method to update the specified row data
- `useModal` added `closeModal` method to close `Modal`
### 🐛 Bug Fixes
- Fix the problem that `redoModalHeight` cannot reduce the height
- Fix the problem that the schema data of `BasicForm` does not take effect
- Fix the problem that multiple tags may cause `KeepAlive` to fail
- Fix the problem that the default `axios` interceptor cannot handle custom code
- Fix the height issue of the lock screen pop-up window
- Fixed the problem that the half-selected state of the `Column Display` checkbox of `BaiscTable` was incorrectly displayed
- Fixed the problem that the preview list of the `BasicUpload` component could not be displayed in some cases
- Fix the problem that the `options` setting of ` RadioButtonGroup``disabled ` does not take effect
- Fix the problem that the button for uploading pictures in the read-only mode of the `Tinymce` component is still available
- Fix the stuttering problem of `BasicForm` under certain circumstances
- Fix the problem that "directory" routing does not work
## 2.4.1(2021-06-01)
### ✨ Features
- Add `DatePicker` and `TimePicker` components to editable tables
- Added `defaultExpandLevel` configuration to `Tree` component
### ⚡ Performance Improvements
-Menu search default focus
### 🐛 Bug Fixes
- Fix known issues of `CodeEditor`
- Fix the issue of `i18n` console warning
- Fix the problem that the editable table `align` configuration does not take effect
- Ensure that `axios` only processes `Object` parameters
- Fix the failure of the `defaultExpandAll` configuration of the `Tree` component
- Fix the problem of missing dividing line in `TableAction`
- Fix the known issues of the table
- Fix that the lang attribute of HTML will not be set when reloading due to the first loading or changing the language
## 2.4.0 (2021-05-25)
### ✨ Features
-New graphical editor example -New code editor (including Json editor) -Added `JsonPreview`Json data viewing component -The fields of the data column and actionColumn of the table can be controlled according to the authority and business. -Added an example of a permission control table (AuthColumn.vue) -Added user login expiration example
### ⚡ Performance Improvements
-Consolidate some language files to reduce the number of files
### 🐛 Bug Fixes
-Fix the flashing white screen when the dark theme refreshes -Fix the problem that other functions are invalid when the tab is closed -Fix known issues in the form -Fix the automatic lock screen failure
## 2.3.0 (2021-04-10)
## (Breaking changes) Breaking changes
- Use `pinia` to replace `vuex`, `vuex-module-decorators`.
-Impact, if you used vuex-module-decorators yourself before, you need to transform it to pinia.
- the reason: -pinia is basically similar to vuex5api and is easy to understand. -Subsequent switching to vuex5 has a very low cost and can also be used as a third-party state management library
- Remove `useKeyPress` and use `vueuse`-`onKeyStroke` instead
- Remove `useDebounceFn` and use `vueuse`-`useDebounceFn` instead
- Remove `useThrottle` and use `vueuse`-`useThrottleFn` instead
### ✨ Features
- Tabs support persistent storage
### ✨ Refactor
- Remove `useElResize`
### 🐛 Bug Fixes
- Login page style fix
- Fix the known problems of the menu
- Fix the problem of theme style switching
## 2.2.0 (2021-04-06) ## 2.2.0 (2021-04-06)
### ✨ Features ### ✨ Features

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,399 @@
## 2.8.0(2021-11.03)
### 升级说明
- 包管理器由`yarn`改为 `pnpm`
- 删除`node_modules``yarn.lock`,全局安装`pnpm`
- 执行`pnpm install`
### ✨ Features
- **其它**
- `.env`文件中的`VITE_PROXY`配置支持单引号
- 移除 build 过程中的警告
### 🐛 Bug Fixes
- **BasicTable**
- 修复可编辑单元格某些情况下无法提交的问题
- 修复`inset`属性不起作用的问题
- 修复`useTable``BasicTable`实例的`reload`方法`await`表现不一致的问题
- 修复`clickToRowSelect`会无视行选择框 disabled 状态的问题
- 修复`BasicTable`在某些情况下,分页会被重置的问题
- 修改 `deleteTableDataRecord` 方法
- **BasicModal**
- 修复点击遮罩、按下`Esc`键都不能关闭`Modal`的问题
- 修复点击关闭按钮、最大化按钮旁边的空白区域也会导致`Modal`关闭的问题
- **BasicTree** 修复节点插槽不起作用的问题
- **CodeEditor** 修复可能会造成的`Build`失败的问题
- **BasicForm** 修复自定义 FormItem 组件的内容宽度可能超出范围的问题
- **ApiTreeSelect** 修复`params`变化未能触发重新请求 api 数据的问题
- **其它**
- 修复多标签在某些情况下关闭页签不会跳转路由的问题
- 修复部分组件可能会造成热更新异常的问题
- 修复直接`import`部分`antdv`子组件时会在 build 过程中报错的问题TabPane、RadioGroup
## 2.7.2(2021-09-14)
### ✨ Features
- **BasicForm** 表单组件新增`Divider`,用于较长表单的区域分割
- **BasicTable**
- 单元格编辑新增提交回调,将根据回调函数返回的结果来决定是否将数据提交到表格
- 行编辑添加校验方法,允许只校验而不提交值,以便异步保存数据成功后才提交倒表格
- 修复`rowClassName`属性无法和`striped`同时使用的问题
- 新增组件 **MarkdownViewer** 用于显示 Markdown 格式的富文本
### 🐛 Bug Fixes
- **CodeEditor** 修复 JSON 编辑器在格式化无效 JSON 文本时会抛出异常的问题
- **Tinymce** 修复 inline 模式在一些场景下会出现异常的问题
- **BasicTable**
- 修复可编辑单元格的内容为空时,不会显示编辑图标的问题
- 修复表尾合计行与表格主体部分的列有时候未能对齐的问题
- **MarkDown** 修复初始 value 属性的值不起作用的问题
- **BasicUpload** 修复`accept`属性不支持`MIME`及点开头的后缀名的问题
- **ApiSelect** 修复`value`属性的类型定义问题
- **其它**
- 修复部分封装组件在使用插槽时报错的问题
- 修复`useECharts``theme`参数不起作用的问题
- 修复`Token`失效时,按 F5 刷新页面可能会出现页面加载异常的问题
- 修复`useRedo`的不当调用可能会导致重定向`path`异常的问题
- 修复`vite`自定义模式名称不支持下划线的问题
## 2.7.1(2021-08-16)
- 升级 vue 3.2,如果运行失败,删除 node_modules 后重装即可
### ✨ Features
- **BasicTree** 添加搜索功能相关属性和方法
- **BasicForm** 新增`alwaysShowLines`用于设置折叠时保留显示的行数
### 🐛 Bug Fixes
- **Cropper** 修复未能及时销毁的问题
- **BasicTable**
- 修复`CellFormat`无法使用`Map`类型数据的问题
- 修复可编辑单元格未能正确显示`0`值的问题
- 修复 selection-change 事件在取消勾选时未能正确触发的问题
- 修复浅色主题下的全屏状态背景颜色不正确的问题
- 修复`getSelectRows`不支持远程数据跨页选择时获取完整数据的问题
- 修复在`editComponentProps`中为编辑组件提供的`size`属性无效的问题
- **Qrcode** 修复二维码组件在创建时未能及时绘制的问题
- **BasicModal** 修复`helpMessage`属性不起作用的问题
- **BasicButton** 修复按钮样式表现与 antd 官方不一致的问题
- **其它** 修复`useRedo`(重新加载当前路由)会丢失路由`params`数据的问题
## 2.7.0(2021-08-03)
## (破坏性更新) Breaking changes
- 将项目`tailwindcss`还原回`windicss`,尝试了`tailwindcss`,问题可能还挺多,先切换回`windicss`提高开发效率,切换成本较低。
- 目前项目不兼容地方有
- `xl:!m-4` 之类的写法需要改为`!xl:m-4`,注意只有`!`这个不兼容,没用到则不用改
- 内存溢出问题可能还在(频率低,重启下即可,重启 vite 较快)
### ✨ Features
- **Preview** 添加新的属性及事件
- **Dark Theme** 新增对 tailwindcss 夜间模式的支持
- **其它** 为 useLoading 添加 setTip 方法
### 🐛 Bug Fixes
- **ApiTreeSelect** 修复未能正确监听`params`变化的问题
- **ImgRotateDragVerify** 修复组件`resume`方法无法调用的问题
- **TableAction** 修复 stopButtonPropagation 属性某些情况下不起作用的问题
- **PageWrapper** 修复`class`属性无效的问题
- **BasicTree** 修复`checkAll`方法会影响到`disabled`状态节点的问题
- **BasicTable**
- 修复可编辑单元格不支持`ellipsis`配置的问题
- 修复全屏模式下看不到子组件弹出层popconfirm 以及 select、treeSelect 等编辑组件)的问题
- 修复启用`expandRowByClick`时,点击不可展开的行可能会导致样式错误的问题
- 修复`pagination`属性动态改变不生效的问题
- 修复`getSelectRows`不支持树形表格子级数据的问题
- **Dark Theme** 黑暗主题下的配色问题修正
- 修复`Tree`组件被选中节点的背景颜色
- 修复`Alert`组件的颜色配置
- 修复禁用状态下的`link`类型的按钮颜色问题
- 修复`Tree`已勾选的复选框的样式问题
- **其它** 修复 useScript 未能自动移除 script 节点的问题
## 2.6.1(2021-07-19)
### ✨ Features
- **NoticeList** 添加分页、超长自动省略、标题点击事件、标题删除线等功能
- **MixSider** 优化 Mix 菜单布局时 底部折叠按钮 的样式,与其它菜单布局时的风格保持一致
- **ApiTreeSelect** 扩展`antdv``TreeSelect`组件,支持远程数据源,用法类似`ApiSelect`
- **BasicTable**
- 新增`ApiTreeSelect`编辑组件
- 新增`headerTop`插槽
- **其它** 可以为不同的用户指定不同的后台首页:
-`getUserInfo`接口返回的用户信息中增加`homePath`字段(可选)即可为当前用户定制首页路径
### 🐛 Bug Fixes
- **BasicTable**
- 修复滚动条样式问题(移除了滚动样式补丁)
- 修复树形表格的带有展开图标的单元格的内容对齐问题
- 修复操作列的按钮在 disabled 状态下的颜色显示
- 修复可编辑单元格的值不能直接通过修改`dataSource`来更新显示的问题
- 修复使用`ApiSelect`编辑组件时的数据回显问题
- 修复在部分场景下编辑组件可能会报`onXXX`类型错误的问题
- **TableAction**
- 仅在 `action.tooltip`存在的情况下 才创建 Tooltip 组件
- 修复组件内的圆形按钮内容没有居中的问题
- **AppSearch** 修复可能会搜索隐藏菜单的问题
- **BasicUpload** 修复处理非`array`值时报错的问题
- **Form** 修复`FormItem``suffix`插槽样式问题
- **Menu**
- 修复左侧混合菜单的悬停触发逻辑
- 修复顶栏菜单在显示包含需要隐藏的菜单项目时出错的问题
- 修复悬停触发模式下左侧混合菜单会在没有子菜单且被激活时直接跳转路由
- **Breadcrumb** 修复带有重定向的菜单点击无法跳转的问题
- **Markdown** 修复初始化异常以及不能正确地动态设置 value 的问题
- **Modal** 确保 props 正确被传递
- **MultipleTab** 修复可能会意外创建登录路由标签的问题
- **BasicTree** 修复搜索功能可能导致`checkedKeys`丢失的问题
- **CodeEditor** 修复 value 不支持 v-model 用法的问题
- **CountdownInput** 修复不支持`input`插槽的问题
- **ApiSelect** 修复`options-change`事件参数不是`select`所使用的标准`options`数据的问题
- **其它**
- 修复菜单默认折叠的配置不起作用的问题
- 修复`safari`浏览器报错导致网站打不开
- 修复在 window 上,拉取代码后 eslint 因 endOfLine 而报错问题
- 修复因动态路由而产生的 `Vue Router warn`
### 🎫 Chores
- 添加 test 环境测试命令
## 2.6.0(2021-07-04)
### ✨ Features
- **Axios** 新增`withToken`配置,用于控制请求是否携带 token
- **BasicUpload**
- 新增在预览 `Modal` 中删除文件时触发`preview-delete` 事件
- `value` 支持 `v-model` 用法
- **Route 配置**
- 增加`ignoreRoute`用于在`ROUTE_MAPPING``BACK`权限模式下仅生成菜单
- 增加`hidePathForChildren`配置,标识为子项目生成菜单时忽略本级`path`
- **TableAction** 新增`tooltip`配置,可以为按钮增加 tooltip 提示
- **CropperAvatar**
- 新增`value`用于设置当前头像
- 新增`onChange`用于接受头像剪裁并上传成功事件
- 新增`btnText``btnProps` 用于自定义上传按钮文案和属性
- 为剪裁`Modal`内的操作按钮添加工具提示
- **Modal** 为右上角的操作按钮添加工具提示
### 🐛 Bug Fixes
- **Modal**
- 修复点击遮罩不能关闭的问题
- 修复 `setModalProps` 不支持设置 `defaultFullscreen` 的问题
- **Table**
- 修复 `editComponentProps` 不支持 `onChange`的问题
- 修复启用`clickToRowSelect`时,点击行不会触发`selection-change`事件的问题
- 修复全局配置`fetchSetting`可能会被局部配置意外修改的问题
- 修复`handleSearchInfoFn`的参数包含多余空白键的问题
- 修复为 table 提供 rowSelection.onChange 时,无法手动变更 table 的选中项的问题
- 修复滚动条在无需显示的时候仍然持续显示的问题
- **Icon** 修复 SvgIcon 缺少部分样式的问题
- **Menu**
- 修复路由映射模式下,单级菜单刷新不会激活
- 修复侧边菜单底部的折叠自定义失效的问题
- **Form** 修复`submitButtonOptions``resetButtonOptions`的类型定义
- **PopConfirmButton** 移除`Button`上多余的`title`
- **Axios** 修复非`GET`请求时,无法同时提交`params``data`数据的问题
- **其它**
- 修复锁屏功能可以通过刷新页面或复制 URL 打开新的浏览器标签来跳过锁定状态的问题
- 修复多个窗口同时打开页面时,`Token` 不会同步的问题
- 修复`ROLE`权限模式下`hasPermission`不工作的问题
- **Table** 修复`handleSearchInfoFn`的参数包含多余空白键的问题
- **Tailwindcss** 移除控制台警告
## 2.5.2(2021-06-27)
### ⚡ Performance Improvements
- **Icon** 移除 Icon 组件全局注册,防止特定情况下热更新问题
### ✨ Features
- **Menu** 新增 `permissionMode=PermissionModeEnum.ROUTE_MAPPING`模式
- 项目默认改为该模式,删除原有菜单文件
- 如果之前已经写好了菜单,可以更改为`PermissionModeEnum.ROLE`模式即可
### 🐛 Bug Fixes
- **Drawer** 修复`visible`状态异常
## 2.5.1(2021-06-26)
### ⚡ Performance Improvements
- 升级`vue``ant-design-vue`版本,解决兼容问题
- **Tree** 性能优化
### 🐛 Bug Fixes
- **Table** 修复分页抖动问题
- **Upload** 确保携带自定义参数
- **Dropdown** 修复 popConfirm 的图标显示问题
- **Table** 修复树形表格的编辑事件不正常的问题
- **Table** 修复当表格数据为空时getDataSource 返回的值不是表格所使用的数据源的问题
## 2.5.0(2021-06-20)
## (破坏性更新) Breaking changes
- 将项目`windicss`改为`tailwindcss`,解决内存溢出问题
- 目前项目不兼容地方有
- `!xl:m-4` 之类的写法需要改为`xl:!m-4`,注意只有`!`这个不兼容,没用到则不用改
- `windicss`自身新增的特性需要调整,比如`Attribute`模式不兼容
### ✨ Refactor
- 移除`useExpose`,使用组件自身提供的`expose`代替
### ⚡ Performance Improvements
- **Locale** 合并多语言文件,减少文件数量
- **Utils** Mitt 默认导出由 `Class` 改为 `Function`
- **Axios** `isTransformRequestResult`更名为`isTransformResponse`
### ✨ Features
- **CropperImage** `Cropper` 头像裁剪新增圆形裁剪功能
- **CropperAvatar** 新增头像上传组件
- **Drawer** `useDrawer`新增`closeDrawer`函数
- **Preview** 新增`createImgPreview`图片预览函数
- **Setup** 新增引导页示例
- **Tests** 添加 jest 测试套件,暂不支持 Vue 组件单测
- **Axios** 新增`authenticationScheme`配置,用于指定认证方案
- **Setting** 新增 `sessionTimeoutProcessing` 项目配置项,用于配置会话超时如何处理
### 🐛 Bug Fixes
- **Modal** 修复全屏高度计算错误
- **Modal** 修复关闭事件触发多次问题
- **PageWrapper** 修复高度计算问题
- **FlowChart** 修复拖放菜单丢失
- 修复后台模式下Iframe 路由错误
- **PageWrapper** 修复 footer 与全局页脚同时开启时的高度计算问题
- **Menu** 修复菜单折叠动画抖动问题
- **Store**修复 pinia 版本升级之后类型错误
## 2.4.2(2021-06-10)
### ✨ Refactor
- `CountTo`组件重构
### ✨ Features
- `radioButtonGroup` 支持`boolean`
- `useModalInner` 新增 `redoModalHeight`用于在 Modal 内部重设`Modal`高度
- `useECharts` 新增`getInstance`用于获取`echart`实例
- `TableAction` 新增 `stopButtonPropagation` 阻止操作按钮点击事件冒泡
- `BasicTable` 在行编辑模式下,可以获取或设置其它处于列的编辑组件的值
- `ApiSelect` 组件在`params`改变后会自动重新`fetch`数据
- `TableImg` 组件改进
- `BasicTable` 新增 `columns-change` 事件用于监听用户改变列排序、展示、固定状态
- `Tinymce`支持动态修改 readonly
- `BasicTable`新增`updateTableDataRecord`方法用于更新指定行数据
- `useModal`新增`closeModal`方法用于关闭`Modal`
### 🐛 Bug Fixes
- 修复`redoModalHeight`不能减小高度的问题
- 修复 `BasicForm`设置 schemas 数据不生效的问题
- 修复多标签可能导致`KeepAlive`失效的问题
- 修复默认的`axios`拦截器不能处理自定义 code 的问题
- 修复锁屏弹窗的高度问题
- 修复`BaiscTable``列展示`复选框的半选状态显示不正确的问题
- 修复`BasicUpload`组件的预览列表某些情况下不能显示的问题
- 修复`RadioButtonGroup``options`设置`disabled`不生效的问题
- 修复`Tinymce`组件在只读模式下上传图片的按钮仍然可用的问题
- 修复`BasicForm`特定情况下的卡顿问题
- 修复"目录"路由不起作用的问题
## 2.4.1(2021-06-01)
### ✨ Features
- 可编辑表格新增`DatePicker``TimePicker`组件
- `Tree` 组件新增`defaultExpandLevel`配置
### ⚡ Performance Improvements
- 菜单搜索默认聚焦
### 🐛 Bug Fixes
- 修复`CodeEditor`已知问题
- 修复`i18n`控制台警告问题
- 修复可编辑表格`align`配置不生效问题
- 确保`axios`只对`Object`参数进行处理
- 修复`Tree`组件 `defaultExpandAll` 配置失效
- 修复`TableAction` 分割线丢失问题
- 修复表格已知问题
- 修复首次加载或改变语言导致重载时,不会设置 HTML 的 lang 属性
## 2.4.0 (2021-05-25)
### ✨ Features
- 新增图形编辑器示例
- 新增代码编辑器(包含 Json 编辑器)
- 新增 `JsonPreview`Json 数据查看组件
- 表格的数据列(column)和操作列(actionColumn)的字段可以根据权限和业务来控制是否显示
- 新增权限控制表格示例(AuthColumn.vue)
- 新增用户登录过期示例
### ⚡ Performance Improvements
- 合并部分语言文件,减少文件数量
### 🐛 Bug Fixes
- 修复黑暗主题刷新闪烁的白屏
- 修复标签页关闭其他功能失效问题
- 修复表单已知问题
- 修复自动锁屏失效
## 2.3.0 (2021-04-10)
## (破坏性更新) Breaking changes
- 使用 `pinia` 替换 `vuex`,`vuex-module-decorators`
- 影响,之前如果有自己使用 vuex-module-decorators需要改造为 pinia。
- 原因:
- pinia 于 vuex5api 基本类似,且简单易懂。
- 后续切换 vuex5 成本非常低,也可以当作第三方状态管理库使用
- 移除 `useKeyPress` 使用`vueuse`-`onKeyStroke`代替
- 移除 `useDebounceFn` 使用`vueuse`-`useDebounceFn`代替
- 移除 `useThrottle` 使用`vueuse`-`useThrottleFn`代替
### ✨ Features
- 标签页支持持久化保存
### ✨ Refactor
- 移除 `useElResize`
### 🐛 Bug Fixes
- 登录页样式修复
- 修复菜单已知问题
- 修复主题样式切换问题
## 2.2.0 (2021-04-06) ## 2.2.0 (2021-04-06)
### ✨ Features ### ✨ Features

View File

@@ -70,20 +70,20 @@ git clone https://github.com/anncwb/vue-vben-admin.git
```bash ```bash
cd vue-vben-admin cd vue-vben-admin
yarn install pnpm install
``` ```
- run - run
```bash ```bash
yarn serve pnpm serve
``` ```
- build - build
```bash ```bash
yarn build pnpm build
``` ```
## Change Log ## Change Log

View File

@@ -70,20 +70,20 @@ git clone https://github.com/anncwb/vue-vben-admin.git
```bash ```bash
cd vue-vben-admin cd vue-vben-admin
yarn install pnpm install
``` ```
- 运行 - 运行
```bash ```bash
yarn serve pnpm serve
``` ```
- 打包 - 打包
```bash ```bash
yarn build pnpm build
``` ```
## 更新日志 ## 更新日志
@@ -150,6 +150,7 @@ yarn build
## 后台整合示例 ## 后台整合示例
- [lamp-cloud](https://github.com/zuihou/lamp-cloud) - 基于 SpringCloud Alibaba 的微服务中后台快速开发平台 - [lamp-cloud](https://github.com/zuihou/lamp-cloud) - 基于 SpringCloud Alibaba 的微服务中后台快速开发平台
- [matecloud](https://github.com/matevip/matecloud) - MateCloud 微服务脚手架,基于 Spring Cloud 2020.0.3、SpringBoot 2.5.3 的全开源平台
## 维护者 ## 维护者

View File

@@ -0,0 +1,63 @@
import path from 'path';
import { RollupOptions } from 'rollup';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import esbuild from 'rollup-plugin-esbuild';
import alias from '@rollup/plugin-alias';
import json from '@rollup/plugin-json';
export function getRollupOptions(): RollupOptions {
return {
input: path.join(__dirname, '../../electron-main/index.ts'),
output: {
file: path.join(__dirname, '../../dist/main/build.js'),
format: 'cjs',
name: 'ElectronMainBundle',
sourcemap: true,
},
plugins: [
nodeResolve({ preferBuiltins: true, browser: true }), // 消除碰到 node.js 模块时⚠警告
commonjs(),
json(),
esbuild({
// All options are optional
include: /\.[jt]sx?$/, // default, inferred from `loaders` option
exclude: /node_modules/, // default
// watch: process.argv.includes('--watch'), // rollup 中有配置
sourceMap: false, // default
minify: process.env.NODE_ENV === 'production',
target: 'es2017', // default, or 'es20XX', 'esnext'
jsxFactory: 'React.createElement',
jsxFragment: 'React.Fragment',
// Like @rollup/plugin-replace
define: {
__VERSION__: '"x.y.z"',
},
// Add extra loaders
loaders: {
// Add .json files support
// require @rollup/plugin-commonjs
'.json': 'json',
// Enable JSX in .js files too
'.js': 'jsx',
},
}),
alias({
entries: [{ find: '/@main/', replacement: path.join(__dirname, '../../electron-main') }],
}),
],
external: [
'crypto',
'assert',
'fs',
'util',
'os',
'events',
'child_process',
'http',
'https',
'path',
'electron',
],
};
}

View File

@@ -6,6 +6,8 @@ export const darkMode = 'light';
type Fn = (...arg: any) => any; type Fn = (...arg: any) => any;
type GenerateTheme = 'default' | 'dark';
export interface GenerateColorsParams { export interface GenerateColorsParams {
mixLighten: Fn; mixLighten: Fn;
mixDarken: Fn; mixDarken: Fn;
@@ -13,19 +15,19 @@ export interface GenerateColorsParams {
color?: string; color?: string;
} }
export function generateAntColors(color: string) { export function generateAntColors(color: string, theme: GenerateTheme = 'default') {
return generate(color, { return generate(color, {
theme: 'default', theme,
}); });
} }
export function getThemeColors(color?: string) { export function getThemeColors(color?: string) {
const tc = color || primaryColor; const tc = color || primaryColor;
const colors = generateAntColors(tc); const lightColors = generateAntColors(tc);
const primary = colors[5]; const primary = lightColors[5];
const modeColors = generateAntColors(primary); const modeColors = generateAntColors(primary, 'dark');
return [...colors, ...modeColors]; return [...lightColors, ...modeColors];
} }
export function generateColors({ export function generateColors({
@@ -49,6 +51,8 @@ export function generateColors({
.toRgbString(); .toRgbString();
}); });
const shortAlphaColors = alphaColors.map((item) => item.replace(/\s/g, '').replace(/0\./g, '.'));
const tinycolorLightens = arr const tinycolorLightens = arr
.map((_t, i) => { .map((_t, i) => {
return tinycolor(color) return tinycolor(color)
@@ -64,5 +68,12 @@ export function generateColors({
.toHexString(); .toHexString();
}) })
.filter((item) => item !== '#000000'); .filter((item) => item !== '#000000');
return [...lightens, ...darkens, ...alphaColors, ...tinycolorDarkens, ...tinycolorLightens]; return [
...lightens,
...darkens,
...alphaColors,
...shortAlphaColors,
...tinycolorDarkens,
...tinycolorLightens,
].filter((item) => !item.includes('-'));
} }

View File

@@ -28,8 +28,10 @@ export function generateModifyVars(dark = false) {
'success-color': '#55D187', // Success color 'success-color': '#55D187', // Success color
'error-color': '#ED6F6F', // False color 'error-color': '#ED6F6F', // False color
'warning-color': '#EFBD47', // Warning color 'warning-color': '#EFBD47', // Warning color
//'border-color-base': '#EEEEEE',
'font-size-base': '14px', // Main font size 'font-size-base': '14px', // Main font size
'border-radius-base': '2px', // Component/float fillet 'border-radius-base': '2px', // Component/float fillet
'link-color': primary, // Link color 'link-color': primary, // Link color
'app-content-background': '#fafafa', // Link color
}; };
} }

View File

@@ -1,7 +1,7 @@
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import inquirer from 'inquirer'; import inquirer from 'inquirer';
import chalk from 'chalk'; import colors from 'picocolors';
import pkg from '../../../package.json'; import pkg from '../../../package.json';
async function generateIcon() { async function generateIcon() {
@@ -52,19 +52,19 @@ async function generateIcon() {
const { prefix } = data; const { prefix } = data;
const isLocal = useType === 'local'; const isLocal = useType === 'local';
const icons = Object.keys(data.icons).map( const icons = Object.keys(data.icons).map(
(item) => `${isLocal ? prefix + ':' : ''}${item}` (item) => `${isLocal ? prefix + ':' : ''}${item}`,
); );
await fs.writeFileSync( await fs.writeFileSync(
path.join(output, `icons.data.ts`), path.join(output, `icons.data.ts`),
`export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}` `export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`,
); );
prefixSet.push(prefix); prefixSet.push(prefix);
} }
} }
fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite')); fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite'));
console.log( console.log(
`${chalk.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]` `${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`,
); );
}); });
} }

View File

@@ -3,20 +3,21 @@
*/ */
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant'; import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
import fs, { writeFileSync } from 'fs-extra'; import fs, { writeFileSync } from 'fs-extra';
import chalk from 'chalk'; import colors from 'picocolors';
import { getRootPath, getEnvConfig } from '../utils'; import { getEnvConfig, getRootPath } from '../utils';
import { getConfigFileName } from '../getConfigFileName'; import { getConfigFileName } from '../getConfigFileName';
import pkg from '../../package.json'; import pkg from '../../package.json';
function createConfig( interface CreateConfigParams {
{ configName: string;
configName, config: any;
config, configFileName?: string;
configFileName = GLOB_CONFIG_FILE_NAME, }
}: { configName: string; config: any; configFileName?: string } = { configName: '', config: {} }
) { function createConfig(params: CreateConfigParams) {
const { configName, config, configFileName } = params;
try { try {
const windowConf = `window.${configName}`; const windowConf = `window.${configName}`;
// Ensure that the variable will not be modified // Ensure that the variable will not be modified
@@ -30,15 +31,15 @@ function createConfig(
fs.mkdirp(getRootPath(OUTPUT_DIR)); fs.mkdirp(getRootPath(OUTPUT_DIR));
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr); writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr);
console.log(chalk.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`); console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`);
console.log(chalk.gray(OUTPUT_DIR + '/' + chalk.green(configFileName)) + '\n'); console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n');
} catch (error) { } catch (error) {
console.log(chalk.red('configuration file configuration file failed to package:\n' + error)); console.log(colors.red('configuration file configuration file failed to package:\n' + error));
} }
} }
export function runBuildConfig() { export function runBuildConfig() {
const config = getEnvConfig(); const config = getEnvConfig();
const configFileName = getConfigFileName(config); const configFileName = getConfigFileName(config);
createConfig({ config, configName: configFileName }); createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME });
} }

View File

@@ -0,0 +1,76 @@
import rollup, { OutputOptions } from 'rollup';
import chalk from 'chalk';
import ora from 'ora';
import waitOn from 'wait-on';
import net from 'net';
import { URL } from 'url';
import minimist from 'minimist';
import electronConnect from 'electron-connect';
import { getRollupOptions } from '../config/rollupElectronConfig';
const argv = minimist(process.argv.slice(2));
const TAG = '[compiler-electron]';
export function startCompilerElectron(port = 80) {
// 因为 vite 不会重定向到 index.html所以直接写 index.html 路由。
const ELECTRON_URL = `https://localhost:${port}/index.html`;
const spinner = ora(`${TAG} Electron build...`);
const electron = electronConnect.server.create({ stopOnClose: true });
const rollupOptions = getRollupOptions();
function watchFunc() {
// once here, all resources are available
const watcher = rollup.watch(rollupOptions);
watcher.on('change', (filename) => {
const log = chalk.green(`change -- ${filename}`);
console.log(TAG, log);
});
watcher.on('event', (ev) => {
if (ev.code === 'END') {
// init-未启动、started-第一次启动、restarted-重新启动
electron.electronState === 'init' ? electron.start() : electron.restart();
} else if (ev.code === 'ERROR') {
console.log(ev.error);
}
});
}
if (argv.watch) {
waitOn(
{
resources: [ELECTRON_URL],
timeout: 5000,
},
(err) => {
if (err) {
const { hostname } = new URL(ELECTRON_URL);
const serverSocket = net.connect(port, hostname, () => {
watchFunc();
});
serverSocket.on('error', (e) => {
console.log(err);
console.log(e);
process.exit(1);
});
} else {
watchFunc();
}
}
);
} else {
spinner.start();
rollup
.rollup(rollupOptions)
.then((build) => {
spinner.stop();
console.log(TAG, chalk.green('Electron build successed.'));
build.write(rollupOptions.output as OutputOptions);
})
.catch((error) => {
spinner.stop();
console.log(`\n${TAG} ${chalk.red('构建报错')}\n`, error, '\n');
});
}
}

View File

@@ -1,7 +1,7 @@
// #!/usr/bin/env node // #!/usr/bin/env node
import { runBuildConfig } from './buildConf'; import { runBuildConfig } from './buildConf';
import chalk from 'chalk'; import colors from 'picocolors';
import pkg from '../../package.json'; import pkg from '../../package.json';
@@ -11,12 +11,12 @@ export const runBuild = async () => {
// Generate configuration file // Generate configuration file
if (!argvList.includes('disabled-config')) { if (!argvList.includes('disabled-config')) {
await runBuildConfig(); runBuildConfig();
} }
console.log(`${chalk.cyan(`[${pkg.name}]`)}` + ' - build successfully!'); console.log(`${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!');
} catch (error) { } catch (error) {
console.log(chalk.red('vite build error:\n' + error)); console.log(colors.red('vite build error:\n' + error));
process.exit(1); process.exit(1);
} }
}; };

View File

@@ -0,0 +1,22 @@
import { createServer } from 'vite';
import path from 'path';
import { startCompilerElectron } from './compilerElectron';
import minimist from 'minimist';
(async () => {
const argv = minimist(process.argv.slice(2));
console.log(argv);
const isDev = argv.env === 'development';
let port: number | undefined = undefined;
if (isDev) {
const server = await createServer({
root: path.resolve(__dirname, '../../'),
});
const app = await server.listen();
port = app.config.server.port;
process.env.PORT = `${port}`;
}
startCompilerElectron(port);
})();

View File

@@ -28,33 +28,54 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
if (envName === 'VITE_PORT') { if (envName === 'VITE_PORT') {
realName = Number(realName); realName = Number(realName);
} }
if (envName === 'VITE_PROXY') { if (envName === 'VITE_PROXY' && realName) {
try { try {
realName = JSON.parse(realName); realName = JSON.parse(realName.replace(/'/g, '"'));
} catch (error) {} } catch (error) {
realName = '';
}
} }
ret[envName] = realName; ret[envName] = realName;
process.env[envName] = realName; if (typeof realName === 'string') {
process.env[envName] = realName;
} else if (typeof realName === 'object') {
process.env[envName] = JSON.stringify(realName);
}
} }
return ret; return ret;
} }
/**
* 获取当前环境下生效的配置文件名
*/
function getConfFiles() {
const script = process.env.npm_lifecycle_script;
const reg = new RegExp('--mode ([a-z_\\d]+)');
const result = reg.exec(script as string) as any;
if (result) {
const mode = result[1] as string;
return ['.env', `.env.${mode}`];
}
return ['.env', '.env.production'];
}
/** /**
* Get the environment variables starting with the specified prefix * Get the environment variables starting with the specified prefix
* @param match prefix * @param match prefix
* @param confFiles ext * @param confFiles ext
*/ */
export function getEnvConfig(match = 'VITE_GLOB_', confFiles = ['.env', '.env.production']) { export function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
let envConfig = {}; let envConfig = {};
confFiles.forEach((item) => { confFiles.forEach((item) => {
try { try {
const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item))); const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item)));
envConfig = { ...envConfig, ...env }; envConfig = { ...envConfig, ...env };
} catch (error) {} } catch (e) {
console.error(`Error in parsing ${item}`, e);
}
}); });
const reg = new RegExp(`^(${match})`);
Object.keys(envConfig).forEach((key) => { Object.keys(envConfig).forEach((key) => {
const reg = new RegExp(`^(${match})`);
if (!reg.test(key)) { if (!reg.test(key)) {
Reflect.deleteProperty(envConfig, key); Reflect.deleteProperty(envConfig, key);
} }

View File

@@ -1,21 +0,0 @@
// TODO
import type { GetManualChunk } from 'rollup';
//
const vendorLibs: { match: string[]; output: string }[] = [
// {
// match: ['xlsx'],
// output: 'xlsx',
// },
];
// @ts-ignore
export const configManualChunk: GetManualChunk = (id: string) => {
if (/[\\/]node_modules[\\/]/.test(id)) {
const matchItem = vendorLibs.find((item) => {
const reg = new RegExp(`[\\/]node_modules[\\/]_?(${item.match.join('|')})(.*)`, 'ig');
return reg.test(id);
});
return matchItem ? matchItem.output : null;
}
};

View File

@@ -2,33 +2,33 @@
* Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated
* https://github.com/anncwb/vite-plugin-compression * https://github.com/anncwb/vite-plugin-compression
*/ */
import type { Plugin } from 'vite'; import type { PluginOption } from 'vite';
import compressPlugin from 'vite-plugin-compression'; import compressPlugin from 'vite-plugin-compression';
export function configCompressPlugin( export function configCompressPlugin(
compress: 'gzip' | 'brotli' | 'none', compress: 'gzip' | 'brotli' | 'none',
deleteOriginFile: boolean = false deleteOriginFile = false,
): Plugin | Plugin[] { ): PluginOption | PluginOption[] {
const compressList = compress.split(','); const compressList = compress.split(',');
const plugins: Plugin[] = []; const plugins: PluginOption[] = [];
if (compressList.includes('gzip')) { if (compressList.includes('gzip')) {
plugins.push( plugins.push(
compressPlugin({ compressPlugin({
ext: '.gz', ext: '.gz',
deleteOriginFile, deleteOriginFile,
}) }),
); );
} }
if (compressList.includes('brotli')) { if (compressList.includes('brotli')) {
plugins.push( plugins.push(
compressPlugin({ compressPlugin({
ext: '.br', ext: '.br',
algorithm: 'brotliCompress', algorithm: 'brotliCompress',
deleteOriginFile, deleteOriginFile,
}) }),
); );
} }
return plugins; return plugins;

View File

@@ -1,21 +0,0 @@
import type { Plugin } from 'vite';
/**
* TODO
* Temporarily solve the Vite circular dependency problem, and wait for a better solution to fix it later. I don't know what problems this writing will bring.
* @returns
*/
export function configHmrPlugin(): Plugin {
return {
name: 'singleHMR',
handleHotUpdate({ modules, file }) {
if (file.match(/xml$/)) return [];
modules.forEach((m) => {
m.importedModules = new Set();
m.importers = new Set();
});
return modules;
},
};
}

View File

@@ -2,10 +2,8 @@
* Plugin to minimize and use ejs template syntax in index.html. * Plugin to minimize and use ejs template syntax in index.html.
* https://github.com/anncwb/vite-plugin-html * https://github.com/anncwb/vite-plugin-html
*/ */
import type { Plugin } from 'vite'; import type { PluginOption } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';
import html from 'vite-plugin-html';
import pkg from '../../../package.json'; import pkg from '../../../package.json';
import { GLOB_CONFIG_FILE_NAME } from '../../constant'; import { GLOB_CONFIG_FILE_NAME } from '../../constant';
@@ -18,11 +16,11 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`; return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
}; };
const htmlPlugin: Plugin[] = html({ const htmlPlugin: PluginOption[] = createHtmlPlugin({
minify: isBuild, minify: isBuild,
inject: { inject: {
// Inject data into ejs template // Inject data into ejs template
injectData: { data: {
title: VITE_GLOB_APP_TITLE, title: VITE_GLOB_APP_TITLE,
}, },
// Embed the generated app.config.js file // Embed the generated app.config.js file

View File

@@ -1,6 +1,5 @@
// Image resource files used to compress the output of the production environment // Image resource files used to compress the output of the production environment
// https://github.com/anncwb/vite-plugin-imagemin // https://github.com/anncwb/vite-plugin-imagemin
import viteImagemin from 'vite-plugin-imagemin'; import viteImagemin from 'vite-plugin-imagemin';
export function configImageminPlugin() { export function configImageminPlugin() {
@@ -13,7 +12,7 @@ export function configImageminPlugin() {
optimizationLevel: 7, optimizationLevel: 7,
}, },
mozjpeg: { mozjpeg: {
quality: 8, quality: 20,
}, },
pngquant: { pngquant: {
quality: [0.8, 0.9], quality: [0.8, 0.9],
@@ -22,10 +21,11 @@ export function configImageminPlugin() {
svgo: { svgo: {
plugins: [ plugins: [
{ {
removeViewBox: false, name: 'removeViewBox',
}, },
{ {
removeEmptyAttrs: false, name: 'removeEmptyAttrs',
active: false,
}, },
], ],
}, },

View File

@@ -1,11 +1,11 @@
import type { Plugin } from 'vite'; import { PluginOption } from 'vite';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'; import vueJsx from '@vitejs/plugin-vue-jsx';
import legacy from '@vitejs/plugin-legacy'; import legacy from '@vitejs/plugin-legacy';
import purgeIcons from 'vite-plugin-purge-icons';
import PurgeIcons from 'vite-plugin-purge-icons'; import windiCSS from 'vite-plugin-windicss';
import VitePluginCertificate from 'vite-plugin-mkcert';
import vueSetupExtend from 'vite-plugin-vue-setup-extend';
import { configHtmlPlugin } from './html'; import { configHtmlPlugin } from './html';
import { configPwaConfig } from './pwa'; import { configPwaConfig } from './pwa';
import { configMockPlugin } from './mock'; import { configMockPlugin } from './mock';
@@ -14,9 +14,7 @@ import { configStyleImportPlugin } from './styleImport';
import { configVisualizerConfig } from './visualizer'; import { configVisualizerConfig } from './visualizer';
import { configThemePlugin } from './theme'; import { configThemePlugin } from './theme';
import { configImageminPlugin } from './imagemin'; import { configImageminPlugin } from './imagemin';
import { configWindiCssPlugin } from './windicss';
import { configSvgIconsPlugin } from './svgSprite'; import { configSvgIconsPlugin } from './svgSprite';
import { configHmrPlugin } from './hmr';
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const { const {
@@ -27,15 +25,20 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE,
} = viteEnv; } = viteEnv;
const vitePlugins: (Plugin | Plugin[])[] = [ const vitePlugins: (PluginOption | PluginOption[])[] = [
// have to // have to
vue(), vue(),
// have to // have to
vueJsx(), vueJsx(),
// support name
vueSetupExtend(),
VitePluginCertificate({
source: 'coding',
}),
]; ];
// TODO // vite-plugin-windicss
!isBuild && vitePlugins.push(configHmrPlugin()); vitePlugins.push(windiCSS());
// @vitejs/plugin-legacy // @vitejs/plugin-legacy
VITE_LEGACY && isBuild && vitePlugins.push(legacy()); VITE_LEGACY && isBuild && vitePlugins.push(legacy());
@@ -46,14 +49,11 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
// vite-plugin-svg-icons // vite-plugin-svg-icons
vitePlugins.push(configSvgIconsPlugin(isBuild)); vitePlugins.push(configSvgIconsPlugin(isBuild));
// vite-plugin-windicss
vitePlugins.push(configWindiCssPlugin());
// vite-plugin-mock // vite-plugin-mock
VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild)); VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild));
// vite-plugin-purge-icons // vite-plugin-purge-icons
vitePlugins.push(PurgeIcons()); vitePlugins.push(purgeIcons());
// vite-plugin-style-import // vite-plugin-style-import
vitePlugins.push(configStyleImportPlugin(isBuild)); vitePlugins.push(configStyleImportPlugin(isBuild));
@@ -61,17 +61,17 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
// rollup-plugin-visualizer // rollup-plugin-visualizer
vitePlugins.push(configVisualizerConfig()); vitePlugins.push(configVisualizerConfig());
//vite-plugin-theme // vite-plugin-theme
vitePlugins.push(configThemePlugin(isBuild)); vitePlugins.push(configThemePlugin(isBuild));
// The following plugins only work in the production environment // The following plugins only work in the production environment
if (isBuild) { if (isBuild) {
//vite-plugin-imagemin // vite-plugin-imagemin
VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin()); VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
// rollup-plugin-gzip // rollup-plugin-gzip
vitePlugins.push( vitePlugins.push(
configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE) configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE),
); );
// vite-plugin-pwa // vite-plugin-pwa

View File

@@ -2,7 +2,6 @@
* Zero-config PWA for Vite * Zero-config PWA for Vite
* https://github.com/antfu/vite-plugin-pwa * https://github.com/antfu/vite-plugin-pwa
*/ */
import { VitePWA } from 'vite-plugin-pwa'; import { VitePWA } from 'vite-plugin-pwa';
export function configPwaConfig(env: ViteEnv) { export function configPwaConfig(env: ViteEnv) {

View File

@@ -2,21 +2,78 @@
* Introduces component library styles on demand. * Introduces component library styles on demand.
* https://github.com/anncwb/vite-plugin-style-import * https://github.com/anncwb/vite-plugin-style-import
*/ */
import { createStyleImportPlugin } from 'vite-plugin-style-import';
import styleImport from 'vite-plugin-style-import'; export function configStyleImportPlugin(_isBuild: boolean) {
// if (!isBuild) {
export function configStyleImportPlugin(isBuild: boolean) { // return [];
if (!isBuild) return []; // }
const pwaPlugin = styleImport({ const styleImportPlugin = createStyleImportPlugin({
libs: [ libs: [
{ {
libraryName: 'ant-design-vue', libraryName: 'ant-design-vue',
esModule: true, esModule: true,
resolveStyle: (name) => { resolveStyle: (name) => {
return `ant-design-vue/es/${name}/style/index`; // 这里是无需额外引入样式文件的“子组件”列表
const ignoreList = [
'anchor-link',
'sub-menu',
'menu-item',
'menu-divider',
'menu-item-group',
'breadcrumb-item',
'breadcrumb-separator',
'form-item',
'step',
'select-option',
'select-opt-group',
'card-grid',
'card-meta',
'collapse-panel',
'descriptions-item',
'list-item',
'list-item-meta',
'table-column',
'table-column-group',
'tab-pane',
'tab-content',
'timeline-item',
'tree-node',
'skeleton-input',
'skeleton-avatar',
'skeleton-title',
'skeleton-paragraph',
'skeleton-image',
'skeleton-button',
];
// 这里是需要额外引入样式的子组件列表
// 单独引入子组件时需引入组件样式,否则会在打包后导致子组件样式丢失
const replaceList = {
'typography-text': 'typography',
'typography-title': 'typography',
'typography-paragraph': 'typography',
'typography-link': 'typography',
'dropdown-button': 'dropdown',
'input-password': 'input',
'input-search': 'input',
'input-group': 'input',
'radio-group': 'radio',
'checkbox-group': 'checkbox',
'layout-sider': 'layout',
'layout-content': 'layout',
'layout-footer': 'layout',
'layout-header': 'layout',
'month-picker': 'date-picker',
};
return ignoreList.includes(name)
? ''
: replaceList.hasOwnProperty(name)
? `ant-design-vue/es/${replaceList[name]}/style/index`
: `ant-design-vue/es/${name}/style/index`;
}, },
}, },
], ],
}); });
return pwaPlugin; return styleImportPlugin;
} }

View File

@@ -3,11 +3,11 @@
* https://github.com/anncwb/vite-plugin-svg-icons * https://github.com/anncwb/vite-plugin-svg-icons
*/ */
import SvgIconsPlugin from 'vite-plugin-svg-icons'; import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import path from 'path'; import path from 'path';
export function configSvgIconsPlugin(isBuild: boolean) { export function configSvgIconsPlugin(isBuild: boolean) {
const svgIconsPlugin = SvgIconsPlugin({ const svgIconsPlugin = createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')], iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
svgoOptions: isBuild, svgoOptions: isBuild,
// default // default

View File

@@ -2,7 +2,8 @@
* Vite plugin for website theme color switching * Vite plugin for website theme color switching
* https://github.com/anncwb/vite-plugin-theme * https://github.com/anncwb/vite-plugin-theme
*/ */
import type { Plugin } from 'vite'; import type { PluginOption } from 'vite';
import path from 'path';
import { import {
viteThemePlugin, viteThemePlugin,
antdDarkThemePlugin, antdDarkThemePlugin,
@@ -13,7 +14,7 @@ import {
import { getThemeColors, generateColors } from '../../config/themeConfig'; import { getThemeColors, generateColors } from '../../config/themeConfig';
import { generateModifyVars } from '../../generate/generateModifyVars'; import { generateModifyVars } from '../../generate/generateModifyVars';
export function configThemePlugin(isBuild: boolean): Plugin[] { export function configThemePlugin(isBuild: boolean): PluginOption[] {
const colors = generateColors({ const colors = generateColors({
mixDarken, mixDarken,
mixLighten, mixLighten,
@@ -21,31 +22,68 @@ export function configThemePlugin(isBuild: boolean): Plugin[] {
}); });
const plugin = [ const plugin = [
viteThemePlugin({ viteThemePlugin({
resolveSelector: (s) => `[data-theme] ${s}`, resolveSelector: (s) => {
s = s.trim();
switch (s) {
case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':
return '.ant-steps-item-icon > .ant-steps-icon';
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)':
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover':
case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active':
return s;
case '.ant-steps-item-icon > .ant-steps-icon':
return s;
case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)':
return s;
default:
if (s.indexOf('.ant-btn') >= -1) {
// 按钮被重新定制过需要过滤掉class防止覆盖
return s;
}
}
return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`;
},
colorVariables: [...getThemeColors(), ...colors], colorVariables: [...getThemeColors(), ...colors],
}), }),
antdDarkThemePlugin({ antdDarkThemePlugin({
filter: (id) => { preloadFiles: [
if (isBuild) { path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.less'),
return !id.endsWith('antd.less'); //path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.dark.less'),
} path.resolve(process.cwd(), 'src/design/index.less'),
return true; ],
}, filter: (id) => (isBuild ? !id.endsWith('antd.less') : true),
// extractCss: false, // extractCss: false,
darkModifyVars: { darkModifyVars: {
...generateModifyVars(true), ...generateModifyVars(true),
'text-color': '#c9d1d9', 'text-color': '#c9d1d9',
'primary-1': 'rgb(255 255 255 / 8%)',
'text-color-base': '#c9d1d9', 'text-color-base': '#c9d1d9',
'component-background': '#151515', 'component-background': '#151515',
'heading-color': 'rgb(255 255 255 / 65%)',
// black: '#0e1117', // black: '#0e1117',
// #8b949e // #8b949e
'text-color-secondary': '#8b949e', 'text-color-secondary': '#8b949e',
// 'border-color-base': '#30363d', 'border-color-base': '#303030',
// 'border-color-split': '#30363d', // 'border-color-split': '#30363d',
'item-active-bg': '#111b26', 'item-active-bg': '#111b26',
'app-content-background': '#1e1e1e',
'tree-node-selected-bg': '#11263c',
'alert-success-border-color': '#274916',
'alert-success-bg-color': '#162312',
'alert-success-icon-color': '#49aa19',
'alert-info-border-color': '#153450',
'alert-info-bg-color': '#111b26',
'alert-info-icon-color': '#177ddc',
'alert-warning-border-color': '#594214',
'alert-warning-bg-color': '#2b2111',
'alert-warning-icon-color': '#d89614',
'alert-error-border-color': '#58181c',
'alert-error-bg-color': '#2a1215',
'alert-error-icon-color': '#a61d24',
}, },
}), }),
]; ];
return (plugin as unknown) as Plugin[]; return plugin as unknown as PluginOption[];
} }

View File

@@ -1,12 +0,0 @@
import type { Plugin } from 'vite';
import windiCSS from 'vite-plugin-windicss';
export function configWindiCssPlugin(): Plugin[] {
return windiCSS({
safelist: 'no-select',
preflight: {
enableAll: true,
},
});
}

View File

@@ -7,7 +7,7 @@ type ProxyItem = [string, string];
type ProxyList = ProxyItem[]; type ProxyList = ProxyItem[];
type ProxyTargetList = Record<string, ProxyOptions & { rewrite: (path: string) => string }>; type ProxyTargetList = Record<string, ProxyOptions>;
const httpsRE = /^https:\/\//; const httpsRE = /^https:\/\//;

View File

@@ -1,37 +1,13 @@
module.exports = { module.exports = {
ignores: [(commit) => commit.includes('init')], ignores: [(commit) => commit.includes('init')],
extends: ['@commitlint/config-conventional'], extends: ['@commitlint/config-conventional'],
parserPreset: {
parserOpts: {
headerPattern: /^(\w*|[\u4e00-\u9fa5]*)(?:[\(\](.*)[\)\])?[\:\] (.*)/,
headerCorrespondence: ['type', 'scope', 'subject'],
referenceActions: [
'close',
'closes',
'closed',
'fix',
'fixes',
'fixed',
'resolve',
'resolves',
'resolved',
],
issuePrefixes: ['#'],
noteKeywords: ['BREAKING CHANGE'],
fieldPattern: /^-(.*?)-$/,
revertPattern: /^Revert\s"([\s\S]*)"\s*This reverts commit (\w*)\./,
revertCorrespondence: ['header', 'hash'],
warn() {},
mergePattern: null,
mergeCorrespondence: null,
},
},
rules: { rules: {
'body-leading-blank': [2, 'always'], 'body-leading-blank': [2, 'always'],
'footer-leading-blank': [1, 'always'], 'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 108], 'header-max-length': [2, 'always', 108],
'subject-empty': [2, 'never'], 'subject-empty': [2, 'never'],
'type-empty': [2, 'never'], 'type-empty': [2, 'never'],
'subject-case': [0],
'type-enum': [ 'type-enum': [
2, 2,
'always', 'always',

64
electron-main/index.ts Normal file
View File

@@ -0,0 +1,64 @@
import { app, BrowserWindow, screen } from 'electron';
import is_dev from 'electron-is-dev';
import { join } from 'path';
let mainWindow: BrowserWindow | null = null;
class createWin {
constructor() {
const displayWorkAreaSize = screen.getAllDisplays()[0].workArea;
mainWindow = new BrowserWindow({
width: parseInt(`${displayWorkAreaSize.width * 0.85}`, 10),
height: parseInt(`${displayWorkAreaSize.height * 0.85}`, 10),
movable: true,
// frame: false,
show: false,
center: true,
resizable: true,
// transparent: true,
titleBarStyle: 'default',
webPreferences: {
devTools: true,
contextIsolation: false,
nodeIntegration: true,
enableRemoteModule: true,
},
backgroundColor: '#fff',
});
const URL = is_dev
? `https://localhost:${process.env.PORT}` // vite 启动的服务器地址
: `file://${join(__dirname, '../index.html')}`; // vite 构建后的静态文件地址
mainWindow.loadURL(URL);
mainWindow.on('ready-to-show', () => {
mainWindow.show();
});
}
}
app.whenReady().then(() => new createWin());
const isFirstInstance = app.requestSingleInstanceLock();
if (!isFirstInstance) {
app.quit();
} else {
app.on('second-instance', () => {
if (mainWindow) {
mainWindow.focus();
}
});
}
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
new createWin();
}
});

View File

@@ -8,7 +8,6 @@
name="viewport" name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/> />
<title><%= title %></title> <title><%= title %></title>
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
</head> </head>
@@ -16,19 +15,21 @@
<script> <script>
(() => { (() => {
var htmlRoot = document.getElementById('htmlRoot'); var htmlRoot = document.getElementById('htmlRoot');
const theme = window.localStorage.getItem('__APP__DARK__MODE__'); var theme = window.localStorage.getItem('__APP__DARK__MODE__');
if (!htmlRoot || !theme) return; if (htmlRoot && theme) {
htmlRoot.setAttribute('data-theme', theme); htmlRoot.setAttribute('data-theme', theme);
theme = htmlRoot = null;
}
})(); })();
</script> </script>
<div id="app"> <div id="app">
<style> <style>
html[data-theme='dark'] .app-loading { html[data-theme='dark'] .app-loading {
background: #2c344a; background-color: #2c344a;
} }
html[data-theme='dark'] .app-loading .app-loading-title { html[data-theme='dark'] .app-loading .app-loading-title {
color: rgba(255, 255, 255, 0.85); color: rgb(255 255 255 / 85%);
} }
.app-loading { .app-loading {
@@ -38,7 +39,7 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
background: #f4f7f9; background-color: #f4f7f9;
} }
.app-loading .app-loading-wrap { .app-loading .app-loading-wrap {
@@ -46,7 +47,6 @@
top: 50%; top: 50%;
left: 50%; left: 50%;
display: flex; display: flex;
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0); transform: translate3d(-50%, -50%, 0);
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@@ -64,7 +64,7 @@
display: flex; display: flex;
margin-top: 30px; margin-top: 30px;
font-size: 30px; font-size: 30px;
color: rgba(0, 0, 0, 0.85); color: rgb(0 0 0 / 85%);
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
@@ -95,7 +95,7 @@
height: 20px; height: 20px;
background-color: #0065cc; background-color: #0065cc;
border-radius: 100%; border-radius: 100%;
opacity: 0.3; opacity: 30%;
transform: scale(0.75); transform: scale(0.75);
animation: antSpinMove 1s infinite linear alternate; animation: antSpinMove 1s infinite linear alternate;
transform-origin: 50% 50%; transform-origin: 50% 50%;
@@ -109,43 +109,38 @@
.dot i:nth-child(2) { .dot i:nth-child(2) {
top: 0; top: 0;
right: 0; right: 0;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s; animation-delay: 0.4s;
} }
.dot i:nth-child(3) { .dot i:nth-child(3) {
right: 0; right: 0;
bottom: 0; bottom: 0;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s; animation-delay: 0.8s;
} }
.dot i:nth-child(4) { .dot i:nth-child(4) {
bottom: 0; bottom: 0;
left: 0; left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s; animation-delay: 1.2s;
} }
@keyframes antRotate { @keyframes antRotate {
to { to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg); transform: rotate(405deg);
} }
} }
@-webkit-keyframes antRotate { @keyframes antRotate {
to { to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg); transform: rotate(405deg);
} }
} }
@keyframes antSpinMove { @keyframes antSpinMove {
to { to {
opacity: 1; opacity: 100%;
} }
} }
@-webkit-keyframes antSpinMove { @keyframes antSpinMove {
to { to {
opacity: 1; opacity: 100%;
} }
} }
</style> </style>

View File

@@ -13,7 +13,7 @@ export function resultPageSuccess<T = any>(
page: number, page: number,
pageSize: number, pageSize: number,
list: T[], list: T[],
{ message = 'ok' } = {} { message = 'ok' } = {},
) { ) {
const pageData = pagination(page, pageSize, list); const pageData = pagination(page, pageSize, list);
@@ -43,3 +43,18 @@ export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]
: array.slice(offset, offset + Number(pageSize)); : array.slice(offset, offset + Number(pageSize));
return ret; return ret;
} }
export interface requestParams {
method: string;
body: any;
headers?: { authorization?: string };
query: any;
}
/**
* @description 本函数用于从request数据中获取token请根据项目的实际情况修改
*
*/
export function getRequestToken({ headers }: requestParams): string | undefined {
return headers?.authorization;
}

View File

@@ -1,5 +1,6 @@
import { MockMethod } from 'vite-plugin-mock'; import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess } from '../_util'; import { resultSuccess, resultError } from '../_util';
import { ResultEnum } from '../../src/enums/httpEnum';
const userInfo = { const userInfo = {
name: 'Vben', name: 'Vben',
@@ -51,4 +52,20 @@ export default [
return resultSuccess(userInfo); return resultSuccess(userInfo);
}, },
}, },
{
url: '/basic-api/user/sessionTimeout',
method: 'post',
statusCode: 401,
response: () => {
return resultError();
},
},
{
url: '/basic-api/user/tokenExpired',
method: 'post',
statusCode: 200,
response: () => {
return resultError('Token Expired!', { code: ResultEnum.TIMEOUT as number });
},
},
] as MockMethod[]; ] as MockMethod[];

325
mock/demo/api-cascader.ts Normal file
View File

@@ -0,0 +1,325 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess } from '../_util';
const areaList: any[] = [
{
id: '530825900854620160',
code: '430000',
parentCode: '100000',
levelType: 1,
name: '湖南省',
province: '湖南省',
city: null,
district: null,
town: null,
village: null,
parentPath: '430000',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530825900883980288',
code: '430100',
parentCode: '430000',
levelType: 2,
name: '长沙市',
province: '湖南省',
city: '长沙市',
district: null,
town: null,
village: null,
parentPath: '430000,430100',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530825900951089152',
code: '430102',
parentCode: '430100',
levelType: 3,
name: '芙蓉区',
province: '湖南省',
city: '长沙市',
district: '芙蓉区',
town: null,
village: null,
parentPath: '430000,430100,430102',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530825901014003712',
code: '430104',
parentCode: '430100',
levelType: 3,
name: '岳麓区',
province: '湖南省',
city: '长沙市',
district: '岳麓区',
town: null,
village: null,
parentPath: '430000,430100,430104',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530825900988837888',
code: '430103',
parentCode: '430100',
levelType: 3,
name: '天心区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: null,
village: null,
parentPath: '430000,430100,430103',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 16:33:42',
customized: false,
usable: true,
},
{
id: '530826672489115648',
code: '430103002',
parentCode: '430103',
levelType: 4,
name: '坡子街街道',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: null,
parentPath: '430000,430100,430103,430103002',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-12-14 15:26:43',
customized: false,
usable: true,
},
{
id: '530840241171607552',
code: '430103002001',
parentCode: '430103002',
levelType: 5,
name: '八角亭社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '八角亭社区',
parentPath: '430000,430100,430103,430103002,430103002001',
createTime: '2020-11-30 15:47:31',
updateTime: '2021-01-20 14:07:23',
customized: false,
usable: true,
},
{
id: '530840241200967680',
code: '430103002002',
parentCode: '430103002',
levelType: 5,
name: '西牌楼社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '西牌楼社区',
parentPath: '430000,430100,430103,430103002,430103002002',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241230327808',
code: '430103002003',
parentCode: '430103002',
levelType: 5,
name: '太平街社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '太平街社区',
parentPath: '430000,430100,430103,430103002,430103002003',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241259687936',
code: '430103002005',
parentCode: '430103002',
levelType: 5,
name: '坡子街社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '坡子街社区',
parentPath: '430000,430100,430103,430103002,430103002005',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241284853760',
code: '430103002006',
parentCode: '430103002',
levelType: 5,
name: '青山祠社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '青山祠社区',
parentPath: '430000,430100,430103,430103002,430103002006',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241310019584',
code: '430103002007',
parentCode: '430103002',
levelType: 5,
name: '沙河社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '沙河社区',
parentPath: '430000,430100,430103,430103002,430103002007',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241381322752',
code: '430103002008',
parentCode: '430103002',
levelType: 5,
name: '碧湘社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '碧湘社区',
parentPath: '430000,430100,430103,430103002,430103002008',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241410682880',
code: '430103002009',
parentCode: '430103002',
levelType: 5,
name: '创远社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '创远社区',
parentPath: '430000,430100,430103,430103002,430103002009',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241431654400',
code: '430103002010',
parentCode: '430103002',
levelType: 5,
name: '楚湘社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '楚湘社区',
parentPath: '430000,430100,430103,430103002,430103002010',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241465208832',
code: '430103002011',
parentCode: '430103002',
levelType: 5,
name: '西湖社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '西湖社区',
parentPath: '430000,430100,430103,430103002,430103002011',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241502957568',
code: '430103002012',
parentCode: '430103002',
levelType: 5,
name: '登仁桥社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '登仁桥社区',
parentPath: '430000,430100,430103,430103002,430103002012',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
{
id: '530840241553289216',
code: '430103002013',
parentCode: '430103002',
levelType: 5,
name: '文庙坪社区',
province: '湖南省',
city: '长沙市',
district: '天心区',
town: '坡子街街道',
village: '文庙坪社区',
parentPath: '430000,430100,430103,430103002,430103002013',
createTime: '2020-11-30 15:47:31',
updateTime: '2020-11-30 17:30:41',
customized: false,
usable: true,
},
];
export default [
{
url: '/basic-api/cascader/getAreaRecord',
timeout: 1000,
method: 'post',
response: ({ body }) => {
const { parentCode } = body || {};
if (!parentCode) {
return resultSuccess(areaList.filter((it) => it.code === '430000'));
}
return resultSuccess(areaList.filter((it) => it.parentCode === parentCode));
},
},
] as MockMethod[];

View File

@@ -1,25 +1,28 @@
import { MockMethod } from 'vite-plugin-mock'; import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess } from '../_util'; import { resultSuccess } from '../_util';
const demoList = (() => { const demoList = (keyword, count = 20) => {
const result: any[] = []; const result = {
for (let index = 0; index < 20; index++) { list: [] as any[],
result.push({ };
label: `选项${index}`, for (let index = 0; index < count; index++) {
value: `${index}`, result.list.push({
name: `${keyword ?? ''}选项${index}`,
id: `${index}`,
}); });
} }
return result; return result;
})(); };
export default [ export default [
{ {
url: '/basic-api/select/getDemoOptions', url: '/basic-api/select/getDemoOptions',
timeout: 2000, timeout: 1000,
method: 'get', method: 'get',
response: ({ query }) => { response: ({ query }) => {
console.log(query); const { keyword, count } = query;
return resultSuccess(demoList); console.log(keyword);
return resultSuccess(demoList(keyword, count));
}, },
}, },
] as MockMethod[]; ] as MockMethod[];

View File

@@ -1,5 +1,5 @@
import { MockMethod } from 'vite-plugin-mock'; import { MockMethod } from 'vite-plugin-mock';
import { resultPageSuccess, resultSuccess } from '../_util'; import { resultError, resultPageSuccess, resultSuccess } from '../_util';
const accountList = (() => { const accountList = (() => {
const result: any[] = []; const result: any[] = [];
@@ -22,12 +22,13 @@ const roleList = (() => {
const result: any[] = []; const result: any[] = [];
for (let index = 0; index < 4; index++) { for (let index = 0; index < 4; index++) {
result.push({ result.push({
id: `${index}`, id: index + 1,
orderNo: `${index + 1}`, orderNo: `${index + 1}`,
roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index], roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index],
roleValue: '@first', roleValue: '@first',
createTime: '@datetime', createTime: '@datetime',
remark: '@cword(10,20)', remark: '@cword(10,20)',
menu: [['0', '1', '2'], ['0', '1'], ['0', '2'], ['2']][index],
'status|1': ['0', '1'], 'status|1': ['0', '1'],
}); });
} }
@@ -72,6 +73,7 @@ const menuList = (() => {
id: `${index}`, id: `${index}`,
icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index], icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index],
component: 'LAYOUT', component: 'LAYOUT',
type: '0',
menuName: ['Dashboard', '权限管理', '功能'][index], menuName: ['Dashboard', '权限管理', '功能'][index],
permission: '', permission: '',
orderNo: index + 1, orderNo: index + 1,
@@ -82,6 +84,7 @@ const menuList = (() => {
for (let j = 0; j < 4; j++) { for (let j = 0; j < 4; j++) {
children.push({ children.push({
id: `${index}-${j}`, id: `${index}-${j}`,
type: '1',
menuName: ['菜单1', '菜单2', '菜单3', '菜单4'][j], menuName: ['菜单1', '菜单2', '菜单3', '菜单4'][j],
icon: 'ion:document', icon: 'ion:document',
permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index], permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index],
@@ -95,7 +98,33 @@ const menuList = (() => {
createTime: '@datetime', createTime: '@datetime',
'status|1': ['0', '1'], 'status|1': ['0', '1'],
parentMenu: `${index}`, parentMenu: `${index}`,
children: undefined, children: (() => {
const children: any[] = [];
for (let k = 0; k < 4; k++) {
children.push({
id: `${index}-${j}-${k}`,
type: '2',
menuName: '按钮' + (j + 1) + '-' + (k + 1),
icon: '',
permission:
['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index] +
':btn' +
(k + 1),
component: [
'/dashboard/welcome/index',
'/dashboard/analysis/index',
'/dashboard/workbench/index',
'/dashboard/test/index',
][j],
orderNo: j + 1,
createTime: '@datetime',
'status|1': ['0', '1'],
parentMenu: `${index}-${j}`,
children: undefined,
});
}
return children;
})(),
}); });
} }
return children; return children;
@@ -124,6 +153,15 @@ export default [
return resultPageSuccess(page, pageSize, roleList); return resultPageSuccess(page, pageSize, roleList);
}, },
}, },
{
url: '/basic-api/system/setRoleStatus',
timeout: 500,
method: 'post',
response: ({ query }) => {
const { id, status } = query;
return resultSuccess({ id, status });
},
},
{ {
url: '/basic-api/system/getAllRoleList', url: '/basic-api/system/getAllRoleList',
timeout: 100, timeout: 100,
@@ -148,4 +186,17 @@ export default [
return resultSuccess(menuList); return resultSuccess(menuList);
}, },
}, },
{
url: '/basic-api/system/accountExist',
timeout: 500,
method: 'post',
response: ({ body }) => {
const { account } = body || {};
if (account && account.indexOf('admin') !== -1) {
return resultError('该字段不能包含admin');
} else {
return resultSuccess(`${account} can use`);
}
},
},
] as MockMethod[]; ] as MockMethod[];

View File

@@ -1,9 +1,18 @@
import { MockMethod } from 'vite-plugin-mock'; import { MockMethod } from 'vite-plugin-mock';
import { Random } from 'mockjs';
import { resultPageSuccess } from '../_util'; import { resultPageSuccess } from '../_util';
function getRandomPics(count = 10): string[] {
const arr: string[] = [];
for (let i = 0; i < count; i++) {
arr.push(Random.image('800x600', Random.color(), Random.color(), Random.title()));
}
return arr;
}
const demoList = (() => { const demoList = (() => {
const result: any[] = []; const result: any[] = [];
for (let index = 0; index < 60; index++) { for (let index = 0; index < 200; index++) {
result.push({ result.push({
id: `${index}`, id: `${index}`,
beginTime: '@datetime', beginTime: '@datetime',
@@ -18,6 +27,11 @@ const demoList = (() => {
name6: '@cname()', name6: '@cname()',
name7: '@cname()', name7: '@cname()',
name8: '@cname()', name8: '@cname()',
avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()),
imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1),
imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1),
date: `@date('yyyy-MM-dd')`,
time: `@time('HH:mm')`,
'no|100000-10000000': 100000, 'no|100000-10000000': 100000,
'status|1': ['normal', 'enable', 'disable'], 'status|1': ['normal', 'enable', 'disable'],
}); });

38
mock/demo/tree-demo.ts Normal file
View File

@@ -0,0 +1,38 @@
import { MockMethod } from 'vite-plugin-mock';
import { resultSuccess } from '../_util';
const demoTreeList = (keyword) => {
const result = {
list: [] as Recordable[],
};
for (let index = 0; index < 5; index++) {
const children: Recordable[] = [];
for (let j = 0; j < 3; j++) {
children.push({
title: `${keyword ?? ''}选项${index}-${j}`,
value: `${index}-${j}`,
key: `${index}-${j}`,
});
}
result.list.push({
title: `${keyword ?? ''}选项${index}`,
value: `${index}`,
key: `${index}`,
children,
});
}
return result;
};
export default [
{
url: '/basic-api/tree/getDemoOptions',
timeout: 1000,
method: 'get',
response: ({ query }) => {
const { keyword } = query;
console.log(keyword);
return resultSuccess(demoTreeList(keyword));
},
},
] as MockMethod[];

View File

@@ -1,59 +1,46 @@
import { resultSuccess } from '../_util'; import { resultSuccess, resultError, getRequestToken, requestParams } from '../_util';
import { MockMethod } from 'vite-plugin-mock'; import { MockMethod } from 'vite-plugin-mock';
import { createFakeUserList } from './user';
// single // single
const dashboardRoute = { const dashboardRoute = {
path: '/dashboard', path: '/dashboard',
name: 'Welcome', name: 'Dashboard',
component: '/dashboard/analysis/index', component: 'LAYOUT',
redirect: '/dashboard/analysis',
meta: { meta: {
title: 'routes.dashboard.analysis', title: 'routes.dashboard.dashboard',
affix: true, hideChildrenInMenu: true,
icon: 'bx:bx-home', icon: 'bx:bx-home',
}, },
};
const frontRoute = {
path: 'front',
name: 'PermissionFrontDemo',
meta: {
title: 'routes.demo.permission.front',
},
children: [ children: [
{ {
path: 'page', path: 'analysis',
name: 'FrontPageAuth', name: 'Analysis',
component: '/demo/permission/front/index', component: '/dashboard/analysis/index',
meta: { meta: {
title: 'routes.demo.permission.frontPage', hideMenu: true,
hideBreadcrumb: true,
title: 'routes.dashboard.analysis',
currentActiveMenu: '/dashboard',
icon: 'bx:bx-home',
}, },
}, },
{ {
path: 'btn', path: 'workbench',
name: 'FrontBtnAuth', name: 'Workbench',
component: '/demo/permission/front/Btn', component: '/dashboard/workbench/index',
meta: { meta: {
title: 'routes.demo.permission.frontBtn', hideMenu: true,
}, hideBreadcrumb: true,
}, title: 'routes.dashboard.workbench',
{ currentActiveMenu: '/dashboard',
path: 'auth-pageA', icon: 'bx:bx-home',
name: 'FrontAuthPageA',
component: '/demo/permission/front/AuthPageA',
meta: {
title: 'routes.demo.permission.frontTestA',
},
},
{
path: 'auth-pageB',
name: 'FrontAuthPageB',
component: '/demo/permission/front/AuthPageB',
meta: {
title: 'routes.demo.permission.frontTestB',
}, },
}, },
], ],
}; };
const backRoute = { const backRoute = {
path: 'back', path: 'back',
name: 'PermissionBackDemo', name: 'PermissionBackDemo',
@@ -80,19 +67,8 @@ const backRoute = {
}, },
], ],
}; };
const authRoute = {
path: '/permission',
name: 'Permission',
component: 'LAYOUT',
redirect: '/permission/front/page',
meta: {
icon: 'carbon:user-role',
title: 'routes.demo.permission.permission',
},
children: [frontRoute, backRoute],
};
const authRoute1 = { const authRoute = {
path: '/permission', path: '/permission',
name: 'Permission', name: 'Permission',
component: 'LAYOUT', component: 'LAYOUT',
@@ -159,19 +135,136 @@ const levelRoute = {
}, },
], ],
}; };
const sysRoute = {
path: '/system',
name: 'System',
component: 'LAYOUT',
redirect: '/system/account',
meta: {
icon: 'ion:settings-outline',
title: 'routes.demo.system.moduleName',
},
children: [
{
path: 'account',
name: 'AccountManagement',
meta: {
title: 'routes.demo.system.account',
ignoreKeepAlive: true,
},
component: '/demo/system/account/index',
},
{
path: 'account_detail/:id',
name: 'AccountDetail',
meta: {
hideMenu: true,
title: 'routes.demo.system.account_detail',
ignoreKeepAlive: true,
showMenu: false,
currentActiveMenu: '/system/account',
},
component: '/demo/system/account/AccountDetail',
},
{
path: 'role',
name: 'RoleManagement',
meta: {
title: 'routes.demo.system.role',
ignoreKeepAlive: true,
},
component: '/demo/system/role/index',
},
{
path: 'menu',
name: 'MenuManagement',
meta: {
title: 'routes.demo.system.menu',
ignoreKeepAlive: true,
},
component: '/demo/system/menu/index',
},
{
path: 'dept',
name: 'DeptManagement',
meta: {
title: 'routes.demo.system.dept',
ignoreKeepAlive: true,
},
component: '/demo/system/dept/index',
},
{
path: 'changePassword',
name: 'ChangePassword',
meta: {
title: 'routes.demo.system.password',
ignoreKeepAlive: true,
},
component: '/demo/system/password/index',
},
],
};
const linkRoute = {
path: '/link',
name: 'Link',
component: 'LAYOUT',
meta: {
icon: 'ion:tv-outline',
title: 'routes.demo.iframe.frame',
},
children: [
{
path: 'doc',
name: 'Doc',
meta: {
title: 'routes.demo.iframe.doc',
frameSrc: 'https://vvbin.cn/doc-next/',
},
},
{
path: 'https://vvbin.cn/doc-next/',
name: 'DocExternal',
component: 'LAYOUT',
meta: {
title: 'routes.demo.iframe.docExternal',
},
},
],
};
export default [ export default [
{ {
url: '/basic-api/getMenuListById', url: '/basic-api/getMenuList',
timeout: 1000, timeout: 1000,
method: 'get', method: 'get',
response: ({ query }) => { response: (request: requestParams) => {
const { id } = query; const token = getRequestToken(request);
if (!id || id === '1') { if (!token) {
return resultSuccess([dashboardRoute, authRoute, levelRoute]); return resultError('Invalid token!');
} }
if (id === '2') { const checkUser = createFakeUserList().find((item) => item.token === token);
return resultSuccess([dashboardRoute, authRoute1, levelRoute]); if (!checkUser) {
return resultError('Invalid user token!');
} }
const id = checkUser.userId;
let menu: Object[];
switch (id) {
case '1':
dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[0].path;
menu = [dashboardRoute, authRoute, levelRoute, sysRoute, linkRoute];
break;
case '2':
dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[1].path;
menu = [dashboardRoute, authRoute, levelRoute, linkRoute];
break;
default:
menu = [];
}
return resultSuccess(menu);
}, },
}, },
] as MockMethod[]; ] as MockMethod[];

View File

@@ -1,15 +1,17 @@
import { MockMethod } from 'vite-plugin-mock'; import { MockMethod } from 'vite-plugin-mock';
import { resultError, resultSuccess } from '../_util'; import { resultError, resultSuccess, getRequestToken, requestParams } from '../_util';
function createFakeUserList() { export function createFakeUserList() {
return [ return [
{ {
userId: '1', userId: '1',
username: 'vben', username: 'vben',
realName: 'Vben Admin', realName: 'Vben Admin',
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=190848757&s=640',
desc: 'manager', desc: 'manager',
password: '123456', password: '123456',
token: 'fakeToken1', token: 'fakeToken1',
homePath: '/dashboard/analysis',
roles: [ roles: [
{ {
roleName: 'Super Admin', roleName: 'Super Admin',
@@ -22,8 +24,10 @@ function createFakeUserList() {
username: 'test', username: 'test',
password: '123456', password: '123456',
realName: 'test user', realName: 'test user',
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=339449197&s=640',
desc: 'tester', desc: 'tester',
token: 'fakeToken2', token: 'fakeToken2',
homePath: '/dashboard/workbench',
roles: [ roles: [
{ {
roleName: 'Tester', roleName: 'Tester',
@@ -48,7 +52,7 @@ export default [
response: ({ body }) => { response: ({ body }) => {
const { username, password } = body; const { username, password } = body;
const checkUser = createFakeUserList().find( const checkUser = createFakeUserList().find(
(item) => item.username === username && password === item.password (item) => item.username === username && password === item.password,
); );
if (!checkUser) { if (!checkUser) {
return resultError('Incorrect account or password'); return resultError('Incorrect account or password');
@@ -65,11 +69,12 @@ export default [
}, },
}, },
{ {
url: '/basic-api/getUserInfoById', url: '/basic-api/getUserInfo',
method: 'get', method: 'get',
response: ({ query }) => { response: (request: requestParams) => {
const { userId } = query; const token = getRequestToken(request);
const checkUser = createFakeUserList().find((item) => item.userId === userId); if (!token) return resultError('Invalid token');
const checkUser = createFakeUserList().find((item) => item.token === token);
if (!checkUser) { if (!checkUser) {
return resultError('The corresponding user information was not obtained!'); return resultError('The corresponding user information was not obtained!');
} }
@@ -77,17 +82,41 @@ export default [
}, },
}, },
{ {
url: '/basic-api/getPermCodeByUserId', url: '/basic-api/getPermCode',
timeout: 200, timeout: 200,
method: 'get', method: 'get',
response: ({ query }) => { response: (request: requestParams) => {
const { userId } = query; const token = getRequestToken(request);
if (!userId) { if (!token) return resultError('Invalid token');
return resultError('userId is not null!'); const checkUser = createFakeUserList().find((item) => item.token === token);
if (!checkUser) {
return resultError('Invalid token!');
} }
const codeList = fakeCodeList[userId]; const codeList = fakeCodeList[checkUser.userId];
return resultSuccess(codeList); return resultSuccess(codeList);
}, },
}, },
{
url: '/basic-api/logout',
timeout: 200,
method: 'get',
response: (request: requestParams) => {
const token = getRequestToken(request);
if (!token) return resultError('Invalid token');
const checkUser = createFakeUserList().find((item) => item.token === token);
if (!checkUser) {
return resultError('Invalid token!');
}
return resultSuccess(undefined, { message: 'Token has been destroyed' });
},
},
{
url: '/basic-api/testRetry',
statusCode: 405,
method: 'get',
response: () => {
return resultError('Error!');
},
},
] as MockMethod[]; ] as MockMethod[];

View File

@@ -1,127 +1,212 @@
{ {
"name": "vben-admin", "name": "vben-admin",
"version": "2.2.0", "version": "2.8.0",
"author": { "author": {
"name": "vben", "name": "vben",
"email": "anncwb@126.com", "email": "anncwb@126.com",
"url": "https://github.com/anncwb" "url": "https://github.com/anncwb"
}, },
"main": "dist/main/build.js",
"build": {
"appId": "xxx@gmail.com",
"electronDownload": {
"mirror": "https://npm.taobao.org/mirrors/electron/"
},
"files": [
"!node_modules",
"dist/**"
],
"asar": false,
"mac": {
"artifactName": "${productName}_setup_${version}.${ext}",
"target": [
"dmg"
]
},
"linux": {
"icon": "build/icons/512x512.png",
"target": [
"deb"
]
},
"win": {
"target": [
{
"target": "nsis",
"arch": [
"x64"
]
}
],
"artifactName": "${productName}_setup_${version}.${ext}"
},
"nsis": {
"oneClick": false,
"perMachine": false,
"allowToChangeInstallationDirectory": true,
"deleteAppDataOnUninstall": false
}
},
"scripts": { "scripts": {
"bootstrap": "yarn install", "bootstrap": "pnpm install",
"serve": "cross-env --max_old_space_size=4096 vite", "serve": "npm run dev",
"dev": "cross-env --max_old_space_size=4096 vite", "dev": "vite",
"build": "vite build && esno ./build/script/postBuild.ts", "build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
"build:no-cache": "yarn clean:cache && npm run build", "build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts",
"report": "cross-env REPORT=true npm run build ", "build:no-cache": "pnpm clean:cache && npm run build",
"dev:app": "esno ./build/script/startElectron.ts --env=development --watch",
"build:app": "npm run build && esno ./build/script/startElectron.ts --env=production && electron-builder ",
"report": "cross-env REPORT=true npm run build",
"type:check": "vue-tsc --noEmit --skipLibCheck",
"preview": "npm run build && vite preview", "preview": "npm run build && vite preview",
"preview:dist": "vite preview", "preview:dist": "vite preview",
"log": "conventional-changelog -p angular -i CHANGELOG.md -s", "log": "conventional-changelog -p angular -i CHANGELOG.md -s",
"clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite", "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
"clean:lib": "rimraf node_modules", "clean:lib": "rimraf node_modules",
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", "lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js", "lint:lint-staged": "lint-staged",
"lint:pretty": "pretty-quick --staged", "test:unit": "jest",
"test:gzip": "http-server dist --cors --gzip -c-1", "test:gzip": "npx http-server dist --cors --gzip -c-1",
"test:br": "http-server dist --cors --brotli -c-1", "test:br": "npx http-server dist --cors --brotli -c-1",
"reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap", "reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
"install:husky": "is-ci || husky install", "prepare": "husky install",
"gen:icon": "esno ./build/generate/icon/index.ts", "gen:icon": "esno ./build/generate/icon/index.ts"
"postinstall": "npm run install:husky"
}, },
"dependencies": { "dependencies": {
"@iconify/iconify": "^2.0.0-rc.6", "@ant-design/colors": "^6.0.0",
"@vueuse/core": "^4.7.0", "@ant-design/icons-vue": "^6.1.0",
"@zxcvbn-ts/core": "^0.3.0", "@logicflow/core": "^0.6.16",
"ant-design-vue": "^2.1.2", "@logicflow/extension": "^0.6.16",
"axios": "^0.21.1", "@iconify/iconify": "^2.2.1",
"cropperjs": "^1.5.11", "@vue/runtime-core": "^3.2.31",
"crypto-js": "^4.0.0", "@vue/shared": "^3.2.31",
"echarts": "^5.0.2", "@vueuse/core": "^6.3.3",
"@vueuse/shared": "^6.3.3",
"@zxcvbn-ts/core": "^2.0.1",
"ant-design-vue": "3.1.1",
"axios": "^0.21.4",
"codemirror": "^5.62.3",
"cropperjs": "^1.5.12",
"electron-is-dev": "^1.2.0",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.0",
"echarts": "^5.2.0",
"intro.js": "^4.2.2",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"path-to-regexp": "^6.2.0", "path-to-regexp": "^6.2.0",
"pinia": "2.0.12",
"print-js": "^1.6.0", "print-js": "^1.6.0",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"sortablejs": "^1.13.0", "qs": "^6.10.3",
"tinymce": "^5.7.1", "resize-observer-polyfill": "^1.5.1",
"vditor": "^3.8.4", "showdown": "^1.9.1",
"vue": "3.0.11", "sortablejs": "^1.14.0",
"vue-i18n": "^9.0.0", "tinymce": "^5.9.2",
"vue-router": "^4.0.6", "vditor": "^3.8.13",
"vue-types": "^3.0.2", "vue": "^3.2.31",
"vuex": "^4.0.0", "vue-i18n": "^9.1.9",
"vuex-module-decorators": "^1.0.1", "vue-json-pretty": "^2.0.6",
"xlsx": "^0.16.9" "vue-router": "^4.0.14",
"vue-types": "^4.1.1",
"xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^12.1.1", "@commitlint/cli": "^13.1.0",
"@commitlint/config-conventional": "^12.1.1", "@commitlint/config-conventional": "^13.1.0",
"@iconify/json": "^1.1.325", "@iconify/json": "^1.1.401",
"@purge-icons/generated": "^0.7.0", "@purge-icons/generated": "^0.7.0",
"@types/crypto-js": "^4.0.1", "@rollup/plugin-alias": "^3.1.1",
"@types/fs-extra": "^9.0.10", "@rollup/plugin-commonjs": "^15.0.0",
"@types/inquirer": "^7.3.1", "@rollup/plugin-json": "^4.1.0",
"@types/lodash-es": "^4.17.4", "@rollup/plugin-node-resolve": "^9.0.0",
"@types/mockjs": "^1.0.3", "@types/codemirror": "^5.60.2",
"@types/crypto-js": "^4.0.2",
"@types/fs-extra": "^9.0.12",
"@types/inquirer": "^8.1.1",
"@types/intro.js": "^3.0.2",
"@types/jest": "^27.0.1",
"@types/lodash-es": "^4.17.5",
"@types/mockjs": "^1.0.4",
"@types/node": "^16.9.1",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.4.0", "@types/qrcode": "^1.4.1",
"@types/qs": "^6.9.6", "@types/qs": "^6.9.7",
"@types/sortablejs": "^1.10.6", "@types/showdown": "^1.9.4",
"@typescript-eslint/eslint-plugin": "^4.21.0", "@types/sortablejs": "^1.10.7",
"@typescript-eslint/parser": "^4.21.0", "@typescript-eslint/eslint-plugin": "^4.31.0",
"@vitejs/plugin-legacy": "^1.3.2", "@typescript-eslint/parser": "^4.31.0",
"@vitejs/plugin-vue": "^1.2.1", "@vitejs/plugin-legacy": "^1.5.3",
"@vitejs/plugin-vue-jsx": "^1.1.3", "@vitejs/plugin-vue": "^1.6.2",
"@vue/compiler-sfc": "3.0.11", "@vitejs/plugin-vue-jsx": "^1.1.8",
"autoprefixer": "^10.2.5", "@vue/compiler-sfc": "3.2.11",
"commitizen": "^4.2.3", "@vue/test-utils": "^2.0.0-rc.14",
"autoprefixer": "^10.3.4",
"commitizen": "^4.2.4",
"conventional-changelog-cli": "^2.1.1", "conventional-changelog-cli": "^2.1.1",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"dotenv": "^8.2.0", "dotenv": "^10.0.0",
"eslint": "^7.23.0", "electron": "^18.0.0",
"eslint-config-prettier": "^8.1.0", "electron-builder": "^22.8.0",
"eslint-define-config": "^1.0.7", "electron-connect": "^0.6.3",
"eslint-plugin-prettier": "^3.3.1", "electron-contextmenu-middleware": "^1.0.3",
"eslint-plugin-vue": "^7.8.0", "electron-input-menu": "^2.1.0",
"esno": "^0.5.0", "eslint": "^7.32.0",
"fs-extra": "^9.1.0", "eslint-config-prettier": "^8.3.0",
"http-server": "^0.12.3", "eslint-define-config": "^1.0.9",
"husky": "^6.0.0", "eslint-plugin-jest": "^24.4.0",
"inquirer": "^8.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^7.17.0",
"esno": "^0.9.1",
"fs-extra": "^10.0.0",
"http-server": "^13.0.1",
"husky": "^7.0.2",
"inquirer": "^8.1.2",
"is-ci": "^3.0.0", "is-ci": "^3.0.0",
"jest": "^27.2.0",
"less": "^4.1.1", "less": "^4.1.1",
"lint-staged": "^10.5.4", "lint-staged": "12.3.7",
"postcss": "^8.2.9", "npm-run-all": "^4.1.5",
"prettier": "^2.2.1", "picocolors": "^1.0.0",
"pretty-quick": "^3.1.0", "postcss": "^8.3.6",
"postcss-html": "^1.3.0",
"postcss-less": "^6.0.0",
"prettier": "^2.4.0",
"pretty-quick": "^3.1.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"rollup-plugin-visualizer": "5.3.0", "rollup-plugin-esbuild": "^3.0.2",
"stylelint": "^13.12.0", "rollup-plugin-visualizer": "5.5.2",
"stylelint": "^13.13.1",
"stylelint-config-prettier": "^8.0.2", "stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^21.0.0", "stylelint-config-standard": "^22.0.0",
"stylelint-order": "^4.1.0", "stylelint-order": "^4.1.0",
"ts-node": "^9.1.1", "ts-jest": "^27.0.5",
"typescript": "4.2.3", "ts-node": "^10.2.1",
"vite": "2.1.5", "typescript": "4.4.3",
"vite-plugin-compression": "^0.2.4", "vite": "^2.9.1",
"vite-plugin-html": "^2.0.6", "vite-plugin-compression": "^0.3.5",
"vite-plugin-imagemin": "^0.3.0", "vite-plugin-html": "^3.2.0",
"vite-plugin-mock": "^2.5.0", "vite-plugin-imagemin": "^0.4.5",
"vite-plugin-mkcert": "^1.6.0",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-purge-icons": "^0.7.0", "vite-plugin-purge-icons": "^0.7.0",
"vite-plugin-pwa": "^0.6.5", "vite-plugin-pwa": "^0.11.2",
"vite-plugin-style-import": "^0.9.2", "vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^0.4.1", "vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-theme": "^0.6.0", "vite-plugin-theme": "^0.8.1",
"vite-plugin-windicss": "0.12.5", "wait-on": "^5.2.1",
"vue-eslint-parser": "^7.6.0" "vite-plugin-vue-setup-extend": "^0.1.0",
"vite-plugin-windicss": "^1.4.2",
"vue-eslint-parser": "^7.11.0",
"vue-tsc": "^0.3.0"
}, },
"resolutions": { "resolutions": {
"//": "Used to install imagemin dependencies, because imagemin may not be installed in China.If it is abroad, you can delete it",
"bin-wrapper": "npm:bin-wrapper-china", "bin-wrapper": "npm:bin-wrapper-china",
"rollup": "^2.44.0" "rollup": "^2.56.3",
"gifsicle": "5.2.0"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@@ -1,20 +1,10 @@
module.exports = { module.exports = {
printWidth: 100, printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: true, semi: true,
vueIndentScriptAndStyle: true, vueIndentScriptAndStyle: true,
singleQuote: true, singleQuote: true,
quoteProps: 'as-needed', trailingComma: 'all',
bracketSpacing: true,
trailingComma: 'es5',
jsxBracketSameLine: false,
jsxSingleQuote: false,
arrowParens: 'always',
insertPragma: false,
requirePragma: false,
proseWrap: 'never', proseWrap: 'never',
htmlWhitespaceSensitivity: 'strict', htmlWhitespaceSensitivity: 'strict',
endOfLine: 'lf', endOfLine: 'auto',
rangeStart: 0,
}; };

View File

@@ -1,38 +1,21 @@
<template> <template>
<ConfigProvider v-bind="lockEvent" :locale="getAntdLocale"> <ConfigProvider :locale="getAntdLocale">
<AppProvider> <AppProvider>
<RouterView /> <RouterView />
</AppProvider> </AppProvider>
</ConfigProvider> </ConfigProvider>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
import { ConfigProvider } from 'ant-design-vue'; import { ConfigProvider } from 'ant-design-vue';
import { AppProvider } from '/@/components/Application'; import { AppProvider } from '/@/components/Application';
import { initAppConfigStore } from '/@/logics/initAppConfig';
import { useLockPage } from '/@/hooks/web/useLockPage';
import { useTitle } from '/@/hooks/web/useTitle'; import { useTitle } from '/@/hooks/web/useTitle';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
export default defineComponent({ import 'dayjs/locale/zh-cn';
name: 'App', // support Multi-language
components: { ConfigProvider, AppProvider }, const { getAntdLocale } = useLocale();
setup() {
// Initialize vuex internal system configuration
initAppConfigStore();
useTitle(); // Listening to page changes and dynamically changing site titles
useTitle();
// support Multi-language
const { getAntdLocale } = useLocale();
// Create a lock screen monitor
const lockEvent = useLockPage();
return { getAntdLocale, lockEvent };
},
});
</script> </script>

View File

@@ -3,8 +3,14 @@ import { GetAccountInfoModel } from './model/accountModel';
enum Api { enum Api {
ACCOUNT_INFO = '/account/getAccountInfo', ACCOUNT_INFO = '/account/getAccountInfo',
SESSION_TIMEOUT = '/user/sessionTimeout',
TOKEN_EXPIRED = '/user/tokenExpired',
} }
// Get personal center-basic settings // Get personal center-basic settings
export const accountInfoApi = () => defHttp.get<GetAccountInfoModel>({ url: Api.ACCOUNT_INFO }); export const accountInfoApi = () => defHttp.get<GetAccountInfoModel>({ url: Api.ACCOUNT_INFO });
export const sessionTimeoutApi = () => defHttp.post<void>({ url: Api.SESSION_TIMEOUT });
export const tokenExpiredApi = () => defHttp.post<void>({ url: Api.TOKEN_EXPIRED });

9
src/api/demo/cascader.ts Normal file
View File

@@ -0,0 +1,9 @@
import { defHttp } from '/@/utils/http/axios';
import { AreaModel, AreaParams } from '/@/api/demo/model/areaModel';
enum Api {
AREA_RECORD = '/cascader/getAreaRecord',
}
export const areaRecord = (data: AreaParams) =>
defHttp.post<AreaModel>({ url: Api.AREA_RECORD, data });

View File

@@ -0,0 +1,12 @@
export interface AreaModel {
id: string;
code: string;
parentCode: string;
name: string;
levelType: number;
[key: string]: string | number;
}
export interface AreaParams {
parentCode: string;
}

View File

@@ -5,7 +5,11 @@ export interface DemoOptionsItem {
value: string; value: string;
} }
export interface selectParams {
id: number | string;
}
/** /**
* @description: Request list return value * @description: Request list return value
*/ */
export type DemoOptionsGetResultModel = BasicFetchResult<DemoOptionsItem[]>; export type DemoOptionsGetResultModel = BasicFetchResult<DemoOptionsItem>;

View File

@@ -1,6 +1,5 @@
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { DemoOptionsGetResultModel } from './model/optionsModel'; import { DemoOptionsItem, selectParams } from './model/optionsModel';
enum Api { enum Api {
OPTIONS_LIST = '/select/getDemoOptions', OPTIONS_LIST = '/select/getDemoOptions',
} }
@@ -8,5 +7,5 @@ enum Api {
/** /**
* @description: Get sample options value * @description: Get sample options value
*/ */
export const optionsListApi = () => export const optionsListApi = (params?: selectParams) =>
defHttp.get<DemoOptionsGetResultModel>({ url: Api.OPTIONS_LIST }); defHttp.get<DemoOptionsItem[]>({ url: Api.OPTIONS_LIST, params });

View File

@@ -14,7 +14,9 @@ import { defHttp } from '/@/utils/http/axios';
enum Api { enum Api {
AccountList = '/system/getAccountList', AccountList = '/system/getAccountList',
IsAccountExist = '/system/accountExist',
DeptList = '/system/getDeptList', DeptList = '/system/getDeptList',
setRoleStatus = '/system/setRoleStatus',
MenuList = '/system/getMenuList', MenuList = '/system/getMenuList',
RolePageList = '/system/getRoleListByPage', RolePageList = '/system/getRoleListByPage',
GetAllRoleList = '/system/getAllRoleList', GetAllRoleList = '/system/getAllRoleList',
@@ -34,3 +36,9 @@ export const getRoleListByPage = (params?: RolePageParams) =>
export const getAllRoleList = (params?: RoleParams) => export const getAllRoleList = (params?: RoleParams) =>
defHttp.get<RoleListGetResultModel>({ url: Api.GetAllRoleList, params }); defHttp.get<RoleListGetResultModel>({ url: Api.GetAllRoleList, params });
export const setRoleStatus = (id: number, status: string) =>
defHttp.post({ url: Api.setRoleStatus, params: { id, status } });
export const isAccountExist = (account: string) =>
defHttp.post({ url: Api.IsAccountExist, params: { account } }, { errorMessageMode: 'none' });

View File

@@ -14,6 +14,7 @@ export const demoListApi = (params: DemoParams) =>
url: Api.DEMO_LIST, url: Api.DEMO_LIST,
params, params,
headers: { headers: {
// @ts-ignore
ignoreCancelToken: true, ignoreCancelToken: true,
}, },
}); });

11
src/api/demo/tree.ts Normal file
View File

@@ -0,0 +1,11 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
TREE_OPTIONS_LIST = '/tree/getDemoOptions',
}
/**
* @description: Get sample options value
*/
export const treeOptionsListApi = (params?: Recordable) =>
defHttp.get<Recordable[]>({ url: Api.TREE_OPTIONS_LIST, params });

View File

@@ -3,7 +3,7 @@ export interface BasicPageParams {
pageSize: number; pageSize: number;
} }
export interface BasicFetchResult<T extends any> { export interface BasicFetchResult<T> {
items: T; items: T[];
total: number; total: number;
} }

View File

@@ -1,14 +1,14 @@
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { getMenuListByIdParams, getMenuListByIdParamsResultModel } from './model/menuModel'; import { getMenuListResultModel } from './model/menuModel';
enum Api { enum Api {
GetMenuListById = '/getMenuListById', GetMenuList = '/getMenuList',
} }
/** /**
* @description: Get user menu based on id * @description: Get user menu based on id
*/ */
export const getMenuListById = (params: getMenuListByIdParams) => { export const getMenuList = () => {
return defHttp.get<getMenuListByIdParamsResultModel>({ url: Api.GetMenuListById, params }); return defHttp.get<getMenuListResultModel>({ url: Api.GetMenuList });
}; };

View File

@@ -1,4 +1,4 @@
import { RouteMeta } from '/@/router/types'; import type { RouteMeta } from 'vue-router';
export interface RouteItem { export interface RouteItem {
path: string; path: string;
component: any; component: any;
@@ -10,14 +10,7 @@ export interface RouteItem {
children?: RouteItem[]; children?: RouteItem[];
} }
/**
* @description: Get menu interface
*/
export interface getMenuListByIdParams {
id: number | string;
}
/** /**
* @description: Get menu return value * @description: Get menu return value
*/ */
export type getMenuListByIdParamsResultModel = RouteItem[]; export type getMenuListResultModel = RouteItem[];

View File

@@ -6,13 +6,6 @@ export interface LoginParams {
password: string; password: string;
} }
/**
* @description: Get user information
*/
export interface GetUserInfoByUserIdParams {
userId: string | number;
}
export interface RoleInfo { export interface RoleInfo {
roleName: string; roleName: string;
value: string; value: string;
@@ -30,7 +23,7 @@ export interface LoginResultModel {
/** /**
* @description: Get user information return value * @description: Get user information return value
*/ */
export interface GetUserInfoByUserIdModel { export interface GetUserInfoModel {
roles: RoleInfo[]; roles: RoleInfo[];
// 用户id // 用户id
userId: string | number; userId: string | number;
@@ -38,6 +31,8 @@ export interface GetUserInfoByUserIdModel {
username: string; username: string;
// 真实名字 // 真实名字
realName: string; realName: string;
// 头像
avatar: string;
// 介绍 // 介绍
desc?: string; desc?: string;
} }

View File

@@ -1,6 +1,6 @@
import { UploadApiResult } from './model/uploadModel'; import { UploadApiResult } from './model/uploadModel';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { UploadFileParams } from '/@/utils/http/axios/types'; import { UploadFileParams } from '/#/axios';
import { useGlobSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
const { uploadUrl = '' } = useGlobSetting(); const { uploadUrl = '' } = useGlobSetting();
@@ -10,13 +10,13 @@ const { uploadUrl = '' } = useGlobSetting();
*/ */
export function uploadApi( export function uploadApi(
params: UploadFileParams, params: UploadFileParams,
onUploadProgress: (progressEvent: ProgressEvent) => void onUploadProgress: (progressEvent: ProgressEvent) => void,
) { ) {
return defHttp.uploadFile<UploadApiResult>( return defHttp.uploadFile<UploadApiResult>(
{ {
url: uploadUrl, url: uploadUrl,
onUploadProgress, onUploadProgress,
}, },
params params,
); );
} }

View File

@@ -1,17 +1,14 @@
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { import { LoginParams, LoginResultModel, GetUserInfoModel } from './model/userModel';
LoginParams,
LoginResultModel,
GetUserInfoByUserIdParams,
GetUserInfoByUserIdModel,
} from './model/userModel';
import { ErrorMessageMode } from '/@/utils/http/axios/types'; import { ErrorMessageMode } from '/#/axios';
enum Api { enum Api {
Login = '/login', Login = '/login',
GetUserInfoById = '/getUserInfoById', Logout = '/logout',
GetPermCodeByUserId = '/getPermCodeByUserId', GetUserInfo = '/getUserInfo',
GetPermCode = '/getPermCode',
TestRetry = '/testRetry',
} }
/** /**
@@ -25,23 +22,34 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
}, },
{ {
errorMessageMode: mode, errorMessageMode: mode,
} },
); );
} }
/** /**
* @description: getUserInfoById * @description: getUserInfo
*/ */
export function getUserInfoById(params: GetUserInfoByUserIdParams) { export function getUserInfo() {
return defHttp.get<GetUserInfoByUserIdModel>({ return defHttp.get<GetUserInfoModel>({ url: Api.GetUserInfo }, { errorMessageMode: 'none' });
url: Api.GetUserInfoById,
params,
});
} }
export function getPermCodeByUserId(params: GetUserInfoByUserIdParams) { export function getPermCode() {
return defHttp.get<string[]>({ return defHttp.get<string[]>({ url: Api.GetPermCode });
url: Api.GetPermCodeByUserId, }
params,
}); export function doLogout() {
return defHttp.get({ url: Api.Logout });
}
export function testRetry() {
return defHttp.get(
{ url: Api.TestRetry },
{
retryRequest: {
isOpenRetry: true,
count: 5,
waitTime: 1000,
},
},
);
} }

View File

@@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="6395" height="1079" viewBox="0 0 6395 1079"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="6395" height="1079" viewBox="0 0 6395 1079">
<defs> <defs>
<clipPath id="clip-path"> <clipPath id="clip-path">
<rect id="Rectangle_73" data-name="Rectangle 73" width="6395" height="1079" transform="translate(-5391)" fill="#fff"/> <rect width="6395" height="1079" transform="translate(-5391)" fill="#fff"/>
</clipPath> </clipPath>
<linearGradient id="linear-gradient" x1="0.747" y1="0.222" x2="0.973" y2="0.807" gradientUnits="objectBoundingBox"> <linearGradient id="linear-gradient" x1="0.747" y1="0.222" x2="0.973" y2="0.807" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#2c41b4"/> <stop offset="0" stop-color="#2c41b4"/>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1595306944988" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1820" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><defs><style type="text/css"></style></defs><path d="M1464.3 279.7" p-id="1821" fill="#ffffff"></path><path d="M512 960c-60.5 0-119.1-11.9-174.4-35.2-53.4-22.6-101.3-54.9-142.4-96s-73.4-89-96-142.4C75.9 631.1 64 572.5 64 512s11.9-119.1 35.2-174.4c22.6-53.4 54.9-101.3 96-142.4s89-73.4 142.4-96C392.9 75.9 451.5 64 512 64s119.1 11.9 174.4 35.2c53.4 22.6 101.3 54.9 142.4 96s73.4 89 96 142.4C948.1 392.9 960 451.5 960 512c0 19.1-15.5 34.6-34.6 34.6s-34.6-15.5-34.6-34.6c0-51.2-10-100.8-29.8-147.4-19.1-45.1-46.4-85.6-81.2-120.4C745 209.4 704.5 182 659.4 163c-46.7-19.7-96.3-29.8-147.4-29.8-51.2 0-100.8 10-147.4 29.8-45.1 19.1-85.6 46.4-120.4 81.2S182 319.5 163 364.6c-19.7 46.7-29.8 96.3-29.8 147.4 0 51.2 10 100.8 29.8 147.4 19.1 45.1 46.4 85.6 81.2 120.4C279 814.6 319.5 842 364.6 861c46.7 19.7 96.3 29.8 147.4 29.8 64.6 0 128.4-16.5 184.4-47.8 54.4-30.4 100.9-74.1 134.6-126.6 10.3-16.1 31.7-20.8 47.8-10.4 16.1 10.3 20.8 31.7 10.4 47.8-39.8 62-94.8 113.7-159.1 149.6-66.2 37-141.7 56.6-218.1 56.6z" p-id="1822" fill="#ffffff"></path><path d="M924 552c-19.8 0-36-16.2-36-36V228c0-19.8 16.2-36 36-36s36 16.2 36 36v288c0 19.8-16.2 36-36 36zM275.4 575.5c9.5-2.5 19.1 2.9 22.3 12.2 3.5 10.2 9.9 17.7 19.1 22.6 7.1 3.9 15.1 5.8 24 5.8 16.6 0 30.8-6.9 42.5-20.8 11.7-13.8 20-32.7 24.9-75.1-7.7 12.2-17.3 20.8-28.7 25.8-11.4 5-23.7 7.4-36.8 7.4-26.7 0-47.7-8.3-63.3-24.9-15.5-16.6-23.3-37.9-23.3-64.1 0-25.1 7.7-47.1 23-66.2 15.3-19 37.9-28.6 67.8-28.6 40.3 0 68.1 18.1 83.4 54.4 8.5 19.9 12.7 44.9 12.7 74.9 0 33.8-5.1 63.8-15.3 89.9-16.9 43.5-45.5 65.2-85.8 65.2-27 0-47.6-7.1-61.6-21.2-10-10.1-16.4-22-19.3-35.8-2-9.6 4-19.1 13.5-21.6l0.9 0.1z m103-74.4c9.4-7.5 14.1-20.6 14.1-39.3 0-16.8-4.2-29.3-12.7-37.5S360.6 412 347.5 412c-14 0-25.2 4.7-33.4 14.1-8.2 9.4-12.4 22-12.4 37.7 0 14.9 3.6 26.7 10.9 35.5 7.2 8.8 18.8 13.1 34.6 13.1 11.4 0 21.8-3.8 31.2-11.3zM646.6 414.4c12.4 22.8 18.5 54 18.5 93.7 0 37.6-5.6 68.7-16.8 93.3-16.2 35.3-42.8 52.9-79.6 52.9-33.2 0-57.9-14.4-74.2-43.3-13.5-24.1-20.3-56.4-20.3-97 0-31.4 4.1-58.4 12.2-80.9 15.2-42 42.7-63 82.5-63 35.9 0 61.8 14.8 77.7 44.3z m-40.2 173.3c9.4-13.9 14-39.9 14-78 0-27.4-3.4-50-10.1-67.7-6.8-17.7-19.9-26.6-39.4-26.6-17.9 0-31 8.4-39.3 25.2-8.3 16.8-12.4 41.6-12.4 74.3 0 24.6 2.6 44.4 7.9 59.4 8.1 22.8 22 34.3 41.6 34.3 15.7 0 28.3-7 37.7-20.9zM803.3 387.2c11.2 11.3 16.8 25 16.8 41.2 0 16.7-5.8 30.7-17.5 41.8C791 481.4 777.4 487 762 487c-17.1 0-31.2-5.8-42.1-17.4-10.9-11.6-16.4-25.1-16.4-40.6 0-16.5 5.8-30.4 17.3-41.7 11.5-11.3 25.3-17 41.2-17 16.3 0 30.1 5.7 41.3 16.9zM739.5 451c6.2 6.2 13.7 9.3 22.5 9.3 8.4 0 15.8-3.1 22.1-9.3 6.3-6.2 9.4-13.7 9.4-22.6 0-8.5-3.1-15.9-9.3-22.1-6.2-6.2-13.6-9.3-22.2-9.3s-16.1 3.1-22.4 9.3c-6.3 6.2-9.4 13.7-9.4 22.6-0.1 8.4 3 15.8 9.3 22.1z" p-id="1823" fill="#ffffff"></path></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1595307154239" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7317" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><defs><style type="text/css"></style></defs><path d="M316 672h60c4.4 0 8-3.6 8-8V360c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v304c0 4.4 3.6 8 8 8zM512 622c22.1 0 40-17.9 40-39 0-23.1-17.9-41-40-41s-40 17.9-40 41c0 21.1 17.9 39 40 39zM512 482c22.1 0 40-17.9 40-39 0-23.1-17.9-41-40-41s-40 17.9-40 41c0 21.1 17.9 39 40 39z" p-id="7318" fill="#ffffff"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32z m-40 728H184V184h656v656z" p-id="7319" fill="#ffffff"></path><path d="M648 672h60c4.4 0 8-3.6 8-8V360c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v304c0 4.4 3.6 8 8 8z" p-id="7320" fill="#ffffff"></path></svg>

After

Width:  |  Height:  |  Size: 996 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1595307195033" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8116" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><defs><style type="text/css"></style></defs><path d="M887.081 904.791a25.8 25.8 0 0 1-18.376-7.619L705.618 734.075l-4.163 3.369c-58.255 47.18-131.522 73.16-206.32 73.16-181.07 0-328.377-147.308-328.377-328.367 0-181.068 147.308-328.376 328.377-328.376 181.063 0 328.376 147.308 328.376 328.376 0 77.072-27.412 152.07-77.169 211.17l-3.522 4.173 162.719 162.744a25.846 25.846 0 0 1 7.639 18.432 26.081 26.081 0 0 1-26.051 26.045l-0.046-0.01zM495.13 205.957c-152.336 0-276.27 123.935-276.27 276.27 0 152.33 123.934 276.27 276.27 276.27 152.34 0 276.275-123.94 276.275-276.27 0-152.335-123.935-276.27-276.275-276.27z" fill="#ffffff" p-id="8117"></path><path d="M626.545 508.355h-262.83a26.127 26.127 0 0 1 0-52.255h262.83a26.127 26.127 0 0 1 0 52.255z" fill="#ffffff" p-id="8118"></path><path d="M495.13 639.77a26.127 26.127 0 0 1-26.128-26.128v-262.83a26.127 26.127 0 0 1 52.255 0v262.835a26.127 26.127 0 0 1-26.127 26.123z" fill="#ffffff" p-id="8119"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1595306911635" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1352" width="48" height="48" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M924.8 337.6c-22.6-53.4-54.9-101.3-96-142.4s-89-73.4-142.4-96C631.1 75.9 572.5 64 512 64S392.9 75.9 337.6 99.2c-53.4 22.6-101.3 54.9-142.4 96-22.4 22.4-42.2 46.8-59.2 73.1V228c0-19.8-16.2-36-36-36s-36 16.2-36 36v288c0 19.8 16.2 36 36 36s36-16.2 36-36v-50.2c4.2-34.8 13.2-68.7 27-101.2 19.1-45.1 46.4-85.6 81.2-120.4C279 209.4 319.5 182 364.6 163c46.7-19.7 96.3-29.8 147.4-29.8 51.2 0 100.8 10 147.4 29.8 45.1 19.1 85.6 46.4 120.4 81.2C814.6 279 842 319.5 861 364.6c19.7 46.7 29.8 96.3 29.8 147.4 0 51.2-10 100.8-29.8 147.4-19.1 45.1-46.4 85.6-81.2 120.4C745 814.6 704.5 842 659.4 861c-46.7 19.7-96.3 29.8-147.4 29.8-64.6 0-128.4-16.5-184.4-47.8-54.4-30.4-100.9-74.1-134.6-126.6-10.3-16.1-31.7-20.8-47.8-10.4-16.1 10.3-20.8 31.7-10.4 47.8 39.8 62 94.8 113.7 159.1 149.6 66.2 37 141.7 56.6 218.1 56.6 60.5 0 119.1-11.9 174.4-35.2 53.4-22.6 101.3-54.9 142.4-96 41.1-41.1 73.4-89 96-142.4C948.1 631.1 960 572.5 960 512s-11.9-119.1-35.2-174.4z" p-id="1353" fill="#ffffff"></path><path d="M275.4 575.5c9.5-2.5 19.1 2.9 22.3 12.2 3.5 10.2 9.9 17.7 19.1 22.6 7.1 3.9 15.1 5.8 24 5.8 16.6 0 30.8-6.9 42.5-20.8 11.7-13.8 20-32.7 24.9-75.1-7.7 12.2-17.3 20.8-28.7 25.8-11.4 5-23.7 7.4-36.8 7.4-26.7 0-47.7-8.3-63.3-24.9-15.5-16.6-23.3-37.9-23.3-64.1 0-25.1 7.7-47.1 23-66.2 15.3-19 37.9-28.6 67.8-28.6 40.3 0 68.1 18.1 83.4 54.4 8.5 19.9 12.7 44.9 12.7 74.9 0 33.8-5.1 63.8-15.3 89.9-16.9 43.5-45.5 65.2-85.8 65.2-27 0-47.6-7.1-61.6-21.2-10-10.1-16.4-22-19.3-35.8-2-9.6 4-19.1 13.5-21.6l0.9 0.1z m103-74.4c9.4-7.5 14.1-20.6 14.1-39.3 0-16.8-4.2-29.3-12.7-37.5S360.6 412 347.5 412c-14 0-25.2 4.7-33.4 14.1-8.2 9.4-12.4 22-12.4 37.7 0 14.9 3.6 26.7 10.9 35.5 7.2 8.8 18.8 13.1 34.6 13.1 11.4 0 21.8-3.8 31.2-11.3zM646.6 414.4c12.4 22.8 18.5 54 18.5 93.7 0 37.6-5.6 68.7-16.8 93.3-16.2 35.3-42.8 52.9-79.6 52.9-33.2 0-57.9-14.4-74.2-43.3-13.5-24.1-20.3-56.4-20.3-97 0-31.4 4.1-58.4 12.2-80.9 15.2-42 42.7-63 82.5-63 35.9 0 61.8 14.8 77.7 44.3z m-40.2 173.3c9.4-13.9 14-39.9 14-78 0-27.4-3.4-50-10.1-67.7-6.8-17.7-19.9-26.6-39.4-26.6-17.9 0-31 8.4-39.3 25.2-8.3 16.8-12.4 41.6-12.4 74.3 0 24.6 2.6 44.4 7.9 59.4 8.1 22.8 22 34.3 41.6 34.3 15.7 0 28.3-7 37.7-20.9zM803.3 387.2c11.2 11.3 16.8 25 16.8 41.2 0 16.7-5.8 30.7-17.5 41.8C791 481.4 777.4 487 762 487c-17.1 0-31.2-5.8-42.1-17.4-10.9-11.6-16.4-25.1-16.4-40.6 0-16.5 5.8-30.4 17.3-41.7 11.5-11.3 25.3-17 41.2-17 16.3 0 30.1 5.7 41.3 16.9zM739.5 451c6.2 6.2 13.7 9.3 22.5 9.3 8.4 0 15.8-3.1 22.1-9.3 6.3-6.2 9.4-13.7 9.4-22.6 0-8.5-3.1-15.9-9.3-22.1-6.2-6.2-13.6-9.3-22.2-9.3s-16.1 3.1-22.4 9.3c-6.3 6.2-9.4 13.7-9.4 22.6-0.1 8.4 3 15.8 9.3 22.1z" p-id="1354" fill="#ffffff"></path></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1595308005241" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9878" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><defs><style type="text/css"></style></defs><path d="M750.3 198.7C598 46.4 351.1 46.4 198.7 198.7s-152.3 399.2 0 551.5C345.1 896.6 578.8 902.3 732 767.3l172.1 172.1 35.4-35.4-172.1-171.9c135-153.2 129.3-387-17.1-533.4z m39.3 403.8c-17.1 42.1-42.2 80-74.7 112.4-32.5 32.5-70.3 57.6-112.4 74.7-40.7 16.5-83.8 24.9-128 24.9s-87.2-8.4-128-24.9c-42.1-17.1-80-42.2-112.4-74.7s-57.6-70.3-74.7-112.4c-16.5-40.7-24.9-83.8-24.9-128s8.4-87.2 24.9-128c17.1-42.1 42.2-80 74.7-112.4s70.3-57.6 112.4-74.7c40.7-16.5 83.8-24.9 128-24.9s87.2 8.4 128 24.9c42.1 17.1 80 42.2 112.4 74.7 32.5 32.5 57.6 70.3 74.7 112.4 16.5 40.7 24.9 83.8 24.9 128s-8.4 87.3-24.9 128zM671 502H271v-50h400v50z" fill="#ffffff" p-id="9879"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,8 +1,15 @@
import AppLogo from './src/AppLogo.vue'; import { withInstall } from '/@/utils';
import AppProvider from './src/AppProvider.vue';
import AppSearch from './src/search/AppSearch.vue'; import appLogo from './src/AppLogo.vue';
import AppLocalePicker from './src/AppLocalePicker.vue'; import appProvider from './src/AppProvider.vue';
import AppDarkModeToggle from './src/AppDarkModeToggle.vue'; import appSearch from './src/search/AppSearch.vue';
import appLocalePicker from './src/AppLocalePicker.vue';
import appDarkModeToggle from './src/AppDarkModeToggle.vue';
export { useAppProviderContext } from './src/useAppContext'; export { useAppProviderContext } from './src/useAppContext';
export { AppLogo, AppProvider, AppSearch, AppLocalePicker, AppDarkModeToggle };
export const AppLogo = withInstall(appLogo);
export const AppProvider = withInstall(appProvider);
export const AppSearch = withInstall(appSearch);
export const AppLocalePicker = withInstall(appLocalePicker);
export const AppDarkModeToggle = withInstall(appDarkModeToggle);

View File

@@ -1,69 +1,45 @@
<template> <template>
<div <div v-if="getShowDarkModeToggle" :class="getClass" @click="toggleDarkMode">
v-if="getShowDarkModeToggle" <div :class="`${prefixCls}-inner`"></div>
:class="[
prefixCls,
`${prefixCls}--${size}`,
{
[`${prefixCls}--dark`]: isDark,
},
]"
@click="toggleDarkMode"
>
<div :class="`${prefixCls}-inner`"> </div>
<SvgIcon size="14" name="sun" /> <SvgIcon size="14" name="sun" />
<SvgIcon size="14" name="moon" /> <SvgIcon size="14" name="moon" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, computed } from 'vue'; import { computed, unref } from 'vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { SvgIcon } from '/@/components/Icon'; import { SvgIcon } from '/@/components/Icon';
import { useDesign } from '/@/hooks/web/useDesign';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground'; import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground';
import { updateDarkTheme } from '/@/logics/theme/dark'; import { updateDarkTheme } from '/@/logics/theme/dark';
import { ThemeEnum } from '/@/enums/appEnum'; import { ThemeEnum } from '/@/enums/appEnum';
export default defineComponent({ const { prefixCls } = useDesign('dark-switch');
name: 'DarkModeToggle', const { getDarkMode, setDarkMode, getShowDarkModeToggle } = useRootSetting();
components: { SvgIcon },
props: {
size: {
type: String,
default: 'default',
validate: (val) => ['default', 'large'].includes(val),
},
},
setup() {
const { prefixCls } = useDesign('dark-mode-toggle');
const { getDarkMode, setDarkMode, getShowDarkModeToggle } = useRootSetting();
const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK);
function toggleDarkMode() {
const darkMode = getDarkMode.value === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
setDarkMode(darkMode);
updateDarkTheme(darkMode);
updateHeaderBgColor();
updateSidebarBgColor();
}
return { const isDark = computed(() => getDarkMode.value === ThemeEnum.DARK);
isDark,
prefixCls, const getClass = computed(() => [
toggleDarkMode, prefixCls,
getShowDarkModeToggle, {
}; [`${prefixCls}--dark`]: unref(isDark),
}, },
}); ]);
function toggleDarkMode() {
const darkMode = getDarkMode.value === ThemeEnum.DARK ? ThemeEnum.LIGHT : ThemeEnum.DARK;
setDarkMode(darkMode);
updateDarkTheme(darkMode);
updateHeaderBgColor();
updateSidebarBgColor();
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-dark-mode-toggle'; @prefix-cls: ~'@{namespace}-dark-switch';
html[data-theme='dark'] { html[data-theme='dark'] {
.@{prefix-cls} { .@{prefix-cls} {
border: 1px solid rgb(196, 188, 188); border: 1px solid rgb(196 188 188);
} }
} }
@@ -96,16 +72,5 @@
transform: translateX(calc(100% + 2px)); transform: translateX(calc(100% + 2px));
} }
} }
&--large {
width: 72px;
height: 34px;
padding: 0 10px;
.@{prefix-cls}-inner {
width: 26px;
height: 26px;
}
}
} }
</style> </style>

View File

@@ -4,69 +4,67 @@
--> -->
<template> <template>
<Dropdown <Dropdown
placement="bottomCenter" placement="bottom"
:trigger="['click']" :trigger="['click']"
:dropMenuList="localeList" :dropMenuList="localeList"
:selectedKeys="selectedKeys" :selectedKeys="selectedKeys"
@menuEvent="handleMenuEvent" @menu-event="handleMenuEvent"
overlayClassName="app-locale-picker-overlay" overlayClassName="app-locale-picker-overlay"
> >
<span class="cursor-pointer flex items-center"> <span class="cursor-pointer flex items-center">
<Icon icon="ion:language" /> <Icon icon="ion:language" />
<span v-if="showText" class="ml-1">{{ getLangText }}</span> <span v-if="showText" class="ml-1">{{ getLocaleText }}</span>
</span> </span>
</Dropdown> </Dropdown>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import type { LocaleType } from '/#/config'; import type { LocaleType } from '/#/config';
import type { DropMenu } from '/@/components/Dropdown'; import type { DropMenu } from '/@/components/Dropdown';
import { ref, watchEffect, unref, computed } from 'vue';
import { defineComponent, ref, watchEffect, unref, computed } from 'vue';
import { Dropdown } from '/@/components/Dropdown'; import { Dropdown } from '/@/components/Dropdown';
import Icon from '/@/components/Icon'; import { Icon } from '/@/components/Icon';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
import { localeList } from '/@/settings/localeSetting'; import { localeList } from '/@/settings/localeSetting';
import { propTypes } from '/@/utils/propTypes';
export default defineComponent({ const props = defineProps({
name: 'AppLocalPicker', /**
components: { Dropdown, Icon }, * Whether to display text
props: { */
// Whether to display text showText: { type: Boolean, default: true },
showText: propTypes.bool.def(true), /**
// Whether to refresh the interface when changing * Whether to refresh the interface when changing
reload: propTypes.bool, */
}, reload: { type: Boolean },
setup(props) {
const selectedKeys = ref<string[]>([]);
const { changeLocale, getLocale } = useLocale();
const getLangText = computed(() => {
const key = selectedKeys.value[0];
if (!key) return '';
return localeList.find((item) => item.event === key)?.text;
});
watchEffect(() => {
selectedKeys.value = [unref(getLocale)];
});
async function toggleLocale(lang: LocaleType | string) {
await changeLocale(lang as LocaleType);
selectedKeys.value = [lang as string];
props.reload && location.reload();
}
function handleMenuEvent(menu: DropMenu) {
if (unref(getLocale) === menu.event) return;
toggleLocale(menu.event as string);
}
return { localeList, handleMenuEvent, selectedKeys, getLangText };
},
}); });
const selectedKeys = ref<string[]>([]);
const { changeLocale, getLocale } = useLocale();
const getLocaleText = computed(() => {
const key = selectedKeys.value[0];
if (!key) {
return '';
}
return localeList.find((item) => item.event === key)?.text;
});
watchEffect(() => {
selectedKeys.value = [unref(getLocale)];
});
async function toggleLocale(lang: LocaleType | string) {
await changeLocale(lang as LocaleType);
selectedKeys.value = [lang as string];
props.reload && location.reload();
}
function handleMenuEvent(menu: DropMenu) {
if (unref(getLocale) === menu.event) {
return;
}
toggleLocale(menu.event as string);
}
</script> </script>
<style lang="less"> <style lang="less">

View File

@@ -3,66 +3,59 @@
* @Description: logo component * @Description: logo component
--> -->
<template> <template>
<div <div class="anticon" :class="getAppLogoClass" @click="goHome">
class="anticon"
:class="[prefixCls, theme, { 'collapsed-show-title': getCollapsedShowTitle }]"
@click="handleGoHome"
>
<img src="../../../assets/images/logo.png" /> <img src="../../../assets/images/logo.png" />
<div <div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
class="ml-2 truncate md:opacity-100"
:class="[
`${prefixCls}__title`,
{
'xs:opacity-0': !alwaysShowTitle,
},
]"
v-show="showTitle"
>
{{ title }} {{ title }}
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { computed, unref } from 'vue';
import { useGlobSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
import { useGo } from '/@/hooks/web/usePage'; import { useGo } from '/@/hooks/web/usePage';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { PageEnum } from '/@/enums/pageEnum'; import { PageEnum } from '/@/enums/pageEnum';
import { propTypes } from '/@/utils/propTypes'; import { useUserStore } from '/@/store/modules/user';
export default defineComponent({ const props = defineProps({
name: 'AppLogo', /**
props: { * The theme of the current parent component
/** */
* The theme of the current parent component theme: { type: String, validator: (v: string) => ['light', 'dark'].includes(v) },
*/ /**
theme: propTypes.oneOf(['light', 'dark']), * Whether to show title
// Whether to show title */
showTitle: propTypes.bool.def(true), showTitle: { type: Boolean, default: true },
alwaysShowTitle: propTypes.bool.def(false), /**
}, * The title is also displayed when the menu is collapsed
setup() { */
const { prefixCls } = useDesign('app-logo'); alwaysShowTitle: { type: Boolean },
const { getCollapsedShowTitle } = useMenuSetting();
const { title } = useGlobSetting();
const go = useGo();
function handleGoHome(): void {
go(PageEnum.BASE_HOME);
}
return {
handleGoHome,
title,
prefixCls,
getCollapsedShowTitle,
};
},
}); });
const { prefixCls } = useDesign('app-logo');
const { getCollapsedShowTitle } = useMenuSetting();
const userStore = useUserStore();
const { title } = useGlobSetting();
const go = useGo();
const getAppLogoClass = computed(() => [
prefixCls,
props.theme,
{ 'collapsed-show-title': unref(getCollapsedShowTitle) },
]);
const getTitleClass = computed(() => [
`${prefixCls}__title`,
{
'xs:opacity-0': !props.alwaysShowTitle,
},
]);
function goHome() {
go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-app-logo'; @prefix-cls: ~'@{namespace}-app-logo';
@@ -94,6 +87,7 @@
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 700;
transition: all 0.5s; transition: all 0.5s;
line-height: normal;
} }
} }
</style> </style>

View File

@@ -1,24 +1,29 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, toRefs, ref, unref } from 'vue'; import { defineComponent, toRefs, ref, unref } from 'vue';
import { createAppProviderContext } from './useAppContext'; import { createAppProviderContext } from './useAppContext';
import designSetting from '/@/settings/designSetting';
import { createBreakpointListen } from '/@/hooks/event/useBreakpoint'; import { createBreakpointListen } from '/@/hooks/event/useBreakpoint';
import { propTypes } from '/@/utils/propTypes'; import { prefixCls } from '/@/settings/designSetting';
import { appStore } from '/@/store/modules/app'; import { useAppStore } from '/@/store/modules/app';
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
const props = {
/**
* class style prefix
*/
prefixCls: { type: String, default: prefixCls },
};
export default defineComponent({ export default defineComponent({
name: 'AppProvider', name: 'AppProvider',
inheritAttrs: false, inheritAttrs: false,
props: { props,
prefixCls: propTypes.string.def(designSetting.prefixCls),
},
setup(props, { slots }) { setup(props, { slots }) {
const isMobile = ref(false); const isMobile = ref(false);
const isSetState = ref(false); const isSetState = ref(false);
const appStore = useAppStore();
// Monitor screen breakpoint information changes
createBreakpointListen(({ screenMap, sizeEnum, width }) => { createBreakpointListen(({ screenMap, sizeEnum, width }) => {
const lgWidth = screenMap.get(sizeEnum.LG); const lgWidth = screenMap.get(sizeEnum.LG);
if (lgWidth) { if (lgWidth) {
@@ -28,8 +33,13 @@
}); });
const { prefixCls } = toRefs(props); const { prefixCls } = toRefs(props);
// Inject variables into the global
createAppProviderContext({ prefixCls, isMobile }); createAppProviderContext({ prefixCls, isMobile });
/**
* Used to maintain the state before the window changes
*/
function handleRestoreState() { function handleRestoreState() {
if (unref(isMobile)) { if (unref(isMobile)) {
if (!unref(isSetState)) { if (!unref(isSetState)) {
@@ -42,20 +52,20 @@
split: menuSplit, split: menuSplit,
}, },
} = appStore.getProjectConfig; } = appStore.getProjectConfig;
appStore.commitProjectConfigState({ appStore.setProjectConfig({
menuSetting: { menuSetting: {
type: MenuTypeEnum.SIDEBAR, type: MenuTypeEnum.SIDEBAR,
mode: MenuModeEnum.INLINE, mode: MenuModeEnum.INLINE,
split: false, split: false,
}, },
}); });
appStore.commitBeforeMiniState({ menuMode, menuCollapsed, menuType, menuSplit }); appStore.setBeforeMiniInfo({ menuMode, menuCollapsed, menuType, menuSplit });
} }
} else { } else {
if (unref(isSetState)) { if (unref(isSetState)) {
isSetState.value = false; isSetState.value = false;
const { menuMode, menuCollapsed, menuType, menuSplit } = appStore.getBeforeMiniState; const { menuMode, menuCollapsed, menuType, menuSplit } = appStore.getBeforeMiniInfo;
appStore.commitProjectConfigState({ appStore.setProjectConfig({
menuSetting: { menuSetting: {
type: menuType, type: menuType,
mode: menuMode, mode: menuMode,

View File

@@ -1,20 +1,14 @@
<script lang="tsx"> <script lang="tsx">
import { defineComponent, ref, unref } from 'vue'; import { defineComponent, ref, unref } from 'vue';
import { Tooltip } from 'ant-design-vue'; import { Tooltip } from 'ant-design-vue';
import { SearchOutlined } from '@ant-design/icons-vue'; import { SearchOutlined } from '@ant-design/icons-vue';
import AppSearchModal from './AppSearchModal.vue'; import AppSearchModal from './AppSearchModal.vue';
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({ export default defineComponent({
name: 'AppSearch', name: 'AppSearch',
components: { AppSearchModal, Tooltip },
setup() { setup() {
const showModal = ref(false); const showModal = ref(false);
const { getShowSearch } = useHeaderSetting();
const { t } = useI18n(); const { t } = useI18n();
function changeModal(show: boolean) { function changeModal(show: boolean) {
@@ -22,9 +16,6 @@
} }
return () => { return () => {
if (!unref(getShowSearch)) {
return null;
}
return ( return (
<div class="p-1" onClick={changeModal.bind(null, true)}> <div class="p-1" onClick={changeModal.bind(null, true)}>
<Tooltip> <Tooltip>

View File

@@ -1,36 +1,21 @@
<template> <template>
<div :class="`${prefixCls}`"> <div :class="`${prefixCls}`">
<AppSearchKeyItem :class="`${prefixCls}__item`" icon="ant-design:enter-outlined" /> <AppSearchKeyItem :class="`${prefixCls}-item`" icon="ant-design:enter-outlined" />
<span>{{ t('component.app.toSearch') }}</span> <span>{{ t('component.app.toSearch') }}</span>
<AppSearchKeyItem :class="`${prefixCls}-item`" icon="ion:arrow-up-outline" />
<AppSearchKeyItem :class="`${prefixCls}__item`" icon="ion:arrow-up-outline" /> <AppSearchKeyItem :class="`${prefixCls}-item`" icon="ion:arrow-down-outline" />
<AppSearchKeyItem :class="`${prefixCls}__item`" icon="ion:arrow-down-outline" />
<span>{{ t('component.app.toNavigate') }}</span> <span>{{ t('component.app.toNavigate') }}</span>
<AppSearchKeyItem :class="`${prefixCls}__item`" icon="mdi:keyboard-esc" /> <AppSearchKeyItem :class="`${prefixCls}-item`" icon="mdi:keyboard-esc" />
<span>{{ t('common.closeText') }}</span> <span>{{ t('common.closeText') }}</span>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
import AppSearchKeyItem from './AppSearchKeyItem.vue'; import AppSearchKeyItem from './AppSearchKeyItem.vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({ const { prefixCls } = useDesign('app-search-footer');
name: 'AppSearchFooter', const { t } = useI18n();
components: { AppSearchKeyItem },
setup() {
const { prefixCls } = useDesign('app-search-footer');
const { t } = useI18n();
return {
prefixCls,
t,
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-app-search-footer'; @prefix-cls: ~'@{namespace}-app-search-footer';
@@ -42,22 +27,22 @@
padding: 0 16px; padding: 0 16px;
font-size: 12px; font-size: 12px;
color: #666; color: #666;
background: @component-background; background-color: @component-background;
border-top: 1px solid @border-color-base; border-top: 1px solid @border-color-base;
border-radius: 0 0 16px 16px; border-radius: 0 0 16px 16px;
align-items: center; align-items: center;
flex-shrink: 0; flex-shrink: 0;
&__item { &-item {
display: flex; display: flex;
width: 20px; width: 20px;
height: 18px; height: 18px;
padding-bottom: 2px; padding-bottom: 2px;
margin-right: 0.4em; margin-right: 0.4em;
background: linear-gradient(-225deg, #d5dbe4, #f8f8f8); background-color: linear-gradient(-225deg, #d5dbe4, #f8f8f8);
border-radius: 2px; border-radius: 2px;
box-shadow: inset 0 -2px 0 0 #cdcde6, inset 0 0 1px 1px #fff, box-shadow: inset 0 -2px 0 0 #cdcde6, inset 0 0 1px 1px #fff,
0 1px 2px 1px rgba(30, 35, 90, 0.4); 0 1px 2px 1px rgb(30 35 90 / 40%);
align-items: center; align-items: center;
justify-content: center; justify-content: center;

View File

@@ -3,15 +3,9 @@
<Icon :icon="icon" /> <Icon :icon="icon" />
</span> </span>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue';
import { Icon } from '/@/components/Icon'; import { Icon } from '/@/components/Icon';
import { propTypes } from '/@/utils/propTypes'; defineProps({
icon: String,
export default defineComponent({
components: { Icon },
props: {
icon: propTypes.string,
},
}); });
</script> </script>

View File

@@ -7,11 +7,11 @@
<a-input <a-input
:class="`${prefixCls}-input`" :class="`${prefixCls}-input`"
:placeholder="t('common.searchText')" :placeholder="t('common.searchText')"
ref="inputRef"
allow-clear allow-clear
@change="handleSearch" @change="handleSearch"
> >
<template #prefix> <template #prefix>
<!-- <Icon icon="ion:search"/> -->
<SearchOutlined /> <SearchOutlined />
</template> </template>
</a-input> </a-input>
@@ -56,84 +56,62 @@
</transition> </transition>
</Teleport> </Teleport>
</template> </template>
<script lang="ts">
import { defineComponent, computed, unref, ref } from 'vue';
<script lang="ts" setup>
import { computed, unref, ref, watch, nextTick } from 'vue';
import { SearchOutlined } from '@ant-design/icons-vue'; import { SearchOutlined } from '@ant-design/icons-vue';
import { Input } from 'ant-design-vue';
import AppSearchFooter from './AppSearchFooter.vue'; import AppSearchFooter from './AppSearchFooter.vue';
import Icon from '/@/components/Icon'; import Icon from '/@/components/Icon';
// @ts-ignore
import clickOutside from '/@/directives/clickOutside'; import vClickOutside from '/@/directives/clickOutside';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useRefs } from '/@/hooks/core/useRefs'; import { useRefs } from '/@/hooks/core/useRefs';
import { useMenuSearch } from './useMenuSearch'; import { useMenuSearch } from './useMenuSearch';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useAppInject } from '/@/hooks/web/useAppInject'; import { useAppInject } from '/@/hooks/web/useAppInject';
import { propTypes } from '/@/utils/propTypes'; const props = defineProps({
visible: { type: Boolean },
export default defineComponent({
name: 'AppSearchModal',
components: { Icon, SearchOutlined, AppSearchFooter, [Input.name]: Input },
directives: {
clickOutside,
},
props: {
visible: propTypes.bool,
},
emits: ['close'],
setup(_, { emit }) {
const scrollWrap = ref<ElRef>(null);
const { prefixCls } = useDesign('app-search-modal');
const { t } = useI18n();
const [refs, setRefs] = useRefs();
const { getIsMobile } = useAppInject();
const {
handleSearch,
searchResult,
keyword,
activeIndex,
handleEnter,
handleMouseenter,
} = useMenuSearch(refs, scrollWrap, emit);
const getIsNotData = computed(() => {
return !keyword || unref(searchResult).length === 0;
});
const getClass = computed(() => {
return [
prefixCls,
{
[`${prefixCls}--mobile`]: unref(getIsMobile),
},
];
});
function handleClose() {
searchResult.value = [];
emit('close');
}
return {
t,
prefixCls,
getClass,
handleSearch,
searchResult,
activeIndex,
getIsNotData,
handleEnter,
setRefs,
scrollWrap,
handleMouseenter,
handleClose,
};
},
}); });
const emit = defineEmits(['close']);
const scrollWrap = ref(null);
const inputRef = ref<Nullable<HTMLElement>>(null);
const { t } = useI18n();
const { prefixCls } = useDesign('app-search-modal');
const [refs, setRefs] = useRefs();
const { getIsMobile } = useAppInject();
const { handleSearch, searchResult, keyword, activeIndex, handleEnter, handleMouseenter } =
useMenuSearch(refs, scrollWrap, emit);
const getIsNotData = computed(() => !keyword || unref(searchResult).length === 0);
const getClass = computed(() => {
return [
prefixCls,
{
[`${prefixCls}--mobile`]: unref(getIsMobile),
},
];
});
watch(
() => props.visible,
(visible: boolean) => {
visible &&
nextTick(() => {
unref(inputRef)?.focus();
});
},
);
function handleClose() {
searchResult.value = [];
emit('close');
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-app-search-modal'; @prefix-cls: ~'@{namespace}-app-search-modal';
@@ -147,7 +125,7 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
padding-top: 50px; padding-top: 50px;
background: rgba(0, 0, 0, 0.25); background-color: rgb(0 0 0 / 25%);
justify-content: center; justify-content: center;
&--mobile { &--mobile {
@@ -181,7 +159,7 @@
&__item { &__item {
&-enter { &-enter {
opacity: 0 !important; opacity: 0% !important;
} }
} }
} }
@@ -190,16 +168,16 @@
&-content { &-content {
position: relative; position: relative;
width: 632px; width: 632px;
margin: 0 auto auto auto; margin: 0 auto auto;
background: @component-background; background-color: @component-background;
border-radius: 16px; border-radius: 16px;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); box-shadow: 0 25px 50px -12px rgb(0 0 0 / 25%);
flex-direction: column; flex-direction: column;
} }
&-input__wrapper { &-input__wrapper {
display: flex; display: flex;
padding: 14px 14px 0 14px; padding: 14px 14px 0;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
@@ -251,7 +229,7 @@
font-size: 14px; font-size: 14px;
color: @text-color-base; color: @text-color-base;
cursor: pointer; cursor: pointer;
background: @component-background; background-color: @component-background;
border-radius: 4px; border-radius: 4px;
box-shadow: 0 1px 3px 0 #d4d9e1; box-shadow: 0 1px 3px 0 #d4d9e1;
align-items: center; align-items: center;
@@ -264,10 +242,10 @@
&--active { &--active {
color: #fff; color: #fff;
background: @primary-color; background-color: @primary-color;
.@{prefix-cls}-list__item-enter { .@{prefix-cls}-list__item-enter {
opacity: 1; opacity: 100%;
} }
} }
@@ -281,7 +259,7 @@
&-enter { &-enter {
width: 30px; width: 30px;
opacity: 0; opacity: 0%;
} }
} }
} }

View File

@@ -1,17 +1,11 @@
import type { Menu } from '/@/router/types'; import type { Menu } from '/@/router/types';
import { ref, onBeforeMount, unref, Ref, nextTick } from 'vue'; import { ref, onBeforeMount, unref, Ref, nextTick } from 'vue';
import { getMenus } from '/@/router/menus'; import { getMenus } from '/@/router/menus';
import { KeyCodeEnum } from '/@/enums/keyCodeEnum';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { filter, forEach } from '/@/utils/helper/treeHelper'; import { filter, forEach } from '/@/utils/helper/treeHelper';
import { useDebounce } from '/@/hooks/core/useDebounce';
import { useGo } from '/@/hooks/web/usePage'; import { useGo } from '/@/hooks/web/usePage';
import { useScrollTo } from '/@/hooks/event/useScrollTo'; import { useScrollTo } from '/@/hooks/event/useScrollTo';
import { useKeyPress } from '/@/hooks/event/useKeyPress'; import { onKeyStroke, useDebounceFn } from '@vueuse/core';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
export interface SearchResult { export interface SearchResult {
@@ -41,7 +35,7 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
const { t } = useI18n(); const { t } = useI18n();
const go = useGo(); const go = useGo();
const [handleSearch] = useDebounce(search, 200); const handleSearch = useDebounceFn(search, 200);
onBeforeMount(async () => { onBeforeMount(async () => {
const list = await getMenus(); const list = await getMenus();
@@ -61,7 +55,7 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
} }
const reg = createSearchReg(unref(keyword)); const reg = createSearchReg(unref(keyword));
const filterMenu = filter(menuList, (item) => { const filterMenu = filter(menuList, (item) => {
return reg.test(item.name); return reg.test(item.name) && !item.hideMenu;
}); });
searchResult.value = handlerSearchResult(filterMenu, reg); searchResult.value = handlerSearchResult(filterMenu, reg);
activeIndex.value = 0; activeIndex.value = 0;
@@ -69,28 +63,29 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) { function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) {
const ret: SearchResult[] = []; const ret: SearchResult[] = [];
filterMenu.forEach((item) => { filterMenu.forEach((item) => {
const { name, path, icon, children } = item; const { name, path, icon, children, hideMenu, meta } = item;
if (reg.test(name) && !children?.length) { if (!hideMenu && reg.test(name) && (!children?.length || meta?.hideChildrenInMenu)) {
ret.push({ ret.push({
name: parent?.name ? `${parent.name} > ${name}` : name, name: parent?.name ? `${parent.name} > ${name}` : name,
path, path,
icon, icon,
}); });
} }
if (Array.isArray(children) && children.length) { if (!meta?.hideChildrenInMenu && Array.isArray(children) && children.length) {
ret.push(...handlerSearchResult(children, reg, item)); ret.push(...handlerSearchResult(children, reg, item));
} }
}); });
return ret; return ret;
} }
// Activate when the mouse moves to a certain line
function handleMouseenter(e: any) { function handleMouseenter(e: any) {
const index = e.target.dataset.index; const index = e.target.dataset.index;
activeIndex.value = Number(index); activeIndex.value = Number(index);
} }
// Arrow key up
function handleUp() { function handleUp() {
if (!searchResult.value.length) return; if (!searchResult.value.length) return;
activeIndex.value--; activeIndex.value--;
@@ -100,6 +95,7 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
handleScroll(); handleScroll();
} }
// Arrow key down
function handleDown() { function handleDown() {
if (!searchResult.value.length) return; if (!searchResult.value.length) return;
activeIndex.value++; activeIndex.value++;
@@ -109,15 +105,23 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
handleScroll(); handleScroll();
} }
// When the keyboard up and down keys move to an invisible place
// the scroll bar needs to scroll automatically
function handleScroll() { function handleScroll() {
const refList = unref(refs); const refList = unref(refs);
if (!refList || !Array.isArray(refList) || refList.length === 0 || !unref(scrollWrap)) return; if (!refList || !Array.isArray(refList) || refList.length === 0 || !unref(scrollWrap)) {
return;
}
const index = unref(activeIndex); const index = unref(activeIndex);
const currentRef = refList[index]; const currentRef = refList[index];
if (!currentRef) return; if (!currentRef) {
return;
}
const wrapEl = unref(scrollWrap); const wrapEl = unref(scrollWrap);
if (!wrapEl) return; if (!wrapEl) {
return;
}
const scrollHeight = currentRef.offsetTop + currentRef.offsetHeight; const scrollHeight = currentRef.offsetTop + currentRef.offsetHeight;
const wrapHeight = wrapEl.offsetHeight; const wrapHeight = wrapEl.offsetHeight;
const { start } = useScrollTo({ const { start } = useScrollTo({
@@ -128,8 +132,11 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
start(); start();
} }
// enter keyboard event
async function handleEnter() { async function handleEnter() {
if (!searchResult.value.length) return; if (!searchResult.value.length) {
return;
}
const result = unref(searchResult); const result = unref(searchResult);
const index = unref(activeIndex); const index = unref(activeIndex);
if (result.length === 0 || index < 0) { if (result.length === 0 || index < 0) {
@@ -141,28 +148,19 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
go(to.path); go(to.path);
} }
// close search modal
function handleClose() { function handleClose() {
searchResult.value = []; searchResult.value = [];
emit('close'); emit('close');
} }
useKeyPress(['enter', 'up', 'down', 'esc'], (events) => { // enter search
const keyCode = events.keyCode; onKeyStroke('Enter', handleEnter);
switch (keyCode) { // Monitor keyboard arrow keys
case KeyCodeEnum.UP: onKeyStroke('ArrowUp', handleUp);
handleUp(); onKeyStroke('ArrowDown', handleDown);
break; // esc close
case KeyCodeEnum.DOWN: onKeyStroke('Escape', handleClose);
handleDown();
break;
case KeyCodeEnum.ENTER:
handleEnter();
break;
case KeyCodeEnum.ESC:
handleClose();
break;
}
});
return { handleSearch, searchResult, keyword, activeIndex, handleMouseenter, handleEnter }; return { handleSearch, searchResult, keyword, activeIndex, handleMouseenter, handleEnter };
} }

View File

@@ -3,7 +3,6 @@ import { createContext, useContext } from '/@/hooks/core/useContext';
export interface AppProviderContextProps { export interface AppProviderContextProps {
prefixCls: Ref<string>; prefixCls: Ref<string>;
isMobile: Ref<boolean>; isMobile: Ref<boolean>;
} }

View File

@@ -1,3 +1,4 @@
import Authority from './src/index.vue'; import { withInstall } from '/@/utils';
import authority from './src/Authority.vue';
export { Authority }; export const Authority = withInstall(authority);

View File

@@ -4,11 +4,8 @@
<script lang="ts"> <script lang="ts">
import type { PropType } from 'vue'; import type { PropType } from 'vue';
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { RoleEnum } from '/@/enums/roleEnum'; import { RoleEnum } from '/@/enums/roleEnum';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
import { getSlot } from '/@/utils/helper/tsxHelper'; import { getSlot } from '/@/utils/helper/tsxHelper';
export default defineComponent({ export default defineComponent({

View File

@@ -1,5 +1,8 @@
import BasicArrow from './src/BasicArrow.vue'; import { withInstall } from '/@/utils';
import BasicTitle from './src/BasicTitle.vue'; import basicArrow from './src/BasicArrow.vue';
import BasicHelp from './src/BasicHelp.vue'; import basicTitle from './src/BasicTitle.vue';
import basicHelp from './src/BasicHelp.vue';
export { BasicArrow, BasicTitle, BasicHelp }; export const BasicArrow = withInstall(basicArrow);
export const BasicTitle = withInstall(basicTitle);
export const BasicHelp = withInstall(basicHelp);

View File

@@ -7,44 +7,44 @@
<Icon icon="ion:chevron-forward" :style="$attrs.iconStyle" /> <Icon icon="ion:chevron-forward" :style="$attrs.iconStyle" />
</span> </span>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, computed } from 'vue'; import { computed } from 'vue';
import { Icon } from '/@/components/Icon';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { propTypes } from '/@/utils/propTypes'; const props = defineProps({
/**
* Arrow expand state
*/
expand: { type: Boolean },
/**
* Arrow up by default
*/
up: { type: Boolean },
/**
* Arrow down by default
*/
down: { type: Boolean },
/**
* Cancel padding/margin for inline
*/
inset: { type: Boolean },
});
import { Icon } from '/@/components/Icon'; const { prefixCls } = useDesign('basic-arrow');
export default defineComponent({ // get component class
name: 'BasicArrow', const getClass = computed(() => {
components: { Icon }, const { expand, up, down, inset } = props;
props: { return [
expand: propTypes.bool, prefixCls,
top: propTypes.bool, {
bottom: propTypes.bool, [`${prefixCls}--active`]: expand,
inset: propTypes.bool, up,
}, inset,
setup(props) { down,
const { prefixCls } = useDesign('basic-arrow'); },
];
const getClass = computed(() => {
const { expand, top, bottom, inset } = props;
return [
prefixCls,
{
[`${prefixCls}--active`]: expand,
top,
inset,
bottom,
},
];
});
return {
getClass,
};
},
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@@ -52,6 +52,7 @@
.@{prefix-cls} { .@{prefix-cls} {
display: inline-block; display: inline-block;
cursor: pointer;
transform: rotate(0deg); transform: rotate(0deg);
transition: all 0.3s ease 0.1s; transition: all 0.3s ease 0.1s;
transform-origin: center center; transform-origin: center center;
@@ -64,19 +65,19 @@
line-height: 0px; line-height: 0px;
} }
&.top { &.up {
transform: rotate(-90deg); transform: rotate(-90deg);
} }
&.bottom { &.down {
transform: rotate(90deg); transform: rotate(90deg);
} }
&.top.@{prefix-cls}--active { &.up.@{prefix-cls}--active {
transform: rotate(90deg); transform: rotate(90deg);
} }
&.bottom.@{prefix-cls}--active { &.down.@{prefix-cls}--active {
transform: rotate(-90deg); transform: rotate(-90deg);
} }
} }

View File

@@ -1,104 +1,90 @@
<script lang="tsx"> <script lang="tsx">
import type { CSSProperties, PropType } from 'vue'; import type { CSSProperties, PropType } from 'vue';
import { defineComponent, computed, unref } from 'vue'; import { defineComponent, computed, unref } from 'vue';
import { Tooltip } from 'ant-design-vue'; import { Tooltip } from 'ant-design-vue';
import { InfoCircleOutlined } from '@ant-design/icons-vue'; import { InfoCircleOutlined } from '@ant-design/icons-vue';
import { getPopupContainer } from '/@/utils'; import { getPopupContainer } from '/@/utils';
import { isString, isArray } from '/@/utils/is'; import { isString, isArray } from '/@/utils/is';
import { getSlot } from '/@/utils/helper/tsxHelper'; import { getSlot } from '/@/utils/helper/tsxHelper';
import { propTypes } from '/@/utils/propTypes';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
const props = {
/**
* Help text max-width
* @default: 600px
*/
maxWidth: { type: String, default: '600px' },
/**
* Whether to display the serial number
* @default: false
*/
showIndex: { type: Boolean },
/**
* Help text font color
* @default: #ffffff
*/
color: { type: String, default: '#ffffff' },
/**
* Help text font size
* @default: 14px
*/
fontSize: { type: String, default: '14px' },
/**
* Help text list
*/
placement: { type: String, default: 'right' },
/**
* Help text list
*/
text: { type: [Array, String] as PropType<string[] | string> },
};
export default defineComponent({ export default defineComponent({
name: 'BasicHelp', name: 'BasicHelp',
components: { Tooltip }, components: { Tooltip },
props: { props,
// max-width
maxWidth: propTypes.string.def('600px'),
// Whether to display the serial number
showIndex: propTypes.bool,
// color
color: propTypes.string.def('#ffffff'),
fontSize: propTypes.string.def('14px'),
placement: propTypes.string.def('right'),
absolute: propTypes.bool,
// Text list
text: {
type: [Array, String] as PropType<string[] | string>,
},
// 定位
position: {
type: [Object] as PropType<any>,
default: () => ({
position: 'absolute',
left: 0,
bottom: 0,
}),
},
},
setup(props, { slots }) { setup(props, { slots }) {
const { prefixCls } = useDesign('basic-help'); const { prefixCls } = useDesign('basic-help');
const getOverlayStyle = computed( const getTooltipStyle = computed(
(): CSSProperties => { (): CSSProperties => ({ color: props.color, fontSize: props.fontSize }),
return {
maxWidth: props.maxWidth,
};
}
); );
const getWrapStyle = computed( const getOverlayStyle = computed((): CSSProperties => ({ maxWidth: props.maxWidth }));
(): CSSProperties => {
return {
color: props.color,
fontSize: props.fontSize,
};
}
);
const getMainStyleRef = computed(() => { function renderTitle() {
return props.absolute ? props.position : {}; const textList = props.text;
});
const renderTitle = () => { if (isString(textList)) {
const list = props.text; return <p>{textList}</p>;
if (isString(list)) {
return <p>{list}</p>;
} }
if (isArray(list)) { if (isArray(textList)) {
return list.map((item, index) => { return textList.map((text, index) => {
return ( return (
<p key={item}> <p key={text}>
<> <>
{props.showIndex ? `${index + 1}. ` : ''} {props.showIndex ? `${index + 1}. ` : ''}
{item} {text}
</> </>
</p> </p>
); );
}); });
} }
return null; return null;
}; }
return () => { return () => {
return ( return (
<Tooltip <Tooltip
title={<div style={unref(getWrapStyle)}>{renderTitle()}</div>}
overlayClassName={`${prefixCls}__wrap`} overlayClassName={`${prefixCls}__wrap`}
title={<div style={unref(getTooltipStyle)}>{renderTitle()}</div>}
autoAdjustOverflow={true} autoAdjustOverflow={true}
overlayStyle={unref(getOverlayStyle)} overlayStyle={unref(getOverlayStyle)}
placement={props.placement as 'left'} placement={props.placement as 'right'}
getPopupContainer={() => getPopupContainer()} getPopupContainer={() => getPopupContainer()}
> >
<span class={prefixCls} style={unref(getMainStyleRef)}> <span class={prefixCls}>{getSlot(slots) || <InfoCircleOutlined />}</span>
{getSlot(slots) || <InfoCircleOutlined />}
</span>
</Tooltip> </Tooltip>
); );
}; };

View File

@@ -1,41 +1,43 @@
<template> <template>
<span :class="getClass"> <span :class="getClass">
<slot></slot> <slot></slot>
<BasicHelp :class="`${prefixCls}__help`" v-if="helpMessage" :text="helpMessage" /> <BasicHelp :class="`${prefixCls}-help`" v-if="helpMessage" :text="helpMessage" />
</span> </span>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import type { PropType } from 'vue'; import type { PropType } from 'vue';
import { useSlots, computed } from 'vue';
import { defineComponent, computed } from 'vue';
import BasicHelp from './BasicHelp.vue'; import BasicHelp from './BasicHelp.vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { propTypes } from '/@/utils/propTypes'; const props = defineProps({
/**
export default defineComponent({ * Help text list or string
name: 'BasicTitle', * @default: ''
components: { BasicHelp }, */
props: { helpMessage: {
helpMessage: { type: [String, Array] as PropType<string | string[]>,
type: [String, Array] as PropType<string | string[]>, default: '',
default: '',
},
span: propTypes.bool,
normal: propTypes.bool.def(false),
},
setup(props, { slots }) {
const { prefixCls } = useDesign('basic-title');
const getClass = computed(() => [
prefixCls,
{ [`${prefixCls}-show-span`]: props.span && slots.default },
{ [`${prefixCls}-normal`]: props.normal },
]);
return { prefixCls, getClass };
}, },
/**
* Whether the color block on the left side of the title
* @default: false
*/
span: { type: Boolean },
/**
* Whether to default the text, that is, not bold
* @default: false
*/
normal: { type: Boolean },
}); });
const { prefixCls } = useDesign('basic-title');
const slots = useSlots();
const getClass = computed(() => [
prefixCls,
{ [`${prefixCls}-show-span`]: props.span && slots.default },
{ [`${prefixCls}-normal`]: props.normal },
]);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@prefix-cls: ~'@{namespace}-basic-title'; @prefix-cls: ~'@{namespace}-basic-title';
@@ -63,11 +65,11 @@
width: 3px; width: 3px;
height: 16px; height: 16px;
margin-right: 4px; margin-right: 4px;
background: @primary-color; background-color: @primary-color;
content: ''; content: '';
} }
&__help { &-help {
margin-left: 10px; margin-left: 10px;
} }
} }

View File

@@ -1,4 +1,9 @@
import Button from './src/BasicButton.vue'; import { withInstall } from '/@/utils';
import PopConfirmButton from './src/PopConfirmButton.vue'; import type { ExtractPropTypes } from 'vue';
import button from './src/BasicButton.vue';
import popConfirmButton from './src/PopConfirmButton.vue';
import { buttonProps } from './src/props';
export { Button, PopConfirmButton }; export const Button = withInstall(button);
export const PopConfirmButton = withInstall(popConfirmButton);
export declare type ButtonProps = Partial<ExtractPropTypes<typeof buttonProps>>;

View File

@@ -1,47 +1,40 @@
<template> <template>
<Button v-bind="getBindValue" :class="[getColor, $attrs.class]" @click="onClick"> <Button v-bind="getBindValue" :class="getButtonClass" @click="onClick">
<template #default="data"> <template #default="data">
<Icon :icon="preIcon" v-if="preIcon" :size="14" /> <Icon :icon="preIcon" v-if="preIcon" :size="iconSize" />
<slot v-bind="data"></slot> <slot v-bind="data || {}"></slot>
<Icon :icon="postIcon" v-if="postIcon" :size="14" /> <Icon :icon="postIcon" v-if="postIcon" :size="iconSize" />
</template> </template>
</Button> </Button>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, computed } from 'vue'; import { defineComponent } from 'vue';
import { Button } from 'ant-design-vue';
import Icon from '/@/components/Icon';
import { propTypes } from '/@/utils/propTypes';
export default defineComponent({ export default defineComponent({
name: 'AButton', name: 'AButton',
components: { Button, Icon },
inheritAttrs: false, inheritAttrs: false,
props: {
type: propTypes.oneOf(['primary', 'default', 'danger', 'dashed', 'link']).def('default'),
color: propTypes.oneOf(['error', 'warning', 'success', '']),
loading: propTypes.bool,
disabled: propTypes.bool,
preIcon: propTypes.string,
postIcon: propTypes.string,
onClick: propTypes.func,
},
setup(props, { attrs }) {
const getColor = computed(() => {
const { color, disabled } = props;
return {
[`ant-btn-${color}`]: !!color,
[`is-disabled`]: disabled,
};
});
const getBindValue = computed((): any => {
return { ...attrs, ...props };
});
return { getBindValue, getColor };
},
}); });
</script> </script>
<script lang="ts" setup>
import { computed, unref } from 'vue';
import { Button } from 'ant-design-vue';
import Icon from '/@/components/Icon/src/Icon.vue';
import { buttonProps } from './props';
import { useAttrs } from '/@/hooks/core/useAttrs';
const props = defineProps(buttonProps);
// get component class
const attrs = useAttrs({ excludeDefaultKeys: false });
const getButtonClass = computed(() => {
const { color, disabled } = props;
return [
{
[`ant-btn-${color}`]: !!color,
[`is-disabled`]: disabled,
},
];
});
// get inherit binding value
const getBindValue = computed(() => ({ ...unref(attrs), ...props }));
</script>

View File

@@ -1,51 +1,53 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, h, unref, computed } from 'vue'; import { computed, defineComponent, h, unref } from 'vue';
import { Popconfirm } from 'ant-design-vue';
import BasicButton from './BasicButton.vue'; import BasicButton from './BasicButton.vue';
import { Popconfirm } from 'ant-design-vue';
import { propTypes } from '/@/utils/propTypes';
import { extendSlots } from '/@/utils/helper/tsxHelper'; import { extendSlots } from '/@/utils/helper/tsxHelper';
import { omit } from 'lodash-es'; import { omit } from 'lodash-es';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
const props = {
/**
* Whether to enable the drop-down menu
* @default: true
*/
enable: {
type: Boolean,
default: true,
},
};
export default defineComponent({ export default defineComponent({
name: 'PopButton', name: 'PopButton',
components: { Popconfirm, BasicButton },
inheritAttrs: false, inheritAttrs: false,
props: { props,
size: propTypes.oneOf(['large', 'default', 'small']).def(),
enable: propTypes.bool.def(true),
okText: propTypes.string,
cancelText: propTypes.string,
},
setup(props, { slots }) { setup(props, { slots }) {
const { t } = useI18n(); const { t } = useI18n();
const attrs = useAttrs(); const attrs = useAttrs();
// get inherit binding value
const getBindValues = computed(() => { const getBindValues = computed(() => {
const popValues = Object.assign( return Object.assign(
{ {
okText: t('common.okText'), okText: t('common.okText'),
cancelText: t('common.cancelText'), cancelText: t('common.cancelText'),
}, },
{ ...props, ...unref(attrs) } { ...props, ...unref(attrs) },
); );
return popValues;
}); });
return () => { return () => {
const values = omit(unref(getBindValues), 'icon'); const bindValues = omit(unref(getBindValues), 'icon');
const Button = h(BasicButton, values, extendSlots(slots)); const btnBind = omit(bindValues, 'title') as Recordable;
if (btnBind.disabled) btnBind.color = '';
const Button = h(BasicButton, btnBind, extendSlots(slots));
// If it is not enabled, it is a normal button
if (!props.enable) { if (!props.enable) {
return Button; return Button;
} }
return h(Popconfirm, bindValues, { default: () => Button });
return h(Popconfirm, values, { default: () => Button });
}; };
}, },
}); });

View File

@@ -0,0 +1,19 @@
export const buttonProps = {
color: { type: String, validator: (v) => ['error', 'warning', 'success', ''].includes(v) },
loading: { type: Boolean },
disabled: { type: Boolean },
/**
* Text before icon.
*/
preIcon: { type: String },
/**
* Text after icon.
*/
postIcon: { type: String },
/**
* preIcon and postIcon icon size.
* @default: 14
*/
iconSize: { type: Number, default: 14 },
onClick: { type: Function as PropType<(...args) => any>, default: null },
};

View File

@@ -0,0 +1,4 @@
import { withInstall } from '/@/utils';
import cardList from './src/CardList.vue';
export const CardList = withInstall(cardList);

View File

@@ -0,0 +1,177 @@
<template>
<div class="p-2">
<div class="p-4 mb-2 bg-white">
<BasicForm @register="registerForm" />
</div>
<div class="p-2 bg-white">
<List
:grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
:data-source="data"
:pagination="paginationProp"
>
<template #header>
<div class="flex justify-end space-x-2"
><slot name="header"></slot>
<Tooltip>
<template #title>
<div class="w-50">每行显示数量</div
><Slider
id="slider"
v-bind="sliderProp"
v-model:value="grid"
@change="sliderChange"
/></template>
<Button><TableOutlined /></Button>
</Tooltip>
<Tooltip @click="fetch">
<template #title>刷新</template>
<Button><RedoOutlined /></Button>
</Tooltip>
</div>
</template>
<template #renderItem="{ item }">
<ListItem>
<Card>
<template #title></template>
<template #cover>
<div :class="height">
<Image :src="item.imgs[0]" />
</div>
</template>
<template #actions>
<!-- <SettingOutlined key="setting" />-->
<EditOutlined key="edit" />
<Dropdown
:trigger="['hover']"
:dropMenuList="[
{
text: '删除',
event: '1',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, item.id),
},
},
]"
popconfirm
>
<EllipsisOutlined key="ellipsis" />
</Dropdown>
</template>
<CardMeta>
<template #title>
<TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
</template>
<template #avatar>
<Avatar :src="item.avatar" />
</template>
<template #description>{{ item.time }}</template>
</CardMeta>
</Card>
</ListItem>
</template>
</List>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue';
import {
EditOutlined,
EllipsisOutlined,
RedoOutlined,
TableOutlined,
} from '@ant-design/icons-vue';
import { List, Card, Image, Typography, Tooltip, Slider, Avatar } from 'ant-design-vue';
import { Dropdown } from '/@/components/Dropdown';
import { BasicForm, useForm } from '/@/components/Form';
import { propTypes } from '/@/utils/propTypes';
import { Button } from '/@/components/Button';
import { isFunction } from '/@/utils/is';
import { useSlider, grid } from './data';
const ListItem = List.Item;
const CardMeta = Card.Meta;
const TypographyText = Typography.Text;
// 获取slider属性
const sliderProp = computed(() => useSlider(4));
// 组件接收参数
const props = defineProps({
// 请求API的参数
params: propTypes.object.def({}),
//api
api: propTypes.func,
});
//暴露内部方法
const emit = defineEmits(['getMethod', 'delete']);
//数据
const data = ref([]);
// 切换每行个数
// cover图片自适应高度
//修改pageSize并重新请求数据
const height = computed(() => {
return `h-${120 - grid.value * 6}`;
});
//表单
const [registerForm, { validate }] = useForm({
schemas: [{ field: 'type', component: 'Input', label: '类型' }],
labelWidth: 80,
baseColProps: { span: 6 },
actionColOptions: { span: 24 },
autoSubmitOnEnter: true,
submitFunc: handleSubmit,
});
//表单提交
async function handleSubmit() {
const data = await validate();
await fetch(data);
}
function sliderChange(n) {
pageSize.value = n * 4;
fetch();
}
// 自动请求并暴露内部方法
onMounted(() => {
fetch();
emit('getMethod', fetch);
});
async function fetch(p = {}) {
const { api, params } = props;
if (api && isFunction(api)) {
const res = await api({ ...params, page: page.value, pageSize: pageSize.value, ...p });
data.value = res.items;
total.value = res.total;
}
}
//分页相关
const page = ref(1);
const pageSize = ref(36);
const total = ref(0);
const paginationProp = ref({
showSizeChanger: false,
showQuickJumper: true,
pageSize,
current: page,
total,
showTotal: (total) => `${total}`,
onChange: pageChange,
onShowSizeChange: pageSizeChange,
});
function pageChange(p, pz) {
page.value = p;
pageSize.value = pz;
fetch();
}
function pageSizeChange(_current, size) {
pageSize.value = size;
fetch();
}
async function handleDelete(id) {
emit('delete', id);
}
</script>

Some files were not shown because too many files have changed in this diff Show More