Compare commits

...

777 Commits

Author SHA1 Message Date
03b1fbacc4 chore(projects): release v1.0.4 2024-04-24 01:42:40 +08:00
9a66979f09 chore(deps): update deps 2024-04-24 01:39:42 +08:00
c695208f62 fix(projects): recovery pnpm-lock.yaml 2024-04-24 01:38:19 +08:00
3ceeb6f942 chore(deps): update deps 2024-04-24 01:04:50 +08:00
04aa0972f9 fix(projects): fix tabs data when role is change. fixed #392 2024-04-24 01:01:52 +08:00
cb83d6d90d fix(projects): fix routes data when role is change. fixed #391 2024-04-24 00:47:58 +08:00
79d9c5143a docs(projects): update README.md 2024-04-23 17:31:15 +08:00
5a5232bdf4 docs(projects): update README.md 2024-04-23 11:25:51 +08:00
7392bebff9 chore(projects): update deps & update pnpm version & update eslint config 2024-04-23 11:20:55 +08:00
23f283aa31 fix(projects): fix disabled page animate 2024-04-16 01:15:45 +08:00
42e16a0165 chore(projects): update pnpm version 2024-04-16 01:02:51 +08:00
ac92817343 chore(deps): update deps 2024-04-16 01:01:46 +08:00
93191737dd refactor(hooks): refactor @sa/color-palette 2024-04-16 00:57:24 +08:00
d9af5aa2d3 fix(projects): fix CHANGELOG versions 2024-04-16 00:17:10 +08:00
d984f75b80 chore(projects): release v1.0.3 2024-04-16 00:15:37 +08:00
27c53cd688 fix(projects): fix update theme color 2024-04-16 00:14:32 +08:00
b7f0749170 perf(projects): perf code 2024-04-16 00:03:00 +08:00
cb8ea2531d Merge pull request #386 from paynezhuang/main 2024-04-15 16:27:08 +08:00
c6648b6c8b feat(hooks): deleting the route export of useRoutePush, use vue-router 2024-04-15 16:20:30 +08:00
bb74d9949b refactor(projects): update naive-ui.d.ts 2024-04-14 15:44:48 +08:00
60beff7e63 fix(projects): update union-key.d.ts 2024-04-14 12:48:02 +08:00
d6eda8f9ed fix(projects): fix axios createRequest: add default state 2024-04-09 17:44:05 +08:00
f4a9cf8339 docs(projects): update README.md 2024-04-09 15:37:23 +08:00
efc0e25c7f fix(projects): fix SvgIcon inheritAttrs warning 2024-04-09 07:27:48 +08:00
35310ed73c Merge pull request #381 from paynezhuang/main 2024-04-08 19:04:13 +08:00
001059cca0 fix(projects): fix menu edit rules 2024-04-08 11:44:12 +08:00
4af884c08b chore(projects): release v1.0.2 2024-04-08 08:00:41 +08:00
41e470ed6e refactor(projects): refactor addThemeVarsToHtml 2024-04-08 07:59:50 +08:00
2f15a2ac6a fix(projects): unify border-radius of Tag. fixed #378 2024-04-08 07:50:26 +08:00
1c72dc76ee chore(projects): disabled unocss eslint rule: order-attributify 2024-04-08 07:46:02 +08:00
a1b484a8eb chore(deps): update deps 2024-04-08 07:42:46 +08:00
d9410e416e Merge pull request #377 from yanbowe/main
fix(styles): fix css var is inserted repeatedly
2024-04-07 17:41:08 +08:00
769d84a7f4 fix(styles): fix css var is inserted repeatedly 2024-04-07 17:34:33 +08:00
0fbb00cee1 chore(projects): release v1.0.1 2024-04-03 00:21:42 +08:00
cc539974b2 fix(projects): add maxWidth for GlobalTab to fix bg with gap. fixed #350 2024-04-03 00:20:55 +08:00
1ec5ea0ff1 fix(projects): fix flatRequest error type. fixed #376 2024-04-03 00:02:09 +08:00
9125cc9b60 chore(projects): update pnpm version 2024-04-02 23:14:34 +08:00
76011af8a9 docs(projects): update README.md 2024-04-02 23:13:31 +08:00
4babbe19a3 chore(projects): update deps 2024-04-02 23:00:17 +08:00
ae508bc572 chore(projects): release v1.0.0 2024-03-31 17:07:09 +08:00
c8260221dd chore(projects): release v1.0.0-beta.3 2024-03-31 17:06:35 +08:00
82b53d7e98 chore(deps): update deps 2024-03-31 17:05:33 +08:00
f69e1523c0 docs(projects): update README.md 2024-03-29 10:03:00 +08:00
c0009203c6 chore(projects): add .gitattributes 2024-03-28 00:37:58 +08:00
f23e1f7ea4 chore(projects): release v1.0.0-beta.2 2024-03-27 22:49:51 +08:00
f89e6c0361 fix(projects): fix pin-toggler toolTip zIndex 2024-03-27 22:32:56 +08:00
6b5132c169 chore(deps): update deps 2024-03-27 22:27:20 +08:00
1a7070f02b docs(projects): update README.md 2024-03-26 14:14:44 +08:00
07d8d25dbf docs(projects): update README.md 2024-03-26 14:13:56 +08:00
a0bad57a4e perf(projects): perf code 2024-03-25 23:20:49 +08:00
8c7ea235d9 docs(projects): add communication 2024-03-25 11:47:00 +08:00
06e204a7fe ci(projects): add issue template 2024-03-25 10:48:22 +08:00
7b298c679e ci(projects): update release.yml 2024-03-25 10:37:38 +08:00
25fc24c746 chore(projects): release v1.0.0-beta.1 2024-03-25 10:32:03 +08:00
4cb17c7440 ci(projects): add github actions config 2024-03-25 10:26:58 +08:00
46b6156620 docs(projects): add CHANGELOG.md 2024-03-25 10:18:04 +08:00
23a4098bba fix(projects): fix route init 2024-03-25 09:55:16 +08:00
000c68ad60 Merge commit '2c543f19ec100af4d6224787956550910e5fb7c8' 2024-03-25 03:14:28 +08:00
2c543f19ec fix(projects): fix repeat routes 2024-03-25 03:13:53 +08:00
37d20b8e0d refactor(projects): new route guard 2024-03-25 02:42:50 +08:00
c11d56da29 feat(projects): add auth example 2024-03-24 15:39:41 +08:00
41e8bc44f8 feat(projects): add request exception example page 2024-03-24 06:23:56 +08:00
11a6a3bd80 feat(projects): add request refresh token & logout 2024-03-24 05:11:30 +08:00
1ed33dc47a feat(projects): login page: register 2024-03-24 04:10:55 +08:00
c91dd282a6 feat(projects): login page: code-login 2024-03-24 04:03:49 +08:00
f91ef30bd5 refactor(projects): perf code 2024-03-24 03:02:08 +08:00
187098136e feat(projects): pef manage role 2024-03-23 15:51:04 +08:00
0abbfa5d0c perf(projects): manage menu: add transform to component 2024-03-22 01:31:38 +08:00
71f2c5535b perf(projects): perf manage menu 2024-03-22 01:23:24 +08:00
49558ca048 feat(projects): change borderRadius to 6px of naiveUI 2024-03-21 19:49:00 +08:00
c0a65a165a chore(deps): update deps 2024-03-21 19:44:22 +08:00
3fd15e5649 refactor(projects): finish refactor useTable and apply 2024-03-21 19:40:48 +08:00
4158a72bd8 feat(projects): update 2024-03-21 08:29:15 +08:00
8630175a3f refactor(projects): finish refactor useTable 2024-03-19 02:46:53 +08:00
c3efa1b6e0 refactor(projects): refactor useTable 2024-03-19 02:44:03 +08:00
51d7758903 Merge pull request #352 from Li-0221/main
fix(components): fix homeTab closeRight and disable colseLeft
2024-03-18 14:56:57 +08:00
~li
d28bf52683 fix(components): fix homeTab closeRight and disable colseLeft 2024-03-18 13:58:22 +08:00
455e48f792 fix(projects): fix class name conflict with unocss icon 2024-03-18 07:38:21 +08:00
6ad51e9431 chore(projects): update pnpm version 2024-03-18 07:34:43 +08:00
0fee104bf9 chore(deps): update deps 2024-03-18 07:32:39 +08:00
0cc8f05a26 fix(projects): fix table row-key ts type 2024-03-16 16:18:44 +08:00
03c2f3aaf0 Merge pull request #349 from vastsa/main
fix(projects):fix invalid footer-height for theme configuration
2024-03-13 14:56:44 +08:00
lan
6c5404610b fix(projects):fix invalid footer-height for theme configuration 2024-03-13 14:46:12 +08:00
8143b0063c chore(projects): update deps & fix eslint vue rule 2024-03-13 14:28:12 +08:00
72745229d6 perf(components): perf global-search 2024-03-11 22:57:37 +08:00
779ba4e415 perf(projects): perf manage page style 2024-03-11 22:42:22 +08:00
b2ee9eef8c chore(deps): update deps 2024-03-11 21:38:10 +08:00
7065f6f073 chore(projects): update pnpm version 2024-03-10 14:37:31 +08:00
dc24a36739 perf(projects): perf code 2024-03-10 14:36:05 +08:00
c05e7ff360 Merge branch 'main' into example 2024-03-10 14:24:46 +08:00
2b7e3c237d Merge pull request #347 from Azir-11/main
feat(projects): Add route meta parameter:fixedQuery
2024-03-10 13:50:46 +08:00
874aaca5bb feat(projects): Add route meta parameter:fixedQuery 2024-03-10 05:19:21 +08:00
7a2f54be8b Merge pull request #345 from Azir-11/main
style(components): Uniform icon size for header
2024-03-07 22:27:23 +08:00
b37c1e94a0 style(components): Uniform icon size for header 2024-03-07 22:19:06 +08:00
cb35a94baf Merge branch 'main' into example 2024-03-07 21:52:49 +08:00
02d4b0a574 chore(deps): update deps 2024-03-07 21:51:08 +08:00
4e29acaae3 chore(projects): update vscode extensions.json 2024-03-07 21:46:26 +08:00
7898d08174 Merge pull request #343 from soybeanjs/main
merge: main to example
2024-03-06 17:34:20 +08:00
ed1c585a6b Merge pull request #342 from yanbowe/main 2024-03-06 12:03:21 +08:00
0126da4778 feat(projects): globalSearch add i18n 2024-03-06 11:43:27 +08:00
04aa10b477 perf(components): components name is converted to uppercase 2024-03-06 11:05:54 +08:00
9ea878915e feat(components): add GlobalSearch components 2024-03-06 10:59:40 +08:00
05db8c08d5 perf(projects): perf code 2024-03-04 14:01:27 +08:00
ffc95d2b7b fix(projects): fix proxy config 2024-03-04 13:57:47 +08:00
c8019c4ff7 fix(projects): fix proxy config 2024-03-04 10:23:25 +08:00
b546ff8625 refactor(projects): use enquirer replace prompts 2024-03-03 20:43:21 +08:00
14aa856a0f chore(deps): update deps 2024-03-03 19:48:00 +08:00
3db82acb02 chore(projects): update launch.json 2024-03-03 13:25:18 +08:00
4063529a25 chore(projects): add unocss eslint config 2024-03-03 03:53:53 +08:00
b4c00ce199 refactor(projects): refactor unocss shortcuts: wh-full => size-full 2024-03-03 03:51:04 +08:00
fb3b94b1e3 chore(deps): update deps 2024-03-03 03:48:01 +08:00
43193e2808 refactor(projects): refactor service env config 2024-03-02 12:31:19 +08:00
bccd6cb3c3 fix(projects): fix repeat home tab 2024-03-02 11:13:09 +08:00
a17d68eb11 Merge pull request #337 from Azir-11/main
Fix home mount issue for static and dynamic routes
2024-03-01 13:32:18 +08:00
9cf2a513f7 fix(projects): Fix homepage mount error under dynamic routing 2024-03-01 13:12:28 +08:00
0123c37de2 fix(projects): Fix the logic of root route redirection to home 2024-03-01 11:35:25 +08:00
418302a34b docs(projects): update README.md 2024-03-01 02:52:15 +08:00
7fa87f53d1 perf(projects): perf code 2024-03-01 02:44:09 +08:00
b235ef3bc0 Merge pull request #335 from dodu2014/main
fix(hooks): Fix Naive Pagination's outdated API
2024-02-29 22:28:32 +08:00
3743612d62 fix(hooks): Fix Naive Pagination's outdated API 2024-02-29 22:22:15 +08:00
c3e8ef2ed2 Merge pull request #333 from dodu2014/main
feat(components): enhance the custom strength of the 'TableHeaderOper…
2024-02-26 10:44:31 +08:00
ccc2b674db fix(components): supplement the NaiveUI type 2024-02-26 10:40:44 +08:00
fdf64f71f4 feat(components): enhance the custom strength of the 'TableHeaderOperation' component 2024-02-26 06:40:32 +08:00
9c4ba6650d chore(deps): update deps 2024-02-26 02:11:37 +08:00
1a6be003e2 feat(projects): mock manage list data with pagination 2024-02-26 01:59:06 +08:00
c7e2c55996 fix(projects): fix table x-scroll. fixed #324 2024-02-23 22:17:31 +08:00
0a3efe3442 fix(projects): add route icon: fucntion_hide-child 2024-02-23 21:59:21 +08:00
7256ad4ee3 feat(projects): support directory menu hide all child menus. fixed #325 2024-02-23 21:51:20 +08:00
8ee2acc1fc Merge pull request #327 from Azir-11/main
fix(projects): Missing default value for tab icon
2024-02-23 21:16:21 +08:00
72a4679c0a fix(projects): Missing default value for tab icon 2024-02-23 15:27:50 +08:00
3bdcbc71eb fix(projects): fix resolve alias 2024-02-20 22:21:46 +08:00
9772aec2bd chore(projects): update deps & update pnpm version 2024-02-20 22:01:23 +08:00
c18d82f9f8 fix(projects): fix build [unocss]: build failed to load icon "close", fixed #319 2024-02-20 21:57:17 +08:00
114c835921 Merge pull request #316 from Azir-11/main
fix(projects): The matched value of TabRoute should be optional
2024-02-17 18:42:16 +08:00
e6fed1fdb5 fix(projects): The matched value of TabRoute should be optional 2024-02-11 13:52:03 +08:00
5d75ca924e Merge pull request #315 from Azir-11/main 2024-02-06 18:03:35 +08:00
2d102a054a feat(projects): Add type to TabRoute: matched 2024-02-06 17:51:40 +08:00
a9c98d9655 fix(projects): Fix the issue of tab error displaying parent localIcon
Fix the issue of abnormal tab display when the parent menu has a localIcon and the child menu does not have one
2024-02-06 17:42:51 +08:00
ef4af79a11 docs(projects): update README.md 2024-02-04 01:09:48 +08:00
806a1cba5f chore(projects): update repository url 2024-02-04 01:04:31 +08:00
147f60d17e chore(projects): update pnpm-lock.yaml 2024-02-04 00:48:04 +08:00
579636b0b4 chore(projects): update deps & remove packages docs 2024-02-04 00:28:38 +08:00
ebb154840a chore(projects): add dev and build command with service env 2024-02-04 00:26:15 +08:00
ae6b6134f3 fix(projects): fix request msg 2024-02-04 00:14:17 +08:00
6ea9b85ff1 docs(projects): update README.md 2024-02-03 04:54:18 +08:00
0b56e44c0e chore(projects): update @elegant-router/vue, fix inject name in windows 2024-02-02 00:52:29 +08:00
13001bc83e chore(projects): update deps & fix keep-alive 2024-02-01 22:46:34 +08:00
adec0d7501 chore(projects): update pnpm version 2024-02-01 22:08:17 +08:00
db17c916ef feat(projects): page manage_menu operateDrawer 2024-01-30 00:33:26 +08:00
e2085e058d docs(projects): update README.md 2024-01-29 22:25:19 +08:00
b8f85692d6 Merge pull request #306 from smileluck/main 2024-01-29 16:38:11 +08:00
da24642783 fix(projects): default proxy prefix 2024-01-29 16:31:24 +08:00
86b445c26a docs(projects): update README.md 2024-01-29 01:50:29 +08:00
4e4d2de54a docs(projects): update README.md 2024-01-29 01:40:37 +08:00
7770b378f3 fix(projects): fix manage_user title 2024-01-29 01:19:29 +08:00
0aa75c0422 perf(projects): perf page manage_menu style 2024-01-28 23:49:01 +08:00
87d65d3b1c feat(projects): page manage_menu 2024-01-28 23:38:44 +08:00
f8467ceb17 refactor(projects): manage_route => manage_menu 2024-01-28 17:14:46 +08:00
babdb5d5cc perf(projects): perf table columns style 2024-01-28 16:37:52 +08:00
8a170eeebd feat(projects): page manage_user 2024-01-28 16:24:43 +08:00
a19f895cd9 refactor(projects): perf page manage_role 2024-01-28 14:27:07 +08:00
39aa7aa2de perf(projects): perf page manage_role, useTable 2024-01-28 01:35:01 +08:00
0e9e2e1dc0 refactor(projects): page manage_role: extract module 2024-01-28 01:25:04 +08:00
237c6d227e feat(projects): page manage_role 2024-01-28 00:44:21 +08:00
2724169eb6 refactor(projects): update mock api 2024-01-26 21:26:26 +08:00
4031fafc1f chore(projects): remove soybean.svg 2024-01-26 21:11:10 +08:00
456c318ac6 perf(projects): echarts loading style 2024-01-26 02:27:10 +08:00
b5477e8996 refactor(projects): perf page function_tab 2024-01-26 02:00:34 +08:00
59bec2d923 refactor(projects): login components => modules 2024-01-26 01:52:24 +08:00
4c61c6ff3c refactor(projects): perf page home 2024-01-26 01:51:06 +08:00
123fd4f96c style(projects): sort defineProps, defineEmits with TS type 2024-01-25 23:24:35 +08:00
b2c61f0306 perf(components): perf count-to 2024-01-25 23:16:12 +08:00
9cc7ee5c94 chore(deps): update deps 2024-01-25 23:15:01 +08:00
502a4d2b85 chore(projects): remove @simonwep/pickr 2024-01-25 21:30:00 +08:00
c1afb9dc50 fix(projects): perf card style 2024-01-25 16:01:23 +08:00
d886e50fd3 fix(projects): fix horizontal menu 2024-01-25 15:26:46 +08:00
4aae6a5297 fix(projects): remove space in tab content 2024-01-25 14:38:16 +08:00
b5551d674a refactor(projects): use naive-ui color-picker 2024-01-25 14:35:49 +08:00
6114b9f9bd chore(deps): update deps 2024-01-25 12:00:45 +08:00
ea02b23721 chore(projects): update pnpm version 2024-01-25 11:59:11 +08:00
6ff86e7777 feat(projects): add page function_tab 2024-01-25 02:35:37 +08:00
7bd1e47af9 feat(projects): finish page home 2024-01-25 01:12:33 +08:00
62e4da053d feat(projects): page home & perf useEcharts 2024-01-24 01:48:23 +08:00
0fae9932ac docs(projects): update README.md 2024-01-23 17:43:41 +08:00
2400c02655 feat(projects): @sa/axios: add qs stringify for params 2024-01-23 00:30:43 +08:00
b3779a6313 fix(projects): fix themeDrawer copy 2024-01-22 00:35:13 +08:00
99097b4632 fix(components): fix tooltip zIndex of ButtonIcon 2024-01-22 00:20:00 +08:00
1b5caa08be fix(projects): fix themeDrawer darkMode segement 2024-01-22 00:01:35 +08:00
db747c4a03 style(projects): fix tooltip zIndex of ButtonIcon 2024-01-21 23:55:00 +08:00
8b6de484b8 fix(projects): fix page about style in mobile 2024-01-21 23:48:44 +08:00
697c1b6106 feat(projects): add script: gen-route 2024-01-21 23:21:27 +08:00
41349555bf perf(projects): remove @soybeanjs/cli 2024-01-21 22:41:01 +08:00
dafb6fa06f feat(projects): packages/scripts: add command changelog,release 2024-01-21 18:17:11 +08:00
840e7f99fc chore(deps): update deps 2024-01-20 20:34:00 +08:00
a24f963121 chore(projects): lock deps versions 2024-01-20 20:32:58 +08:00
f59f34884c feat(projects): filter tabs which are not in routes 2024-01-20 19:58:58 +08:00
b4f3dd2f7a refactor(projects): refactor app-loading 2024-01-20 19:16:34 +08:00
726abe4208 feat(hooks): add use-echarts 2024-01-19 02:17:17 +08:00
b43c925696 feat(projects): add custom route exception 2024-01-19 01:28:46 +08:00
4955f1af89 feat(projects): add page: about 2024-01-18 23:51:04 +08:00
f1b86ccb1d chore(deps): update deps 2024-01-18 23:49:06 +08:00
affcc26b3d feat(projects): add copyright, unocss shortcut: card-wrapper, update package.json 2024-01-18 23:43:33 +08:00
03c42aa8cc docs(projects): update README.md 2024-01-18 22:46:16 +08:00
c260fe26ae docs(projects): update README.md 2024-01-18 22:10:22 +08:00
0ba19d5479 fix(projects): fix app loading theme color 2024-01-18 02:44:10 +08:00
b30c0359f6 docs(projects): update README.md 2024-01-18 02:17:07 +08:00
57b6d8a058 docs(projects): update README.md 2024-01-18 02:09:48 +08:00
6a771eae42 docs(projects): update README.md 2024-01-18 01:57:20 +08:00
c624f325c7 perf(projects): remove useless file 2024-01-18 01:08:31 +08:00
c65451b34c feat(projects): add app loading 2024-01-17 22:48:36 +08:00
2372dc9bb7 fix(projects): fix theme mode segment 2024-01-17 22:09:22 +08:00
d16a9d58a8 docs(projects): update README 2024-01-17 02:16:47 +08:00
2371ba8448 docs(projects): add README 2024-01-17 02:06:19 +08:00
4d8469e2d1 style(projects): update theme mode segment height 2024-01-16 23:43:18 +08:00
5023f37125 chore(projects): update eslint config 2024-01-16 23:32:22 +08:00
5534294163 chore(deps): update deps 2024-01-16 23:31:45 +08:00
5c49d24504 perf(projects): perf code 2024-01-16 02:07:31 +08:00
87143172e8 fix(projects): fix menu indent 2024-01-16 01:56:05 +08:00
f6bab0cc9d perf(projects): add detailed annotations for route role 2024-01-16 01:54:19 +08:00
1335d47ae8 fix(projects): add duration of login success notification 2024-01-16 01:52:32 +08:00
bac1632457 feat(projects): @sa/axios: createRequest, createFlatRequest, createHookRequest 2024-01-16 01:50:12 +08:00
fbf4cc430d fix(projects): fix i18n vscode settings 2024-01-16 01:37:58 +08:00
55f7638531 chore(projects): update pnpm version 2024-01-16 01:36:54 +08:00
36fe1dad0b chore(deps): update deps 2024-01-16 01:34:52 +08:00
ff4c8cc21c Merge pull request #295 from Azir-11/v1.0-beta
feat(router): add sortRoutesByOrder function
2024-01-16 01:24:29 +08:00
0cf09baef8 feat(router): add sortRoutesByOrder function 2024-01-12 02:51:39 +08:00
257bbfc527 Merge pull request #294 from Azir-11/v1.0-beta
fix(projects): Fix welcome notification not closing
2024-01-11 12:53:15 +08:00
748cfa2c62 fix(projects): Fix welcome notification not closing 2024-01-11 12:17:41 +08:00
d778560dbd chore(projects): update @sa/scripts 2023-12-14 21:54:10 +08:00
a748166399 style(projects): format code 2023-12-14 21:45:29 +08:00
a176dc443e chore(projects): use eslint flat config & update config 2023-12-14 21:00:53 +08:00
3346bcdfad refactor(projects): fix conflict with locale file 2023-11-21 16:54:35 +08:00
1bac3b78d7 perf(projects): env config 2023-11-20 21:32:55 +08:00
8081e19ebc perf(projects): perf code 2023-11-18 00:36:10 +08:00
96e4aff5c8 feat(projects): support Vite5 2023-11-18 00:34:14 +08:00
377db8298b chore(project): delete src/locales/lang/zh-CN.ts 2023-11-17 12:00:20 +08:00
a8a77ea5d7 fix(projects): rename zh-ch 2023-11-17 11:39:13 +08:00
e918a2c0f5 feat(projects): 1.0 beta 2023-11-17 10:25:32 +08:00
1ea4817f6a docs(projects): update README.md 2023-11-14 12:35:02 +08:00
ecbb96f3a5 Merge pull request #286 from yanbowe/main
perf(components): Optimize internationalized menu search code
2023-10-18 22:42:35 +08:00
296a2d2f0e perf(components): Optimize menu search code 2023-10-18 21:13:05 +08:00
8c1ef4b0fd perf(components): Optimize internationalized menu search code 2023-10-18 20:58:04 +08:00
04d3330463 Merge pull request #285 from Kori000/main
feat: internationalized menu search
2023-10-18 00:01:11 +08:00
9e115daeb9 feat: internationalized menu search 2023-10-16 22:53:01 +08:00
3eaf05bd4d chore(deps): update deps 2023-10-12 22:26:11 +08:00
a195980547 Merge pull request #280 from Particaly/main
fix(projects): 修复路由命名为包含关系时导致导航数据出错的问题
2023-09-27 23:08:18 +08:00
f04a929856 Update menu.ts 2023-09-27 08:43:12 +08:00
5b8af29496 Update breadcrumb.ts
防止找不到顶级路由时报错
2023-09-26 13:50:04 +08:00
766369f911 fix(projects): 修复路由命名为包含关系时导致导航数据出错的问题 2023-09-25 17:16:25 +08:00
f6c6dbd312 refactor(projects): remove plugin-web-update-notification 2023-09-21 01:08:28 +08:00
783648f516 docs(projects): update README.md 2023-09-21 00:55:19 +08:00
ead48f4502 chore(projects): release v0.10.4 2023-09-20 23:42:22 +08:00
305d95672a chore(deps): update deps 2023-09-20 23:40:51 +08:00
8a792c7d63 Merge pull request #278 from eltociear/patch-1
docs(projects): update README.md
2023-09-20 23:31:05 +08:00
93ed5ad085 docs(projects): update README.md
github -> GitHub
2023-09-20 14:35:47 +09:00
41f23386b2 fix(projects): fix reload button animate 2023-09-07 23:25:30 +08:00
c91644b829 feat(projects): add plugin-web-update-notification 2023-09-06 01:27:39 +08:00
073fd16bd7 refactor(projects): update soybean domain 2023-09-06 01:07:29 +08:00
f92ee770e0 refactor(projects): add reCacheRoute method 2023-09-06 00:34:48 +08:00
1e6d52357e Merge pull request #272 from linjiangl/main
chore(projects): When tab is switched, keep the page without refreshing
2023-09-06 00:18:04 +08:00
751ded44f3 chore(deps): update deps 2023-09-06 00:14:35 +08:00
8567f3e34e Merge pull request #271 from lapislazulisch/dynamicRoute
Dynamic route
2023-08-31 00:31:40 +08:00
83f2514403 chore(projects): When tab is switched, keep the page without refreshing 2023-08-24 16:26:49 +08:00
ad6ac7222c fix(components): 修复动态路由home页404 2023-08-23 16:03:19 +08:00
3ae1952624 fix(components): 修复动态路由主页404 2023-08-23 16:00:17 +08:00
3db549af40 fix:动态路由首页404 2023-08-23 15:41:40 +08:00
94179ae552 Merge pull request #269 from snowords/main
Update Docker deployment method and git hooks init command
2023-08-11 16:49:32 +08:00
7f35e87ed8 docs(projects): update git hooks init command 2023-08-11 14:47:47 +08:00
00da0009ef docs(projects): update Docker deployment method 2023-08-11 11:08:05 +08:00
cffc30afa3 chore(projects): correct word spell & eslint fix code 2023-08-04 01:55:00 +08:00
24cf1d9284 style(projects): prettier format code 2023-08-04 01:39:12 +08:00
9296e6987d chore(deps): update deps 2023-08-04 01:37:21 +08:00
809fa85706 perf(hooks): perf useHookTable 2023-07-26 00:50:21 +08:00
b3ae7605d3 feat(hooks): add useHookTable 2023-07-24 00:59:45 +08:00
864ec4737d fix(projects): correct the lang file name & add recommend vscode plugin i18n-ally 2023-07-23 20:31:59 +08:00
854d0bcf20 feat(projects): new i18n function $t & login page and setting drawer config i18n 2023-07-23 20:29:39 +08:00
458e387b68 chore(projects): correct the word spell 2023-07-19 23:44:18 +08:00
56c770c49d chore(projects): update VSCode setting 2023-07-19 23:28:32 +08:00
946447394d chore(projects): update pnpm-lock.yaml 2023-07-19 23:25:29 +08:00
44ba3273cb chore(deps): update deps 2023-07-19 23:15:27 +08:00
0f7b9d5e2b fix(styles): 用户管理页面布局自适应屏幕高度 (fixed #253) 2023-07-19 23:14:33 +08:00
8a3f66db7b Merge pull request #260 from eAliwei/issues/255
feat(auth): 防止多次刷新token
2023-07-15 01:06:43 +08:00
0eaa327d47 feat(auth): 防止多次刷新token 2023-07-13 21:34:34 +08:00
08e0cf5ad5 chore(projects): update deps & fix eslint code 2023-07-09 13:40:33 +08:00
d7aea9d11c chore(projects): update package.json 2023-07-07 01:50:05 +08:00
135ce77288 chore(deps): update deps 2023-07-07 01:49:02 +08:00
19141a73d2 docs(projects): update README.md logo 2023-07-07 01:33:34 +08:00
9d1051b0bd chore(projects): update deps and fix swiper 2023-07-05 01:54:30 +08:00
c46a5920e5 refactor(projects): 生产环境缓存主题变更为sessionStorage 2023-07-05 01:41:57 +08:00
43ac23f113 style(projects): update default theme color 2023-07-05 01:37:29 +08:00
13f6cd8ef4 fix(projects): fix set tab title (fixed #256) 2023-06-27 22:48:04 +08:00
0e6d289128 chore(deps): update deps 2023-06-27 22:24:08 +08:00
bba68bff29 chore(deps): update deps 2023-06-25 07:55:39 +08:00
6e0cce4d49 feat(projects): add switch for customize darkmode transition 2023-06-20 22:33:22 +08:00
d3ebe95076 perf(projects): add type declaration for document startViewTransition 2023-06-20 22:07:21 +08:00
cbda4a38a3 style(projects): unify card border radius, 16px to 8px 2023-06-20 00:17:18 +08:00
3318041b92 perf(hooks): perf use-table 2023-06-19 23:43:16 +08:00
af53ec7625 feat(projects): add websocket demo 2023-06-18 22:24:21 +08:00
de2829fde7 chore(projects): release v0.10.3 2023-06-15 19:26:12 +08:00
c1bee4046c chore(projects): add vite-plugin-vue-devtools 2023-06-15 19:25:32 +08:00
473095b01b fix(styles): fix toggle-lang bg 2023-06-15 01:00:14 +08:00
e6abf93457 chore(deps): update deps 2023-06-14 23:59:43 +08:00
882f281482 chore(deps): decrease vite-plugin-page-route 2023-06-12 13:35:05 +08:00
0b2f68ac04 chore(projects): update deps & update package.json 2023-06-12 01:30:50 +08:00
2ca2b766f8 fix(projects): fix userRoleOptions 2023-06-10 12:05:57 +08:00
da611fb10b perf(projects): use transformObjectToOption to generate option of object labels 2023-06-08 23:56:27 +08:00
eb8e49e23c perf(projects): remove useless code 2023-06-08 23:38:14 +08:00
0907d38c06 chore(projects): update deps & update unocss deprecated api exclude 2023-06-08 23:05:08 +08:00
2a9b725c6a docs(projects): update CHANGELOG.md by regenerate changelog 2023-06-07 22:50:59 +08:00
8f24a94ed3 docs(projects): update README.md 2023-06-07 02:22:13 +08:00
4eefc95baa docs(projects): update README.md picture url 2023-06-07 02:16:18 +08:00
1681c34a52 docs(projects): update README.md 2023-06-07 02:06:40 +08:00
47ab0184b7 chore(deps): update deps 2023-06-07 01:48:55 +08:00
58591f660a chore(projects): update @soybeanjs/cli and generate total changelog 2023-06-07 01:46:09 +08:00
3c7e1cf442 docs(projects): update README.md 2023-06-05 02:13:15 +08:00
055d4cce33 docs(projects): generate full CHANGELOG.md 2023-06-05 02:00:59 +08:00
a3dfe61a7b chore(projects): remove bumpp & add release script 2023-06-05 01:57:23 +08:00
f9d47c081f chore(deps): update deps 2023-06-05 01:55:09 +08:00
ff5bf62989 docs(projects): CHANGELOG.md 2023-05-31 18:25:40 +00:00
1f6d079644 chore: release v0.10.2 2023-06-01 02:24:57 +08:00
5c085a1986 fix(components): fix mix-menu layout when the locale is English (fixed 241) 2023-06-01 02:24:26 +08:00
9a23817473 chore(projects): update deps and use soy lint-staged replace lint-staged 2023-06-01 02:10:07 +08:00
56ea8937f6 docs(projects): fix README.md: example image link 2023-05-31 09:28:34 +08:00
4f51263501 docs(projects): update README.md: update example image url [更新示例图片的链接] 2023-05-31 02:32:06 +08:00
bb2eab60f4 docs(projects): CHANGELOG.md 2023-05-30 18:20:40 +00:00
44e4c04811 chore: release v0.10.1 2023-05-31 02:19:56 +08:00
b5839eab26 docs(projects): update README.md 2023-05-31 02:18:19 +08:00
780ac75bf6 chore(projects): add switch for pageRoute plugin [添加自动生成路由的插件的开关] 2023-05-31 01:52:57 +08:00
a252138594 docs(projects): CHANGELOG.md 2023-05-30 17:47:56 +00:00
270a055072 chore: release v0.10.0 2023-05-31 01:47:13 +08:00
08e194efe9 perf(projects): move changing document title by locale to global event of composables & add appLoading unmount 2023-05-31 01:44:49 +08:00
5f6caab338 docs(projects): update CHANGELOG.md 2023-05-31 01:35:04 +08:00
5aaa318142 chore(projects): remove useless packages, update lint-staged config, add githublogen 2023-05-31 01:33:46 +08:00
cebbef680f chore(deps): update deps 2023-05-31 01:08:31 +08:00
0abde46ef4 fix(projects): hide the drawer when it is initial mobile mode [初始化时为移动端布局则隐藏侧边栏] fixed #238 2023-05-26 13:08:35 +08:00
f2b518ed26 feat(projects): support mobile layout [支持移动端布局] 2023-05-26 03:27:41 +08:00
c6207f35e1 Merge pull request #237 from abstain23/fix-i18n
fix(projects): 修复面包屑导航下拉菜单语言显示问题
2023-05-25 21:13:45 +08:00
cc
ee8fa04814 fix(projects): 修复面包屑导航下拉菜单语言显示问题 2023-05-25 21:11:42 +08:00
7b746fa053 perf(projects): complete dynamic route translate [补充动态路由的翻译] 2023-05-24 23:17:29 +08:00
b7fea53107 Merge pull request #234 from chhinsras/main
Add Khmer Translation
2023-05-24 23:03:23 +08:00
f89f3e6a38 Added Khmer Translation 2023-05-24 21:07:35 +07:00
a0da2f6e16 Delete actions-template-sync.yml 2023-05-24 15:52:05 +07:00
3b5380e0d1 Update Sras.md 2023-05-24 15:38:43 +07:00
35276bfe41 Update and rename .github/workflows/actions-template-sync.yml to actions-template-sync.yml 2023-05-24 15:30:10 +07:00
215c1ecbd9 Update and rename sync-from-template.yml to actions-template-sync.yml 2023-05-24 15:24:51 +07:00
1698b21d7a Create Sras.md 2023-05-24 15:18:35 +07:00
ca1e66be47 Rename sync-from-template to sync-from-template.yml 2023-05-24 15:13:58 +07:00
22bf2823e8 Update and rename actions-template-sync to sync-from-template 2023-05-24 15:12:03 +07:00
32e98f1b3a Create actions-template-sync 2023-05-24 15:06:44 +07:00
c1c4335ce7 build(projects): update deps and fix style [升级依赖&修复代码格式] 2023-05-24 00:17:00 +08:00
6c50662280 Merge pull request #233 from fast-crud/优化README.md
优化readme.md
2023-05-24 00:12:44 +08:00
f3a1707b94 docs(projects): readme.md 二次开发的项目内容换行 2023-05-23 17:52:06 +08:00
6ea755f2a8 docs(projects): 优化README.md 2023-05-23 17:43:00 +08:00
a989b44a15 docs(projects): update README.md [更新README.md] 2023-05-22 23:04:57 +08:00
40f8587fd6 build(deps): update deps [升级依赖] 2023-05-21 22:35:30 +08:00
9f5638f16d fix(projects): add prod mockjs switch [添加生产模式的mockjs的开关] 2023-05-17 07:55:12 +08:00
9b19f96ff6 fix(projects): fix mockjs [修复mockjs] 2023-05-16 22:29:35 +08:00
15da557892 Merge pull request #230 from kirklin/fix_tsconfig
fix(projects): tsconfig missing isolatedModules
2023-05-16 19:36:04 +08:00
2d23c9a2e6 Merge pull request #229 from kirklin/vue3.3
refactor(projects): upgrade vue3.3, official support defineOptions
2023-05-16 19:34:16 +08:00
ab49afd3db fix(projects): tsconfig missing isolatedModules 2023-05-16 17:39:05 +08:00
86a370fd69 refactor(projects): upgrade vue3.3, official support defineOptions 2023-05-16 17:32:38 +08:00
36fc74ce07 Merge pull request #226 from abstain23/feat/theme-transtion
feat(projects): 增加主题切换过渡效果
2023-05-14 16:49:26 +08:00
cc
8da8843fd0 feat(projects): 增加主题切换过渡效果 2023-05-14 16:35:38 +08:00
f68285fbe5 feat(projects): add menu translate [翻译菜单] 2023-05-13 14:20:06 +08:00
85b8ef8f88 Merge pull request #225 from abstain23/feat-i18n
feat(projects): 增加i18n支持翻译菜单,tab,title
2023-05-13 13:12:28 +08:00
cc
3d48aa8bbe feat(projects): 增加i18n支持翻译菜单,tab,title 2023-05-13 12:58:35 +08:00
a765da6e28 docs(projects): update README.md [更新README.md] 2023-05-10 22:23:18 +08:00
c57640acd0 fix(projects): fix better-mock usage [修复better-mock用法] 2023-05-06 19:41:55 +08:00
c264216053 build(deps): update deps [升级依赖] 2023-05-06 19:35:54 +08:00
9d3c732993 refactor(projects): use better-mock replace mockjs [用better-mock替换mockjs] 2023-05-06 19:34:31 +08:00
34f023c4b1 build(projects): update deps and fix type error [升级依赖并修复类型问题] 2023-05-04 19:02:20 +08:00
5a4f842774 docs(projects): update README.md [更新README.md] 2023-04-26 08:40:07 +08:00
bae1767141 build(deps): update deps [升级依赖] 2023-04-26 08:32:54 +08:00
5957833a4f fix(projects): fix router guide [修复路由跳转异常] fixed #216 2023-04-21 00:46:03 +08:00
397092c21f docs(projects): update README.md [更新README.md] 2023-04-20 01:41:07 +08:00
f309003e67 refactor(projects): remove page examples: tree [去除tree相关示例页面] 2023-04-20 01:37:52 +08:00
eaf3678758 build(deps): update deps and remove vite-plugin-html [升级依赖,去除vite-plugin-html] 2023-04-20 01:32:53 +08:00
f2e82da7c8 build(deps): update deps [升级依赖] 2023-04-19 09:10:36 +08:00
211ae1f905 refactor(projects): update useTable 2023-04-04 19:19:13 +08:00
db629593c6 build(deps): update deps 2023-04-02 12:57:36 +08:00
80d58cce2b Merge pull request #210 from SonyLeo/feature/tree
Feature/tree
2023-04-02 12:56:00 +08:00
a0f55aca69 feat(components): Add routing data related to tree components and page display optimization 2023-04-02 10:45:51 +08:00
d203a3586c feat(components): Add tree related component instances 2023-04-02 10:07:50 +08:00
f74a6424d0 docs(projects): add qq to README.md [文档添加QQ群] 2023-03-15 18:14:25 +08:00
209ef3d890 style(projects): per style [完善样式] 2023-03-15 09:01:06 +08:00
b549b32cbb Merge pull request #205 from yanbowe/main
feat(projects): fix to top [返回顶部功能适配新布局]
2023-03-14 22:31:41 +08:00
54e2cb51cf feat(projects): 返回顶部功能适配新布局 2023-03-14 13:50:23 +08:00
42e6de395f build(projects): remove old layout,tab package [去除旧的布局和页签依赖] 2023-03-14 00:34:47 +08:00
c0066b22b0 chore(release): 0.9.9 2023-03-13 23:55:02 +08:00
aaef0bec27 docs(projects): update README.md 2023-03-13 23:51:28 +08:00
912c3531c5 feat(projects): new layout,tab and add update theme settings 2023-03-13 23:47:39 +08:00
488e6e3204 feat(projects): custom unocss colors support opacity 2023-03-13 20:52:26 +08:00
f73e3f648d fix(projects): fix github bug-report 2023-03-13 19:52:40 +08:00
36e5feac98 build(projects): update deps, add prettier format command 2023-03-12 22:47:00 +08:00
cc13fcc8aa feat(hooks): add useNaiveTable 2023-03-10 08:32:39 +08:00
7f748f2a61 Merge pull request #200 from guuuuo/main
fix(utils): make AxiosRequestConfig optional for request.handleDelete()
2023-03-08 12:27:48 +08:00
4a6fec8af0 fix(utils): make AxiosRequestConfig optional for request.handleDelete() 2023-03-08 01:30:33 +00:00
e2b320ad27 refactor(projects): rename union key 2023-03-08 06:41:42 +08:00
21d5214247 refactor(projects): remove enum 2023-03-08 06:41:10 +08:00
44b544745d Merge pull request #199 from elliotxiang/main
proxy fail fix
2023-03-07 16:04:02 +08:00
5499a559c8 proxy fail fix
修复代理地址缺少/导致代理失败
2023-03-07 15:51:53 +08:00
ebe2c56348 proxy fail fix
修改代理地址缺少/导致代理失败问题
2023-03-07 15:51:07 +08:00
8debfe7e95 refactor(projects): update service and proxy config 2023-03-07 07:58:37 +08:00
1ef1b6bda9 docs(projects): update README.md 2023-03-07 07:36:38 +08:00
fb46d7ec7c style(projects): format yaml 2023-03-06 21:07:02 +08:00
cea600f12c refactor(projects): all file and folder use kebab-case 2023-03-06 21:06:36 +08:00
bf2f617255 fix(projects): fix pwa logo 2023-03-06 13:33:51 +08:00
cf8c7cb258 docs(projects): update README.md 2023-03-06 13:22:43 +08:00
4e87f0b665 Merge pull request #198 from lixin59/issue/fix-bug-repo-style
chore(projects): 修复issue模板格式问题
2023-03-05 00:33:13 +08:00
d8baba586b chore(projects): 修复issue模板格式问题 2023-03-04 21:39:26 +08:00
3cff2eb4ce Merge pull request #195 from lixin59/issue/add-github-action
chore(projects): add github action
2023-03-04 00:44:05 +08:00
f355a698ad chore(projects): add github action 2023-03-03 17:40:26 +08:00
c3d0b74c75 Merge pull request #194 from taisha/main
fix(components): refresh cached routes
2023-03-02 08:20:41 +08:00
b0f98e4bfa fix(components): refresh cached routes 2023-03-01 13:56:04 +08:00
506ffb8adf Merge pull request #182 from Shadowsight9/main
fix(projects): the length of routes children list should greater than 0
2023-02-19 19:33:53 +08:00
e1afc10b80 fix(projects): the length of routes children list should greater than 0 2023-02-19 17:04:55 +08:00
960b436c79 Merge pull request #180 from sunhao1256/main
fix(projects): not only `/login` claim dynamic path scenario
2023-02-14 12:11:44 +08:00
6059891556 fix(projects): not only /login claim dynamic path scenario , but also others , eg:/user/1 2023-02-13 16:57:54 +08:00
3503dff663 build(projects): update unocss config 2023-02-13 01:40:07 +08:00
61998886ac build(deps): update deps 2023-02-13 01:39:43 +08:00
608d7fb34d build(projects): update vscode config 2023-02-13 01:39:17 +08:00
6bb6d9f71e Merge pull request #179 from sunhao1256/main
fix(projects): sortRoutes recursively
2023-02-13 01:20:26 +08:00
918894147a fix(projects): sortRoutes recursively 2023-02-12 13:13:03 +08:00
0b5afda287 fix(projects): fix eslint svg cause incorrect icon render 2023-02-10 02:55:42 +08:00
a8a6ed97b9 build(projects): perf logo 2023-02-10 02:24:52 +08:00
919376b77c Merge pull request #178 from yanbowe/main
fix(components): 修复iconSelect选择器点击事件失效
2023-02-09 23:58:41 +08:00
7e505f9b96 fix(components): 修复iconSelect选择器点击事件失效 2023-02-09 10:59:34 +08:00
de517be613 Merge pull request #177 from taisha/fix-tab
fix(components): 页面跳转被拦截, 则会出现 tab 页签与页面不一致的问题
2023-02-09 00:43:18 +08:00
bd5dd2cf28 fix(components): 页面跳转被拦截, 则会出现 tab 页签与页面不一致的问题 2023-02-08 22:29:54 +08:00
da521b35e6 build(projects): update deps and fix project config 2023-02-03 00:39:43 +08:00
34ffd9c1f3 chore(release): 0.9.8 2023-01-15 23:36:40 +08:00
3131e00f0f feat(projects): add new route plugin @soybeanjs/vite-plugin-vue-page-route [集成新的路由插件] 2023-01-15 23:35:31 +08:00
f71812d622 build(projects): update deps 2023-01-15 23:34:01 +08:00
0c12665fda build(projects): add VSCode debug config file 2023-01-15 23:33:54 +08:00
458b7adb29 Merge pull request #173 from shabby2333/main
fix(components): 修复路由在path中包含重复路单词径菜单时,被激活会错误展开
2023-01-15 19:27:47 +08:00
264da00e5d fix(components): 修复路由在path中包含重复路单词径菜单时,被激活会错误展开 2023-01-13 13:03:38 +00:00
0882c25034 build(projects): update lint-staged config 2023-01-11 23:09:56 +08:00
a3562d9212 docs(projects): update README 2023-01-11 22:28:34 +08:00
b08c389e4a build(projects): update deps and update config 2023-01-11 21:23:15 +08:00
91bc1519f1 Merge pull request #169 from soup-Lee/main
fix(projects): 修复动态路由模式下路由不排序的问题
2023-01-09 12:06:03 +08:00
58b27c9693 fix(projects): 修复动态路由模式下路由不排序的问题 2023-01-09 10:39:42 +08:00
25daa23606 feat(projects): add generate logo script 2023-01-04 01:25:15 +08:00
9110d87580 refactor(projects): add simple-git-hooks replace husky 2023-01-04 01:13:45 +08:00
c097b5681d build(deps): update deps 2023-01-04 00:48:36 +08:00
beb705f8a9 Merge pull request #163 from yanbowe/main
refactor(hooks): 重构hook函数取消监听方式
2022-12-12 02:10:23 +08:00
fd9488673c refactor(hooks): 重构hook函数取消监听方式 2022-12-10 17:52:31 +08:00
70aeefea02 feat(projects): add script about generating png logo from [添加根据svg生成png图标的命令] 2022-12-09 19:15:29 +08:00
1b3d2a6168 Merge pull request #161 from yanbowe/main
refactor(czg): update cz-git,czg breaking changes
2022-12-07 22:43:47 +08:00
fcb7ad965d refactor(czg): update cz-git,czg breaking changes 2022-12-07 15:25:15 +08:00
828a2f5b60 docs(projects): update README 2022-12-07 01:46:40 +08:00
be6d431485 feat(projects): add compress script [添加压缩命令] 2022-12-07 01:28:37 +08:00
61a43b8efd build(projects): update deps and perfect the details [升级依赖,完善细节] 2022-12-07 01:11:45 +08:00
e3a9c77fd1 Merge pull request #160 from zuihou/main
新增2个功能
2022-12-03 13:40:58 +08:00
e772ff05fb feat: 新增 affix 属性,用于将其固定在tab卡 2022-12-02 17:00:49 +08:00
d064f6285a feat: setting 页面新增 是否显示footer的开关 2022-12-02 16:47:18 +08:00
091ca1a4fe Merge pull request #159 from jake484/main
fix echarts
2022-12-02 01:53:19 +08:00
9cec6a31a5 fix echarts 2022-12-01 17:37:24 +08:00
bb8af263e1 Merge pull request #158 from yanbowe/main
fix(projects): 修复tabs在static路由模式下可以关闭首页
2022-11-29 23:27:24 +08:00
7211a17a81 fix(projects): 修复tabs在static路由模式下可以关闭首页 2022-11-29 15:12:59 +08:00
810398abb8 fix(projects): fix login success message [修复登录成功的消息提示] 2022-11-18 16:15:54 +08:00
f2b580fc06 fix(projects): fix router when the dynamic routes api was failed [修复当动态路由接口失败后路由异常问题] 2022-11-18 15:45:40 +08:00
3bd8858121 Merge pull request #151 from codearhat/main
fix: set password attributes
2022-11-17 17:47:54 +08:00
5efd1dbec4 Merge branch 'honghuangdc:main' into main 2022-11-17 10:11:43 +08:00
971915948b refactor(projects): new storage system [新的本地数据存储系统] 2022-11-17 01:47:06 +08:00
a9a37036d5 fix: set password attributes 2022-11-17 00:19:30 +08:00
7a58035514 fix(projects): add router-page.d.ts to git [将router-page.d.ts添加git提交] 2022-11-16 23:48:58 +08:00
57bfe27819 refactor(projects): refactor app init loading [重构系统初始化的加载] 2022-11-16 23:35:26 +08:00
fcc65c3751 build(deps): update deps 2022-11-16 22:53:38 +08:00
f2d8dfc3ef Merge pull request #148 from codearhat/main
fix: remove height limit h-360px
2022-11-16 22:39:11 +08:00
b5c570adf5 fix: remove height limit h-360px 2022-11-16 10:52:31 +08:00
94098d02e8 fix(projects): fix vite-pwa plugin config 2022-11-14 21:39:55 +08:00
436b15f010 Merge pull request #147 from RockerHX/patch-2
fix(components): count can't display when endValue is 0.
2022-11-14 11:51:15 +08:00
0282feb173 Fix: count can't display when endValue is 0. 2022-11-14 10:51:39 +08:00
8456750901 build(deps): update deps 2022-11-13 15:36:35 +08:00
1a02cab97c refactor(projects): perfect scrollbar style [完善滚动条] 2022-11-13 01:39:40 +08:00
1bdd81a1d8 refactor(projects): import cz-git, czg replace @soybeanjs/cli [引入cz-git、czg替换@soybeanjs/cli] 2022-11-08 18:37:27 +08:00
a9d58f88aa refactor(projects): format code style [调整代码格式] 2022-11-08 18:30:48 +08:00
6a344ff2c7 build(projects): update plugin config 2022-11-08 09:18:05 +08:00
cc00c8f03a chore(other): release v0.9.7 2022-11-08 01:26:24 +08:00
c7b6a3fbec feat(projects): new router system [新的路由系统] 2022-11-08 01:23:41 +08:00
40c1e13b50 build(projects): add vite plugin @soybeanjs/router-page 2022-11-07 18:47:44 +08:00
288d586dbc build(projects): new router branch 2022-11-07 00:47:08 +08:00
7d69992694 build(projects): update deps and update config 2022-11-07 00:45:48 +08:00
6c14bfe6a9 build(projects): move tauri to branch tauri 2022-10-31 19:11:36 +08:00
6773659e89 build(projects): remove useless file: commitlint.config.js 2022-10-31 19:09:13 +08:00
9455ad9a4f build(projects): use pnpm patch replace @milahu/patch-package 2022-10-31 16:56:29 +08:00
428d41b485 build(projects): use @soybeanjs/cli replace commitizen 2022-10-31 00:29:52 +08:00
74772a1f03 build(deps): update deps 2022-10-31 00:21:23 +08:00
1f3e6e4fac build(deps): update deps 2022-10-24 19:39:13 +08:00
41b3bcb445 build(deps): update deps 2022-10-23 23:02:53 +08:00
8e801dd790 build(deps): update deps 2022-10-19 17:02:54 +08:00
d6b1530720 build(deps): update deps 2022-10-15 16:44:50 +08:00
b632b7ffed feat(projects): import i18n [引入i18n] 2022-10-12 01:03:14 +08:00
1b45b71f20 build(projects): add tauri scripts, change tauri icon, fix mockjs [添加tauri相关的命令,变更tauri图标,修复mockjs] 2022-10-11 23:20:31 +08:00
149d22a4a4 fix(deps): decrease @types/node version to fix TS type error [降低@types/node版本修复TS的类型错误] 2022-10-11 22:39:37 +08:00
83a2e01070 Merge pull request #140 from better-rs/dev/tauri-support
使用 rust + tauri 支持打包成 Windows/Mac/Linux 应用
2022-10-11 15:37:45 +08:00
11d615f807 update: change tauri window size 2022-10-11 15:23:01 +08:00
853745587d update: tauri support 2022-10-11 15:18:49 +08:00
f29108aa14 update: add tauri cli 2022-10-11 15:18:11 +08:00
abd02d1990 build(deps): update deps 2022-10-10 00:37:47 +08:00
65ac69ef71 build(deps): update deps 2022-10-03 21:58:37 +08:00
8998581b99 build(deps): update deps 2022-10-01 03:31:52 +08:00
468b4bb0e1 refactor(projects): refactor page: user-management [重构用户管理页面] 2022-09-29 02:02:28 +08:00
88e535f63c build(deps): update deps 2022-09-28 21:35:41 +08:00
13d0c4153a build(projects): add constant page content 2022-09-28 09:35:38 +08:00
331b14e74d build(deps): update deps [升级依赖]
ISSUES CLOSED: #133
2022-09-27 15:55:00 +08:00
c29b887eb2 refactor(projects): cancel autoinstall @iconify-json [取消@iconify-json自动安装] 2022-09-24 17:22:08 +08:00
8a1ec938e7 fix(projects): add iconify json 2022-09-24 16:19:38 +08:00
c045e3fe4e build(deps): unplugin-icon autoinstall @iconify-json [unplugin-icon自动安装@iconify-json] 2022-09-23 12:42:06 +08:00
811f820644 feat(projects): refactor icon system, unify icon usage [重构图标系统,统一图标用法] 2022-09-23 03:18:53 +08:00
fe8cab3d1c build(deps): update deps 2022-09-22 23:31:01 +08:00
78efd7793a feat(projects): add constant route page without login status[添加未登录可访问的固定路由示例页面] 2022-09-21 18:45:28 +08:00
82c4b09b94 feat(projects): add pinia setup syntax example: setup-store[添加setup syntax的pinia示例setup-store] 2022-09-21 18:17:33 +08:00
a539112a0f feat(projects): support constant route without login status[支持未登录状态下访问自定义的固定路由] 2022-09-21 15:30:35 +08:00
22c05674f8 build(projects): update deps, update logos 2022-09-20 12:09:15 +08:00
7dd7c71d01 build(deps): update deps 2022-09-15 06:37:36 +08:00
22c90257de build(deps): unplugin-vue-define-options替换为unplugin-vue-macros 2022-09-15 06:33:48 +08:00
3d03d6ddb5 Merge pull request #132 from zqxu1993/main
ci: change docker image name
2022-09-14 12:35:03 +08:00
6fbde1eb57 ci: change docker image name 2022-09-14 06:28:14 +02:00
0ee16e0228 Merge pull request #130 from zqxu1993/main
ci: add docker build
2022-09-13 21:11:19 +08:00
af74046124 ci: add docker build 2022-09-13 14:56:59 +02:00
d823ee5684 build(deps): update deps 2022-09-12 23:52:47 +08:00
f7ca2782b0 Merge pull request #129 from shy1118999/patch-1
fix:cannot re-render if dom is deleted <Update echarts.ts>
2022-09-09 22:32:15 +08:00
af8c133914 Update echarts.ts
fix:cannot re-render if dom is deleted

If the chart is opened in the pop-up window, opening the chart again will not display properly.
2022-09-09 18:06:30 +08:00
21b6fb697e build(deps): update deps 2022-09-05 00:37:45 +08:00
3e0cc8c2c1 build(deps): update deps 2022-09-03 01:48:10 +08:00
3540b75557 build(projects): 引入@unocss/vite替换unocss,精简体积 2022-08-31 23:29:37 +08:00
73ce53a388 build(projects): 升级依赖,修复TS类型 2022-08-31 22:57:53 +08:00
f408ea017c build(projects): 升级依赖,降低naive-ui版本修复打包问题 2022-08-29 22:01:40 +08:00
c5ba63182e build(deps): update deps 2022-08-29 02:39:46 +08:00
07325a4236 build(projects): 更换eslint依赖为eslint-config-soybeanjs-vue 2022-08-28 04:46:44 +08:00
7240be8495 build(deps): 升级依赖 2022-08-24 19:22:34 +08:00
71a753f323 build(projects): 引入TS高级类型库 2022-08-24 19:21:22 +08:00
639c4458be build(projects): 升级依赖、修复T标签右键菜单连续显示问题
ISSUES CLOSED: #125
2022-08-24 00:15:46 +08:00
1ad92a2d1b build(deps): update deps 2022-08-22 23:36:15 +08:00
49f95c4e45 refactor(projects): 代码优化 2022-08-22 23:34:14 +08:00
44ab07779e build(projects): 引入vite-plugin-progress 2022-08-22 12:05:17 +08:00
40ecc320a5 build(projects): 更新依赖、调整页面 2022-08-22 12:01:57 +08:00
695ec7e50d build(projects): 引入pwa插件,更新配置 2022-08-19 12:32:33 +08:00
85901d2d5e Merge pull request #121 from yanbowe/main
feat(projects): 全局搜索菜单及消息通知适配移动端
2022-08-18 19:43:25 +08:00
97e2ffddf4 feat(projects): 全局搜索菜单及消息通知适配移动端 2022-08-18 10:02:15 +08:00
907cf44cc1 build(projects): update eslint 2022-08-15 18:40:24 +08:00
d9324f07b5 build(deps): update deps 2022-08-15 12:23:30 +08:00
d7f5bf3373 fix(projects): 修复eslint规则 2022-08-15 12:14:20 +08:00
36f06bc899 build(deps): 更新@soybeanjs/eslint-config 2022-08-11 14:37:22 +08:00
182dac0d2e build(projects): 去除prettier,已集成进@soybeanjs/eslint-config 2022-08-10 21:49:22 +08:00
f4d37cf7f0 refactor(projects): 抽离格式化相关依赖配置 2022-08-10 21:31:59 +08:00
16dce9a4ce fix(projects): 修复TS类型问题 2022-08-08 13:37:32 +08:00
0f0cd0b759 build(deps): update deps 2022-08-08 01:08:54 +08:00
472f93bfc1 feat(projects): 实现用户管理页面 2022-08-07 04:59:05 +08:00
77572855c3 fix(projects): 修复构建后mockjs对xhr的影响问题 2022-08-07 00:49:30 +08:00
19942625d5 fix(projects): 修复import.meta.env的TS类型 2022-08-03 23:19:25 +08:00
dbd676095b fix(projects): 修复图标的TS类型 2022-08-03 22:39:08 +08:00
ed9cd6ce39 refactor(projects): 更新搜索弹窗的图标 2022-08-03 22:34:59 +08:00
ee434b465a build(projects): 升级依赖、vite配置optimizeDeps 2022-08-03 22:25:04 +08:00
2aba58c973 fix(projects): 修复多个后端服务时的本地代理 2022-08-03 22:14:42 +08:00
2c56233155 docs(projects): revert docs 2022-07-31 23:18:26 +08:00
8d11a6affc feat(projects): 添加请求适配adapter层应用的示例页面 2022-07-30 22:16:42 +08:00
f6b61418e5 build(deps): update deps 2022-07-30 05:22:32 +08:00
7f9c98ab8d refactor(projects): 请求适配器函数范型重构、优化请求相关的命名 2022-07-28 15:16:37 +08:00
02992dc02d feat(projects): useNaiveTable函数:类型部分 2022-07-28 00:34:29 +08:00
b32bca4984 build(deps): update deps 2022-07-26 22:39:51 +08:00
c37d0ac788 fix(utils): 修复iconifyRender 2022-07-26 20:55:37 +08:00
35aeedf320 build(projects): update deps and README.md 2022-07-20 00:41:31 +08:00
94ff787053 build(deps): update deps 2022-07-19 00:03:25 +08:00
d0823b030b build(deps): update deps 2022-07-17 13:04:57 +08:00
2d722db243 Merge pull request #114 from xiaotao2018/main
fix(components): 添加更多主题颜色模态窗的层级覆盖设置按钮
2022-07-16 02:06:34 +08:00
6143605297 refactor(projects): 代码优化 2022-07-16 02:04:59 +08:00
e2d6554313 perf(components): 添加更多主题颜色设置模态窗的层级,z-index为int
z-index为int类型,修复在小屏幕下,系统设置按钮悬浮至模态窗之上的缺陷,提升用户体验
2022-07-15 23:58:54 +08:00
872bb84502 chore(projects): 更新eslint配置 2022-07-15 10:09:47 +08:00
ee7eb3ac0d perf(components): 添加更多主题颜色设置模态窗的层级
修复在小屏幕下,系统设置按钮悬浮至模态窗之上的缺陷,提升用户体验
2022-07-15 10:08:21 +08:00
dd1132482e build(deps): update deps 2022-07-14 23:34:05 +08:00
c33b5ebfef feat(projects): 添加系统管理的页面 2022-07-14 23:32:19 +08:00
711a4ae34f build(projects): 升级依赖,添加对json的eslint检测及格式化 2022-07-14 02:16:38 +08:00
d9cfeabb47 build(deps): update deps
ISSUES CLOSED: #87,#106,#109,#111
2022-07-12 23:26:23 +08:00
296b154be5 feat(projects): 适配移动端,修复Tab关闭图标的bug
ISSUES CLOSED: #87,#106,#109,#111
2022-07-12 01:49:46 +08:00
cec0f25c6b build(deps): update deps 2022-07-11 20:53:13 +08:00
b18c49e9d2 chore(projects): 更新.cz-config 2022-07-10 16:55:26 +08:00
f64bc91ce2 feat(projects): 添加组件名称,调整vue文件里面的类型声明位置 2022-07-10 16:47:56 +08:00
b60db89801 refactor(projects): 代码优化 2022-07-10 03:06:02 +08:00
da407b6653 build(deps): update deps 2022-07-09 16:13:02 +08:00
6a9a362caa build(projects): 代码优化 2022-07-07 23:46:07 +08:00
aa2f78a86f refactor(projects): 添加subscribeAppStore 2022-07-07 23:33:52 +08:00
a444731e9e feat(projects): 添加provide、inject上下文示例 2022-07-07 23:27:58 +08:00
1523c7b075 build(deps): update deps 2022-07-07 21:56:30 +08:00
896e6f2eac build(projects): 添加.gitattributes 2022-07-07 21:15:49 +08:00
8dcfbb29f9 build(deps): update deps 2022-07-01 00:47:41 +08:00
750000ec66 build(deps): update deps 2022-06-30 00:28:04 +08:00
a792bb5cb3 fix(projects): 修复tab不显示路由首页的问题 2022-06-28 07:49:26 +08:00
973ab14442 build(deps): update deps 2022-06-28 07:35:05 +08:00
3fe4e92f4a build(projects): update vscode settings 2022-06-28 07:31:16 +08:00
9ce58073dd build(projects): update tsconfig 2022-06-26 00:42:42 +08:00
e2727e6fa1 docs(projects): update README.md 2022-06-26 00:30:48 +08:00
73fa3d14c5 build(deps): update deps 2022-06-25 01:07:26 +08:00
ea1a336535 build(deps): update deps 2022-06-24 00:19:13 +08:00
69e39c142e build(deps): update deps 2022-06-20 23:41:58 +08:00
718c36263e feat(projects): 添加生产的主题配置缓存 2022-06-20 23:29:58 +08:00
5c1b086cb4 build(projects): 代码优化 2022-06-19 15:34:18 +08:00
414ccbe360 Merge pull request #105 from yanbowe/main
feat(projects): 增加返回顶部功能
2022-06-17 17:54:31 +08:00
41147b34fa refactor(projects): 代码优化 2022-06-17 16:29:06 +08:00
894b0f1c18 feat(projects): 增加返回顶部功能 2022-06-17 15:59:56 +08:00
d214bb2f2a Merge pull request #104 from yanbowe/main
feat(projects): 增加系统消息组件
2022-06-17 13:48:14 +08:00
9518372fe0 feat(projects): 系统消息组件代码优化 2022-06-17 12:49:53 +08:00
afa0134fdd feat(projects): 增加系统消息组件 2022-06-17 11:39:38 +08:00
c6ed9b1558 Merge pull request #103 from yanbowe/main
feat(tabs): 多页签增加关闭所有
2022-06-16 12:06:28 +08:00
0523f08382 fix(svg-icon): 自定义图标在Dropdown组件下hover状态无法显示图标 2022-06-16 11:07:43 +08:00
8237adb9c0 feat(tabs): 多页签增加关闭所有 2022-06-16 10:00:23 +08:00
65c21812bb chore(release): 0.9.6 2022-06-16 01:18:18 +08:00
c3c975ee11 feat(projects): 本地svg动态渲染图标
ISSUES CLOSED: #61
2022-06-16 01:17:31 +08:00
833018a831 build(deps): update deps 2022-06-15 23:44:46 +08:00
3eb7f6f593 Merge pull request #102 from yanbowe/main
feat(projects): 增加设置当前Tab页签名称功能
2022-06-14 16:54:03 +08:00
efcfa576d5 fix(projects): 设置tab标题导致meta属性丢失 2022-06-14 16:09:33 +08:00
487213b648 feat(projects): 增加设置当前Tab页签名称功能 2022-06-14 15:42:59 +08:00
4ee0d94f1b fix(projects): 修复顶部菜单的位置失效问题 2022-06-11 15:27:19 +08:00
5fa822f4d4 refactor(projects): 代码优化 2022-06-11 13:37:52 +08:00
8e6e787543 build(projects): update deps, update config 2022-06-11 13:30:25 +08:00
9917b5e53c build(deps): update deps 2022-06-10 01:02:50 +08:00
8f3e855f41 refactor(projects): 优化菜单支持横向滚动
ISSUES CLOSED: #76
2022-06-10 01:02:50 +08:00
808051b29d feat(projects): 上下结构,菜单支持横向滚动 2022-06-10 01:02:24 +08:00
906aed5e75 build(deps): update deps 2022-06-08 00:08:16 +08:00
2d64a2e57c feat(projects): 新增Antv G2图表示例 2022-06-07 23:58:47 +08:00
0c70a9e083 docs(projects): update README.md 2022-06-07 23:49:02 +08:00
08d83ecbea chore(release): 0.9.5 2022-06-07 01:55:57 +08:00
4122685803 feat(projects): 支持同一路由根据不同query和hash同时显示不同Tab
ISSUES CLOSED: #64
2022-06-07 01:51:40 +08:00
434ab1c560 feat(projects): 动态路由根路由重定向只需取决于后端返回的路由首页
ISSUES CLOSED: \
2022-06-06 22:47:46 +08:00
ae99e57c52 docs(projects): update README.md 2022-06-06 18:37:27 +08:00
e3c4a6ece6 build(deps): 依赖升级 2022-06-06 12:14:19 +08:00
c8717c25b8 build(projects): 配置更改 2022-06-06 12:11:01 +08:00
e9656c6e76 docs(projects): update docs 2022-06-04 12:04:44 +08:00
fd78791229 build(projects): 配置优化 2022-06-04 11:48:24 +08:00
de09f82586 build(projects): 代码优化
ISSUES CLOSED: \
2022-06-02 02:39:26 +08:00
c7762490de feat(projects): 补充更多的ECharts示例
ISSUES CLOSED: \
2022-06-01 00:27:28 +08:00
4558c24d1c fix(projects): 修复@antv/g2生产环境报错
ISSUES CLOSED: \
2022-05-31 23:02:24 +08:00
d9ac7e4de0 refactor(projects): 代码优化
ISSUES CLOSED: \
2022-05-31 00:26:52 +08:00
6a5a357f50 build(deps): update deps
ISSUES CLOSED: \
2022-05-30 22:53:44 +08:00
44b022aefd feat(projects): 添加antv g2图表示例
ISSUES CLOSED: \
2022-05-30 22:39:44 +08:00
0a46ea0844 feat(projects): 添加插件页面:图表
ISSUES CLOSED: \
2022-05-29 23:44:47 +08:00
39854a492b feat(projects): 添加百度地图、升级依赖
ISSUES CLOSED: \
2022-05-29 22:39:07 +08:00
4c2f535a9b refactor(projects): 代码优化
ISSUES CLOSED: \
2022-05-28 20:26:29 +08:00
be45d83766 build(deps): update deps
ISSUES CLOSED: \
2022-05-28 17:06:55 +08:00
d28b9039bb refactor(projects): 代码优化
ISSUES CLOSED: \
2022-05-28 13:33:09 +08:00
8f6d6ce3cb refactor(styles): 代码格式
ISSUES CLOSED: \
2022-05-28 12:30:17 +08:00
07baac7cf8 build(other): update cz config 2022-05-27 09:53:40 +08:00
7487ab79b3 chore(deps): update deps
ISSUES CLOSED: \
2022-05-27 00:54:13 +08:00
a70e4161be chore(deps): update deps
ISSUES CLOSED: \
2022-05-19 23:51:28 +08:00
095c432363 refactor(projects): 代码优化
ISSUES CLOSED: \
2022-05-19 00:15:37 +08:00
028096e53f build(deps): update deps
ISSUES CLOSED: \
2022-05-19 00:00:47 +08:00
44ab55d594 refactor(projects): 代码优化
ISSUES CLOSED: \
2022-05-18 23:43:41 +08:00
4b80a66114 docs(projects): update README.md
ISSUES CLOSED: \
2022-05-18 23:23:04 +08:00
cc0bb088ec Merge pull request #91 from yanbowe/main
路由meta新增activeMenu属性
2022-05-17 19:09:05 +08:00
3e4f9e2824 fix(route): 当为左侧混合菜单时activeMenu无效情况 2022-05-17 14:06:20 +08:00
ebd16a4d1a feat(route): 路由meta新增activeMenu属性 2022-05-17 13:54:48 +08:00
84cb07baec docs(projects): update README.md
ISSUES CLOSED: \
2022-05-16 22:17:01 +08:00
0811ffa5ae docs(projects): update README.md 2022-05-16 20:09:07 +08:00
3f822a7d76 build(deps): update deps
ISSUES CLOSED: \
2022-05-14 00:57:23 +08:00
a1c7e10574 refactor(projects): 代码优化 2022-05-11 00:18:36 +08:00
50d7ccd82d build(deps): update deps 2022-05-10 23:53:56 +08:00
e0233061d3 fix(projects): 修复页面切换时导致的溢出滚动条 2022-05-10 23:22:24 +08:00
a0c405dadd build(projects): update config 2022-05-10 22:07:53 +08:00
60f912508b fix(projects): 修复权限切换路由数据未更新的问题 2022-05-09 23:53:09 +08:00
3590b65e22 refactor(projects): 代码优化 2022-05-09 20:52:43 +08:00
92b8406444 build(deps): update deps 2022-05-07 01:01:46 +08:00
e7ad08685e feat(projects): 引入echarts替换antvG2plot 2022-05-07 00:58:24 +08:00
14c145eef1 refactor(projects): 代码优化 2022-05-05 18:42:29 +08:00
518f7eed28 build(deps): update deps 2022-05-05 13:11:16 +08:00
21e63998d0 docs(projects): update README.md 2022-05-05 12:50:14 +08:00
38ee2a62cd Merge pull request #86 from dxxzst/patch-1
fix(projects): 修复插件不存在的错误提示
2022-05-04 21:14:17 +08:00
716528206e fix(projects): 修复插件不存在的错误提示
已经改成小写
2022-05-04 09:35:19 +08:00
b81143e55e Merge pull request #84 from tclyjy/main
refactor(layouts): layout/header 反转色样式补充
2022-04-29 20:59:59 +08:00
0243b27505 style(GlobalBreadcrumb): 代码格式fix 2022-04-29 19:19:10 +08:00
909c12d3c6 Merge pull request #83 from toolvcn/相思
feat(projects): 添加自动跟随系统主题设置
2022-04-29 17:56:27 +08:00
01d0bcbfd0 refactor(layouts): layout/header 反转色样式补充 2022-04-29 15:53:12 +08:00
ba07b695dd feat(projects): 添加自动跟随系统主题设置 2022-04-29 15:02:51 +08:00
3d8befa376 docs(projects): update README.md 2022-04-29 02:05:00 +08:00
97c92626cc chore(release): 0.9.4 2022-04-29 02:02:52 +08:00
55ddc9cab0 refactor(projects): 动态路由权限完善 2022-04-29 02:00:51 +08:00
401f0c748d build(projects): 细节调整 2022-04-28 01:02:41 +08:00
d5c751153c docs(projects): update README.md 2022-04-28 00:54:40 +08:00
69d51318ff refactor(projects): merge branch unocss to main 2022-04-28 00:50:22 +08:00
de5fb84215 refactor(projects): layout和tab组件依赖名称变更、样式修复 2022-04-27 22:51:28 +08:00
c275f2632c refactor(projects): 细节优化 2022-04-27 22:27:46 +08:00
e899914426 fix(projects): 修复样式 2022-04-27 19:31:40 +08:00
861c8b9852 feat(layouts): 添加侧边栏/头部的反转模式来增加对比度 2022-04-27 19:15:23 +08:00
a782461453 refactor(projects): 代码优化 2022-04-27 19:05:58 +08:00
e8488e4d52 fix(projects): 添加.npmrc修复无法获取自动引入的全局组件声明类型 2022-04-27 18:08:39 +08:00
889c859865 Merge pull request #82 from tclyjy/main
feat(layouts): 添加侧边栏/头部的反转模式来增加对比度
2022-04-27 16:46:09 +08:00
3c8dd772f8 feat(layouts): 添加侧边栏/头部的反转模式来增加对比度 2022-04-27 16:39:20 +08:00
251b5b9664 refactor(projects): 代码优化 2022-04-27 07:47:26 +08:00
41e46a5d80 refactor(projects): mock权限相关数据优化 2022-04-26 00:12:20 +08:00
5c75e9d958 build(deps): update deps 2022-04-24 00:23:45 +08:00
7f4350aeb6 feat(projects): mock添加权限过滤 2022-04-23 12:31:06 +08:00
807448aec5 feat(projects): 权限完善及权限示例页面 2022-04-23 02:21:02 +08:00
b9c5c34979 feat(projects): HTML lang 修改为 zh-cmn-Hans 2022-04-22 13:35:22 +08:00
20347b7d65 Merge pull request #79 from toolvcn/相思
feat(projects): HTML lang 修改为 zh-cmn-Hans
2022-04-22 13:31:11 +08:00
dbeb595c0b feat(projects): HTML lang 修改为 zh-cmn-Hans 2022-04-22 13:00:50 +08:00
c9d3e5a3fd feat(projects): 引入unocss替换windicss 2022-04-22 12:29:22 +08:00
5e276421ad refactor(projects): 代码优化 2022-04-22 09:07:53 +08:00
219f87f467 fix(projects): 添加获取路由组件文件未找到时的错误提示 2022-04-21 09:04:18 +08:00
b35ed8960d refactor(projects): 去除在pinia的getters的函数调用副作用,用watch代替 2022-04-21 00:46:03 +08:00
24010d05fb feat(projects): 登录页背景图片位置适配移动端 2022-04-21 00:26:21 +08:00
ec0776e268 feat(projects): 登录页面适配移动端 2022-04-21 00:15:34 +08:00
cecce83bc3 build(deps): update deps 2022-04-18 23:47:38 +08:00
4eb46ea3dd chore(deps): update deps 2022-04-14 00:02:19 +08:00
e8b534b84e refactor(projects): 代码优化 2022-04-13 23:45:15 +08:00
46e1ae7825 fix(projects): 修复获取vite环境变量的方式 2022-04-07 22:48:52 +08:00
60a55a776e docs(projects): update README.md 2022-04-06 14:34:52 +08:00
bed4292ed3 feat(projects): 添加请求适配器的请求示例 2022-04-04 19:13:15 +08:00
6bed9ead38 feat(projects): 插件方式按需引入naiveUI 2022-04-04 17:41:55 +08:00
3fb13ca9e7 fix(projects): 修复在新版vite下环境变量获取不到的问题 2022-04-04 17:30:26 +08:00
2d6d179d66 fix(projects): 去除从环境文件引入端口号导致的错误 2022-04-03 01:07:25 +08:00
eebb753884 Merge pull request #70 from yanbowe/main
fix(projects): 全局搜索弹窗弹出时动画闪屏问题
2022-04-02 14:13:39 +08:00
bb1bbf2724 fix(projects): 全局搜索弹窗弹出时动画闪屏问题 2022-04-02 10:35:21 +08:00
df56abe18d style(projects): update prettier config 2022-04-01 14:47:57 +08:00
ca2dfa6185 feat(projects): 新增静态路由 2022-03-30 01:30:12 +08:00
bbfdcc8276 Merge pull request #67 from Southliu/main
perf: refresh-koken命名
2022-03-24 15:59:00 +08:00
1715504789 perf: refresh-koken命名 2022-03-24 11:49:07 +08:00
9a90f18e77 docs(projects): update README.md 2022-03-23 15:21:09 +08:00
21645537d5 docs(projects): update README.md 2022-03-15 01:34:31 +08:00
e6c26fcb4a fix(projects): 修复路由守卫的动态路由逻辑 2022-03-14 15:16:28 +08:00
20911dd882 refactor(projects): lint命令修改 2022-03-13 19:42:01 +08:00
cd7ca8f4c7 fix(projects): 修复vite alias 2022-03-13 18:37:44 +08:00
ca707a456b build(projects): vite.config代码优化 2022-03-13 18:14:27 +08:00
d0522ce514 chore(release): 0.9.3 2022-03-12 21:22:49 +08:00
f83c7b59b8 feat(projects): 新增自定义svg图标动态渲染 2022-03-12 21:22:01 +08:00
f5a043b11a feat(projects): 添加全局组件自动引入注册 2022-03-12 19:56:58 +08:00
094dca961f feat(projects): 添加网络代理 2022-03-12 19:35:49 +08:00
8191490f39 feat(projects): 重构项目的TS类型架构,去除interface文件夹 2022-03-12 17:45:37 +08:00
75de2b0604 build(projects): update tsconfig、eslintrc 2022-03-12 16:21:40 +08:00
4093dcd6dc Merge pull request #62 from Imgodmaoyouknow/main
docs(other): 注释文案修改
2022-03-10 17:40:52 +08:00
d00643c9f5 docs(other): 注释文案修改 2022-03-10 17:07:06 +08:00
b8db2116df docs(projects): update README.md 2022-03-06 21:23:00 +08:00
a0dfa3d30d docs(projects): update README.md 2022-03-06 03:33:37 +08:00
4e31abd446 refactor(projects): 代码优化 2022-03-06 00:00:51 +08:00
f42ee9dbe5 build(projects): 更新tsconfig.json 2022-03-05 23:20:00 +08:00
f5c56c355c feat(projects): 新增子菜单图标和多页签图标 2022-03-05 05:37:40 +08:00
a1a57a185c feat(projects): 引入soybean-admin-tab、去除vite-plugin-svg-icons,用unplugin-icons实现自定义svg的iconify写法、代码优化 2022-03-05 05:00:26 +08:00
b298af1ddb build(deps): upgrade deps 2022-03-04 04:20:35 +08:00
43d685ccd3 Merge pull request #54 from pany-ang/main
fix(projects): 修复 BASE_URL 没有生效的问题
2022-03-03 16:26:44 +08:00
72d7dcfa5e fix(projects): 修复 BASE_URL 没有生效的问题 2022-03-03 12:01:14 +08:00
1e2fdda090 style(components): 代码优化 2022-03-03 00:35:44 +08:00
8d00b238f7 build(deps): upgrade deps 2022-03-03 00:11:04 +08:00
8cdad54236 docs(projects): update README.md 2022-03-01 12:07:13 +08:00
6298e61328 Merge pull request #52 from bundlejs/main
fix(projects): 修复页面切换动画开关不生效
2022-02-28 14:57:29 +08:00
9d4ed617fb fix(projects): 修复页面切换动画开关不生效 2022-02-28 13:50:52 +08:00
f92d7ecfbe Merge pull request #51 from Lsq128/main
feat(components): svgIcon,添加type,调整size方案
2022-02-27 08:45:59 +08:00
ce4e039f48 feat(components): svgIcon,添加type,调整size方案 2022-02-26 23:47:34 +08:00
1a9efee591 Merge pull request #48 from Lsq128/main
feat(projects): 添加SvgIcon,配置vite plugin
2022-02-25 21:58:03 +08:00
378d55ac0e feat(projects): 添加SvgIcon,配置vite plugin 2022-02-25 17:56:00 +08:00
50c8b9daa1 build(deps): upgrade deps 2022-02-25 11:06:48 +08:00
c4546bdfa3 fix(projects): 修复页面切换动画无变化 2022-02-25 10:57:05 +08:00
5b401a79ba docs(projects): update README.md 2022-02-24 17:30:48 +08:00
7add5c2edf fix(components): 组件LoadingEmptyWrapper添加背景颜色动画过渡 2022-02-23 21:44:32 +08:00
811b15e672 fix(components): 修复组件LoadingEmptyWrapper适应暗黑模式 2022-02-23 21:38:04 +08:00
c1182fef0a refactor(components): 去除packages的soybean-layout,通过npm的方式引入 2022-02-23 02:29:10 +08:00
7ba332cd6a build(deps): 升级依赖 2022-02-20 22:57:08 +08:00
a810ef85b1 feat(projects): 添加naiveUI按需引入 2022-02-17 01:01:17 +08:00
225e7128b6 docs(projects): update README.md 2022-02-16 19:28:49 +08:00
3aded40461 docs(projects): update README.md 2022-02-16 19:17:21 +08:00
57c692be74 build(deps): 升级依赖 2022-02-16 13:14:59 +08:00
284af63cfe build(deps): 升级依赖 2022-02-12 23:39:42 +08:00
e856cdb7b2 docs(projects): update README.md 2022-02-11 16:55:14 +08:00
114072277f chore(release): 0.9.2 2022-02-11 16:27:20 +08:00
e65034d946 refactor(projects): 重构路由页面组件的导入 2022-02-11 16:15:50 +08:00
a7a269d6a6 fix(projects): 修复项目配置拷贝功能 2022-02-07 23:22:55 +08:00
2c9660fdbf fix(components): 修复Tab在移动端设备无法点击的问题 2022-02-07 15:46:35 +08:00
e93b94cb24 fix(projects): 修复分析页和工作台的布局问题 2022-02-07 15:00:04 +08:00
3befb22903 docs(projects): update README.md 2022-02-07 09:17:27 +08:00
7ed5d0de2d docs(projects): update README.md 2022-02-07 09:16:18 +08:00
47f2871cb5 docs(projects): update README.md 2022-02-03 17:48:04 +08:00
852ddb64ad Merge pull request #37 from yanbowe/main
feat(projects): 迁移全局搜索菜单功能
2022-01-24 15:52:11 +08:00
7e1f9f1138 Merge branch 'honghuangdc:main' into main 2022-01-24 15:44:11 +08:00
554d7fd611 feat(projects): 迁移全局搜索菜单功能 2022-01-24 15:34:57 +08:00
1797f29a79 Merge pull request #36 from dxxzst/main
build(projects): update .eslintignore
2022-01-24 14:28:37 +08:00
50063187ec Update .eslintignore
add package.json to .eslintignore
2022-01-24 13:57:42 +08:00
b16721b2b7 build(projects): add license 2022-01-24 12:26:04 +08:00
facc00e8b4 fix(projects): vite配置修复 2022-01-24 11:30:08 +08:00
02c51e6fb9 docs(projects): update README.md 2022-01-24 01:28:35 +08:00
577 changed files with 31191 additions and 24717 deletions

View File

@ -1,45 +0,0 @@
module.exports = {
types: [
{ value: 'feat', name: 'feat: 新增功能' },
{ value: 'fix', name: 'fix: 修复bug' },
{ value: 'docs', name: 'docs: 文档变更' },
{ value: 'style', name: 'style: 代码格式(不影响功能,例如空格、分号等格式修正)' },
{ value: 'refactor', name: 'refactor: 代码重构(不包括 bug 修复、功能新增)' },
{ value: 'perf', name: 'perf: 性能优化' },
{ value: 'test', name: 'test: 添加、修改测试用例' },
{ value: 'build', name: 'build: 构建流程、外部依赖变更(如升级 npm 包、修改 脚手架 配置等)' },
{ value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
{ value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)' },
{ value: 'revert', name: 'revert: 回滚 commit' }
],
scopes: [
['projects', '项目搭建'],
['components', '组件相关'],
['hooks', 'hook 相关'],
['utils', 'utils 相关'],
['types', 'ts类型相关'],
['styles', '样式相关'],
['deps', '项目依赖'],
['auth', '对 auth 修改'],
['other', '其他修改'],
['custom', '以上都不是?我要自定义']
].map(([value, description]) => {
return {
value,
name: `${value.padEnd(30)} (${description})`
}
}),
messages: {
type: '确保本次提交遵循 Angular 规范!\n选择你要提交的类型',
scope: '\n选择一个 scope可选',
customScope: '请输入自定义的 scope',
subject: '填写简短精炼的变更描述:\n',
body: '填写更加详细的变更描述(可选)。使用 "|" 换行:\n',
breaking: '列举非兼容性重大的变更(可选):\n',
footer: '列举出所有变更的 ISSUES CLOSED可选。 例如: #31, #34\n',
confirmCommit: '确认提交?'
},
allowBreakingChanges: ['feat', 'fix'],
subjectLimit: 100,
breaklineChar: '|'
}

View File

@ -1,12 +1,11 @@
# Editor configuration, see http://editorconfig.org
# 表示是最顶层的 EditorConfig 配置文件
root = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = tab # 缩进风格tab | space
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true

43
.env
View File

@ -1,7 +1,42 @@
BASE_URL=/
VITE_BASE_URL=/
VITE_APP_NAME=SoybeanAdmin
VITE_APP_TITLE=SoybeanAdmin
VITE_APP_TITLE=Soybean管理系统
VITE_APP_DESC=SoybeanAdmin is a fresh and elegant admin template
VITE_APP_DESC=SoybeanAdmin是一个中后台管理系统模版
# the prefix of the icon name
VITE_ICON_PREFIX=icon
# the prefix of the local svg icon component, must include VITE_ICON_PREFIX
# format {VITE_ICON_PREFIX}-{local icon name}
VITE_ICON_LOCAL_PREFIX=icon-local
# auth route mode: static dynamic
VITE_AUTH_ROUTE_MODE=static
# static auth route home
VITE_ROUTE_HOME=home
# default menu icon
VITE_MENU_ICON=mdi:menu
# whether to enable http proxy when is dev mode
VITE_HTTP_PROXY=Y
# vue-router mode: hash | history | memory
VITE_ROUTER_HISTORY_MODE=history
# success code of backend service, when the code is received, the request is successful
VITE_SERVICE_SUCCESS_CODE=0000
# logout codes of backend service, when the code is received, the user will be logged out and redirected to login page
VITE_SERVICE_LOGOUT_CODES=8888,8889
# modal logout codes of backend service, when the code is received, the user will be logged out by displaying a modal
VITE_SERVICE_MODAL_LOGOUT_CODES=7777,7778
# token expired codes of backend service, when the code is received, it will refresh the token and resend the request
VITE_SERVICE_EXPIRED_TOKEN_CODES=9999,9998
# when the route mode is static, the defined super role
VITE_STATIC_SUPER_ROLE=R_SUPER

View File

@ -1,22 +0,0 @@
/** 请求环境配置 */
type ServiceEnv = Record<
Service.HttpEnv,
{
/** 请求环境 */
env: Service.HttpEnv;
/** 请求地址 */
url: string;
}
>;
/** 请求的环境 */
export const serviceEnv: ServiceEnv = {
test: {
env: 'test',
url: 'http://120.76.42.91:18888'
},
prod: {
env: 'prod',
url: 'http://120.76.42.91:18888'
}
};

7
.env.prod Normal file
View File

@ -0,0 +1,7 @@
# backend service base url, prod environment
VITE_SERVICE_BASE_URL=https://mock.apifox.com/m1/3109515-0-default
# other backend service base url, prod environment
VITE_OTHER_SERVICE_BASE_URL= `{
"demo": "http://localhost:9529"
}`

7
.env.test Normal file
View File

@ -0,0 +1,7 @@
# backend service base url, test environment
VITE_SERVICE_BASE_URL=https://mock.apifox.com/m1/3109515-0-default
# other backend service base url, test environment
VITE_OTHER_SERVICE_BASE_URL= `{
"demo": "http://localhost:9528"
}`

View File

@ -1,14 +0,0 @@
*.sh
node_modules
lib
*.md
*.woff
*.ttf
.vscode
.idea
/dist/
/public
/docs
.vscode
.local
!.env-config.ts

View File

@ -1,162 +0,0 @@
module.exports = {
env: {
browser: true,
es2021: true
},
globals: {
defineProps: 'readonly',
defineEmits: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly',
PROJECT_BUILD_TIME: 'readonly',
AMap: 'readonly',
BMap: 'readonly',
TMap: 'readonly'
},
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 12,
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
plugins: ['vue', '@typescript-eslint'],
extends: ['plugin:vue/vue3-recommended', 'airbnb-base', '@vue/typescript/recommended', 'plugin:prettier/recommended'],
rules: {
'import/extensions': 'off',
'import/no-extraneous-dependencies': 'off',
'import/no-unresolved': 0,
'import/order': [
'error',
{
'newlines-between': 'never',
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
pathGroups: [
{
pattern: 'vue',
group: 'external',
position: 'before'
},
{
pattern: 'vue-router',
group: 'external',
position: 'before'
},
{
pattern: 'pinia',
group: 'external',
position: 'before'
},
{
pattern: 'naive-ui',
group: 'external',
position: 'before'
},
{
pattern: '@/config',
group: 'internal',
position: 'before'
},
{
pattern: '@/settings',
group: 'internal',
position: 'before'
},
{
pattern: '@/enum',
group: 'internal',
position: 'before'
},
{
pattern: '@/plugins',
group: 'internal',
position: 'before'
},
{
pattern: '@/layouts',
group: 'internal',
position: 'before'
},
{
pattern: '@/layouts',
group: 'internal',
position: 'before'
},
{
pattern: '@/views',
group: 'internal',
position: 'before'
},
{
pattern: '@/components',
group: 'internal',
position: 'before'
},
{
pattern: '@/router',
group: 'internal',
position: 'before'
},
{
pattern: '@/store',
group: 'internal',
position: 'before'
},
{
pattern: '@/composables',
group: 'internal',
position: 'before'
},
{
pattern: '@/hooks',
group: 'internal',
position: 'before'
},
{
pattern: '@/service',
group: 'internal',
position: 'before'
},
{
pattern: '@/utils',
group: 'internal',
position: 'before'
},
{
pattern: '@/assets',
group: 'internal',
position: 'before'
},
{
pattern: '@/**',
group: 'internal',
position: 'before'
},
{
pattern: '@/interface',
group: 'internal',
position: 'before'
}
],
pathGroupsExcludedImportTypes: ['vue', 'vue-router', 'pinia', 'naive-ui']
}
],
'import/prefer-default-export': 0,
'max-classes-per-file': 0,
'no-shadow': 0,
'no-unused-vars': 'off',
'no-use-before-define': 'off',
'vue/comment-directive': 0,
'vue/multi-word-component-names': 0,
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-inferrable-types': 0,
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { ignoreRestSiblings: true, varsIgnorePattern: 'Ignored' }],
'@typescript-eslint/no-use-before-define': ['error', { classes: true, functions: false, typedefs: false }],
'@typescript-eslint/no-var-requires': 'off'
}
};

13
.gitattributes vendored Normal file
View File

@ -0,0 +1,13 @@
"*.vue" eol=lf
"*.js" eol=lf
"*.ts" eol=lf
"*.jsx" eol=lf
"*.tsx" eol=lf
"*.mjs" eol=lf
"*.json" eol=lf
"*.html" eol=lf
"*.css" eol=lf
"*.scss" eol=lf
"*.md" eol=lf
"*.yaml" eol=lf
"*.yml" eol=lf

View File

@ -0,0 +1,90 @@
name: Bug提交
description: 在使用软件或功能的过程中遇到了错误
title: '[Bug]: '
labels: [ "bug?" ]
body:
- type: markdown
attributes:
value: |
## 请按照以下要求进行提交
### 1. 提交后需要指定标签和截止时间。
---
- type: markdown
attributes:
value: |
## 环境信息
请根据实际使用环境修改以下信息。
- type: input
id: env-program-ver
attributes:
label: 软件版本
validations:
required: true
- type: dropdown
id: env-vm-ver
attributes:
label: 运行环境
description: 选择运行软件的系统版本
options:
- Windows (64)
- Windows (32/x84)
- MacOS
- Linux
- Ubuntu
- CentOS
- ArchLinux
- UNIX (Android)
- 其它(请在下方说明)
validations:
required: true
- type: dropdown
id: env-vm-arch
attributes:
label: 运行架构
description: (可选) 选择运行软件的系统架构
options:
- AMD64
- x86
- ARM [32] (别名AArch32 / ARMv7
- ARM [64] (别名AArch64 / ARMv8
- 其它
- type: textarea
id: reproduce-steps
attributes:
label: 重现步骤
description: |
我们需要执行哪些操作才能让 bug 出现?
简洁清晰的重现步骤能够帮助我们更迅速地定位问题所在。
validations:
required: true
- type: textarea
id: expected
attributes:
label: 期望的结果是什么?
validations:
required: true
- type: textarea
id: actual
attributes:
label: 实际的结果是什么?
validations:
required: true
- type: textarea
id: logging
attributes:
label: 日志记录(可选)
render: golang
- type: textarea
id: extra-desc
attributes:
label: 补充说明(可选)

View File

@ -0,0 +1,90 @@
name: Bug Report
description: Encountered an error while using the software or feature
title: '[Bug]: '
labels: [ "bug?" ]
body:
- type: markdown
attributes:
value: |
## Please submit according to the following requirements
### 1. After submission, you need to specify the label and deadline.
---
- type: markdown
attributes:
value: |
## Environment Information
Please modify the following information according to the actual usage environment.
- type: input
id: env-program-ver
attributes:
label: Software Version
validations:
required: true
- type: dropdown
id: env-vm-ver
attributes:
label: Operating Environment
description: Select the system version on which the software is running
options:
- Windows (64)
- Windows (32/x84)
- MacOS
- Linux
- Ubuntu
- CentOS
- ArchLinux
- UNIX (Android)
- Other (please specify below)
validations:
required: true
- type: dropdown
id: env-vm-arch
attributes:
label: Operating Architecture
description: (Optional) Select the system architecture on which the software is running
options:
- AMD64
- x86
- ARM [32] (AliasAArch32 / ARMv7
- ARM [64] (AliasAArch64 / ARMv8
- Other
- type: textarea
id: reproduce-steps
attributes:
label: Reproduce Steps
description: |
What operations do we need to perform to make the bug appear?
The concise and clear reproduction steps can help us locate the problem more quickly.
validations:
required: true
- type: textarea
id: expected
attributes:
label: What is the expected result?
validations:
required: true
- type: textarea
id: actual
attributes:
label: What is the actual result?
validations:
required: true
- type: textarea
id: logging
attributes:
label: Logging (Optional)
render: golang
- type: textarea
id: extra-desc
attributes:
label: Additional Description (Optional)

50
.github/PULL_REQUEST_TEMPLATE/pr_cn.md vendored Normal file
View File

@ -0,0 +1,50 @@
首先,感谢你的贡献! 😄
新特性请提交至 feature 分支,其余可提交至 main 分支。在一个维护者审核通过后合并。请确保填写以下 pull request 的信息,谢谢!~
[[English Template / 英文模板](./pr_en.md)]
### 这个变动的性质是
- [ ] 新特性提交
- [ ] 日常 bug 修复
- [ ] 站点、文档改进
- [ ] 组件样式改进
- [ ] TypeScript 定义更新
- [ ] 重构
- [ ] 代码风格优化
- [ ] 分支合并
- [ ] 其他改动(是关于什么的改动?)
### 需求背景
> 1. 描述相关需求的来源。
> 2. 要解决的问题。
> 3. 相关的 issue 讨论链接。
### 实现方案和 API非新功能可选
> 1. 基本的解决思路和其他可选方案。
> 2. 列出最终的 API 实现和用法。
> 3. 涉及 UI/交互变动需要有截图或 GIF。
### 对用户的影响和可能的风险(非新功能可选)
> 1. 这个改动对用户端是否有影响?影响的方面有哪些?
> 2. 是否有可能隐含的 break change 和其他风险?
### Changelog 描述(非新功能可选)
> 1. 英文描述
> 2. 中文描述(可选)
### 请求合并前的自查清单
- [ ] 文档已补充或无须补充
- [ ] 代码演示已提供或无须提供
- [ ] TypeScript 定义已补充或无须补充
- [ ] Changelog 已提供或无须提供
### 后续计划(非新功能可选)
> 如果这个提交后面还有相关的其他提交和跟进信息,可以写在这里。

51
.github/PULL_REQUEST_TEMPLATE/pr_en.md vendored Normal file
View File

@ -0,0 +1,51 @@
First of all, thank you for your contribution! 😄
New feature please send pull request to feature branch, and rest to main branch. Pull request will be merged after one of collaborators approve. Please makes sure that these form are filled before submitting your pull request, thank you!
[[中文版模板 / Chinese template](./pr_cn.md)]
### This is a ...
- [ ] New feature
- [ ] Bug fix
- [ ] Site / document update
- [ ] Component style update
- [ ] TypeScript definition update
- [ ] Refactoring
- [ ] Code style optimization
- [ ] Branch merge
- [ ] Other (about what?)
### What's the background?
> 1. Describe the source of requirement.
> 2. Resolve what problem.
> 3. Related issue link.
### API Realization (Optional if not new feature)
> 1. Basic thought of solution and other optional proposal.
> 2. List final API realization and usage sample.
> 3. GIF or snapshot should be provided if includes UI/interactive modification.
### What's the effect? (Optional if not new feature)
> 1. Does this PR affect user? Which part will be affected?
> 2. What will say in changelog?
> 3. Does this PR contains potential break change or other risk?
### Changelog description (Optional if not new feature)
> 1. English description
> 2. Chinese description (optional)
### Self Check before Merge
- [ ] Doc is updated/provided or not needed
- [ ] Demo is updated/provided or not needed
- [ ] TypeScript definition is updated/provided or not needed
- [ ] Changelog is provided or not needed
### Additional Plan? (Optional if not new feature)
> If this PR related with other PR or following info. You can type here.

30
.github/workflows/linter.yml vendored Normal file
View File

@ -0,0 +1,30 @@
---
name: Lint Code
permissions:
contents: write
on:
pull_request:
branches: [main]
jobs:
lint:
name: Lint All Code
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Lint Code Base
uses: github/super-linter@v4
env:
VALIDATE_ALL_CODEBASE: false
DEFAULT_BRANCH: main
# To change branch master or main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FILTER_REGEX_EXCLUDE: (docs|.github)
VALIDATE_MARKDOWN: false

25
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Release
permissions:
contents: write
on:
push:
tags:
- "v*"
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 18.x
- run: npx githublogen
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

10
.gitignore vendored
View File

@ -11,12 +11,17 @@ node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
!.vscode/launch.json
.idea
*.suo
*.ntvs*
@ -24,4 +29,7 @@ dist-ssr
*.sln
*.sw?
stats.html
package-lock.json
yarn.lock
.VSCodeCounter

View File

@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit

View File

@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm lint && pnpm typecheck

3
.npmrc Normal file
View File

@ -0,0 +1,3 @@
registry=https://registry.npmmirror.com/
shamefully-hoist=true
ignore-workspace-root-check=true

View File

@ -1,27 +0,0 @@
module.exports = {
printWidth: 120, // 超过最大值换行
tabWidth: 2, // 缩进字节数
useTabs: false, // 缩进使用tab不使用空格
semi: true, // 句尾添加分号
singleQuote: true, // 使用单引号代替双引号
proseWrap: 'preserve', // 默认值。因为使用了一些折行敏感型的渲染器如GitHub comment而按照markdown文本样式进行折行
arrowParens: 'avoid', // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid省略括号
bracketSpacing: true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
endOfLine: 'auto', // 结尾是 \n \r \n\r auto
eslintIntegration: false, //不让prettier使用eslint的代码格式进行校验
htmlWhitespaceSensitivity: 'ignore', // 指定HTML文件的全局空白区域敏感度 有效选项:"css"- 遵守CSS display属性的默认值。"strict" - 空格被认为是敏感的。"ignore" - 空格被认为是不敏感的。html 中空格也会占位影响布局prettier 格式化的时候可能会将文本换行,造成布局错乱
ignorePath: '.prettierignore', // 不使用prettier格式化的文件填写在项目的.prettierignore文件中
jsxSingleQuote: false, // 在jsx中使用单引号代替双引号
requireConfig: false, // Require a 'prettierconfig' to format prettier
stylelintIntegration: false, //不让prettier使用stylelint的代码格式进行校验
trailingComma: 'none', // 在对象或数组最后一个元素后面是否加逗号在ES5中加尾逗号
tslintIntegration: false, // 不让prettier使用tslint的代码格式进行校验
overrides: [
{
files: '*.html',
options: {
parser: 'html'
}
}
]
};

View File

@ -1,35 +1,22 @@
{
"recommendations": [
"formulahendry.auto-close-tag",
"formulahendry.auto-complete-tag",
"steoates.autoimport",
"formulahendry.auto-rename-tag",
"coenraads.bracket-pair-colorizer-2",
"naumovs.color-highlight",
"pranaygp.vscode-css-peek",
"mikestead.dotenv",
"editorconfig.editorconfig",
"dsznajder.es7-react-js-snippets",
"dbaeumer.vscode-eslint",
"miguelsolorio.fluent-icons",
"mhutchie.git-graph",
"eamodio.gitlens",
"lokalise.i18n-ally",
"afzalsayed96.icones",
"antfu.iconify",
"kisstkondoros.vscode-gutter-preview",
"xabikos.javascriptsnippets",
"whtouche.vscode-js-console-utils",
"ritwickdey.liveserver",
"yzhang.markdown-all-in-one",
"pkief.material-icon-theme",
"zhuangtongfa.material-theme",
"christian-kohler.path-intellisense",
"esbenp.prettier-vscode",
"johnsoncodehk.volar",
"johnsoncodehk.vscode-typescript-vue-plugin",
"dariofuzinato.vue-peek",
"wscats.vue",
"voorjaar.windicss-intellisense"
]
"recommendations": [
"afzalsayed96.icones",
"antfu.iconify",
"antfu.unocss",
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"esbenp.prettier-vscode",
"formulahendry.auto-close-tag",
"formulahendry.auto-complete-tag",
"formulahendry.auto-rename-tag",
"lokalise.i18n-ally",
"mhutchie.git-graph",
"mikestead.dotenv",
"naumovs.color-highlight",
"pkief.material-icon-theme",
"sdras.vue-vscode-snippets",
"vue.volar",
"whtouche.vscode-js-console-utils",
"zhuangtongfa.material-theme"
]
}

20
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Vue Debugger",
"url": "http://localhost:9527",
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "TS Debugger",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/tsx",
"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/**"],
"program": "${file}"
}
]
}

89
.vscode/settings.json vendored
View File

@ -1,74 +1,19 @@
{
"editor.quickSuggestions": {
"strings": true
},
"workbench.iconTheme": "material-icon-theme",
"workbench.colorTheme": "One Dark Pro",
"editor.tabSize": 2,
"editor.fontLigatures": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": "active",
"git.enableSmartCommit": true,
"path-intellisense.mappings": {
"@": "${workspaceFolder}/src",
"~@": "${workspaceFolder}/src",
},
"gutterpreview.paths": {
"@": "/src",
"~@": "/src"
},
"terminal.integrated.cursorStyle": "line",
"files.associations": {
"*.env.*": "dotenv"
},
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"javascript.updateImportsOnFileMove.enabled": "always",
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"terminal.integrated.fontSize": 14,
"terminal.integrated.fontWeight": 500,
"i18n-ally.displayLanguage": "zh",
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "johnsoncodehk.volar"
},
"terminal.integrated.tabs.enabled": true,
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "yzhang.markdown-all-in-one"
},
"vue3snippets.enable-compile-vue-file-on-did-save-code": false,
"editor.formatOnSave": false,
"material-icon-theme.activeIconPack": "angular",
"material-icon-theme.files.associations": {},
"material-icon-theme.folders.associations": {
"enum": "typescript",
"enums": "typescript",
"store": "context",
"stores": "context",
"composable": "hook",
"composables": "hook",
"directive": "tools",
"directives": "tools",
"business": "core"
}
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
},
"eslint.experimental.useFlatConfig": true,
"editor.formatOnSave": false,
"eslint.validate": ["html", "css", "scss", "json", "jsonc"],
"i18n-ally.displayLanguage": "zh-cn",
"i18n-ally.enabledParsers": ["ts"],
"i18n-ally.enabledFrameworks": ["vue"],
"i18n-ally.editor.preferEditor": true,
"i18n-ally.keystyle": "nested",
"i18n-ally.localesPaths": ["src/locales/langs"],
"prettier.enable": false,
"unocss.root": ["./"],
"typescript.tsdk": "node_modules/typescript/lib",
"vue.server.hybridMode": true
}

File diff suppressed because it is too large Load Diff

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Soybean
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

163
README.md
View File

@ -1,125 +1,164 @@
<div align="center">
<img src="https://i.loli.net/2021/11/24/x5lLfuSnEawBAgi.png"/>
<img src="./public/favicon.svg" width="160" />
<h1>Soybean Admin</h1>
<span>English | <a href="./README.zh_CN.md">中文</a></span>
</div>
---
[![license](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
[![github stars](https://img.shields.io/github/stars/soybeanjs/soybean-admin)](https://github.com/soybeanjs/soybean-admin)
[![github forks](https://img.shields.io/github/forks/soybeanjs/soybean-admin)](https://github.com/soybeanjs/soybean-admin)
[![gitee stars](https://gitee.com/honghuangdc/soybean-admin/badge/star.svg)](https://gitee.com/honghuangdc/soybean-admin)
## 简介
> [!NOTE]
> If you think `Soybean Admin` is helpful to you, or you like our project, please give us a ⭐️ on GitHub. Your support is the driving force for us to continue to improve and add new features! Thank you for your support!
Soybean Admin 是一个基于 Vue3、Vite、TypeScript、Naive UI 的免费中后台模版它使用了最新的前端技术栈内置丰富的主题配置有着极高的代码规范基于mock实现的动态权限路由开箱即用的中后台前端解决方案也可用于学习参考。
## Introduction
## 特性
[`Soybean Admin`](https://github.com/soybeanjs/soybean-admin) is a clean, elegant, beautiful and powerful admin template, based on the latest front-end technology stack, including Vue3, Vite5, TypeScript, Pinia and UnoCSS. It has built-in rich theme configuration and components, strict code specifications, and an automated file routing system. In addition, it also uses the online mock data solution based on ApiFox. `Soybean Admin` provides you with a one-stop admin solution, no additional configuration, and out of the box. It is also a best practice for learning cutting-edge technologies quickly.
- **最新技术栈**:使用 Vue3/vite2 等前端前沿技术开发, 使用高效率的npm包管理器pnpm
- **TypeScript**: 应用程序级 JavaScript 的语言
- **主题**丰富可配置的主题、暗黑模式基于windicss的动态主题颜色
- **代码规范**:丰富的规范插件及极高的代码规范
- **权限路由**简易的路由配置、基于mock的动态路由能快速实现后端动态路由
- **请求函数**完善的请求函数封装提供Promise和hooks两种请求函数
## 预览
## Features
- [soybean-admin](https://soybean.pro/)
- **Cutting-edge technology application**: using the latest popular technology stack such as Vue3, Vite5, TypeScript, Pinia and UnoCSS.
- **Clear project architecture**: using pnpm monorepo architecture, clear structure, elegant and easy to understand.
- **Strict code specifications**: follow the [SoybeanJS specification](https://docs.soybeanjs.cn/standard), integrate eslint, prettier and simple-git-hooks to ensure the code is standardized.
- **TypeScript**: support strict type checking to improve code maintainability.
- **Rich theme configuration**: built-in a variety of theme configurations, perfectly integrated with UnoCSS.
- **Built-in internationalization solution**: easily realize multi-language support.
- **Automated file routing system**: automatically generate route import, declaration and type. For more details, please refer to [Elegant Router](https://github.com/soybeanjs/elegant-router).
- **Flexible permission routing**: support both front-end static routing and back-end dynamic routing.
- **Rich page components**: built-in a variety of pages and components, including 403, 404, 500 pages, as well as layout components, tag components, theme configuration components, etc.
- **Command line tool**: built-in efficient command line tool, git commit, delete file, release, etc.
- **Mobile adaptation**: perfectly support mobile terminal to realize adaptive layout.
## 文档
- [项目文档](https://docs.soybean.pro)
## Version
### 代码仓库
- **NaiveUI Version:**
- [Preview Link](https://naive.soybeanjs.cn/)
- [Github Repository](https://github.com/soybeanjs/soybean-admin)
- [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin)
- [github](https://github.com/honghuangdc/soybean-admin)
- **AntDesignVue Version:**
- [Preview Link](https://antd.soybeanjs.cn/)
- [Github Repository](https://github.com/soybeanjs/soybean-admin-antd)
- [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin-antd)
- [gitee](https://gitee.com/honghuangdc/soybean-admin)
- **Legacy Version:**
- [Preview Link](https://legacy.soybeanjs.cn/)
- [Github Repository](https://github.com/soybeanjs/soybean-admin/tree/legacy)
## 项目示例图
![](https://s2.loli.net/2022/01/24/ovK6Oyqr7gIMu2n.png)
![](https://s2.loli.net/2022/01/24/O8loxYhMySHwGfJ.png)
## Documentation
![](https://s2.loli.net/2022/01/24/HKwpJ7Ab6j8fVvk.png)
- [Link](https://docs.soybeanjs.cn)
- [Legacy Docs](https://legacy-docs.soybeanjs.cn)
![](https://s2.loli.net/2022/01/24/bqJRSDZHBv3jsif.png)
## Example Images
![](https://s2.loli.net/2022/01/24/wXpHeau6UrSTWdF.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-01.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-02.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-03.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-04.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-05.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-06.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-07.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-08.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-09.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-10.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-mobile.png)
### 使用 Gitpod
在 Gitpod适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码.
## Usage
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/honghuangdc/soybean-admin)
**Environment Preparation**
## 安装使用
Make sure your environment meets the following requirements:
- 克隆代码
- **git**: you need git to clone and manage project versions.
- **NodeJS**: >=18.0.0, recommended 18.19.0 or higher.
- **pnpm**: >= 8.0.0, recommended 8.14.0 or higher.
**Clone Project**
```bash
git clone https://github.com/honghuangdc/soybean-admin.git
git clone https://github.com/soybeanjs/soybean-admin.git
```
- 安装依赖
**Install Dependencies**
```bash
pnpm i
```
> Since this project uses the pnpm monorepo management method, please do not use npm or yarn to install dependencies.
- 运行
**Start Project**
```bash
pnpm dev
```
- 打包
**Build Project**
```bash
pnpm build
```
## 如何贡献
## How to Contribute
非常欢迎您的加入![提一个 Issue](https://github.com/honghuangdc/soybean-admin/issues/new) 或者提交一个 Pull Request。
We warmly welcome and appreciate all forms of contributions. If you have any ideas or suggestions, please feel free to share them by submitting [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) or creating GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new).
## Git 贡献提交规范
## Git Commit Guidelines
项目已经内置angular提交规范通过git cz 代替git commit 命令即可。
This project has built-in `commit` command, you can execute `pnpm commit` to generate commit information that conforms to [Conventional Commits](https://www.conventionalcommits.org/) specification. When submitting PR, please be sure to use `commit` command to create commit information to ensure the standardization of information.
git cz命令需要全局安装 commitizen
## Browser Support
```bash
pnpm i -g commitizen
```
It is recommended to use the latest version of Chrome in development for a better experience.
## 浏览器支持
本地开发推荐使用`Chrome 90+` 浏览器
支持现代浏览器, 不支持 IE
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="IE" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)Safari |
| :-: | :-: | :-: | :-: | :-: |
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="IE" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) |
| --- | --- | --- | --- | --- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 开源作者
## OpenSource Author
[@Soybean](https://github.com/honghuangdc)
[Soybean](https://github.com/honghuangdc)
## 交流
## Contributors
`Soybean Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供 QQ 交流群使用问题欢迎在群内提问。
Thanks the following people for their contributions. If you want to contribute to this project, please refer to [How to Contribute](#how-to-contribute).
- 微信交流群:
<div style="text-align:left">
<img src="https://s2.loli.net/2022/01/24/uX8KaGt7W2jbw6V.jpg" style="width:200px" />
<a href="https://github.com/soybeanjs/soybean-admin/graphs/contributors">
<img src="https://contrib.rocks/image?repo=soybeanjs/soybean-admin" />
</a>
## Communication
`Soybean Admin` is a completely open source and free project, helping developers to develop medium and large-scale management systems more conveniently. It also provides WeChat and QQ communication groups. If you have any questions, please feel free to ask in the group.
<div>
<p>QQ Group</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-2.jpg" style="width:200px" />
</div>
<!-- <div>
<p>WeChat Group</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/wechat-0402.jpg" style="width:200px" />
</div> -->
<div>
<p>Add the following WeChat to invite to the WeChat group</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/wechat-soybeanjs.jpg" style="width:200px" />
</div>
<div>
<p>Add Soybean's WeChat for business consultation, cooperation, project architecture, one-on-one guidance, etc.</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/wechat-soybean.jpg" style="width:200px" />
</div>
- QQ 群 `711301266`
## Star Trend
<div style="text-align:left">
<img src="https://i.loli.net/2021/11/24/1J6REWXiHomU2kM.jpg" style="width:200px" />
</div>
- 本人微信号honghuangdc欢迎来技术交流业务咨询。
[![Star History Chart](https://api.star-history.com/svg?repos=soybeanjs/soybean-admin&type=Date)](https://star-history.com/#soybeanjs/soybean-admin&Date)
## License
[MIT © Soybean-2021](./LICENSE)
This project is based on the [MIT © 2021 Soybean](./LICENSE) protocol, for learning purposes only, please retain the author's copyright information for commercial use, the author does not guarantee and is not responsible for the software.

164
README.zh_CN.md Normal file
View File

@ -0,0 +1,164 @@
<div align="center">
<img src="./public/favicon.svg" width="160" />
<h1>Soybean Admin</h1>
<span><a href="./README.zh_CN.md">English</a> | 中文</span>
</div>
---
[![license](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
[![github stars](https://img.shields.io/github/stars/honghuangdc/soybean-admin)](https://github.com/soybeanjs/soybean-admin)
[![github forks](https://img.shields.io/github/forks/honghuangdc/soybean-admin)](https://github.com/soybeanjs/soybean-admin)
[![gitee stars](https://gitee.com/honghuangdc/soybean-admin/badge/star.svg)](https://gitee.com/honghuangdc/soybean-admin)
> [!NOTE]
> 如果您觉得 `Soybean Admin`对您有所帮助,或者您喜欢我们的项目,请在 GitHub 上给我们一个 ⭐️。您的支持是我们持续改进和增加新功能的动力!感谢您的支持!
## 简介
[`Soybean Admin`](https://github.com/soybeanjs/soybean-admin) 是一个清新优雅、高颜值且功能强大的后台管理模板,基于最新的前端技术栈,包括 Vue3, Vite5, TypeScript, Pinia 和 UnoCSS。它内置了丰富的主题配置和组件代码规范严谨实现了自动化的文件路由系统。此外它还采用了基于 ApiFox 的在线Mock数据方案。`Soybean Admin` 为您提供了一站式的后台管理解决方案,无需额外配置,开箱即用。同样是一个快速学习前沿技术的最佳实践。
## 特性
- **前沿技术应用**:采用 Vue3, Vite5, TypeScript, Pinia 和 UnoCSS 等最新流行的技术栈。
- **清晰的项目架构**:采用 pnpm monorepo 架构,结构清晰,优雅易懂。
- **严格的代码规范**:遵循 [SoybeanJS 规范](https://docs.soybeanjs.cn/zh/standard)集成了eslint, prettier 和 simple-git-hooks保证代码的规范性。
- **TypeScript** 支持严格的类型检查,提高代码的可维护性。
- **丰富的主题配置**:内置多样的主题配置,与 UnoCSS 完美结合。
- **内置国际化方案**:轻松实现多语言支持。
- **自动化文件路由系统**:自动生成路由导入、声明和类型。更多细节请查看 [Elegant Router](https://github.com/soybeanjs/elegant-router)。
- **灵活的权限路由**:同时支持前端静态路由和后端动态路由。
- **丰富的页面组件**内置多样页面和组件包括403、404、500页面以及布局组件、标签组件、主题配置组件等。
- **命令行工具**内置高效的命令行工具git提交、删除文件、发布等。
- **移动端适配**:完美支持移动端,实现自适应布局。
## 版本
- **NaiveUI 版本:**
- [预览地址](https://naive.soybeanjs.cn/)
- [Github 仓库](https://github.com/soybeanjs/soybean-admin)
- [Gitee 仓库](https://gitee.com/honghuangdc/soybean-admin)
- **AntDesignVue 版本:**
- [预览地址](https://antd.soybeanjs.cn/)
- [Github 仓库](https://github.com/soybeanjs/soybean-admin-antd)
- [Gitee 仓库](https://gitee.com/honghuangdc/soybean-admin-antd)
- **旧版:**
- [预览地址](https://legacy.soybeanjs.cn/)
- [Github 仓库](https://github.com/soybeanjs/soybean-admin/tree/legacy)
## 文档
- [地址](https://docs.soybeanjs.cn)
- [旧版文档](https://legacy-docs.soybeanjs.cn)
## 示例图片
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-01.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-02.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-03.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-04.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-05.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-06.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-07.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-08.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-09.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-10.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-mobile.png)
## 使用
**环境准备**
确保你的环境满足以下要求:
- **git**: 你需要git来克隆和管理项目版本。
- **NodeJS**: >=18.0.0,推荐 18.19.0 或更高。
- **pnpm**: >= 8.0.0,推荐 8.14.0 或更高。
**克隆项目**
```bash
git clone https://github.com/soybeanjs/soybean-admin.git
```
**安装依赖**
```bash
pnpm i
```
> 由于本项目采用了 pnpm monorepo 的管理方式,因此请不要使用 npm 或 yarn 来安装依赖。
**启动项目**
```bash
pnpm dev
```
**构建项目**
```bash
pnpm build
```
## 如何贡献
我们热烈欢迎并感谢所有形式的贡献。如果您有任何想法或建议,欢迎通过提交 [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) 或创建 GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new) 来分享。
## Git 提交规范
本项目已内置 `commit` 命令,您可以通过执行 `pnpm commit` 来生成符合 [Conventional Commits]([conventionalcommits](https://www.conventionalcommits.org/)) 规范的提交信息。在提交PR时请务必使用 `commit` 命令来创建提交信息,以确保信息的规范性。
## 浏览器支持
推荐使用最新版的 Chrome 浏览器进行开发,以获得更好的体验。
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="IE" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) |
| --- | --- | --- | --- | --- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 开源作者
[Soybean](https://github.com/honghuangdc)
## 贡献者
感谢以下贡献者的贡献。如果您想为本项目做出贡献,请参考 [如何贡献](#如何贡献)。
<a href="https://github.com/soybeanjs/soybean-admin/graphs/contributors">
<img src="https://contrib.rocks/image?repo=soybeanjs/soybean-admin" />
</a>
## 交流
`Soybean Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供微信和 QQ 交流群,使用问题欢迎在群内提问。
<div>
<p>QQ交流群</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-2.jpg" style="width:200px" />
</div>
<!-- <div>
<p>微信群</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/wechat-0402.jpg" style="width:200px" />
</div> -->
<div>
<p>添加下面微信邀请进微信群</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/wechat-soybeanjs.jpg" style="width:200px" />
</div>
<div>
<p>添加 Soybean 的微信,业务咨询、合作、项目架构、一对一指导等</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/wechat-soybean.jpg" style="width:200px" />
</div>
## Star 趋势
[![Star History Chart](https://api.star-history.com/svg?repos=soybeanjs/soybean-admin&type=Date)](https://star-history.com/#soybeanjs/soybean-admin&Date)
## 开源协议
项目基于 [MIT © 2021 Soybean](./LICENSE) 协议,仅供学习参考,商业使用请保留作者版权信息,作者不保证也不承担任何软件的使用风险。

1
build/config/index.ts Normal file
View File

@ -0,0 +1 @@
export * from './proxy';

36
build/config/proxy.ts Normal file
View File

@ -0,0 +1,36 @@
import type { ProxyOptions } from 'vite';
import { createServiceConfig } from '../../src/utils/service';
/**
* Set http proxy
*
* @param env - The current env
* @param isDev - Is development environment
*/
export function createViteProxy(env: Env.ImportMeta, isDev: boolean) {
const isEnableHttpProxy = isDev && env.VITE_HTTP_PROXY === 'Y';
if (!isEnableHttpProxy) return undefined;
const { baseURL, proxyPattern, other } = createServiceConfig(env);
const proxy: Record<string, ProxyOptions> = createProxyItem({ baseURL, proxyPattern });
other.forEach(item => {
Object.assign(proxy, createProxyItem(item));
});
return proxy;
}
function createProxyItem(item: App.Service.ServiceConfigItem) {
const proxy: Record<string, ProxyOptions> = {};
proxy[item.proxyPattern] = {
target: item.baseURL,
changeOrigin: true,
rewrite: path => path.replace(new RegExp(`^${item.proxyPattern}`), '')
};
return proxy;
}

View File

@ -1,8 +0,0 @@
import dayjs from 'dayjs';
/** 项目构建时间 */
const PROJECT_BUILD_TIME = JSON.stringify(dayjs().format('YYYY-MM-DD HH:mm:ss'));
export const define = {
PROJECT_BUILD_TIME
};

View File

@ -1,2 +0,0 @@
export * from './plugins';
export * from './define';

View File

@ -1,17 +0,0 @@
import { loadEnv } from 'vite';
import type { ConfigEnv, PluginOption } from 'vite';
import { minifyHtml, injectHtml } from 'vite-plugin-html'; // html插件(使用变量、压缩)
export default (config: ConfigEnv): PluginOption[] => {
const viteEnv = loadEnv(config.mode, `.env.${config.mode}`);
return [
minifyHtml(),
injectHtml({
injectData: {
appName: viteEnv.VITE_APP_NAME,
appTitle: viteEnv.VITE_APP_TITLE
}
})
];
};

View File

@ -1,11 +0,0 @@
import Icons from 'unplugin-icons/vite'; // iconify图标
import IconsResolver from 'unplugin-icons/resolver';
import Components from 'unplugin-vue-components/vite'; // 从指定目录自动导入组件
export default [
Components({
dts: false,
resolvers: [IconsResolver({ componentPrefix: 'icon' })]
}),
Icons({ scale: 1, defaultClass: 'inline-block' })
];

View File

@ -1,17 +1,26 @@
import type { ConfigEnv, PluginOption } from 'vite';
import vue from './vue';
import html from './html';
import iconify from './iconify';
import windicss from './windicss';
import mock from './mock';
import visualizer from './visualizer';
import type { PluginOption } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import VueDevtools from 'vite-plugin-vue-devtools';
import progress from 'vite-plugin-progress';
import { setupElegantRouter } from './router';
import { setupUnocss } from './unocss';
import { setupUnplugin } from './unplugin';
export function setupVitePlugins(configEnv: ConfigEnv): (PluginOption | PluginOption[])[] {
const plugins = [vue, ...html(configEnv), ...iconify, windicss, mock];
if (configEnv.command === 'build') {
plugins.push(visualizer);
}
export function setupVitePlugins(viteEnv: Env.ImportMeta) {
const plugins: PluginOption = [
vue({
script: {
defineModel: true
}
}),
vueJsx(),
VueDevtools(),
setupElegantRouter(),
setupUnocss(viteEnv),
...setupUnplugin(viteEnv),
progress()
];
return plugins;
}

View File

@ -1,9 +0,0 @@
import { viteMockServe } from 'vite-plugin-mock';
export default viteMockServe({
mockPath: 'mock',
injectCode: `
import { setupMockServer } from '../mock';
setupMockServer();
`
});

44
build/plugins/router.ts Normal file
View File

@ -0,0 +1,44 @@
import type { RouteMeta } from 'vue-router';
import ElegantVueRouter from '@elegant-router/vue/vite';
import type { RouteKey } from '@elegant-router/types';
export function setupElegantRouter() {
return ElegantVueRouter({
layouts: {
base: 'src/layouts/base-layout/index.vue',
blank: 'src/layouts/blank-layout/index.vue'
},
customRoutes: {
names: ['exception_403', 'exception_404', 'exception_500']
},
routePathTransformer(routeName, routePath) {
const key = routeName as RouteKey;
if (key === 'login') {
const modules: UnionKey.LoginModule[] = ['pwd-login', 'code-login', 'register', 'reset-pwd', 'bind-wechat'];
const moduleReg = modules.join('|');
return `/login/:module(${moduleReg})?`;
}
return routePath;
},
onRouteMetaGen(routeName) {
const key = routeName as RouteKey;
const constantRoutes: RouteKey[] = ['login', '403', '404', '500'];
const meta: Partial<RouteMeta> = {
title: key,
i18nKey: `route.${key}` as App.I18n.I18nKey
};
if (constantRoutes.includes(key)) {
meta.constant = true;
}
return meta;
}
});
}

32
build/plugins/unocss.ts Normal file
View File

@ -0,0 +1,32 @@
import process from 'node:process';
import path from 'node:path';
import unocss from '@unocss/vite';
import presetIcons from '@unocss/preset-icons';
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders';
export function setupUnocss(viteEnv: Env.ImportMeta) {
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv;
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
/** The name of the local icon collection */
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
return unocss({
presets: [
presetIcons({
prefix: `${VITE_ICON_PREFIX}-`,
scale: 1,
extraProperties: {
display: 'inline-block'
},
collections: {
[collectionName]: FileSystemIconLoader(localIconPath, svg =>
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
)
},
warn: true
})
]
});
}

50
build/plugins/unplugin.ts Normal file
View File

@ -0,0 +1,50 @@
import process from 'node:process';
import path from 'node:path';
import type { PluginOption } from 'vite';
import Icons from 'unplugin-icons/vite';
import IconsResolver from 'unplugin-icons/resolver';
import Components from 'unplugin-vue-components/vite';
import { AntDesignVueResolver, NaiveUiResolver } from 'unplugin-vue-components/resolvers';
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
export function setupUnplugin(viteEnv: Env.ImportMeta) {
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv;
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon');
/** The name of the local icon collection */
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
const plugins: PluginOption[] = [
Icons({
compiler: 'vue3',
customCollections: {
[collectionName]: FileSystemIconLoader(localIconPath, svg =>
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
)
},
scale: 1,
defaultClass: 'inline-block'
}),
Components({
dts: 'src/typings/components.d.ts',
types: [{ from: 'vue-router', names: ['RouterLink', 'RouterView'] }],
resolvers: [
AntDesignVueResolver({
importStyle: false
}),
NaiveUiResolver(),
IconsResolver({ customCollections: [collectionName], componentPrefix: VITE_ICON_PREFIX })
]
}),
createSvgIconsPlugin({
iconDirs: [localIconPath],
symbolId: `${VITE_ICON_LOCAL_PREFIX}-[dir]-[name]`,
inject: 'body-last',
customDomId: '__SVG_ICON_LOCAL__'
})
];
return plugins;
}

View File

@ -1,6 +0,0 @@
import { visualizer } from 'rollup-plugin-visualizer';
export default visualizer({
gzipSize: true,
brotliSize: true
});

View File

@ -1,3 +0,0 @@
import vue from '@vitejs/plugin-vue';
export default vue({});

View File

@ -1,3 +0,0 @@
import windiCSS from 'vite-plugin-windicss';
export default windiCSS();

View File

@ -1 +0,0 @@
module.exports = { extends: ['@commitlint/config-conventional'] };

24
eslint.config.js Normal file
View File

@ -0,0 +1,24 @@
import { defineConfig } from '@soybeanjs/eslint-config';
export default defineConfig(
{ vue: true, unocss: true },
{
rules: {
'vue/multi-word-component-names': [
'warn',
{
ignores: ['index', 'App', '[id]']
}
],
'vue/component-name-in-template-casing': [
'warn',
'PascalCase',
{
registeredComponentsOnly: false,
ignores: ['/^icon-/']
}
],
'unocss/order-attributify': 'off'
}
}
);

View File

@ -1,30 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<!doctype html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<link rel="icon" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= appName %></title>
<title>%VITE_APP_TITLE%</title>
</head>
<body>
<div id="app">
<div class="loading-container">
<div id="loadingLogo" class="loading-svg"></div>
<div class="loading-spin__container">
<div class="loading-spin">
<div class="left-0 top-0 loading-spin-item"></div>
<div class="left-0 bottom-0 loading-spin-item loading-delay-500"></div>
<div class="right-0 top-0 loading-spin-item loading-delay-1000"></div>
<div class="right-0 bottom-0 loading-spin-item loading-delay-1500"></div>
</div>
</div>
<h2 class="loading-title"><%= appTitle %></h2>
</div>
<style>
@import '/resource/loading.css';
</style>
<script src="/resource/loading.js"></script>
</div>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@ -1,93 +0,0 @@
import type { MockMethod } from 'vite-plugin-mock';
const token: ApiAuth.Token = {
token: '__TEMP_TOKEN__',
refreshToken: '__TEMP_REFRESH_TOKEN__'
};
const apis: MockMethod[] = [
// 获取验证码
{
url: '/mock/getSmsCode',
method: 'post',
response: (): Service.MockServiceResult<boolean> => {
return {
code: 200,
message: 'ok',
data: true
};
}
},
// 密码登录
{
url: '/mock/loginByPwd',
method: 'post',
response: (): Service.MockServiceResult<ApiAuth.Token> => {
return {
code: 200,
message: 'ok',
data: token
};
}
},
// 验证码登录
{
url: '/mock/loginByCode',
method: 'post',
response: (): Service.MockServiceResult<ApiAuth.Token> => {
return {
code: 200,
message: 'ok',
data: token
};
}
},
// 获取用户信息(请求头携带token)
{
url: '/mock/getUserInfo',
method: 'get',
response: (): Service.MockServiceResult<ApiAuth.UserInfo> => {
return {
code: 200,
message: 'ok',
data: {
userId: '0',
userName: 'Soybean',
userPhone: '15170283876',
userRole: 'super'
}
};
}
},
{
url: '/mock/testToken',
method: 'post',
response: (option: any): Service.MockServiceResult<true | null> => {
if (option.headers?.authorization !== token.token) {
return {
code: 66666,
message: 'token 失效',
data: null
};
}
return {
code: 200,
message: 'ok',
data: true
};
}
},
{
url: '/mock/updateToken',
method: 'post',
response: (): Service.MockServiceResult<string> => {
return {
code: 200,
message: 'ok',
data: token.token
};
}
}
];
export default apis;

View File

@ -1,4 +0,0 @@
import auth from './auth';
import route from './route';
export default [...auth, ...route];

View File

@ -1,355 +0,0 @@
import type { MockMethod } from 'vite-plugin-mock';
const routes: AuthRoute.Route[] = [
{
name: 'dashboard',
path: '/dashboard',
component: 'basic',
children: [
{
name: 'dashboard_analysis',
path: '/dashboard/analysis',
component: 'self',
meta: {
title: '分析页',
requiresAuth: true
}
},
{
name: 'dashboard_workbench',
path: '/dashboard/workbench',
component: 'self',
meta: {
title: '工作台',
requiresAuth: true,
permissions: ['super', 'admin']
}
}
],
meta: {
title: '仪表盘',
icon: 'carbon:dashboard',
order: 1
}
},
{
name: 'document',
path: '/document',
component: 'basic',
children: [
{
name: 'document_vue',
path: '/document/vue',
component: 'self',
meta: {
title: 'vue文档',
requiresAuth: true
}
},
{
name: 'document_vue-new',
path: '/document/vue-new',
component: 'self',
meta: {
title: 'vue文档(新版)',
requiresAuth: true
}
},
{
name: 'document_vite',
path: '/document/vite',
component: 'self',
meta: {
title: 'vite文档',
requiresAuth: true
}
},
{
name: 'document_naive',
path: '/document/naive',
component: 'self',
meta: {
title: 'naive文档',
requiresAuth: true
}
},
{
name: 'document_project',
path: '/document/project',
meta: {
title: '项目文档(外链)',
requiresAuth: true,
href: 'https://docs.soybean.pro/'
}
}
],
meta: {
title: '文档',
icon: 'carbon:document',
order: 2
}
},
{
name: 'component',
path: '/component',
component: 'basic',
children: [
{
name: 'component_button',
path: '/component/button',
component: 'self',
meta: {
title: '按钮',
requiresAuth: true
}
},
{
name: 'component_card',
path: '/component/card',
component: 'self',
meta: {
title: '卡片',
requiresAuth: true
}
},
{
name: 'component_table',
path: '/component/table',
component: 'self',
meta: {
title: '表格',
requiresAuth: true
}
}
],
meta: {
title: '组件示例',
icon: 'fluent:app-store-24-regular',
order: 3
}
},
{
name: 'plugin',
path: '/plugin',
component: 'basic',
children: [
{
name: 'plugin_map',
path: '/plugin/map',
component: 'self',
meta: {
title: '地图',
requiresAuth: true
}
},
{
name: 'plugin_video',
path: '/plugin/video',
component: 'self',
meta: {
title: '视频',
requiresAuth: true
}
},
{
name: 'plugin_editor',
path: '/plugin/editor',
component: 'multi',
children: [
{
name: 'plugin_editor_quill',
path: '/plugin/editor/quill',
component: 'self',
meta: {
title: '富文本编辑器'
}
},
{
name: 'plugin_editor_markdown',
path: '/plugin/editor/markdown',
component: 'self',
meta: {
title: 'markdown编辑器'
}
}
],
meta: {
title: '编辑器',
requiresAuth: true
}
},
{
name: 'plugin_swiper',
path: '/plugin/swiper',
component: 'self',
meta: {
title: 'Swiper插件',
requiresAuth: true
}
},
{
name: 'plugin_copy',
path: '/plugin/copy',
component: 'self',
meta: {
title: '剪贴板',
requiresAuth: true
}
},
{
name: 'plugin_icon',
path: '/plugin/icon',
component: 'self',
meta: {
title: '图标',
requiresAuth: true
}
},
{
name: 'plugin_print',
path: '/plugin/print',
component: 'self',
meta: {
title: '打印',
requiresAuth: true
}
}
],
meta: {
title: '插件示例',
icon: 'clarity:plugin-line',
order: 4
}
},
{
name: 'exception',
path: '/exception',
component: 'basic',
children: [
{
name: 'exception_403',
path: '/exception/403',
component: 'self',
meta: {
title: '异常页403',
requiresAuth: true
}
},
{
name: 'exception_404',
path: '/exception/404',
component: 'self',
meta: {
title: '异常页404',
requiresAuth: true
}
},
{
name: 'exception_500',
path: '/exception/500',
component: 'self',
meta: {
title: '异常页500',
requiresAuth: true
}
}
],
meta: {
title: '异常页',
icon: 'ant-design:exception-outlined',
order: 5
}
},
{
name: 'multi-menu',
path: '/multi-menu',
component: 'basic',
children: [
{
name: 'multi-menu_first',
path: '/multi-menu/first',
component: 'multi',
children: [
{
name: 'multi-menu_first_second',
path: '/multi-menu/first/second',
component: 'self',
meta: {
title: '二级菜单',
requiresAuth: true
}
},
{
name: 'multi-menu_first_second-new',
path: '/multi-menu/first/second-new',
component: 'multi',
children: [
{
name: 'multi-menu_first_second-new_third',
path: '/multi-menu/first/second-new/third',
component: 'self',
meta: {
title: '三级菜单',
requiresAuth: true
}
}
],
meta: {
title: '二级菜单(有子菜单)'
}
}
],
meta: {
title: '一级菜单'
}
}
],
meta: {
title: '多级菜单',
icon: 'carbon:menu',
order: 6
}
},
{
name: 'about',
path: '/about',
component: 'self',
meta: {
title: '关于',
requiresAuth: true,
singleLayout: 'basic',
permissions: ['super', 'admin', 'test'],
icon: 'fluent:book-information-24-regular',
order: 7
}
}
];
function dataMiddleware(data: AuthRoute.Route[]): ApiRoute.Route {
const routeHomeName: AuthRoute.RouteKey = 'dashboard_analysis';
function sortRoutes(sorts: AuthRoute.Route[]) {
return sorts.sort((next, pre) => Number(next.meta?.order) - Number(pre.meta?.order));
}
return {
routes: sortRoutes(data),
home: routeHomeName
};
}
const apis: MockMethod[] = [
{
url: '/mock/getUserRoutes',
method: 'post',
response: (): Service.MockServiceResult => {
return {
code: 200,
message: 'ok',
data: dataMiddleware(routes)
};
}
}
];
export default apis;

View File

@ -1,6 +0,0 @@
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
import api from './api';
export function setupMockServer() {
createProdMockServer(api);
}

View File

@ -1,92 +1,107 @@
{
"name": "soybean-admin",
"version": "0.9.1",
"type": "module",
"version": "1.0.4",
"packageManager": "pnpm@9.0.5",
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
"author": {
"name": "Soybean",
"email": "soybeanjs@outlook.com",
"url": "https://github.com/soybeanjs"
},
"license": "MIT",
"homepage": "https://github.com/soybeanjs/soybean-admin",
"repository": {
"url": "https://github.com/soybeanjs/soybean-admin.git"
},
"bugs": {
"url": "https://github.com/soybeanjs/soybean-admin/issues"
},
"keywords": [
"Vue3 admin ",
"vue-admin-template",
"Vite5",
"TypeScript",
"naive-ui",
"naive-ui-admin",
"ant-design-vue v4",
"UnoCSS"
],
"scripts": {
"dev": "cross-env VITE_HTTP_ENV=test vite",
"dev:prod": "cross-env VITE_HTTP_ENV=prod vite",
"typecheck": "vue-tsc",
"build": "npm run typecheck && cross-env VITE_HTTP_ENV=prod vite build",
"build:test": "npm run typecheck && cross-env VITE_HTTP_ENV=test vite build",
"build:vercel": "npm run typecheck && cross-env VITE_HTTP_ENV=prod VITE_IS_VERCEL=1 vite build",
"preview": "vite preview --port 5050",
"release": "standard-version",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
"lint": "eslint --fix ./ --ext .vue,.js,jsx,.ts,tsx",
"prepare": "husky install",
"postinstall": "patch-package"
},
"lint-staged": {
"*.{vue,js,jsx,ts,tsx}": "eslint --fix"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-customizable"
}
"build": "vite build --mode prod",
"build:test": "vite build --mode test",
"cleanup": "sa cleanup",
"commit": "sa git-commit",
"dev": "vite --mode test",
"dev:prod": "vite --mode prod",
"gen-route": "sa gen-route",
"lint": "eslint . --fix",
"prepare": "simple-git-hooks",
"preview": "vite preview",
"release": "sa release",
"typecheck": "vue-tsc --noEmit --skipLibCheck",
"update-pkg": "sa update-pkg"
},
"dependencies": {
"@antv/g2plot": "^2.4.7",
"@better-scroll/core": "^2.4.2",
"@vueuse/core": "^7.5.4",
"axios": "^0.25.0",
"clipboard": "^2.0.8",
"colord": "^2.9.2",
"crypto-js": "^4.1.1",
"dayjs": "^1.10.7",
"form-data": "^4.0.0",
"lodash-es": "^4.17.21",
"naive-ui": "^2.24.1",
"pinia": "^2.0.9",
"print-js": "^1.6.0",
"qs": "^6.10.3",
"swiper": "^7.4.1",
"vditor": "^3.8.11",
"vue": "^3.2.26",
"vue-router": "^4.0.12",
"wangeditor": "^4.7.11",
"xgplayer": "^2.31.4"
"@better-scroll/core": "2.5.1",
"@iconify/vue": "4.1.2",
"@sa/axios": "workspace:*",
"@sa/color-palette": "workspace:*",
"@sa/hooks": "workspace:*",
"@sa/materials": "workspace:*",
"@sa/utils": "workspace:*",
"@vueuse/core": "10.9.0",
"clipboard": "2.0.11",
"dayjs": "1.11.10",
"echarts": "5.5.0",
"lodash-es": "4.17.21",
"naive-ui": "2.38.1",
"nprogress": "0.2.0",
"pinia": "2.1.7",
"vue": "3.4.24",
"vue-draggable-plus": "0.4.0",
"vue-i18n": "9.13.1",
"vue-router": "4.3.2"
},
"devDependencies": {
"@amap/amap-jsapi-types": "^0.0.8",
"@commitlint/cli": "^16.1.0",
"@commitlint/config-conventional": "^16.0.0",
"@iconify/json": "^1.1.459",
"@iconify/vue": "^3.1.2",
"@types/bmapgl": "^0.0.5",
"@types/crypto-js": "^4.1.0",
"@types/node": "^17.0.10",
"@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"@vitejs/plugin-vue": "^2.1.0",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^10.0.0",
"commitizen": "^4.2.4",
"cross-env": "^7.0.3",
"cz-conventional-changelog": "^3.3.0",
"cz-customizable": "^6.3.0",
"eslint": "^8.7.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.3.0",
"husky": "^7.0.4",
"lint-staged": "^12.3.1",
"mockjs": "^1.1.0",
"patch-package": "^6.4.7",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.5.1",
"rollup-plugin-visualizer": "^5.5.4",
"sass": "^1.49.0",
"typescript": "^4.5.5",
"unplugin-icons": "^0.13.0",
"unplugin-vue-components": "^0.17.14",
"vite": "^2.7.13",
"vite-plugin-html": "^2.1.2",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-windicss": "^1.6.3",
"vue-tsc": "^0.31.1",
"vueuc": "^0.4.23",
"windicss": "^3.4.3"
}
"@elegant-router/vue": "0.3.6",
"@iconify/json": "2.2.203",
"@sa/scripts": "workspace:*",
"@sa/uno-preset": "workspace:*",
"@soybeanjs/eslint-config": "1.3.2",
"@types/lodash-es": "4.17.12",
"@types/node": "20.12.7",
"@types/nprogress": "0.2.3",
"@unocss/eslint-config": "0.59.4",
"@unocss/preset-icons": "0.59.4",
"@unocss/preset-uno": "0.59.4",
"@unocss/transformer-directives": "0.59.4",
"@unocss/transformer-variant-group": "0.59.4",
"@unocss/vite": "0.59.4",
"@vitejs/plugin-vue": "5.0.4",
"@vitejs/plugin-vue-jsx": "3.1.0",
"eslint": "9.1.1",
"eslint-plugin-vue": "9.25.0",
"lint-staged": "15.2.2",
"sass": "1.75.0",
"simple-git-hooks": "2.11.1",
"tsx": "4.7.2",
"typescript": "5.4.5",
"unplugin-icons": "0.18.5",
"unplugin-vue-components": "0.26.0",
"vite": "5.2.10",
"vite-plugin-progress": "0.0.7",
"vite-plugin-svg-icons": "2.0.1",
"vite-plugin-vue-devtools": "7.1.2",
"vue-eslint-parser": "9.4.2",
"vue-tsc": "2.0.14"
},
"simple-git-hooks": {
"commit-msg": "pnpm sa git-commit-verify",
"pre-commit": "pnpm typecheck && pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
},
"website": "https://admin.soybeanjs.cn"
}

View File

@ -0,0 +1,21 @@
{
"name": "@sa/axios",
"version": "1.0.4",
"exports": {
".": "./src/index.ts"
},
"typesVersions": {
"*": {
"*": ["./src/*"]
}
},
"dependencies": {
"@sa/utils": "workspace:*",
"axios": "1.6.8",
"axios-retry": "4.1.0",
"qs": "6.12.1"
},
"devDependencies": {
"@types/qs": "6.9.15"
}
}

View File

@ -0,0 +1,5 @@
/** request id key */
export const REQUEST_ID_KEY = 'X-Request-Id';
/** the backend error code key */
export const BACKEND_ERROR_CODE = 'BACKEND_ERROR';

179
packages/axios/src/index.ts Normal file
View File

@ -0,0 +1,179 @@
import axios, { AxiosError } from 'axios';
import type { AxiosResponse, CancelTokenSource, CreateAxiosDefaults, InternalAxiosRequestConfig } from 'axios';
import axiosRetry from 'axios-retry';
import { nanoid } from '@sa/utils';
import { createAxiosConfig, createDefaultOptions, createRetryOptions } from './options';
import { BACKEND_ERROR_CODE, REQUEST_ID_KEY } from './constant';
import type {
CustomAxiosRequestConfig,
FlatRequestInstance,
MappedType,
RequestInstance,
RequestOption,
ResponseType
} from './type';
function createCommonRequest<ResponseData = any>(
axiosConfig?: CreateAxiosDefaults,
options?: Partial<RequestOption<ResponseData>>
) {
const opts = createDefaultOptions<ResponseData>(options);
const axiosConf = createAxiosConfig(axiosConfig);
const instance = axios.create(axiosConf);
const cancelTokenSourceMap = new Map<string, CancelTokenSource>();
// config axios retry
const retryOptions = createRetryOptions(axiosConf);
axiosRetry(instance, retryOptions);
instance.interceptors.request.use(conf => {
const config: InternalAxiosRequestConfig = { ...conf };
// set request id
const requestId = nanoid();
config.headers.set(REQUEST_ID_KEY, requestId);
// config cancel token
const cancelTokenSource = axios.CancelToken.source();
config.cancelToken = cancelTokenSource.token;
cancelTokenSourceMap.set(requestId, cancelTokenSource);
// handle config by hook
const handledConfig = opts.onRequest?.(config) || config;
return handledConfig;
});
instance.interceptors.response.use(
async response => {
if (opts.isBackendSuccess(response)) {
return Promise.resolve(response);
}
const fail = await opts.onBackendFail(response, instance);
if (fail) {
return fail;
}
const backendError = new AxiosError<ResponseData>(
'the backend request error',
BACKEND_ERROR_CODE,
response.config,
response.request,
response
);
await opts.onError(backendError);
return Promise.reject(backendError);
},
async (error: AxiosError<ResponseData>) => {
await opts.onError(error);
return Promise.reject(error);
}
);
function cancelRequest(requestId: string) {
const cancelTokenSource = cancelTokenSourceMap.get(requestId);
if (cancelTokenSource) {
cancelTokenSource.cancel();
cancelTokenSourceMap.delete(requestId);
}
}
function cancelAllRequest() {
cancelTokenSourceMap.forEach(cancelTokenSource => {
cancelTokenSource.cancel();
});
cancelTokenSourceMap.clear();
}
return {
instance,
opts,
cancelRequest,
cancelAllRequest
};
}
/**
* create a request instance
*
* @param axiosConfig axios config
* @param options request options
*/
export function createRequest<ResponseData = any, State = Record<string, unknown>>(
axiosConfig?: CreateAxiosDefaults,
options?: Partial<RequestOption<ResponseData>>
) {
const { instance, opts, cancelRequest, cancelAllRequest } = createCommonRequest<ResponseData>(axiosConfig, options);
const request: RequestInstance<State> = async function request<T = any, R extends ResponseType = 'json'>(
config: CustomAxiosRequestConfig
) {
const response: AxiosResponse<ResponseData> = await instance(config);
const responseType = response.config?.responseType || 'json';
if (responseType === 'json') {
return opts.transformBackendResponse(response);
}
return response.data as MappedType<R, T>;
} as RequestInstance<State>;
request.cancelRequest = cancelRequest;
request.cancelAllRequest = cancelAllRequest;
request.state = {} as State;
return request;
}
/**
* create a flat request instance
*
* The response data is a flat object: { data: any, error: AxiosError }
*
* @param axiosConfig axios config
* @param options request options
*/
export function createFlatRequest<ResponseData = any, State = Record<string, unknown>>(
axiosConfig?: CreateAxiosDefaults,
options?: Partial<RequestOption<ResponseData>>
) {
const { instance, opts, cancelRequest, cancelAllRequest } = createCommonRequest<ResponseData>(axiosConfig, options);
const flatRequest: FlatRequestInstance<State, ResponseData> = async function flatRequest<
T = any,
R extends ResponseType = 'json'
>(config: CustomAxiosRequestConfig) {
try {
const response: AxiosResponse<ResponseData> = await instance(config);
const responseType = response.config?.responseType || 'json';
if (responseType === 'json') {
const data = opts.transformBackendResponse(response);
return { data, error: null };
}
return { data: response.data as MappedType<R, T>, error: null };
} catch (error) {
return { data: null, error };
}
} as FlatRequestInstance<State, ResponseData>;
flatRequest.cancelRequest = cancelRequest;
flatRequest.cancelAllRequest = cancelAllRequest;
flatRequest.state = {} as State;
return flatRequest;
}
export { BACKEND_ERROR_CODE, REQUEST_ID_KEY };
export type * from './type';
export type { CreateAxiosDefaults, AxiosError };

View File

@ -0,0 +1,48 @@
import type { CreateAxiosDefaults } from 'axios';
import type { IAxiosRetryConfig } from 'axios-retry';
import { stringify } from 'qs';
import { isHttpSuccess } from './shared';
import type { RequestOption } from './type';
export function createDefaultOptions<ResponseData = any>(options?: Partial<RequestOption<ResponseData>>) {
const opts: RequestOption<ResponseData> = {
onRequest: async config => config,
isBackendSuccess: _response => true,
onBackendFail: async () => {},
transformBackendResponse: async response => response.data,
onError: async () => {}
};
Object.assign(opts, options);
return opts;
}
export function createRetryOptions(config?: Partial<CreateAxiosDefaults>) {
const retryConfig: IAxiosRetryConfig = {
retries: 3
};
Object.assign(retryConfig, config);
return retryConfig;
}
export function createAxiosConfig(config?: Partial<CreateAxiosDefaults>) {
const TEN_SECONDS = 10 * 1000;
const axiosConfig: CreateAxiosDefaults = {
timeout: TEN_SECONDS,
headers: {
'Content-Type': 'application/json'
},
validateStatus: isHttpSuccess,
paramsSerializer: params => {
return stringify(params);
}
};
Object.assign(axiosConfig, config);
return axiosConfig;
}

View File

@ -0,0 +1,28 @@
import type { AxiosHeaderValue, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
export function getContentType(config: InternalAxiosRequestConfig) {
const contentType: AxiosHeaderValue = config.headers?.['Content-Type'] || 'application/json';
return contentType;
}
/**
* check if http status is success
*
* @param status
*/
export function isHttpSuccess(status: number) {
const isSuccessCode = status >= 200 && status < 300;
return isSuccessCode || status === 304;
}
/**
* is response json
*
* @param response axios response
*/
export function isResponseJson(response: AxiosResponse) {
const { responseType } = response.config;
return responseType === 'json' || responseType === undefined;
}

101
packages/axios/src/type.ts Normal file
View File

@ -0,0 +1,101 @@
import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
export type ContentType =
| 'text/html'
| 'text/plain'
| 'multipart/form-data'
| 'application/json'
| 'application/x-www-form-urlencoded'
| 'application/octet-stream';
export interface RequestOption<ResponseData = any> {
/**
* The hook before request
*
* For example: You can add header token in this hook
*
* @param config Axios config
*/
onRequest: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;
/**
* The hook to check backend response is success or not
*
* @param response Axios response
*/
isBackendSuccess: (response: AxiosResponse<ResponseData>) => boolean;
/**
* The hook after backend request fail
*
* For example: You can handle the expired token in this hook
*
* @param response Axios response
* @param instance Axios instance
*/
onBackendFail: (
response: AxiosResponse<ResponseData>,
instance: AxiosInstance
) => Promise<AxiosResponse | null> | Promise<void>;
/**
* transform backend response when the responseType is json
*
* @param response Axios response
*/
transformBackendResponse(response: AxiosResponse<ResponseData>): any | Promise<any>;
/**
* The hook to handle error
*
* For example: You can show error message in this hook
*
* @param error
*/
onError: (error: AxiosError<ResponseData>) => void | Promise<void>;
}
interface ResponseMap {
blob: Blob;
text: string;
arrayBuffer: ArrayBuffer;
stream: ReadableStream<Uint8Array>;
document: Document;
}
export type ResponseType = keyof ResponseMap | 'json';
export type MappedType<R extends ResponseType, JsonType = any> = R extends keyof ResponseMap
? ResponseMap[R]
: JsonType;
export type CustomAxiosRequestConfig<R extends ResponseType = 'json'> = Omit<AxiosRequestConfig, 'responseType'> & {
responseType?: R;
};
export interface RequestInstanceCommon<T> {
cancelRequest: (requestId: string) => void;
cancelAllRequest: () => void;
/** you can set custom state in the request instance */
state: T;
}
/** The request instance */
export interface RequestInstance<S = Record<string, unknown>> extends RequestInstanceCommon<S> {
<T = any, R extends ResponseType = 'json'>(config: CustomAxiosRequestConfig<R>): Promise<MappedType<R, T>>;
}
export type FlatResponseSuccessData<T = any> = {
data: T;
error: null;
};
export type FlatResponseFailData<ResponseData = any> = {
data: null;
error: AxiosError<ResponseData>;
};
export type FlatResponseData<T = any, ResponseData = any> =
| FlatResponseSuccessData<T>
| FlatResponseFailData<ResponseData>;
export interface FlatRequestInstance<S = Record<string, unknown>, ResponseData = any> extends RequestInstanceCommon<S> {
<T = any, R extends ResponseType = 'json'>(
config: CustomAxiosRequestConfig<R>
): Promise<FlatResponseData<MappedType<R, T>, ResponseData>>;
}

View File

@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "ESNext",
"jsx": "preserve",
"lib": ["DOM", "ESNext"],
"baseUrl": ".",
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"types": ["node"],
"strict": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

View File

@ -0,0 +1,15 @@
{
"name": "@sa/color-palette",
"version": "1.0.4",
"exports": {
".": "./src/index.ts"
},
"typesVersions": {
"*": {
"*": ["./src/*"]
}
},
"dependencies": {
"colord": "2.9.3"
}
}

View File

@ -0,0 +1,2 @@
export * from './name';
export * from './palette';

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,356 @@
import type { ColorPaletteFamily } from '../types';
export const colorPalettes: ColorPaletteFamily[] = [
{
name: 'Slate',
palettes: [
{ hex: '#f8fafc', number: 50 },
{ hex: '#f1f5f9', number: 100 },
{ hex: '#e2e8f0', number: 200 },
{ hex: '#cbd5e1', number: 300 },
{ hex: '#94a3b8', number: 400 },
{ hex: '#64748b', number: 500 },
{ hex: '#475569', number: 600 },
{ hex: '#334155', number: 700 },
{ hex: '#1e293b', number: 800 },
{ hex: '#0f172a', number: 900 },
{ hex: '#020617', number: 950 }
]
},
{
name: 'Gray',
palettes: [
{ hex: '#f9fafb', number: 50 },
{ hex: '#f3f4f6', number: 100 },
{ hex: '#e5e7eb', number: 200 },
{ hex: '#d1d5db', number: 300 },
{ hex: '#9ca3af', number: 400 },
{ hex: '#6b7280', number: 500 },
{ hex: '#4b5563', number: 600 },
{ hex: '#374151', number: 700 },
{ hex: '#1f2937', number: 800 },
{ hex: '#111827', number: 900 },
{ hex: '#030712', number: 950 }
]
},
{
name: 'Zinc',
palettes: [
{ hex: '#fafafa', number: 50 },
{ hex: '#f4f4f5', number: 100 },
{ hex: '#e4e4e7', number: 200 },
{ hex: '#d4d4d8', number: 300 },
{ hex: '#a1a1aa', number: 400 },
{ hex: '#71717a', number: 500 },
{ hex: '#52525b', number: 600 },
{ hex: '#3f3f46', number: 700 },
{ hex: '#27272a', number: 800 },
{ hex: '#18181b', number: 900 },
{ hex: '#09090b', number: 950 }
]
},
{
name: 'Neutral',
palettes: [
{ hex: '#fafafa', number: 50 },
{ hex: '#f5f5f5', number: 100 },
{ hex: '#e5e5e5', number: 200 },
{ hex: '#d4d4d4', number: 300 },
{ hex: '#a3a3a3', number: 400 },
{ hex: '#737373', number: 500 },
{ hex: '#525252', number: 600 },
{ hex: '#404040', number: 700 },
{ hex: '#262626', number: 800 },
{ hex: '#171717', number: 900 },
{ hex: '#0a0a0a', number: 950 }
]
},
{
name: 'Stone',
palettes: [
{ hex: '#fafaf9', number: 50 },
{ hex: '#f5f5f4', number: 100 },
{ hex: '#e7e5e4', number: 200 },
{ hex: '#d6d3d1', number: 300 },
{ hex: '#a8a29e', number: 400 },
{ hex: '#78716c', number: 500 },
{ hex: '#57534e', number: 600 },
{ hex: '#44403c', number: 700 },
{ hex: '#292524', number: 800 },
{ hex: '#1c1917', number: 900 },
{ hex: '#0c0a09', number: 950 }
]
},
{
name: 'Red',
palettes: [
{ hex: '#fef2f2', number: 50 },
{ hex: '#fee2e2', number: 100 },
{ hex: '#fecaca', number: 200 },
{ hex: '#fca5a5', number: 300 },
{ hex: '#f87171', number: 400 },
{ hex: '#ef4444', number: 500 },
{ hex: '#dc2626', number: 600 },
{ hex: '#b91c1c', number: 700 },
{ hex: '#991b1b', number: 800 },
{ hex: '#7f1d1d', number: 900 },
{ hex: '#450a0a', number: 950 }
]
},
{
name: 'Orange',
palettes: [
{ hex: '#fff7ed', number: 50 },
{ hex: '#ffedd5', number: 100 },
{ hex: '#fed7aa', number: 200 },
{ hex: '#fdba74', number: 300 },
{ hex: '#fb923c', number: 400 },
{ hex: '#f97316', number: 500 },
{ hex: '#ea580c', number: 600 },
{ hex: '#c2410c', number: 700 },
{ hex: '#9a3412', number: 800 },
{ hex: '#7c2d12', number: 900 },
{ hex: '#431407', number: 950 }
]
},
{
name: 'Amber',
palettes: [
{ hex: '#fffbeb', number: 50 },
{ hex: '#fef3c7', number: 100 },
{ hex: '#fde68a', number: 200 },
{ hex: '#fcd34d', number: 300 },
{ hex: '#fbbf24', number: 400 },
{ hex: '#f59e0b', number: 500 },
{ hex: '#d97706', number: 600 },
{ hex: '#b45309', number: 700 },
{ hex: '#92400e', number: 800 },
{ hex: '#78350f', number: 900 },
{ hex: '#451a03', number: 950 }
]
},
{
name: 'Yellow',
palettes: [
{ hex: '#fefce8', number: 50 },
{ hex: '#fef9c3', number: 100 },
{ hex: '#fef08a', number: 200 },
{ hex: '#fde047', number: 300 },
{ hex: '#facc15', number: 400 },
{ hex: '#eab308', number: 500 },
{ hex: '#ca8a04', number: 600 },
{ hex: '#a16207', number: 700 },
{ hex: '#854d0e', number: 800 },
{ hex: '#713f12', number: 900 },
{ hex: '#422006', number: 950 }
]
},
{
name: 'Lime',
palettes: [
{ hex: '#f7fee7', number: 50 },
{ hex: '#ecfccb', number: 100 },
{ hex: '#d9f99d', number: 200 },
{ hex: '#bef264', number: 300 },
{ hex: '#a3e635', number: 400 },
{ hex: '#84cc16', number: 500 },
{ hex: '#65a30d', number: 600 },
{ hex: '#4d7c0f', number: 700 },
{ hex: '#3f6212', number: 800 },
{ hex: '#365314', number: 900 },
{ hex: '#1a2e05', number: 950 }
]
},
{
name: 'Green',
palettes: [
{ hex: '#f0fdf4', number: 50 },
{ hex: '#dcfce7', number: 100 },
{ hex: '#bbf7d0', number: 200 },
{ hex: '#86efac', number: 300 },
{ hex: '#4ade80', number: 400 },
{ hex: '#22c55e', number: 500 },
{ hex: '#16a34a', number: 600 },
{ hex: '#15803d', number: 700 },
{ hex: '#166534', number: 800 },
{ hex: '#14532d', number: 900 },
{ hex: '#052e16', number: 950 }
]
},
{
name: 'Emerald',
palettes: [
{ hex: '#ecfdf5', number: 50 },
{ hex: '#d1fae5', number: 100 },
{ hex: '#a7f3d0', number: 200 },
{ hex: '#6ee7b7', number: 300 },
{ hex: '#34d399', number: 400 },
{ hex: '#10b981', number: 500 },
{ hex: '#059669', number: 600 },
{ hex: '#047857', number: 700 },
{ hex: '#065f46', number: 800 },
{ hex: '#064e3b', number: 900 },
{ hex: '#022c22', number: 950 }
]
},
{
name: 'Teal',
palettes: [
{ hex: '#f0fdfa', number: 50 },
{ hex: '#ccfbf1', number: 100 },
{ hex: '#99f6e4', number: 200 },
{ hex: '#5eead4', number: 300 },
{ hex: '#2dd4bf', number: 400 },
{ hex: '#14b8a6', number: 500 },
{ hex: '#0d9488', number: 600 },
{ hex: '#0f766e', number: 700 },
{ hex: '#115e59', number: 800 },
{ hex: '#134e4a', number: 900 },
{ hex: '#042f2e', number: 950 }
]
},
{
name: 'Cyan',
palettes: [
{ hex: '#ecfeff', number: 50 },
{ hex: '#cffafe', number: 100 },
{ hex: '#a5f3fc', number: 200 },
{ hex: '#67e8f9', number: 300 },
{ hex: '#22d3ee', number: 400 },
{ hex: '#06b6d4', number: 500 },
{ hex: '#0891b2', number: 600 },
{ hex: '#0e7490', number: 700 },
{ hex: '#155e75', number: 800 },
{ hex: '#164e63', number: 900 },
{ hex: '#083344', number: 950 }
]
},
{
name: 'Sky',
palettes: [
{ hex: '#f0f9ff', number: 50 },
{ hex: '#e0f2fe', number: 100 },
{ hex: '#bae6fd', number: 200 },
{ hex: '#7dd3fc', number: 300 },
{ hex: '#38bdf8', number: 400 },
{ hex: '#0ea5e9', number: 500 },
{ hex: '#0284c7', number: 600 },
{ hex: '#0369a1', number: 700 },
{ hex: '#075985', number: 800 },
{ hex: '#0c4a6e', number: 900 },
{ hex: '#082f49', number: 950 }
]
},
{
name: 'Blue',
palettes: [
{ hex: '#eff6ff', number: 50 },
{ hex: '#dbeafe', number: 100 },
{ hex: '#bfdbfe', number: 200 },
{ hex: '#93c5fd', number: 300 },
{ hex: '#60a5fa', number: 400 },
{ hex: '#3b82f6', number: 500 },
{ hex: '#2563eb', number: 600 },
{ hex: '#1d4ed8', number: 700 },
{ hex: '#1e40af', number: 800 },
{ hex: '#1e3a8a', number: 900 },
{ hex: '#172554', number: 950 }
]
},
{
name: 'Indigo',
palettes: [
{ hex: '#eef2ff', number: 50 },
{ hex: '#e0e7ff', number: 100 },
{ hex: '#c7d2fe', number: 200 },
{ hex: '#a5b4fc', number: 300 },
{ hex: '#818cf8', number: 400 },
{ hex: '#6366f1', number: 500 },
{ hex: '#4f46e5', number: 600 },
{ hex: '#4338ca', number: 700 },
{ hex: '#3730a3', number: 800 },
{ hex: '#312e81', number: 900 },
{ hex: '#1e1b4b', number: 950 }
]
},
{
name: 'Violet',
palettes: [
{ hex: '#f5f3ff', number: 50 },
{ hex: '#ede9fe', number: 100 },
{ hex: '#ddd6fe', number: 200 },
{ hex: '#c4b5fd', number: 300 },
{ hex: '#a78bfa', number: 400 },
{ hex: '#8b5cf6', number: 500 },
{ hex: '#7c3aed', number: 600 },
{ hex: '#6d28d9', number: 700 },
{ hex: '#5b21b6', number: 800 },
{ hex: '#4c1d95', number: 900 },
{ hex: '#2e1065', number: 950 }
]
},
{
name: 'Purple',
palettes: [
{ hex: '#faf5ff', number: 50 },
{ hex: '#f3e8ff', number: 100 },
{ hex: '#e9d5ff', number: 200 },
{ hex: '#d8b4fe', number: 300 },
{ hex: '#c084fc', number: 400 },
{ hex: '#a855f7', number: 500 },
{ hex: '#9333ea', number: 600 },
{ hex: '#7e22ce', number: 700 },
{ hex: '#6b21a8', number: 800 },
{ hex: '#581c87', number: 900 },
{ hex: '#3b0764', number: 950 }
]
},
{
name: 'Fuchsia',
palettes: [
{ hex: '#fdf4ff', number: 50 },
{ hex: '#fae8ff', number: 100 },
{ hex: '#f5d0fe', number: 200 },
{ hex: '#f0abfc', number: 300 },
{ hex: '#e879f9', number: 400 },
{ hex: '#d946ef', number: 500 },
{ hex: '#c026d3', number: 600 },
{ hex: '#a21caf', number: 700 },
{ hex: '#86198f', number: 800 },
{ hex: '#701a75', number: 900 },
{ hex: '#4a044e', number: 950 }
]
},
{
name: 'Pink',
palettes: [
{ hex: '#fdf2f8', number: 50 },
{ hex: '#fce7f3', number: 100 },
{ hex: '#fbcfe8', number: 200 },
{ hex: '#f9a8d4', number: 300 },
{ hex: '#f472b6', number: 400 },
{ hex: '#ec4899', number: 500 },
{ hex: '#db2777', number: 600 },
{ hex: '#be185d', number: 700 },
{ hex: '#9d174d', number: 800 },
{ hex: '#831843', number: 900 },
{ hex: '#500724', number: 950 }
]
},
{
name: 'Rose',
palettes: [
{ hex: '#fff1f2', number: 50 },
{ hex: '#ffe4e6', number: 100 },
{ hex: '#fecdd3', number: 200 },
{ hex: '#fda4af', number: 300 },
{ hex: '#fb7185', number: 400 },
{ hex: '#f43f5e', number: 500 },
{ hex: '#e11d48', number: 600 },
{ hex: '#be123c', number: 700 },
{ hex: '#9f1239', number: 800 },
{ hex: '#881337', number: 900 },
{ hex: '#4c0519', number: 950 }
]
}
];

View File

@ -0,0 +1,6 @@
import { colorPalettes } from './constant';
import { getColorName, getHex, getHsl, getRgb } from './shared';
export * from './palette';
export { getColorName, getHex, getHsl, getRgb, colorPalettes };
export * from './types';

View File

@ -0,0 +1,152 @@
import { getColorName, getDeltaE, getHsl, isValidColor, transformHslToHex } from '../shared';
import { colorPalettes } from '../constant';
import type {
ColorPalette,
ColorPaletteFamily,
ColorPaletteFamilyWithNearestPalette,
ColorPaletteMatch,
ColorPaletteNumber
} from '../types';
/**
* get color palette by provided color and color name
*
* @param color the provided color
*/
export function getColorPalette(color: string) {
const colorPaletteFamily = getColorPaletteFamily(color);
const colorMap = new Map<ColorPaletteNumber, ColorPalette>();
colorPaletteFamily.palettes.forEach(palette => {
colorMap.set(palette.number, palette);
});
const mainColor = colorMap.get(500)!;
const matchColor = colorPaletteFamily.palettes.find(palette => palette.hex === color)!;
const colorPalette: ColorPaletteMatch = {
...colorPaletteFamily,
colorMap,
main: mainColor,
match: matchColor
};
return colorPalette;
}
/**
* get color by number
*
* @param color the provided color
* @param number the color palette number
*/
export function getColorByPaletteNumber(color: string, number: ColorPaletteNumber) {
const colorPalette = getColorPalette(color);
const { hex } = colorPalette.colorMap.get(number)!;
return hex;
}
/**
* get color palette family by provided color and color name
*
* @param color the provided color
*/
export function getColorPaletteFamily(color: string) {
if (!isValidColor(color)) {
throw new Error('Invalid color, please check color value!');
}
let colorName = getColorName(color);
colorName = colorName.toLowerCase().replace(/\s/g, '-');
const { h: h1, s: s1 } = getHsl(color);
const { nearestLightnessPalette, palettes } = getNearestColorPaletteFamily(color, colorPalettes);
const { number, hex } = nearestLightnessPalette;
const { h: h2, s: s2 } = getHsl(hex);
const deltaH = h1 - h2;
const sRatio = s1 / s2;
const colorPaletteFamily: ColorPaletteFamily = {
name: colorName,
palettes: palettes.map(palette => {
let hexValue = color;
const isSame = number === palette.number;
if (!isSame) {
const { h: h3, s: s3, l } = getHsl(palette.hex);
const newH = deltaH < 0 ? h3 + deltaH : h3 - deltaH;
const newS = s3 * sRatio;
hexValue = transformHslToHex({
h: newH,
s: newS,
l
});
}
return {
hex: hexValue,
number: palette.number
};
})
};
return colorPaletteFamily;
}
/**
* get nearest color palette family
*
* @param color color
* @param families color palette families
*/
function getNearestColorPaletteFamily(color: string, families: ColorPaletteFamily[]) {
const familyWithConfig = families.map(family => {
const palettes = family.palettes.map(palette => {
return {
...palette,
delta: getDeltaE(color, palette.hex)
};
});
const nearestPalette = palettes.reduce((prev, curr) => (prev.delta < curr.delta ? prev : curr));
return {
...family,
palettes,
nearestPalette
};
});
const nearestPaletteFamily = familyWithConfig.reduce((prev, curr) =>
prev.nearestPalette.delta < curr.nearestPalette.delta ? prev : curr
);
const { l } = getHsl(color);
const paletteFamily: ColorPaletteFamilyWithNearestPalette = {
...nearestPaletteFamily,
nearestLightnessPalette: nearestPaletteFamily.palettes.reduce((prev, curr) => {
const { l: prevLightness } = getHsl(prev.hex);
const { l: currLightness } = getHsl(curr.hex);
const deltaPrev = Math.abs(prevLightness - l);
const deltaCurr = Math.abs(currLightness - l);
return deltaPrev < deltaCurr ? prev : curr;
})
};
return paletteFamily;
}

View File

@ -0,0 +1,29 @@
import { colord, extend } from 'colord';
import type { HslColor } from 'colord';
import labPlugin from 'colord/plugins/lab';
extend([labPlugin]);
export function isValidColor(color: string) {
return colord(color).isValid();
}
export function getHex(color: string) {
return colord(color).toHex();
}
export function getRgb(color: string) {
return colord(color).toRgb();
}
export function getHsl(color: string) {
return colord(color).toHsl();
}
export function getDeltaE(color1: string, color2: string) {
return colord(color1).delta(color2);
}
export function transformHslToHex(color: HslColor) {
return colord(color).toHex();
}

View File

@ -0,0 +1,2 @@
export * from './colord';
export * from './name';

View File

@ -0,0 +1,49 @@
import { colorNames } from '../constant';
import { getHex, getHsl, getRgb } from './colord';
/**
* Get color name
*
* @param color
*/
export function getColorName(color: string) {
const hex = getHex(color);
const rgb = getRgb(color);
const hsl = getHsl(color);
let ndf = 0;
let ndf1 = 0;
let ndf2 = 0;
let cl = -1;
let df = -1;
let name = '';
colorNames.some((item, index) => {
const [hexValue, colorName] = item;
const match = hex === hexValue;
if (match) {
name = colorName;
} else {
const { r, g, b } = getRgb(hexValue);
const { h, s, l } = getHsl(hexValue);
ndf1 = (rgb.r - r) ** 2 + (rgb.g - g) ** 2 + (rgb.b - b) ** 2;
ndf2 = (hsl.h - h) ** 2 + (hsl.s - s) ** 2 + (hsl.l - l) ** 2;
ndf = ndf1 + ndf2 * 2;
if (df < 0 || df > ndf) {
df = ndf;
cl = index;
}
}
return match;
});
name = colorNames[cl][1];
return name;
}

View File

@ -0,0 +1,47 @@
/** the color palette number */
export type ColorPaletteNumber = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950;
/** the color palette */
export type ColorPalette = {
/** the color hex value */
hex: string;
/**
* the color number
*
* - 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950
*/
number: ColorPaletteNumber;
};
/** the color palette family */
export type ColorPaletteFamily = {
/** the color palette family name */
name: string;
/** the color palettes */
palettes: ColorPalette[];
};
/** the color palette with delta */
export type ColorPaletteWithDelta = ColorPalette & {
delta: number;
};
/** the color palette family with nearest palette */
export type ColorPaletteFamilyWithNearestPalette = ColorPaletteFamily & {
nearestPalette: ColorPaletteWithDelta;
nearestLightnessPalette: ColorPaletteWithDelta;
};
/** the color palette match */
export type ColorPaletteMatch = ColorPaletteFamily & {
/** the color map of the palette */
colorMap: Map<ColorPaletteNumber, ColorPalette>;
/**
* the main color of the palette
*
* which number is 500
*/
main: ColorPalette;
/** the match color of the palette */
match: ColorPalette;
};

View File

@ -0,0 +1,15 @@
{
"name": "@sa/hooks",
"version": "1.0.4",
"exports": {
".": "./src/index.ts"
},
"typesVersions": {
"*": {
"*": ["./src/*"]
}
},
"dependencies": {
"@sa/axios": "workspace:*"
}
}

View File

@ -0,0 +1,10 @@
import useBoolean from './use-boolean';
import useLoading from './use-loading';
import useCountDown from './use-count-down';
import useContext from './use-context';
import useSvgIconRender from './use-svg-icon-render';
import useHookTable from './use-table';
export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useHookTable };
export * from './use-table';

View File

@ -1,6 +1,11 @@
import { ref } from 'vue';
export default function useBoolean(initValue: boolean = false) {
/**
* Boolean
*
* @param initValue Init value
*/
export default function useBoolean(initValue = false) {
const bool = ref(initValue);
function setBool(value: boolean) {

View File

@ -0,0 +1,96 @@
import { inject, provide } from 'vue';
import type { InjectionKey } from 'vue';
/**
* Use context
*
* @example
* ```ts
* // there are three vue files: A.vue, B.vue, C.vue, and A.vue is the parent component of B.vue and C.vue
*
* // context.ts
* import { ref } from 'vue';
* import { useContext } from '@sa/hooks';
*
* export const { setupStore, useStore } = useContext('demo', () => {
* const count = ref(0);
*
* function increment() {
* count.value++;
* }
*
* function decrement() {
* count.value--;
* }
*
* return {
* count,
* increment,
* decrement
* };
* })
* ``` // A.vue
* ```vue
* <template>
* <div>A</div>
* </template>
* <script setup lang="ts">
* import { setupStore } from './context';
*
* setupStore();
* // const { increment } = setupStore(); // also can control the store in the parent component
* </script>
* ``` // B.vue
* ```vue
* <template>
* <div>B</div>
* </template>
* <script setup lang="ts">
* import { useStore } from './context';
*
* const { count, increment } = useStore();
* </script>
* ```;
*
* // C.vue is same as B.vue
*
* @param contextName Context name
* @param fn Context function
*/
export default function useContext<T extends (...args: any[]) => any>(contextName: string, fn: T) {
type Context = ReturnType<T>;
const { useProvide, useInject: useStore } = createContext<Context>(contextName);
function setupStore(...args: Parameters<T>) {
const context: Context = fn(...args);
return useProvide(context);
}
return {
/** Setup store in the parent component */
setupStore,
/** Use store in the child component */
useStore
};
}
/** Create context */
function createContext<T>(contextName: string) {
const injectKey: InjectionKey<T> = Symbol(contextName);
function useProvide(context: T) {
provide(injectKey, context);
return context;
}
function useInject() {
return inject(injectKey) as T;
}
return {
useProvide,
useInject
};
}

View File

@ -0,0 +1,49 @@
import { computed, onScopeDispose, ref } from 'vue';
import { useRafFn } from '@vueuse/core';
/**
* count down
*
* @param seconds - count down seconds
*/
export default function useCountDown(seconds: number) {
const FPS_PER_SECOND = 60;
const fps = ref(0);
const count = computed(() => Math.ceil(fps.value / FPS_PER_SECOND));
const isCounting = computed(() => fps.value > 0);
const { pause, resume } = useRafFn(
() => {
if (fps.value > 0) {
fps.value -= 1;
} else {
pause();
}
},
{ immediate: false }
);
function start(updateSeconds: number = seconds) {
fps.value = FPS_PER_SECOND * updateSeconds;
resume();
}
function stop() {
fps.value = 0;
pause();
}
onScopeDispose(() => {
pause();
});
return {
count,
isCounting,
start,
stop
};
}

View File

@ -1,6 +1,11 @@
import useBoolean from './useBoolean';
import useBoolean from './use-boolean';
export default function useLoading(initValue: boolean = false) {
/**
* Loading
*
* @param initValue Init value
*/
export default function useLoading(initValue = false) {
const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(initValue);
return {

View File

@ -0,0 +1,79 @@
import { ref } from 'vue';
import type { Ref } from 'vue';
import { createFlatRequest } from '@sa/axios';
import type {
AxiosError,
CreateAxiosDefaults,
CustomAxiosRequestConfig,
MappedType,
RequestOption,
ResponseType
} from '@sa/axios';
import useLoading from './use-loading';
export type HookRequestInstanceResponseSuccessData<T = any> = {
data: Ref<T>;
error: Ref<null>;
};
export type HookRequestInstanceResponseFailData<ResponseData = any> = {
data: Ref<null>;
error: Ref<AxiosError<ResponseData>>;
};
export type HookRequestInstanceResponseData<T = any, ResponseData = any> = {
loading: Ref<boolean>;
} & (HookRequestInstanceResponseSuccessData<T> | HookRequestInstanceResponseFailData<ResponseData>);
export interface HookRequestInstance<ResponseData = any> {
<T = any, R extends ResponseType = 'json'>(
config: CustomAxiosRequestConfig
): HookRequestInstanceResponseData<MappedType<R, T>, ResponseData>;
cancelRequest: (requestId: string) => void;
cancelAllRequest: () => void;
}
/**
* create a hook request instance
*
* @param axiosConfig
* @param options
*/
export default function createHookRequest<ResponseData = any>(
axiosConfig?: CreateAxiosDefaults,
options?: Partial<RequestOption<ResponseData>>
) {
const request = createFlatRequest<ResponseData>(axiosConfig, options);
const hookRequest: HookRequestInstance<ResponseData> = function hookRequest<T = any, R extends ResponseType = 'json'>(
config: CustomAxiosRequestConfig
) {
const { loading, startLoading, endLoading } = useLoading();
const data = ref<MappedType<R, T> | null>(null) as Ref<MappedType<R, T>>;
const error = ref<AxiosError<ResponseData> | null>(null) as Ref<AxiosError<ResponseData> | null>;
startLoading();
request(config).then(res => {
if (res.data) {
data.value = res.data;
} else {
error.value = res.error;
}
endLoading();
});
return {
loading,
data,
error
};
} as HookRequestInstance<ResponseData>;
hookRequest.cancelRequest = request.cancelRequest;
hookRequest.cancelAllRequest = request.cancelAllRequest;
return hookRequest;
}

View File

@ -0,0 +1,50 @@
import { h } from 'vue';
import type { Component } from 'vue';
/**
* Svg icon render hook
*
* @param SvgIcon Svg icon component
*/
export default function useSvgIconRender(SvgIcon: Component) {
interface IconConfig {
/** Iconify icon name */
icon?: string;
/** Local icon name */
localIcon?: string;
/** Icon color */
color?: string;
/** Icon size */
fontSize?: number;
}
type IconStyle = Partial<Pick<CSSStyleDeclaration, 'color' | 'fontSize'>>;
/**
* Svg icon VNode
*
* @param config
*/
const SvgIconVNode = (config: IconConfig) => {
const { color, fontSize, icon, localIcon } = config;
const style: IconStyle = {};
if (color) {
style.color = color;
}
if (fontSize) {
style.fontSize = `${fontSize}px`;
}
if (!icon && !localIcon) {
return undefined;
}
return () => h(SvgIcon, { icon, localIcon, style });
};
return {
SvgIconVNode
};
}

View File

@ -0,0 +1,151 @@
import { computed, reactive, ref } from 'vue';
import type { Ref } from 'vue';
import useBoolean from './use-boolean';
import useLoading from './use-loading';
export type MaybePromise<T> = T | Promise<T>;
export type ApiFn = (args: any) => Promise<unknown>;
export type TableColumnCheck = {
key: string;
title: string;
checked: boolean;
};
export type TableDataWithIndex<T> = T & { index: number };
export type TransformedData<T> = {
data: TableDataWithIndex<T>[];
pageNum: number;
pageSize: number;
total: number;
};
export type Transformer<T, Response> = (response: Response) => TransformedData<T>;
export type TableConfig<A extends ApiFn, T, C> = {
/** api function to get table data */
apiFn: A;
/** api params */
apiParams?: Parameters<A>[0];
/** transform api response to table data */
transformer: Transformer<T, Awaited<ReturnType<A>>>;
/** columns factory */
columns: () => C[];
/**
* get column checks
*
* @param columns
*/
getColumnChecks: (columns: C[]) => TableColumnCheck[];
/**
* get columns
*
* @param columns
*/
getColumns: (columns: C[], checks: TableColumnCheck[]) => C[];
/**
* callback when response fetched
*
* @param transformed transformed data
*/
onFetched?: (transformed: TransformedData<T>) => MaybePromise<void>;
/**
* whether to get data immediately
*
* @default true
*/
immediate?: boolean;
};
export default function useHookTable<A extends ApiFn, T, C>(config: TableConfig<A, T, C>) {
const { loading, startLoading, endLoading } = useLoading();
const { bool: empty, setBool: setEmpty } = useBoolean();
const { apiFn, apiParams, transformer, immediate = true, getColumnChecks, getColumns } = config;
const searchParams: NonNullable<Parameters<A>[0]> = reactive({ ...apiParams });
const allColumns = ref(config.columns()) as Ref<C[]>;
const data: Ref<T[]> = ref([]);
const columnChecks: Ref<TableColumnCheck[]> = ref(getColumnChecks(config.columns()));
const columns = computed(() => getColumns(allColumns.value, columnChecks.value));
function reloadColumns() {
allColumns.value = config.columns();
const checkMap = new Map(columnChecks.value.map(col => [col.key, col.checked]));
const defaultChecks = getColumnChecks(allColumns.value);
columnChecks.value = defaultChecks.map(col => ({
...col,
checked: checkMap.get(col.key) ?? col.checked
}));
}
async function getData() {
startLoading();
const formattedParams = formatSearchParams(searchParams);
const response = await apiFn(formattedParams);
const transformed = transformer(response as Awaited<ReturnType<A>>);
data.value = transformed.data;
setEmpty(transformed.data.length === 0);
await config.onFetched?.(transformed);
endLoading();
}
function formatSearchParams(params: Record<string, unknown>) {
const formattedParams: Record<string, unknown> = {};
Object.entries(params).forEach(([key, value]) => {
if (value !== null && value !== undefined) {
formattedParams[key] = value;
}
});
return formattedParams;
}
/**
* update search params
*
* @param params
*/
function updateSearchParams(params: Partial<Parameters<A>[0]>) {
Object.assign(searchParams, params);
}
/** reset search params */
function resetSearchParams() {
Object.assign(searchParams, apiParams);
}
if (immediate) {
getData();
}
return {
loading,
empty,
data,
columns,
columnChecks,
reloadColumns,
getData,
searchParams,
updateSearchParams,
resetSearchParams
};
}

View File

@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "ESNext",
"jsx": "preserve",
"lib": ["DOM", "ESNext"],
"baseUrl": ".",
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"types": ["node"],
"strict": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

View File

@ -0,0 +1,19 @@
{
"name": "@sa/materials",
"version": "1.0.4",
"exports": {
".": "./src/index.ts"
},
"typesVersions": {
"*": {
"*": ["./src/*"]
}
},
"dependencies": {
"@sa/utils": "workspace:*",
"simplebar-vue": "2.3.3"
},
"devDependencies": {
"typed-css-modules": "0.9.1"
}
}

View File

@ -0,0 +1,6 @@
import AdminLayout, { LAYOUT_MAX_Z_INDEX, LAYOUT_SCROLL_EL_ID } from './libs/admin-layout';
import PageTab from './libs/page-tab';
import SimpleScrollbar from './libs/simple-scrollbar';
export { AdminLayout, LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX, PageTab, SimpleScrollbar };
export * from './types';

View File

@ -0,0 +1,63 @@
/* @type */
.layout-header,
.layout-header-placement {
height: var(--soy-header-height);
}
.layout-header {
z-index: var(--soy-header-z-index);
}
.layout-tab {
top: var(--soy-header-height);
height: var(--soy-tab-height);
z-index: var(--soy-tab-z-index);
}
.layout-tab-placement {
height: var(--soy-tab-height);
}
.layout-sider {
width: var(--soy-sider-width);
z-index: var(--soy-sider-z-index);
}
.layout-mobile-sider {
z-index: var(--soy-sider-z-index);
}
.layout-mobile-sider-mask {
z-index: var(--soy-mobile-sider-z-index);
}
.layout-sider_collapsed {
width: var(--soy-sider-collapsed-width);
z-index: var(--soy-sider-z-index);
}
.layout-footer,
.layout-footer-placement {
height: var(--soy-footer-height);
}
.layout-footer {
z-index: var(--soy-footer-z-index);
}
.left-gap {
padding-left: var(--soy-sider-width);
}
.left-gap_collapsed {
padding-left: var(--soy-sider-collapsed-width);
}
.sider-padding-top {
padding-top: var(--soy-header-height);
}
.sider-padding-bottom {
padding-bottom: var(--soy-footer-height);
}

View File

@ -0,0 +1,18 @@
declare const styles: {
readonly 'layout-header': string;
readonly 'layout-header-placement': string;
readonly 'layout-tab': string;
readonly 'layout-tab-placement': string;
readonly 'layout-sider': string;
readonly 'layout-mobile-sider': string;
readonly 'layout-mobile-sider-mask': string;
readonly 'layout-sider_collapsed': string;
readonly 'layout-footer': string;
readonly 'layout-footer-placement': string;
readonly 'left-gap': string;
readonly 'left-gap_collapsed': string;
readonly 'sider-padding-top': string;
readonly 'sider-padding-bottom': string;
};
export default styles;

View File

@ -0,0 +1,5 @@
import AdminLayout from './index.vue';
import { LAYOUT_MAX_Z_INDEX, LAYOUT_SCROLL_EL_ID } from './shared';
export default AdminLayout;
export { LAYOUT_SCROLL_EL_ID, LAYOUT_MAX_Z_INDEX };

View File

@ -0,0 +1,237 @@
<script setup lang="ts">
import { computed } from 'vue';
import type { AdminLayoutProps } from '../../types';
import { LAYOUT_MAX_Z_INDEX, LAYOUT_SCROLL_EL_ID, createLayoutCssVars } from './shared';
import style from './index.module.css';
defineOptions({
name: 'AdminLayout'
});
const props = withDefaults(defineProps<AdminLayoutProps>(), {
mode: 'vertical',
scrollMode: 'content',
scrollElId: LAYOUT_SCROLL_EL_ID,
commonClass: 'transition-all-300',
fixedTop: true,
maxZIndex: LAYOUT_MAX_Z_INDEX,
headerVisible: true,
headerHeight: 56,
tabVisible: true,
tabHeight: 48,
siderVisible: true,
siderCollapse: false,
siderWidth: 220,
siderCollapsedWidth: 64,
footerVisible: true,
footerHeight: 48,
rightFooter: false
});
interface Emits {
/** Update siderCollapse */
(e: 'update:siderCollapse', collapse: boolean): void;
}
const emit = defineEmits<Emits>();
type SlotFn = (props?: Record<string, unknown>) => any;
type Slots = {
/** Main */
default?: SlotFn;
/** Header */
header?: SlotFn;
/** Tab */
tab?: SlotFn;
/** Sider */
sider?: SlotFn;
/** Footer */
footer?: SlotFn;
};
const slots = defineSlots<Slots>();
const cssVars = computed(() => createLayoutCssVars(props));
// config visible
const showHeader = computed(() => Boolean(slots.header) && props.headerVisible);
const showTab = computed(() => Boolean(slots.tab) && props.tabVisible);
const showSider = computed(() => !props.isMobile && Boolean(slots.sider) && props.siderVisible);
const showMobileSider = computed(() => props.isMobile && Boolean(slots.sider) && props.siderVisible);
const showFooter = computed(() => Boolean(slots.footer) && props.footerVisible);
// scroll mode
const isWrapperScroll = computed(() => props.scrollMode === 'wrapper');
const isContentScroll = computed(() => props.scrollMode === 'content');
// layout direction
const isVertical = computed(() => props.mode === 'vertical');
const isHorizontal = computed(() => props.mode === 'horizontal');
const fixedHeaderAndTab = computed(() => props.fixedTop || (isHorizontal.value && isWrapperScroll.value));
// css
const leftGapClass = computed(() => {
if (!props.fullContent && showSider.value) {
return props.siderCollapse ? style['left-gap_collapsed'] : style['left-gap'];
}
return '';
});
const headerLeftGapClass = computed(() => (isVertical.value ? leftGapClass.value : ''));
const footerLeftGapClass = computed(() => {
const condition1 = isVertical.value;
const condition2 = isHorizontal.value && isWrapperScroll.value && !props.fixedFooter;
const condition3 = Boolean(isHorizontal.value && props.rightFooter);
if (condition1 || condition2 || condition3) {
return leftGapClass.value;
}
return '';
});
const siderPaddingClass = computed(() => {
let cls = '';
if (showHeader.value && !headerLeftGapClass.value) {
cls += style['sider-padding-top'];
}
if (showFooter.value && !footerLeftGapClass.value) {
cls += ` ${style['sider-padding-bottom']}`;
}
return cls;
});
function handleClickMask() {
emit('update:siderCollapse', true);
}
</script>
<template>
<div class="relative h-full" :class="[commonClass]" :style="cssVars">
<div
:id="isWrapperScroll ? scrollElId : undefined"
class="h-full flex flex-col"
:class="[commonClass, scrollWrapperClass, { 'overflow-y-auto': isWrapperScroll }]"
>
<!-- Header -->
<template v-if="showHeader">
<header
v-show="!fullContent"
class="flex-shrink-0"
:class="[
style['layout-header'],
commonClass,
headerClass,
headerLeftGapClass,
{ 'absolute top-0 left-0 w-full': fixedHeaderAndTab }
]"
>
<slot name="header"></slot>
</header>
<div
v-show="!fullContent && fixedHeaderAndTab"
class="flex-shrink-0 overflow-hidden"
:class="[style['layout-header-placement']]"
></div>
</template>
<!-- Tab -->
<template v-if="showTab">
<div
class="flex-shrink-0"
:class="[
style['layout-tab'],
commonClass,
tabClass,
{ 'top-0!': fullContent || !showHeader },
leftGapClass,
{ 'absolute left-0 w-full': fixedHeaderAndTab }
]"
>
<slot name="tab"></slot>
</div>
<div
v-show="fullContent || fixedHeaderAndTab"
class="flex-shrink-0 overflow-hidden"
:class="[style['layout-tab-placement']]"
></div>
</template>
<!-- Sider -->
<template v-if="showSider">
<aside
v-show="!fullContent"
class="absolute left-0 top-0 h-full"
:class="[
commonClass,
siderClass,
siderPaddingClass,
siderCollapse ? style['layout-sider_collapsed'] : style['layout-sider']
]"
>
<slot name="sider"></slot>
</aside>
</template>
<!-- Mobile Sider -->
<template v-if="showMobileSider">
<aside
class="absolute left-0 top-0 h-full w-0 bg-white"
:class="[
commonClass,
mobileSiderClass,
style['layout-mobile-sider'],
siderCollapse ? 'overflow-hidden' : style['layout-sider']
]"
>
<slot name="sider"></slot>
</aside>
<div
v-show="!siderCollapse"
class="absolute left-0 top-0 h-full w-full bg-[rgba(0,0,0,0.2)]"
:class="[style['layout-mobile-sider-mask']]"
@click="handleClickMask"
></div>
</template>
<!-- Main Content -->
<main
:id="isContentScroll ? scrollElId : undefined"
class="flex flex-col flex-grow"
:class="[commonClass, contentClass, leftGapClass, { 'overflow-y-auto': isContentScroll }]"
>
<slot></slot>
</main>
<!-- Footer -->
<template v-if="showFooter">
<footer
v-show="!fullContent"
class="flex-shrink-0"
:class="[
style['layout-footer'],
commonClass,
footerClass,
footerLeftGapClass,
{ 'absolute left-0 bottom-0 w-full': fixedFooter }
]"
>
<slot name="footer"></slot>
</footer>
<div
v-show="!fullContent && fixedFooter"
class="flex-shrink-0 overflow-hidden"
:class="[style['layout-footer-placement']]"
></div>
</template>
</div>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,68 @@
import type { AdminLayoutProps, LayoutCssVars, LayoutCssVarsProps } from '../../types';
/** The id of the scroll element of the layout */
export const LAYOUT_SCROLL_EL_ID = '__SCROLL_EL_ID__';
/** The max z-index of the layout */
export const LAYOUT_MAX_Z_INDEX = 100;
/**
* Create layout css vars by css vars props
*
* @param props Css vars props
*/
function createLayoutCssVarsByCssVarsProps(props: LayoutCssVarsProps) {
const cssVars: LayoutCssVars = {
'--soy-header-height': `${props.headerHeight}px`,
'--soy-header-z-index': props.headerZIndex,
'--soy-tab-height': `${props.tabHeight}px`,
'--soy-tab-z-index': props.tabZIndex,
'--soy-sider-width': `${props.siderWidth}px`,
'--soy-sider-collapsed-width': `${props.siderCollapsedWidth}px`,
'--soy-sider-z-index': props.siderZIndex,
'--soy-mobile-sider-z-index': props.mobileSiderZIndex,
'--soy-footer-height': `${props.footerHeight}px`,
'--soy-footer-z-index': props.footerZIndex
};
return cssVars;
}
/**
* Create layout css vars
*
* @param props
*/
export function createLayoutCssVars(props: AdminLayoutProps) {
const {
mode,
isMobile,
maxZIndex = LAYOUT_MAX_Z_INDEX,
headerHeight,
tabHeight,
siderWidth,
siderCollapsedWidth,
footerHeight
} = props;
const headerZIndex = maxZIndex - 3;
const tabZIndex = maxZIndex - 5;
const siderZIndex = mode === 'vertical' || isMobile ? maxZIndex - 1 : maxZIndex - 4;
const mobileSiderZIndex = isMobile ? maxZIndex - 2 : 0;
const footerZIndex = maxZIndex - 5;
const cssProps: LayoutCssVarsProps = {
headerHeight,
headerZIndex,
tabHeight,
tabZIndex,
siderWidth,
siderZIndex,
mobileSiderZIndex,
siderCollapsedWidth,
footerHeight,
footerZIndex
};
return createLayoutCssVarsByCssVarsProps(cssProps);
}

View File

@ -0,0 +1,53 @@
<script setup lang="ts">
import type { PageTabProps } from '../../types';
import style from './index.module.css';
defineOptions({
name: 'ButtonTab'
});
defineProps<PageTabProps>();
type SlotFn = (props?: Record<string, unknown>) => any;
type Slots = {
/**
* Slot
*
* The center content of the tab
*/
default?: SlotFn;
/**
* Slot
*
* The left content of the tab
*/
prefix?: SlotFn;
/**
* Slot
*
* The right content of the tab
*/
suffix?: SlotFn;
};
defineSlots<Slots>();
</script>
<template>
<div
class=":soy: relative inline-flex cursor-pointer items-center justify-center gap-12px whitespace-nowrap border-1px rounded-4px border-solid px-12px py-4px"
:class="[
style['button-tab'],
{ [style['button-tab_dark']]: darkMode },
{ [style['button-tab_active']]: active },
{ [style['button-tab_active_dark']]: active && darkMode }
]"
>
<slot name="prefix"></slot>
<slot></slot>
<slot name="suffix"></slot>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,31 @@
<script setup lang="ts">
defineOptions({
name: 'ChromeTabBg'
});
</script>
<template>
<svg class="size-full">
<defs>
<symbol id="geometry-left" viewBox="0 0 214 36">
<path d="M17 0h197v36H0v-2c4.5 0 9-3.5 9-8V8c0-4.5 3.5-8 8-8z" />
</symbol>
<symbol id="geometry-right" viewBox="0 0 214 36">
<use xlink:href="#geometry-left" />
</symbol>
<clipPath>
<rect width="100%" height="100%" x="0" />
</clipPath>
</defs>
<svg width="51%" height="100%">
<use xlink:href="#geometry-left" width="214" height="36" fill="currentColor" />
</svg>
<g transform="scale(-1, 1)">
<svg width="51%" height="100%" x="-100%" y="0">
<use xlink:href="#geometry-right" width="214" height="36" fill="currentColor" />
</svg>
</g>
</svg>
</template>
<style scoped></style>

View File

@ -0,0 +1,58 @@
<script setup lang="ts">
import type { PageTabProps } from '../../types';
import ChromeTabBg from './chrome-tab-bg.vue';
import style from './index.module.css';
defineOptions({
name: 'ChromeTab'
});
defineProps<PageTabProps>();
type SlotFn = (props?: Record<string, unknown>) => any;
type Slots = {
/**
* Slot
*
* The center content of the tab
*/
default?: SlotFn;
/**
* Slot
*
* The left content of the tab
*/
prefix?: SlotFn;
/**
* Slot
*
* The right content of the tab
*/
suffix?: SlotFn;
};
defineSlots<Slots>();
</script>
<template>
<div
class=":soy: relative inline-flex cursor-pointer items-center justify-center gap-16px whitespace-nowrap px-24px py-6px -mr-18px"
:class="[
style['chrome-tab'],
{ [style['chrome-tab_dark']]: darkMode },
{ [style['chrome-tab_active']]: active },
{ [style['chrome-tab_active_dark']]: active && darkMode }
]"
>
<div class=":soy: pointer-events-none absolute left-0 top-0 h-full w-full -z-1" :class="[style['chrome-tab__bg']]">
<ChromeTabBg />
</div>
<slot name="prefix"></slot>
<slot></slot>
<slot name="suffix"></slot>
<div class=":soy: absolute right-7px h-16px w-1px bg-#1f2225" :class="[style['chrome-tab-divider']]"></div>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,97 @@
/* @type */
.button-tab {
border-color: #e5e7eb;
}
.button-tab_dark {
border-color: #ffffff3d;
}
.button-tab:hover {
color: var(--soy-primary-color);
border-color: var(--soy-primary-color-opacity3);
}
.button-tab_active {
color: var(--soy-primary-color);
border-color: var(--soy-primary-color-opacity3);
background-color: var(--soy-primary-color-opacity1);
}
.button-tab_active_dark {
background-color: var(--soy-primary-color-opacity2);
}
.button-tab .svg-close:hover {
font-size: 12px;
color: #ffffff;
background-color: var(--soy-primary-color);
}
.button-tab_dark .svg-close:hover {
color: #000000;
}
.chrome-tab:hover {
z-index: 9;
}
.chrome-tab_active {
z-index: 10;
color: var(--soy-primary-color);
}
.chrome-tab__bg {
color: transparent;
}
.chrome-tab_active .chrome-tab__bg {
color: var(--soy-primary-color1);
}
.chrome-tab_active_dark .chrome-tab__bg {
color: var(--soy-primary-color2);
}
.chrome-tab:hover .chrome-tab__bg {
color: #dee1e6;
}
.chrome-tab_active:hover .chrome-tab__bg {
color: var(--soy-primary-color1);
}
.chrome-tab_dark:hover .chrome-tab__bg {
color: #333333;
}
.chrome-tab_active_dark:hover .chrome-tab__bg {
color: var(--soy-primary-color2);
}
.chrome-tab .svg-close:hover {
font-size: 12px;
color: #ffffff;
background-color: #9ca3af;
}
.chrome-tab_active .svg-close:hover {
background-color: var(--soy-primary-color);
}
.chrome-tab_dark .svg-close:hover {
color: #000000;
}
.chrome-tab_active .chrome-tab-divider {
opacity: 0;
}
.chrome-tab:hover .chrome-tab-divider {
opacity: 0;
}
.chrome-tab_dark .chrome-tab-divider {
background-color: rgba(255, 255, 255, 0.9);
}

View File

@ -0,0 +1,15 @@
declare const styles: {
readonly 'button-tab': string;
readonly 'button-tab_dark': string;
readonly 'button-tab_active': string;
readonly 'button-tab_active_dark': string;
readonly 'chrome-tab': string;
readonly 'chrome-tab_active': string;
readonly 'chrome-tab__bg': string;
readonly 'chrome-tab_active_dark': string;
readonly 'chrome-tab_dark': string;
readonly 'chrome-tab-divider': string;
readonly 'svg-close': string;
};
export default styles;

View File

@ -0,0 +1,3 @@
import PageTab from './index.vue';
export default PageTab;

View File

@ -0,0 +1,72 @@
<script setup lang="ts">
import { computed } from 'vue';
import type { Component } from 'vue';
import type { PageTabMode, PageTabProps } from '../../types';
import { ACTIVE_COLOR, createTabCssVars } from './shared';
import ChromeTab from './chrome-tab.vue';
import ButtonTab from './button-tab.vue';
import SvgClose from './svg-close.vue';
import style from './index.module.css';
defineOptions({
name: 'PageTab'
});
const props = withDefaults(defineProps<PageTabProps>(), {
mode: 'chrome',
commonClass: 'transition-all-300',
activeColor: ACTIVE_COLOR,
closable: true
});
interface Emits {
(e: 'close'): void;
}
const emit = defineEmits<Emits>();
const activeTabComponent = computed(() => {
const { mode, chromeClass, buttonClass } = props;
const tabComponentMap = {
chrome: {
component: ChromeTab,
class: chromeClass
},
button: {
component: ButtonTab,
class: buttonClass
}
} satisfies Record<PageTabMode, { component: Component; class?: string }>;
return tabComponentMap[mode];
});
const cssVars = computed(() => createTabCssVars(props.activeColor));
const bindProps = computed(() => {
const { chromeClass: _chromeCls, buttonClass: _btnCls, ...rest } = props;
return rest;
});
function handleClose() {
emit('close');
}
</script>
<template>
<component :is="activeTabComponent.component" :class="activeTabComponent.class" :style="cssVars" v-bind="bindProps">
<template #prefix>
<slot name="prefix"></slot>
</template>
<slot></slot>
<template #suffix>
<slot name="suffix">
<SvgClose v-if="closable" :class="[style['svg-close']]" @click.stop="handleClose" />
</slot>
</template>
</component>
</template>
<style scoped></style>

View File

@ -0,0 +1,31 @@
import { addColorAlpha, transformColorWithOpacity } from '@sa/utils';
import type { PageTabCssVars, PageTabCssVarsProps } from '../../types';
/** The active color of the tab */
export const ACTIVE_COLOR = '#1890ff';
function createCssVars(props: PageTabCssVarsProps) {
const cssVars: PageTabCssVars = {
'--soy-primary-color': props.primaryColor,
'--soy-primary-color1': props.primaryColor1,
'--soy-primary-color2': props.primaryColor2,
'--soy-primary-color-opacity1': props.primaryColorOpacity1,
'--soy-primary-color-opacity2': props.primaryColorOpacity2,
'--soy-primary-color-opacity3': props.primaryColorOpacity3
};
return cssVars;
}
export function createTabCssVars(primaryColor: string) {
const cssProps: PageTabCssVarsProps = {
primaryColor,
primaryColor1: transformColorWithOpacity(primaryColor, 0.1, '#ffffff'),
primaryColor2: transformColorWithOpacity(primaryColor, 0.3, '#000000'),
primaryColorOpacity1: addColorAlpha(primaryColor, 0.1),
primaryColorOpacity2: addColorAlpha(primaryColor, 0.15),
primaryColorOpacity3: addColorAlpha(primaryColor, 0.3)
};
return createCssVars(cssProps);
}

View File

@ -0,0 +1,18 @@
<script setup lang="ts">
defineOptions({
name: 'SvgClose'
});
</script>
<template>
<div class=":soy: relative h-16px w-16px inline-flex items-center justify-center rd-50% text-14px">
<svg width="1em" height="1em" viewBox="0 0 1024 1024">
<path
fill="currentColor"
d="m563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8L295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512L196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1l216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,3 @@
import SimpleScrollbar from './index.vue';
export default SimpleScrollbar;

View File

@ -0,0 +1,18 @@
<script setup lang="ts">
import Simplebar from 'simplebar-vue';
import 'simplebar-vue/dist/simplebar.min.css';
defineOptions({
name: 'SimpleScrollbar'
});
</script>
<template>
<div class="h-full flex-1-hidden">
<Simplebar class="h-full">
<slot />
</Simplebar>
</div>
</template>
<style scoped></style>

View File

@ -0,0 +1,294 @@
/** Header config */
interface AdminLayoutHeaderConfig {
/**
* Whether header is visible
*
* @default true
*/
headerVisible?: boolean;
/**
* Header class
*
* @default ''
*/
headerClass?: string;
/**
* Header height
*
* @default 56px
*/
headerHeight?: number;
}
/** Tab config */
interface AdminLayoutTabConfig {
/**
* Whether tab is visible
*
* @default true
*/
tabVisible?: boolean;
/**
* Tab class
*
* @default ''
*/
tabClass?: string;
/**
* Tab height
*
* @default 48px
*/
tabHeight?: number;
}
/** Sider config */
interface AdminLayoutSiderConfig {
/**
* Whether sider is visible
*
* @default true
*/
siderVisible?: boolean;
/**
* Sider class
*
* @default ''
*/
siderClass?: string;
/**
* Mobile sider class
*
* @default ''
*/
mobileSiderClass?: string;
/**
* Sider collapse status
*
* @default false
*/
siderCollapse?: boolean;
/**
* Sider width when collapse is false
*
* @default '220px'
*/
siderWidth?: number;
/**
* Sider width when collapse is true
*
* @default '64px'
*/
siderCollapsedWidth?: number;
}
/** Content config */
export interface AdminLayoutContentConfig {
/**
* Content class
*
* @default ''
*/
contentClass?: string;
/**
* Whether content is full the page
*
* If true, other elements will be hidden by `display: none`
*/
fullContent?: boolean;
}
/** Footer config */
export interface AdminLayoutFooterConfig {
/**
* Whether footer is visible
*
* @default true
*/
footerVisible?: boolean;
/**
* Whether footer is fixed
*
* @default true
*/
fixedFooter?: boolean;
/**
* Footer class
*
* @default ''
*/
footerClass?: string;
/**
* Footer height
*
* @default 48px
*/
footerHeight?: number;
/**
* Whether footer is on the right side
*
* When the layout is vertical, the footer is on the right side
*/
rightFooter?: boolean;
}
/**
* Layout mode
*
* - Horizontal
* - Vertical
*/
export type LayoutMode = 'horizontal' | 'vertical';
/**
* The scroll mode when content overflow
*
* - Wrapper: the layout component's wrapper element has a scrollbar
* - Content: the layout component's content element has a scrollbar
*
* @default 'wrapper'
*/
export type LayoutScrollMode = 'wrapper' | 'content';
/** Admin layout props */
export interface AdminLayoutProps
extends AdminLayoutHeaderConfig,
AdminLayoutTabConfig,
AdminLayoutSiderConfig,
AdminLayoutContentConfig,
AdminLayoutFooterConfig {
/**
* Layout mode
*
* - {@link LayoutMode}
*/
mode?: LayoutMode;
/** Is mobile layout */
isMobile?: boolean;
/**
* Scroll mode
*
* - {@link ScrollMode}
*/
scrollMode?: LayoutScrollMode;
/**
* The id of the scroll element of the layout
*
* It can be used to get the corresponding Dom and scroll it
*
* @example
* use the default id by import
* ```ts
* import { adminLayoutScrollElId } from '@sa/vue-materials';
* ```
*
* @default
* ```ts
* const adminLayoutScrollElId = '__ADMIN_LAYOUT_SCROLL_EL_ID__'
* ```
*/
scrollElId?: string;
/** The class of the scroll element */
scrollElClass?: string;
/** The class of the scroll wrapper element */
scrollWrapperClass?: string;
/**
* The common class of the layout
*
* Is can be used to configure the transition animation
*
* @default 'transition-all-300'
*/
commonClass?: string;
/**
* Whether fix the header and tab
*
* @default true
*/
fixedTop?: boolean;
/**
* The max z-index of the layout
*
* The z-index of Header,Tab,Sider and Footer will not exceed this value
*/
maxZIndex?: number;
}
type Kebab<S extends string> = S extends Uncapitalize<S> ? S : `-${Uncapitalize<S>}`;
type KebabCase<S extends string> = S extends `${infer Start}${infer End}`
? `${Uncapitalize<Start>}${KebabCase<Kebab<End>>}`
: S;
type Prefix = '--soy-';
export type LayoutCssVarsProps = Pick<
AdminLayoutProps,
'headerHeight' | 'tabHeight' | 'siderWidth' | 'siderCollapsedWidth' | 'footerHeight'
> & {
headerZIndex?: number;
tabZIndex?: number;
siderZIndex?: number;
mobileSiderZIndex?: number;
footerZIndex?: number;
};
export type LayoutCssVars = {
[K in keyof LayoutCssVarsProps as `${Prefix}${KebabCase<K>}`]: string | number;
};
/**
* The mode of the tab
*
* - Button: button style
* - Chrome: chrome style
*
* @default chrome
*/
export type PageTabMode = 'button' | 'chrome';
export interface PageTabProps {
/** Whether is dark mode */
darkMode?: boolean;
/**
* The mode of the tab
*
* - {@link TabMode}
*/
mode?: PageTabMode;
/**
* The common class of the layout
*
* Is can be used to configure the transition animation
*
* @default 'transition-all-300'
*/
commonClass?: string;
/** The class of the button tab */
buttonClass?: string;
/** The class of the chrome tab */
chromeClass?: string;
/** Whether the tab is active */
active?: boolean;
/** The color of the active tab */
activeColor?: string;
/**
* Whether the tab is closable
*
* Show the close icon when true
*/
closable?: boolean;
}
export type PageTabCssVarsProps = {
primaryColor: string;
primaryColor1: string;
primaryColor2: string;
primaryColorOpacity1: string;
primaryColorOpacity2: string;
primaryColorOpacity3: string;
};
export type PageTabCssVars = {
[K in keyof PageTabCssVarsProps as `${Prefix}${KebabCase<K>}`]: string | number;
};

View File

@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "ESNext",
"jsx": "preserve",
"lib": ["DOM", "ESNext"],
"baseUrl": ".",
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"types": ["node"],
"strict": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

View File

@ -0,0 +1,15 @@
{
"name": "@sa/fetch",
"version": "1.0.4",
"exports": {
".": "./src/index.ts"
},
"typesVersions": {
"*": {
"*": ["./src/*"]
}
},
"dependencies": {
"ofetch": "1.3.4"
}
}

View File

@ -0,0 +1,10 @@
import { ofetch } from 'ofetch';
import type { FetchOptions } from 'ofetch';
export function createRequest(options: FetchOptions) {
const request = ofetch.create(options);
return request;
}
export default createRequest;

View File

@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "ESNext",
"jsx": "preserve",
"lib": ["DOM", "ESNext"],
"baseUrl": ".",
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"types": ["node"],
"strict": true,
"strictNullChecks": true,
"noUnusedLocals": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

3
packages/scripts/bin.ts Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env tsx
import './src/index.ts';

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