mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-11-20 23:46:47 +08:00
Compare commits
40 Commits
6eaec8705d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb232bf884 | ||
|
|
f8dc639e05 | ||
|
|
46081c365c | ||
|
|
4a9cf6c3da | ||
|
|
ec792fa749 | ||
|
|
232f56fd62 | ||
|
|
6010f51801 | ||
|
|
9755c31361 | ||
|
|
0b9982bdc6 | ||
|
|
1d14269557 | ||
|
|
5cfb606042 | ||
|
|
e471e9140e | ||
|
|
b2c919b673 | ||
|
|
8dc17e62f1 | ||
|
|
60115572a8 | ||
|
|
56ad0df974 | ||
|
|
6cbf5705bb | ||
|
|
87a66a4236 | ||
|
|
3549c4dbd5 | ||
|
|
24c6df528b | ||
|
|
dac5075be9 | ||
|
|
a8d1e5d266 | ||
|
|
345aa2932f | ||
|
|
017440c1e6 | ||
|
|
d5a3a25d3d | ||
|
|
d567c057a8 | ||
|
|
91fae50260 | ||
|
|
61fa4b7f3b | ||
|
|
ef7acc626f | ||
|
|
2a0c9f1b41 | ||
|
|
e18d39724a | ||
|
|
5be864a80b | ||
|
|
fd087f59fa | ||
|
|
b041fdd864 | ||
|
|
9fa951aa06 | ||
|
|
12b25e0d58 | ||
|
|
e33f944a74 | ||
|
|
8d7f91dccf | ||
|
|
33ade53904 | ||
|
|
923eb98a5c |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -33,5 +33,3 @@ package-lock.json
|
||||
yarn.lock
|
||||
|
||||
.VSCodeCounter
|
||||
|
||||
.temp
|
||||
281
CHANGELOG.md
281
CHANGELOG.md
@@ -1,6 +1,287 @@
|
||||
# Changelog
|
||||
|
||||
|
||||
## [v2.0.0](https://github.com/soybeanjs/soybean-admin/compare/v1.3.15...v2.0.0) (2025-11-02)
|
||||
|
||||
### 🚨 Breaking Changes
|
||||
|
||||
- **hooks**: refactor useTable and enhance type definitions - by @soybeanjs [<samp>(8cc51)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8cc5177c)
|
||||
- **projects**: optimize layout mode, split horizontal mix component into two layouts, and rename the component. - by **Azir** [<samp>(b6ac3)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b6ac3106)
|
||||
- **request**: remove cancelRequest method and related logic from request instances - by @soybeanjs [<samp>(b4e12)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b4e12530)
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- **components**:
|
||||
- add the IconTooltip component. - by **Azir-11** [<samp>(a55b4)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a55b4dc0)
|
||||
- replace NTooltip with IconTooltip and optimize the layout of related components. - by **Azir-11** [<samp>(40057)</samp>](https://github.com/soybeanjs/soybean-admin/commit/4005763c)
|
||||
- **global-tab**:
|
||||
- add support for switching tabs with right mouse button click - by @soybeanjs [<samp>(b2c91)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b2c919b6)
|
||||
- **hooks**:
|
||||
- add scrollX computation for total table width in useNaiveTable - by @Lruihao [<samp>(358e1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/358e1297)
|
||||
- **packages**:
|
||||
- materials support slider-tab. closed #823 - by @CyberShen in https://github.com/soybeanjs/soybean-admin/issues/823 [<samp>(61fa4)</samp>](https://github.com/soybeanjs/soybean-admin/commit/61fa4b7f)
|
||||
- **projects**:
|
||||
- refactor theme drawer with tabbed layout for better UX. - by **Azir** [<samp>(8ba71)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8ba71a08)
|
||||
- Add current time display option for watermark - by @wenyuanw in https://github.com/soybeanjs/soybean-admin/issues/772 [<samp>(f238f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f238fcbd)
|
||||
- add 'vertical-hybrid-header-first' layout mode - by @wenyuanw [<samp>(b4e5c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b4e5c6d9)
|
||||
- add prompt information for scrolling mode and tab bar caching. - by **Azir-11** [<samp>(29a2a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/29a2a5c6)
|
||||
- support theme preset function. - by **Azir-11** [<samp>(257f1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/257f1183)
|
||||
- modify the default value of the reset cache policy to 'refresh'. - by **Azir-11** [<samp>(3c0a5)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3c0a5282)
|
||||
- optimize tabs cache cleaning strategy. close #820. - by **Azir-11** in https://github.com/soybeanjs/soybean-admin/issues/820 [<samp>(ef7ac)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ef7acc62)
|
||||
- support closing tabs with middle mouse button click - by @wenyuanw [<samp>(a8d1e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a8d1e5d2)
|
||||
- support set global redius - by **CyberShen123** [<samp>(24c6d)</samp>](https://github.com/soybeanjs/soybean-admin/commit/24c6df52)
|
||||
- support set global redius - by **CyberShen123** [<samp>(3549c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3549c4db)
|
||||
- compatible with the new Echarts API and optimized styles. - by **Azir-11** [<samp>(9755c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9755c313)
|
||||
- **styles**:
|
||||
- add text-autospace property to improve text layout - by @wenyuanw [<samp>(345aa)</samp>](https://github.com/soybeanjs/soybean-admin/commit/345aa293)
|
||||
|
||||
### 🐞 Bug Fixes
|
||||
|
||||
- **hooks**:
|
||||
- correct chart rendering logic in useEcharts - by @soybeanjs [<samp>(8a7cd)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8a7cd593)
|
||||
- **layout**:
|
||||
- fix getSiderWidth - by @soybeanjs [<samp>(e471e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e471e914)
|
||||
- **packages**:
|
||||
- fix the parsing logic for stored data to ensure correct return of boolean values - by @Lruihao [<samp>(9ea56)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9ea56c9b)
|
||||
- axios: fix json response. fixed #815 - by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/815 [<samp>(fd087)</samp>](https://github.com/soybeanjs/soybean-admin/commit/fd087f59)
|
||||
- axios: fix json response. fixed #815 - by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/815 [<samp>(5be86)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5be864a8)
|
||||
- **projects**:
|
||||
- Fix i18n-ally not working when setting moduleResolution to bundler. fixed #780 - by @xiaobao0505 in https://github.com/soybeanjs/soybean-admin/issues/780 [<samp>(41191)</samp>](https://github.com/soybeanjs/soybean-admin/commit/41191d54)
|
||||
- adjust legend position in line chart options. - by **Azir-11** [<samp>(0b998)</samp>](https://github.com/soybeanjs/soybean-admin/commit/0b9982bd)
|
||||
- **readme**:
|
||||
- update GitHub stars and forks links for gitee - by @soybeanjs [<samp>(923eb)</samp>](https://github.com/soybeanjs/soybean-admin/commit/923eb98a)
|
||||
- **scripts**:
|
||||
- update command to use 'npm-check-updates' instead of 'ncu' - by @soybeanjs [<samp>(8dc17)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8dc17e62)
|
||||
- **styles**:
|
||||
- show light color scrollbar while dark mode is on - by **whyang** [<samp>(dac50)</samp>](https://github.com/soybeanjs/soybean-admin/commit/dac5075b)
|
||||
- **table**:
|
||||
- add type annotations for records in useTable hook - by @soybeanjs [<samp>(32b8f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/32b8f990)
|
||||
- **types**:
|
||||
- fix proxy types - by @soybeanjs [<samp>(3d72f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3d72f954)
|
||||
- fix proxy types - by @soybeanjs [<samp>(12b25)</samp>](https://github.com/soybeanjs/soybean-admin/commit/12b25e0d)
|
||||
- fix ts type error - by @soybeanjs [<samp>(d5a3a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d5a3a25d)
|
||||
|
||||
### 🛠 Optimizations
|
||||
|
||||
- **hooks**:
|
||||
- optimize useEcharts - by @soybeanjs [<samp>(936b8)</samp>](https://github.com/soybeanjs/soybean-admin/commit/936b834e)
|
||||
- **packages**:
|
||||
- remove ofetch package - by @soybeanjs [<samp>(abaaa)</samp>](https://github.com/soybeanjs/soybean-admin/commit/abaaa4a0)
|
||||
- **projects**:
|
||||
- improve theme drawer responsive width for mobile devices - by @wenyuanw [<samp>(8439a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8439a600)
|
||||
- improve robustness of second-level menu key logic - by @wenyuanw [<samp>(8b8a2)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8b8a2083)
|
||||
- optimize theme drawer width - by @soybeanjs [<samp>(81468)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8146858b)
|
||||
- optimize api type file - by @soybeanjs [<samp>(3a343)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3a343eea)
|
||||
- optimize radius settings - by @soybeanjs [<samp>(87a66)</samp>](https://github.com/soybeanjs/soybean-admin/commit/87a66a42)
|
||||
- **request**:
|
||||
- enhance request options and response handling with generic types - by @soybeanjs [<samp>(50a5c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/50a5cba0)
|
||||
- **typings**:
|
||||
- update component typings - by @soybeanjs [<samp>(1d142)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1d142695)
|
||||
|
||||
### 💅 Refactors
|
||||
|
||||
- **hooks**:
|
||||
- optimize useContext and update useMixMenuContext - by @soybeanjs [<samp>(c9651)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c965140b)
|
||||
- streamline column visibility handling in useTable and table components - by @soybeanjs [<samp>(ee434)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ee434145)
|
||||
- remove useSignal hook and update exports - by @soybeanjs [<samp>(87adc)</samp>](https://github.com/soybeanjs/soybean-admin/commit/87adc35f)
|
||||
- **menu**:
|
||||
- optimize the margin on the menu - by **NicholasLD** [<samp>(d7311)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d7311111)
|
||||
- **projects**:
|
||||
- remove unnecessary logic in onRouteSwitchWhenLoggedIn - by @wenyuanw [<samp>(d6c81)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d6c8142b)
|
||||
- **request**:
|
||||
- unify response transformation methods and deprecate transformBackendResponse - by @soybeanjs [<samp>(f83ee)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f83eefbc)
|
||||
- **types**:
|
||||
- move Auth and Route namespaces to separate files and clean up api.d.ts - by **Azir** [<samp>(d37ce)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d37ce046)
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- **projects**:
|
||||
- add github trendshift info. - by **恕瑞玛的皇帝** [<samp>(e18d3)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e18d3972)
|
||||
- add github trendshift info. - by **恕瑞玛的皇帝** [<samp>(2a0c9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/2a0c9f1b)
|
||||
- add contribution leaderboard - by @wenyuanw [<samp>(01744)</samp>](https://github.com/soybeanjs/soybean-admin/commit/017440c1)
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- **deps**:
|
||||
- update NodeJS and pnpm version requirements in package.json and documentation - by **Junior25306** [<samp>(a5c4b)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a5c4b4e3)
|
||||
- update deps - by @soybeanjs [<samp>(5cb1c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5cb1cebd)
|
||||
- update deps - by @soybeanjs [<samp>(aeb63)</samp>](https://github.com/soybeanjs/soybean-admin/commit/aeb63690)
|
||||
- update deps - by @soybeanjs [<samp>(e89b8)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e89b86ce)
|
||||
- update deps - by @soybeanjs [<samp>(c962f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c962f7b2)
|
||||
- update deps - by @soybeanjs [<samp>(12135)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1213531b)
|
||||
- update deps - by @soybeanjs [<samp>(e33f9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e33f944a)
|
||||
- update deps - by @soybeanjs [<samp>(9fa95)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9fa951aa)
|
||||
- update deps - by @soybeanjs [<samp>(b041f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b041fdd8)
|
||||
- update deps - by @soybeanjs [<samp>(d567c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d567c057)
|
||||
- update deps - by @soybeanjs [<samp>(6cbf5)</samp>](https://github.com/soybeanjs/soybean-admin/commit/6cbf5705)
|
||||
- update deps - by @soybeanjs [<samp>(6010f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/6010f518)
|
||||
- update deps - by @soybeanjs [<samp>(232f5)</samp>](https://github.com/soybeanjs/soybean-admin/commit/232f56fd)
|
||||
- **other**:
|
||||
- update the ESLint validation configuration to support more file types. - by **Azir-11** [<samp>(8d7f9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8d7f91dc)
|
||||
- update the ESLint validation configuration to support more file types. - by **Azir-11** [<samp>(be8f9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/be8f915a)
|
||||
- **packages**:
|
||||
- update Vite version to 7 in package.json and documentation. - by **Azir** [<samp>(03dd6)</samp>](https://github.com/soybeanjs/soybean-admin/commit/03dd64c5)
|
||||
- add picomatch to fix scripts - by @soybeanjs [<samp>(805c3)</samp>](https://github.com/soybeanjs/soybean-admin/commit/805c3381)
|
||||
- **readme**:
|
||||
- remove DartNode sponsorship badge from README files - by @soybeanjs [<samp>(33ade)</samp>](https://github.com/soybeanjs/soybean-admin/commit/33ade539)
|
||||
- **vscode**:
|
||||
- remove unused vue.server.hybridMode setting from .vscode/settings.json - by @soybeanjs [<samp>(13319)</samp>](https://github.com/soybeanjs/soybean-admin/commit/133196f3)
|
||||
|
||||
### 🎨 Styles
|
||||
|
||||
- **projects**: format code. - by **Azir-11** [<samp>(100e0)</samp>](https://github.com/soybeanjs/soybean-admin/commit/100e0ea5)
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
[](https://github.com/soybeanjs) [](https://github.com/wenyuanw) [](https://github.com/CyberShen) [](https://github.com/Lruihao) [](https://github.com/xiaobao0505)
|
||||
[Azir-11](mailto:2075125282@qq.com), [CyberShen123](mailto:s.lijun@qq.com), [whyang](mailto:whyang9701@gmail.com), [HongxuanG](mailto:1359774872@qq.com), [NicholasLD](mailto:878639947@qq.com), [Junior25306](mailto:dayu429@qq.com)
|
||||
|
||||
## [v2.0.0-beta.2](https://github.com/soybeanjs/soybean-admin/compare/v2.0.0-beta.1...v2.0.0-beta.2) (2025-10-27)
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- **global-tab**: add support for switching tabs with right mouse button click - by @soybeanjs [<samp>(b2c91)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b2c919b6)
|
||||
|
||||
### 🐞 Bug Fixes
|
||||
|
||||
- **layout**: fix getSiderWidth - by @soybeanjs [<samp>(e471e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e471e914)
|
||||
- **packages**: axios: fix json response. fixed #815 - by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/815 [<samp>(fd087)</samp>](https://github.com/soybeanjs/soybean-admin/commit/fd087f59)
|
||||
- **readme**: update GitHub stars and forks links for gitee - by @soybeanjs [<samp>(923eb)</samp>](https://github.com/soybeanjs/soybean-admin/commit/923eb98a)
|
||||
- **scripts**: update command to use 'npm-check-updates' instead of 'ncu' - by @soybeanjs [<samp>(8dc17)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8dc17e62)
|
||||
- **types**: fix proxy types - by @soybeanjs [<samp>(12b25)</samp>](https://github.com/soybeanjs/soybean-admin/commit/12b25e0d)
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- **projects**:
|
||||
- add github trendshift info. - by **恕瑞玛的皇帝** [<samp>(e18d3)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e18d3972)
|
||||
- add contribution leaderboard - by @wenyuanw [<samp>(01744)</samp>](https://github.com/soybeanjs/soybean-admin/commit/017440c1)
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- **deps**:
|
||||
- update deps - by @soybeanjs [<samp>(e33f9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e33f944a)
|
||||
- update deps - by @soybeanjs [<samp>(9fa95)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9fa951aa)
|
||||
- **other**:
|
||||
- update the ESLint validation configuration to support more file types. - by **Azir-11** [<samp>(8d7f9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8d7f91dc)
|
||||
- **readme**:
|
||||
- remove DartNode sponsorship badge from README files - by @soybeanjs [<samp>(33ade)</samp>](https://github.com/soybeanjs/soybean-admin/commit/33ade539)
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
[](https://github.com/soybeanjs) [](https://github.com/wenyuanw)
|
||||
[恕瑞玛的皇帝](mailto:2075125282@qq.com)
|
||||
|
||||
## [v2.0.0-beta.1](https://github.com/soybeanjs/soybean-admin/compare/v1.3.15...v2.0.0-beta.1) (2025-10-25)
|
||||
|
||||
### 🚨 Breaking Changes
|
||||
|
||||
- **hooks**: refactor useTable and enhance type definitions - by @soybeanjs [<samp>(8cc51)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8cc5177)
|
||||
- **projects**: optimize layout mode, split horizontal mix component into two layouts, and rename the component. - by **Azir** [<samp>(b6ac3)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b6ac310)
|
||||
- **request**: remove cancelRequest method and related logic from request instances - by @soybeanjs [<samp>(b4e12)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b4e1253)
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- **components**:
|
||||
- add the IconTooltip component. - by **Azir-11** [<samp>(a55b4)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a55b4dc)
|
||||
- replace NTooltip with IconTooltip and optimize the layout of related components. - by **Azir-11** [<samp>(40057)</samp>](https://github.com/soybeanjs/soybean-admin/commit/4005763)
|
||||
- **hooks**:
|
||||
- add scrollX computation for total table width in useNaiveTable - by @Lruihao [<samp>(358e1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/358e129)
|
||||
- **packages**:
|
||||
- materials support slider-tab. closed #823 - by @CyberShen in https://github.com/soybeanjs/soybean-admin/issues/823 [<samp>(61fa4)</samp>](https://github.com/soybeanjs/soybean-admin/commit/61fa4b7)
|
||||
- **projects**:
|
||||
- refactor theme drawer with tabbed layout for better UX. - by **Azir** [<samp>(8ba71)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8ba71a0)
|
||||
- Add current time display option for watermark - by @wenyuanw in https://github.com/soybeanjs/soybean-admin/issues/772 [<samp>(f238f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f238fcb)
|
||||
- add 'vertical-hybrid-header-first' layout mode - by @wenyuanw [<samp>(b4e5c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b4e5c6d)
|
||||
- add prompt information for scrolling mode and tab bar caching. - by **Azir-11** [<samp>(29a2a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/29a2a5c)
|
||||
- support theme preset function. - by **Azir-11** [<samp>(257f1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/257f118)
|
||||
- modify the default value of the reset cache policy to 'refresh'. - by **Azir-11** [<samp>(3c0a5)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3c0a528)
|
||||
- optimize tabs cache cleaning strategy. close #820. - by **Azir-11** in https://github.com/soybeanjs/soybean-admin/issues/820 [<samp>(ef7ac)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ef7acc6)
|
||||
- support closing tabs with middle mouse button click - by @wenyuanw [<samp>(a8d1e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a8d1e5d)
|
||||
- support set global redius - by **CyberShen123** [<samp>(24c6d)</samp>](https://github.com/soybeanjs/soybean-admin/commit/24c6df5)
|
||||
- support set global redius - by **CyberShen123** [<samp>(3549c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3549c4d)
|
||||
- **styles**:
|
||||
- add text-autospace property to improve text layout - by @wenyuanw [<samp>(345aa)</samp>](https://github.com/soybeanjs/soybean-admin/commit/345aa29)
|
||||
|
||||
### 🐞 Bug Fixes
|
||||
|
||||
- **hooks**:
|
||||
- correct chart rendering logic in useEcharts - by @soybeanjs [<samp>(8a7cd)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8a7cd59)
|
||||
- **packages**:
|
||||
- fix the parsing logic for stored data to ensure correct return of boolean values - by @Lruihao [<samp>(9ea56)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9ea56c9)
|
||||
- axios: fix json response. fixed #815 - by @soybeanjs in https://github.com/soybeanjs/soybean-admin/issues/815 [<samp>(5be86)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5be864a)
|
||||
- **projects**:
|
||||
- Fix i18n-ally not working when setting moduleResolution to bundler. fixed #780 - by @xiaobao0505 in https://github.com/soybeanjs/soybean-admin/issues/780 [<samp>(41191)</samp>](https://github.com/soybeanjs/soybean-admin/commit/41191d5)
|
||||
- **styles**:
|
||||
- show light color scrollbar while dark mode is on - by **whyang** [<samp>(dac50)</samp>](https://github.com/soybeanjs/soybean-admin/commit/dac5075)
|
||||
- **table**:
|
||||
- add type annotations for records in useTable hook - by @soybeanjs [<samp>(32b8f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/32b8f99)
|
||||
- **types**:
|
||||
- fix proxy types - by @soybeanjs [<samp>(3d72f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3d72f95)
|
||||
- fix ts type error - by @soybeanjs [<samp>(d5a3a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d5a3a25)
|
||||
|
||||
### 🛠 Optimizations
|
||||
|
||||
- **hooks**:
|
||||
- optimize useEcharts - by @soybeanjs [<samp>(936b8)</samp>](https://github.com/soybeanjs/soybean-admin/commit/936b834)
|
||||
- **packages**:
|
||||
- remove ofetch package - by @soybeanjs [<samp>(abaaa)</samp>](https://github.com/soybeanjs/soybean-admin/commit/abaaa4a)
|
||||
- **projects**:
|
||||
- improve theme drawer responsive width for mobile devices - by @wenyuanw [<samp>(8439a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8439a60)
|
||||
- improve robustness of second-level menu key logic - by @wenyuanw [<samp>(8b8a2)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8b8a208)
|
||||
- optimize theme drawer width - by @soybeanjs [<samp>(81468)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8146858)
|
||||
- optimize api type file - by @soybeanjs [<samp>(3a343)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3a343ee)
|
||||
- optimize radius settings - by @soybeanjs [<samp>(87a66)</samp>](https://github.com/soybeanjs/soybean-admin/commit/87a66a4)
|
||||
- **request**:
|
||||
- enhance request options and response handling with generic types - by @soybeanjs [<samp>(50a5c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/50a5cba)
|
||||
|
||||
### 💅 Refactors
|
||||
|
||||
- **hooks**:
|
||||
- optimize useContext and update useMixMenuContext - by @soybeanjs [<samp>(c9651)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c965140)
|
||||
- streamline column visibility handling in useTable and table components - by @soybeanjs [<samp>(ee434)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ee43414)
|
||||
- remove useSignal hook and update exports - by @soybeanjs [<samp>(87adc)</samp>](https://github.com/soybeanjs/soybean-admin/commit/87adc35)
|
||||
- **menu**:
|
||||
- optimize the margin on the menu - by **NicholasLD** [<samp>(d7311)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d731111)
|
||||
- **projects**:
|
||||
- remove unnecessary logic in onRouteSwitchWhenLoggedIn - by @wenyuanw [<samp>(d6c81)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d6c8142)
|
||||
- **request**:
|
||||
- unify response transformation methods and deprecate transformBackendResponse - by @soybeanjs [<samp>(f83ee)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f83eefb)
|
||||
- **types**:
|
||||
- move Auth and Route namespaces to separate files and clean up api.d.ts - by **Azir** [<samp>(d37ce)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d37ce04)
|
||||
|
||||
### 📖 Documentation
|
||||
|
||||
- **projects**: add github trendshift info. - by **恕瑞玛的皇帝** [<samp>(2a0c9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/2a0c9f1)
|
||||
|
||||
### 🏡 Chore
|
||||
|
||||
- **deps**:
|
||||
- update NodeJS and pnpm version requirements in package.json and documentation - by **Junior25306** [<samp>(a5c4b)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a5c4b4e)
|
||||
- update deps - by @soybeanjs [<samp>(5cb1c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5cb1ceb)
|
||||
- update deps - by @soybeanjs [<samp>(aeb63)</samp>](https://github.com/soybeanjs/soybean-admin/commit/aeb6369)
|
||||
- update deps - by @soybeanjs [<samp>(e89b8)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e89b86c)
|
||||
- update deps - by @soybeanjs [<samp>(c962f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c962f7b)
|
||||
- update deps - by @soybeanjs [<samp>(12135)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1213531)
|
||||
- update deps - by @soybeanjs [<samp>(b041f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b041fdd)
|
||||
- update deps - by @soybeanjs [<samp>(d567c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d567c05)
|
||||
- update deps - by @soybeanjs [<samp>(6cbf5)</samp>](https://github.com/soybeanjs/soybean-admin/commit/6cbf570)
|
||||
- **other**:
|
||||
- update the ESLint validation configuration to support more file types. - by **Azir-11** [<samp>(be8f9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/be8f915)
|
||||
- **packages**:
|
||||
- update Vite version to 7 in package.json and documentation. - by **Azir** [<samp>(03dd6)</samp>](https://github.com/soybeanjs/soybean-admin/commit/03dd64c)
|
||||
- add picomatch to fix scripts - by @soybeanjs [<samp>(805c3)</samp>](https://github.com/soybeanjs/soybean-admin/commit/805c338)
|
||||
- **vscode**:
|
||||
- remove unused vue.server.hybridMode setting from .vscode/settings.json - by @soybeanjs [<samp>(13319)</samp>](https://github.com/soybeanjs/soybean-admin/commit/133196f)
|
||||
|
||||
### 🎨 Styles
|
||||
|
||||
- **projects**: format code. - by **Azir-11** [<samp>(100e0)</samp>](https://github.com/soybeanjs/soybean-admin/commit/100e0ea)
|
||||
|
||||
### ❤️ Contributors
|
||||
|
||||
[](https://github.com/soybeanjs) [](https://github.com/wenyuanw) [](https://github.com/CyberShen) [](https://github.com/Lruihao) [](https://github.com/xiaobao0505)
|
||||
[CyberShen123](mailto:s.lijun@qq.com), [whyang](mailto:whyang9701@gmail.com), [HongxuanG](mailto:1359774872@qq.com), [Azir-11](mailto:2075125282@qq.com), [NicholasLD](mailto:878639947@qq.com), [Junior25306](mailto:dayu429@qq.com)
|
||||
|
||||
## [v1.3.15](https://github.com/soybeanjs/soybean-admin/compare/v1.3.14...v1.3.15) (2025-06-24)
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
---
|
||||
|
||||
[](./LICENSE)
|
||||
[](https://github.com/soybeanjs/soybean-admin)
|
||||
[](https://github.com/soybeanjs/soybean-admin)
|
||||
[](https://github.com/soybeanjs/soybean-admin)
|
||||
[](https://github.com/soybeanjs/soybean-admin)
|
||||
[](https://gitee.com/honghuangdc/soybean-admin)
|
||||
[](https://gitcode.com/soybeanjs/soybean-admin)
|
||||
[](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")
|
||||
|
||||
<a href="https://hellogithub.com/repository/1298f27d5fe54959a16cf9686516ddb3" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=1298f27d5fe54959a16cf9686516ddb3&claim_uid=IiDXWmP4TEntjbV" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
|
||||
<div style="display: flex; gap: 12px; align-items: center;">
|
||||
<a href="https://trendshift.io/repositories/7963" target="_blank"><img src="https://trendshift.io/api/badge/repositories/7963" alt="soybeanjs%2Fsoybean-admin | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||
<a href="https://hellogithub.com/repository/1298f27d5fe54959a16cf9686516ddb3" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=1298f27d5fe54959a16cf9686516ddb3&claim_uid=IiDXWmP4TEntjbV" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
</div>
|
||||
|
||||
> [!NOTE]
|
||||
> If you think `SoybeanAdmin` 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!
|
||||
@@ -138,7 +139,7 @@ Refer to the [Code Synchronization](https://docs.soybeanjs.cn/guide/sync) docume
|
||||
|
||||
## Ecosystem
|
||||
|
||||
- [react-soybean-admin](https://github.com/mufeng889/react-soybean-admin): SoybeanAdmin based version of React.
|
||||
- [skyroc-admin](https://github.com/Ohh-889/skyroc-admin): SoybeanAdmin's React version implementation.
|
||||
- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): A Mock Api management system that helps front-end developers quickly implement interface mocks.
|
||||
- [T-Shell](https://github.com/TheBlindM/T-Shell): A terminal emulator and SSH client with configurable command prompts.
|
||||
- [pea](https://github.com/haitang1894/pea) : Adopting SpringBoot3.2 + JDK21, MyBatis-Plus, SpringSecurity security framework, etc., suitable for the simple permission system developed by [soybean-admin](https://gitee.com/honghuangdc/soybean-admin).
|
||||
@@ -179,13 +180,21 @@ Thanks the following people for their contributions. If you want to contribute t
|
||||
<img src="https://contrib.rocks/image?repo=soybeanjs/soybean-admin" />
|
||||
</a>
|
||||
|
||||
---
|
||||
|
||||
Here are the most active contributors from the past year. Thank you all for your support, which has enabled the project's continued development.
|
||||
|
||||
<a href="https://openomy.com/soybeanjs/soybean-admin" target="_blank" style="display: block; width: 100%;" align="center">
|
||||
<img src="https://www.openomy.com/svg?repo=soybeanjs/soybean-admin&chart=list&latestMonth=12" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
|
||||
</a>
|
||||
|
||||
## Communication
|
||||
|
||||
`SoybeanAdmin` 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-4.jpg" style="width:200px" />
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-5.jpg" style="width:200px" />
|
||||
</div>
|
||||
<!-- <div>
|
||||
<p>WeChat Group</p>
|
||||
|
||||
22
README.md
22
README.md
@@ -7,13 +7,15 @@
|
||||
---
|
||||
|
||||
[](./LICENSE)
|
||||
[](https://github.com/soybeanjs/soybean-admin)
|
||||
[](https://github.com/soybeanjs/soybean-admin)
|
||||
[](https://github.com/soybeanjs/soybean-admin)
|
||||
[](https://github.com/soybeanjs/soybean-admin)
|
||||
[](https://gitee.com/honghuangdc/soybean-admin)
|
||||
[](https://gitcode.com/soybeanjs/soybean-admin)
|
||||
[](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")
|
||||
|
||||
<a href="https://hellogithub.com/repository/1298f27d5fe54959a16cf9686516ddb3" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=1298f27d5fe54959a16cf9686516ddb3&claim_uid=IiDXWmP4TEntjbV" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
<div style="display: flex; gap: 12px; align-items: center;">
|
||||
<a href="https://trendshift.io/repositories/7963" target="_blank"><img src="https://trendshift.io/api/badge/repositories/7963" alt="soybeanjs%2Fsoybean-admin | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||
<a href="https://hellogithub.com/repository/1298f27d5fe54959a16cf9686516ddb3" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=1298f27d5fe54959a16cf9686516ddb3&claim_uid=IiDXWmP4TEntjbV" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
</div>
|
||||
|
||||
> [!NOTE]
|
||||
> 如果您觉得 `SoybeanAdmin`对您有所帮助,或者您喜欢我们的项目,请在 GitHub 上给我们一个 ⭐️。您的支持是我们持续改进和增加新功能的动力!感谢您的支持!
|
||||
@@ -163,7 +165,7 @@ pnpm build
|
||||
|
||||
## 周边生态
|
||||
|
||||
- [react-soybean-admin](https://github.com/mufeng889/react-soybean-admin): 基于SoybeanAdmin的React版本.
|
||||
- [skyroc-admin](https://github.com/Ohh-889/skyroc-admin): SoybeanAdmin的React版本实现.
|
||||
- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): 一个 Mock Api 管理系统,帮助前端开发伙伴快速实现接口的 mock。
|
||||
- [T-Shell](https://github.com/TheBlindM/T-Shell): 是一个可配置命令提示的终端模拟器和 SSH 客户端。
|
||||
- [pea](https://github.com/haitang1894/pea) : 采用SpringBoot3.2 + JDK21、MyBatis-Plus、SpringSecurity安全框架等,适配 [soybean-admin](https://gitee.com/honghuangdc/soybean-admin) 开发的简单权限系统。
|
||||
@@ -206,13 +208,21 @@ pnpm build
|
||||
<img src="https://contrib.rocks/image?repo=soybeanjs/soybean-admin" />
|
||||
</a>
|
||||
|
||||
---
|
||||
|
||||
以下是近一年中活跃度较高的贡献者,感谢各位的支持,让项目得以持续发展。
|
||||
|
||||
<a href="https://openomy.com/soybeanjs/soybean-admin" target="_blank" style="display: block; width: 100%;" align="center">
|
||||
<img src="https://www.openomy.com/svg?repo=soybeanjs/soybean-admin&chart=list&latestMonth=12" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
|
||||
</a>
|
||||
|
||||
## 交流
|
||||
|
||||
`SoybeanAdmin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供微信和 QQ 交流群,使用问题欢迎在群内提问。
|
||||
|
||||
<div>
|
||||
<p>QQ交流群</p>
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-4.jpg" style="width:200px" />
|
||||
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/qq-soybean-admin-5.jpg" style="width:200px" />
|
||||
</div>
|
||||
<!-- <div>
|
||||
<p>微信群</p>
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { PluginOption } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import progress from 'vite-plugin-progress';
|
||||
import elegantRouter from 'elegant-router/vite';
|
||||
import { setupElegantRouter } from './router';
|
||||
import { setupUnocss } from './unocss';
|
||||
import { setupUnplugin } from './unplugin';
|
||||
import { setupHtmlPlugin } from './html';
|
||||
@@ -13,7 +13,7 @@ export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
|
||||
vue(),
|
||||
vueJsx(),
|
||||
setupDevtoolsPlugin(viteEnv),
|
||||
elegantRouter(),
|
||||
setupElegantRouter(),
|
||||
setupUnocss(viteEnv),
|
||||
...setupUnplugin(viteEnv),
|
||||
progress(),
|
||||
|
||||
41
build/plugins/router.ts
Normal file
41
build/plugins/router.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
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'
|
||||
},
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
37
er.config.ts
37
er.config.ts
@@ -1,37 +0,0 @@
|
||||
import type { RouteMeta } from 'vue-router';
|
||||
import { defineConfig } from 'elegant-router';
|
||||
import type { RouteKey } from '@elegant-router/types';
|
||||
|
||||
export default defineConfig({
|
||||
pageDir: ['src/views'],
|
||||
layouts: {
|
||||
base: 'src/layouts/base-layout/index.vue',
|
||||
blank: 'src/layouts/blank-layout/index.vue'
|
||||
},
|
||||
getRoutePath: node => {
|
||||
if (node.name === 'Login') {
|
||||
const modules: UnionKey.LoginModule[] = ['pwd-login', 'code-login', 'register', 'reset-pwd', 'bind-wechat'];
|
||||
|
||||
const moduleReg = modules.join('|');
|
||||
|
||||
return `/login/:module(${moduleReg})?`;
|
||||
}
|
||||
|
||||
return node.path;
|
||||
},
|
||||
getRouteMeta: node => {
|
||||
const constantRoutes: RouteKey[] = ['Login', '403', '404', '500'];
|
||||
|
||||
const name = node.name as RouteKey;
|
||||
|
||||
const meta: Partial<RouteMeta> = {
|
||||
title: name
|
||||
};
|
||||
|
||||
if (constantRoutes.includes(name)) {
|
||||
meta.constant = true;
|
||||
}
|
||||
|
||||
return meta;
|
||||
}
|
||||
});
|
||||
59
package.json
59
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "soybean-admin",
|
||||
"type": "module",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"description": "A fresh and elegant admin template, based on Vue3、Vite7、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite7、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
||||
"author": {
|
||||
"name": "Soybean",
|
||||
@@ -54,54 +54,53 @@
|
||||
"@sa/hooks": "workspace:*",
|
||||
"@sa/materials": "workspace:*",
|
||||
"@sa/utils": "workspace:*",
|
||||
"@vueuse/core": "13.8.0",
|
||||
"@vueuse/core": "14.0.0",
|
||||
"clipboard": "2.0.11",
|
||||
"dayjs": "1.11.14",
|
||||
"dayjs": "1.11.19",
|
||||
"defu": "6.1.4",
|
||||
"echarts": "6.0.0",
|
||||
"json5": "2.2.3",
|
||||
"naive-ui": "2.42.0",
|
||||
"naive-ui": "2.43.1",
|
||||
"nprogress": "0.2.0",
|
||||
"pinia": "3.0.3",
|
||||
"tailwind-merge": "3.3.1",
|
||||
"vue": "3.5.20",
|
||||
"pinia": "3.0.4",
|
||||
"tailwind-merge": "3.4.0",
|
||||
"vue": "3.5.24",
|
||||
"vue-draggable-plus": "0.6.0",
|
||||
"vue-i18n": "11.1.11",
|
||||
"vue-router": "4.5.1"
|
||||
"vue-i18n": "11.1.12",
|
||||
"vue-router": "4.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@elegant-router/vue": "0.3.8",
|
||||
"@iconify/json": "2.2.378",
|
||||
"@iconify/json": "2.2.407",
|
||||
"@sa/scripts": "workspace:*",
|
||||
"@sa/uno-preset": "workspace:*",
|
||||
"@soybeanjs/eslint-config": "1.7.1",
|
||||
"@types/node": "24.3.0",
|
||||
"@soybeanjs/eslint-config": "1.7.3",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/nprogress": "0.2.3",
|
||||
"@unocss/eslint-config": "66.4.2",
|
||||
"@unocss/preset-icons": "66.4.2",
|
||||
"@unocss/preset-uno": "66.4.2",
|
||||
"@unocss/transformer-directives": "66.4.2",
|
||||
"@unocss/transformer-variant-group": "66.4.2",
|
||||
"@unocss/vite": "66.4.2",
|
||||
"@unocss/eslint-config": "66.5.6",
|
||||
"@unocss/preset-icons": "66.5.6",
|
||||
"@unocss/preset-uno": "66.5.6",
|
||||
"@unocss/transformer-directives": "66.5.6",
|
||||
"@unocss/transformer-variant-group": "66.5.6",
|
||||
"@unocss/vite": "66.5.6",
|
||||
"@vitejs/plugin-vue": "6.0.1",
|
||||
"@vitejs/plugin-vue-jsx": "5.1.0",
|
||||
"@vitejs/plugin-vue-jsx": "5.1.1",
|
||||
"consola": "3.4.2",
|
||||
"elegant-router": "1.0.4-beta.10",
|
||||
"eslint": "9.34.0",
|
||||
"eslint-plugin-vue": "10.4.0",
|
||||
"eslint": "9.39.1",
|
||||
"eslint-plugin-vue": "10.5.1",
|
||||
"kolorist": "1.8.0",
|
||||
"sass": "1.91.0",
|
||||
"sass": "1.94.0",
|
||||
"simple-git-hooks": "2.13.1",
|
||||
"tsx": "4.20.5",
|
||||
"typescript": "5.9.2",
|
||||
"unplugin-icons": "22.2.0",
|
||||
"unplugin-vue-components": "29.0.0",
|
||||
"vite": "7.1.3",
|
||||
"tsx": "4.20.6",
|
||||
"typescript": "5.9.3",
|
||||
"unplugin-icons": "22.5.0",
|
||||
"unplugin-vue-components": "30.0.0",
|
||||
"vite": "7.2.2",
|
||||
"vite-plugin-progress": "0.0.7",
|
||||
"vite-plugin-svg-icons": "2.0.1",
|
||||
"vite-plugin-vue-devtools": "8.0.1",
|
||||
"vite-plugin-vue-devtools": "8.0.3",
|
||||
"vue-eslint-parser": "10.2.0",
|
||||
"vue-tsc": "3.0.6"
|
||||
"vue-tsc": "3.1.4"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"commit-msg": "pnpm sa git-commit-verify",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/alova",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./fetch": "./src/fetch.ts",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/axios",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@sa/utils": "workspace:*",
|
||||
"axios": "1.11.0",
|
||||
"axios": "1.13.2",
|
||||
"axios-retry": "4.5.0",
|
||||
"qs": "6.14.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig } f
|
||||
import axiosRetry from 'axios-retry';
|
||||
import { nanoid } from '@sa/utils';
|
||||
import { createAxiosConfig, createDefaultOptions, createRetryOptions } from './options';
|
||||
import { transformResponse } from './shared';
|
||||
import { BACKEND_ERROR_CODE, REQUEST_ID_KEY } from './constant';
|
||||
import type {
|
||||
CustomAxiosRequestConfig,
|
||||
@@ -53,6 +54,8 @@ function createCommonRequest<
|
||||
async response => {
|
||||
const responseType: ResponseType = (response.config?.responseType as ResponseType) || 'json';
|
||||
|
||||
await transformResponse(response);
|
||||
|
||||
if (responseType !== 'json' || opts.isBackendSuccess(response)) {
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { AxiosHeaderValue, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||
import type { ResponseType } from './type';
|
||||
|
||||
export function getContentType(config: InternalAxiosRequestConfig) {
|
||||
const contentType: AxiosHeaderValue = config.headers?.['Content-Type'] || 'application/json';
|
||||
@@ -26,3 +27,53 @@ export function isResponseJson(response: AxiosResponse) {
|
||||
|
||||
return responseType === 'json' || responseType === undefined;
|
||||
}
|
||||
|
||||
export async function transformResponse(response: AxiosResponse) {
|
||||
const responseType: ResponseType = (response.config?.responseType as ResponseType) || 'json';
|
||||
if (responseType === 'json') return;
|
||||
|
||||
const isJson = response.headers['content-type']?.includes('application/json');
|
||||
if (!isJson) return;
|
||||
|
||||
if (responseType === 'blob') {
|
||||
await transformBlobToJson(response);
|
||||
}
|
||||
|
||||
if (responseType === 'arrayBuffer') {
|
||||
await transformArrayBufferToJson(response);
|
||||
}
|
||||
}
|
||||
|
||||
export async function transformBlobToJson(response: AxiosResponse) {
|
||||
try {
|
||||
let data = response.data;
|
||||
|
||||
if (typeof data === 'string') {
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if (Object.prototype.toString.call(data) === '[object Blob]') {
|
||||
const json = await data.text();
|
||||
data = JSON.parse(json);
|
||||
}
|
||||
|
||||
response.data = data;
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export async function transformArrayBufferToJson(response: AxiosResponse) {
|
||||
try {
|
||||
let data = response.data;
|
||||
|
||||
if (typeof data === 'string') {
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
|
||||
if (Object.prototype.toString.call(data) === '[object ArrayBuffer]') {
|
||||
const json = new TextDecoder().decode(data);
|
||||
data = JSON.parse(json);
|
||||
}
|
||||
|
||||
response.data = data;
|
||||
} catch {}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/color",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/hooks",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/materials",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
@@ -95,3 +95,27 @@
|
||||
.chrome-tab_dark .chrome-tab-divider {
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.slider-tab {
|
||||
background-color: transparent;
|
||||
height: 100%;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.slider-tab_dark {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.slider-tab:hover {
|
||||
color: var(--soy-primary-color);
|
||||
}
|
||||
|
||||
.slider-tab_active {
|
||||
color: var(--soy-primary-color);
|
||||
background-color: var(--soy-primary-color-opacity1);
|
||||
border-bottom-color: var(--soy-primary-color);
|
||||
}
|
||||
|
||||
.slider-tab_active_dark {
|
||||
background-color: var(--soy-primary-color-opacity2);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ declare const styles: {
|
||||
readonly 'chrome-tab_dark': string;
|
||||
readonly 'chrome-tab-divider': string;
|
||||
readonly 'svg-close': string;
|
||||
readonly 'slider-tab': string;
|
||||
readonly 'slider-tab_active': string;
|
||||
readonly 'slider-tab_active_dark': string;
|
||||
readonly 'slider-tab_dark': string;
|
||||
};
|
||||
|
||||
export default styles;
|
||||
|
||||
@@ -5,6 +5,7 @@ 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 SliderTab from './slider-tab.vue';
|
||||
import SvgClose from './svg-close.vue';
|
||||
import style from './index.module.css';
|
||||
|
||||
@@ -26,7 +27,7 @@ interface Emits {
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const activeTabComponent = computed(() => {
|
||||
const { mode, chromeClass, buttonClass } = props;
|
||||
const { mode, chromeClass, buttonClass, sliderClass } = props;
|
||||
|
||||
const tabComponentMap = {
|
||||
chrome: {
|
||||
@@ -36,6 +37,10 @@ const activeTabComponent = computed(() => {
|
||||
button: {
|
||||
component: ButtonTab,
|
||||
class: buttonClass
|
||||
},
|
||||
slider: {
|
||||
component: SliderTab,
|
||||
class: sliderClass
|
||||
}
|
||||
} satisfies Record<PageTabMode, { component: Component; class?: string }>;
|
||||
|
||||
@@ -45,7 +50,7 @@ const activeTabComponent = computed(() => {
|
||||
const cssVars = computed(() => createTabCssVars(props.activeColor));
|
||||
|
||||
const bindProps = computed(() => {
|
||||
const { chromeClass: _chromeCls, buttonClass: _btnCls, ...rest } = props;
|
||||
const { chromeClass: _chromeCls, buttonClass: _btnCls, sliderClass: _sliderCls, ...rest } = props;
|
||||
|
||||
return rest;
|
||||
});
|
||||
|
||||
53
packages/materials/src/libs/page-tab/slider-tab.vue
Normal file
53
packages/materials/src/libs/page-tab/slider-tab.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<script setup lang="ts">
|
||||
import type { PageTabProps } from '../../types';
|
||||
import style from './index.module.css';
|
||||
|
||||
defineOptions({
|
||||
name: 'SliderTab'
|
||||
});
|
||||
|
||||
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-6px whitespace-nowrap px-12px py-4px"
|
||||
:class="[
|
||||
style['slider-tab'],
|
||||
{ [style['slider-tab_dark']]: darkMode },
|
||||
{ [style['slider-tab_active']]: active },
|
||||
{ [style['slider-tab_active_dark']]: active && darkMode }
|
||||
]"
|
||||
>
|
||||
<slot name="prefix"></slot>
|
||||
<slot></slot>
|
||||
<slot name="suffix"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -239,7 +239,7 @@ export type LayoutCssVars = {
|
||||
*
|
||||
* @default chrome
|
||||
*/
|
||||
export type PageTabMode = 'button' | 'chrome';
|
||||
export type PageTabMode = 'button' | 'chrome' | 'slider';
|
||||
|
||||
export interface PageTabProps {
|
||||
/** Whether is dark mode */
|
||||
@@ -262,6 +262,8 @@ export interface PageTabProps {
|
||||
buttonClass?: string;
|
||||
/** The class of the chrome tab */
|
||||
chromeClass?: string;
|
||||
/** The class of the title tab */
|
||||
sliderClass?: string;
|
||||
/** Whether the tab is active */
|
||||
active?: boolean;
|
||||
/** The color of the active tab */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/scripts",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"bin": {
|
||||
"sa": "./bin.ts"
|
||||
},
|
||||
@@ -13,16 +13,16 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@soybeanjs/changelog": "0.3.24",
|
||||
"bumpp": "10.2.3",
|
||||
"c12": "3.2.0",
|
||||
"@soybeanjs/changelog": "0.3.25",
|
||||
"bumpp": "10.3.1",
|
||||
"c12": "3.3.2",
|
||||
"cac": "6.7.14",
|
||||
"consola": "3.4.2",
|
||||
"enquirer": "2.4.1",
|
||||
"execa": "9.6.0",
|
||||
"kolorist": "1.8.0",
|
||||
"npm-check-updates": "18.0.3",
|
||||
"npm-check-updates": "19.1.2",
|
||||
"picomatch": "4.0.3",
|
||||
"rimraf": "6.0.1"
|
||||
"rimraf": "6.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { execCommand } from '../shared';
|
||||
|
||||
export async function updatePkg(args: string[] = ['--deep', '-u']) {
|
||||
execCommand('npx', ['ncu', ...args], { stdio: 'inherit' });
|
||||
execCommand('npx', ['npm-check-updates', ...args], { stdio: 'inherit' });
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/uno-preset",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sa/utils",
|
||||
"version": "1.3.15",
|
||||
"version": "2.0.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
@@ -14,7 +14,7 @@
|
||||
"crypto-js": "4.2.0",
|
||||
"klona": "2.0.6",
|
||||
"localforage": "1.10.0",
|
||||
"nanoid": "5.1.5"
|
||||
"nanoid": "5.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "4.2.2"
|
||||
|
||||
2877
pnpm-lock.yaml
generated
2877
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,8 @@ export const themeScrollModeOptions = transformRecordToOption(themeScrollModeRec
|
||||
|
||||
export const themeTabModeRecord: Record<UnionKey.ThemeTabMode, App.I18n.I18nKey> = {
|
||||
chrome: 'theme.layout.tab.mode.chrome',
|
||||
button: 'theme.layout.tab.mode.button'
|
||||
button: 'theme.layout.tab.mode.button',
|
||||
slider: 'theme.layout.tab.mode.slider'
|
||||
};
|
||||
|
||||
export const themeTabModeOptions = transformRecordToOption(themeTabModeRecord);
|
||||
@@ -57,13 +58,6 @@ export const themePageAnimationModeRecord: Record<UnionKey.ThemePageAnimateMode,
|
||||
|
||||
export const themePageAnimationModeOptions = transformRecordToOption(themePageAnimationModeRecord);
|
||||
|
||||
export const resetCacheStrategyRecord: Record<UnionKey.ResetCacheStrategy, App.I18n.I18nKey> = {
|
||||
refresh: 'theme.layout.resetCacheStrategy.refresh',
|
||||
close: 'theme.layout.resetCacheStrategy.close'
|
||||
};
|
||||
|
||||
export const resetCacheStrategyOptions = transformRecordToOption(resetCacheStrategyRecord);
|
||||
|
||||
export const DARK_CLASS = 'dark';
|
||||
|
||||
export const watermarkTimeFormatOptions = [
|
||||
|
||||
@@ -18,7 +18,7 @@ defineOptions({
|
||||
|
||||
const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
const { childLevelMenus, isActiveFirstLevelMenuHasChildren } = provideMixMenuContext();
|
||||
const { secondLevelMenus, childLevelMenus, isActiveFirstLevelMenuHasChildren } = provideMixMenuContext();
|
||||
|
||||
const GlobalMenu = defineAsyncComponent(() => import('../modules/global-menu/index.vue'));
|
||||
|
||||
@@ -77,9 +77,9 @@ const isTopHybridSidebarFirst = computed(() => themeStore.layout.mode === 'top-h
|
||||
|
||||
const isTopHybridHeaderFirst = computed(() => themeStore.layout.mode === 'top-hybrid-header-first');
|
||||
|
||||
const siderWidth = computed(() => getSiderWidth());
|
||||
const siderWidth = computed(() => getSiderAndCollapsedWidth(false));
|
||||
|
||||
const siderCollapsedWidth = computed(() => getSiderCollapsedWidth());
|
||||
const siderCollapsedWidth = computed(() => getSiderAndCollapsedWidth(true));
|
||||
|
||||
function getSiderAndCollapsedWidth(isCollapsed: boolean) {
|
||||
const {
|
||||
@@ -104,7 +104,7 @@ function getSiderAndCollapsedWidth(isCollapsed: boolean) {
|
||||
const isMixMode = isVerticalMix.value || isTopHybridSidebarFirst.value || isVerticalHybridHeaderFirst.value;
|
||||
let finalWidth = isMixMode ? mixWidth : width;
|
||||
|
||||
if (isVerticalMix.value && appStore.mixSiderFixed && childLevelMenus.value.length) {
|
||||
if (isVerticalMix.value && appStore.mixSiderFixed && secondLevelMenus.value.length) {
|
||||
finalWidth += mixChildMenuWidth;
|
||||
}
|
||||
|
||||
@@ -114,14 +114,6 @@ function getSiderAndCollapsedWidth(isCollapsed: boolean) {
|
||||
|
||||
return finalWidth;
|
||||
}
|
||||
|
||||
function getSiderWidth() {
|
||||
return getSiderAndCollapsedWidth(false);
|
||||
}
|
||||
|
||||
function getSiderCollapsedWidth() {
|
||||
return getSiderAndCollapsedWidth(true);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -26,6 +26,8 @@ const tabRef = ref<HTMLElement>();
|
||||
const isPCFlag = isPC();
|
||||
|
||||
const TAB_DATA_ID = 'data-tab-id';
|
||||
const MIDDLE_MOUSE_BUTTON = 1;
|
||||
const RIGHT_MOUSE_BUTTON = 2;
|
||||
|
||||
type TabNamedNodeMap = NamedNodeMap & {
|
||||
[TAB_DATA_ID]: Attr;
|
||||
@@ -84,6 +86,26 @@ function handleCloseTab(tab: App.Global.Tab) {
|
||||
tabStore.removeTab(tab.id);
|
||||
}
|
||||
|
||||
function handleMousedown(e: MouseEvent, tab: App.Global.Tab) {
|
||||
const isMiddleClick = e.button === MIDDLE_MOUSE_BUTTON;
|
||||
if (!isMiddleClick || !themeStore.tab.closeTabByMiddleClick) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tabStore.isTabRetain(tab.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
handleCloseTab(tab);
|
||||
}
|
||||
|
||||
function switchTab(e: MouseEvent, tab: App.Global.Tab) {
|
||||
if ([MIDDLE_MOUSE_BUTTON, RIGHT_MOUSE_BUTTON].includes(e.button)) return;
|
||||
|
||||
tabStore.switchRouteByTab(tab);
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
appStore.reloadPage(500);
|
||||
}
|
||||
@@ -169,7 +191,9 @@ init();
|
||||
<div
|
||||
ref="tabRef"
|
||||
class="h-full flex pr-18px"
|
||||
:class="[themeStore.tab.mode === 'chrome' ? 'items-end' : 'items-center gap-12px']"
|
||||
:class="[
|
||||
themeStore.tab.mode === 'chrome' || themeStore.tab.mode === 'slider' ? 'items-end' : 'items-center gap-12px'
|
||||
]"
|
||||
>
|
||||
<PageTab
|
||||
v-for="tab in tabStore.tabs"
|
||||
@@ -180,7 +204,8 @@ init();
|
||||
:active="tab.id === tabStore.activeTabId"
|
||||
:active-color="themeStore.themeColor"
|
||||
:closable="!tabStore.isTabRetain(tab.id)"
|
||||
@pointerdown="tabStore.switchRouteByTab(tab)"
|
||||
@pointerdown="switchTab($event, tab)"
|
||||
@mousedown="handleMousedown($event, tab)"
|
||||
@close="handleCloseTab(tab)"
|
||||
@contextmenu="handleContextMenu($event, tab.id)"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import ThemeSchema from './modules/theme-schema.vue';
|
||||
import ThemeColor from './modules/theme-color.vue';
|
||||
import ThemeRadius from './modules/theme-radius.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'AppearanceSettings'
|
||||
@@ -11,6 +12,7 @@ defineOptions({
|
||||
<div class="flex-col-stretch gap-16px">
|
||||
<ThemeSchema />
|
||||
<ThemeColor />
|
||||
<ThemeRadius />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { $t } from '@/locales';
|
||||
import SettingItem from '../../../components/setting-item.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'ThemeRadius'
|
||||
});
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NDivider>{{ $t('theme.appearance.themeRadius.title') }}</NDivider>
|
||||
<TransitionGroup tag="div" name="setting-list" class="flex-col-stretch gap-12px">
|
||||
<SettingItem key="1" :label="$t('theme.appearance.themeRadius.title')">
|
||||
<NInputNumber v-model:value="themeStore.themeRadius" size="small" :step="1" :min="0" :max="16" class="w-120px" />
|
||||
</SettingItem>
|
||||
</TransitionGroup>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { resetCacheStrategyOptions, themeTabModeOptions } from '@/constants/app';
|
||||
import { themeTabModeOptions } from '@/constants/app';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { translateOptions } from '@/utils/common';
|
||||
import { $t } from '@/locales';
|
||||
@@ -15,14 +15,6 @@ const themeStore = useThemeStore();
|
||||
<template>
|
||||
<NDivider>{{ $t('theme.layout.tab.title') }}</NDivider>
|
||||
<TransitionGroup tag="div" name="setting-list" class="flex-col-stretch gap-12px">
|
||||
<SettingItem key="0" :label="$t('theme.layout.resetCacheStrategy.title')">
|
||||
<NSelect
|
||||
v-model:value="themeStore.resetCacheStrategy"
|
||||
:options="translateOptions(resetCacheStrategyOptions)"
|
||||
size="small"
|
||||
class="w-120px"
|
||||
/>
|
||||
</SettingItem>
|
||||
<SettingItem key="1" :label="$t('theme.layout.tab.visible')">
|
||||
<NSwitch v-model:value="themeStore.tab.visible" />
|
||||
</SettingItem>
|
||||
@@ -43,6 +35,12 @@ const themeStore = useThemeStore();
|
||||
class="w-120px"
|
||||
/>
|
||||
</SettingItem>
|
||||
<SettingItem v-if="themeStore.tab.visible" key="5" :label="$t('theme.layout.tab.closeByMiddleClick')">
|
||||
<template #suffix>
|
||||
<IconTooltip :desc="$t('theme.layout.tab.closeByMiddleClickTip')" />
|
||||
</template>
|
||||
<NSwitch v-model:value="themeStore.tab.closeTabByMiddleClick" />
|
||||
</SettingItem>
|
||||
</TransitionGroup>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ type ThemePreset = Pick<
|
||||
| 'colourWeakness'
|
||||
| 'recommendColor'
|
||||
| 'themeColor'
|
||||
| 'themeRadius'
|
||||
| 'otherColor'
|
||||
| 'isInfoFollowPrimary'
|
||||
| 'resetCacheStrategy'
|
||||
| 'layout'
|
||||
| 'page'
|
||||
| 'header'
|
||||
|
||||
@@ -83,6 +83,9 @@ const local: App.I18n.Schema = {
|
||||
error: 'Error',
|
||||
followPrimary: 'Follow Primary'
|
||||
},
|
||||
themeRadius: {
|
||||
title: 'Theme Radius'
|
||||
},
|
||||
recommendColor: 'Apply Recommended Color Algorithm',
|
||||
recommendColorDesc: 'The recommended color algorithm refers to',
|
||||
preset: {
|
||||
@@ -135,9 +138,12 @@ const local: App.I18n.Schema = {
|
||||
height: 'Tab Height',
|
||||
mode: {
|
||||
title: 'Tab Mode',
|
||||
slider: 'Slider',
|
||||
chrome: 'Chrome',
|
||||
button: 'Button'
|
||||
}
|
||||
},
|
||||
closeByMiddleClick: 'Close Tab by Middle Click',
|
||||
closeByMiddleClickTip: 'Enable closing tabs by clicking with the middle mouse button'
|
||||
},
|
||||
header: {
|
||||
title: 'Header Settings',
|
||||
@@ -185,11 +191,6 @@ const local: App.I18n.Schema = {
|
||||
}
|
||||
},
|
||||
fixedHeaderAndTab: 'Fixed Header And Tab'
|
||||
},
|
||||
resetCacheStrategy: {
|
||||
title: 'Reset Cache Strategy',
|
||||
close: 'Close Page',
|
||||
refresh: 'Refresh Page'
|
||||
}
|
||||
},
|
||||
general: {
|
||||
|
||||
@@ -83,6 +83,9 @@ const local: App.I18n.Schema = {
|
||||
error: '错误色',
|
||||
followPrimary: '跟随主色'
|
||||
},
|
||||
themeRadius: {
|
||||
title: '主题圆角'
|
||||
},
|
||||
recommendColor: '应用推荐算法的颜色',
|
||||
recommendColorDesc: '推荐颜色的算法参照',
|
||||
preset: {
|
||||
@@ -132,9 +135,12 @@ const local: App.I18n.Schema = {
|
||||
height: '标签栏高度',
|
||||
mode: {
|
||||
title: '标签栏风格',
|
||||
slider: '滑块风格',
|
||||
chrome: '谷歌风格',
|
||||
button: '按钮风格'
|
||||
}
|
||||
},
|
||||
closeByMiddleClick: '鼠标中键关闭标签页',
|
||||
closeByMiddleClickTip: '启用后可以使用鼠标中键点击标签页进行关闭'
|
||||
},
|
||||
header: {
|
||||
title: '头部设置',
|
||||
@@ -158,7 +164,7 @@ const local: App.I18n.Schema = {
|
||||
visible: '显示底部',
|
||||
fixed: '固定底部',
|
||||
height: '底部高度',
|
||||
right: '底部局右'
|
||||
right: '底部居右'
|
||||
},
|
||||
content: {
|
||||
title: '内容区域设置',
|
||||
@@ -182,11 +188,6 @@ const local: App.I18n.Schema = {
|
||||
}
|
||||
},
|
||||
fixedHeaderAndTab: '固定头部和标签栏'
|
||||
},
|
||||
resetCacheStrategy: {
|
||||
title: '重置缓存策略',
|
||||
close: '关闭页面',
|
||||
refresh: '刷新页面'
|
||||
}
|
||||
},
|
||||
general: {
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
/* oxlint-disable */
|
||||
// biome-ignore lint: disable
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
import type { RouteFileKey, RouteLayoutKey, RawRouteComponent } from "@elegant-router/types";
|
||||
|
||||
export const layouts: Record<RouteLayoutKey, RawRouteComponent> = {
|
||||
base: () => import("@/layouts/base-layout/index.vue"),
|
||||
blank: () => import("@/layouts/blank-layout/index.vue"),
|
||||
};
|
||||
|
||||
export const views: Record<RouteFileKey, RawRouteComponent> = {
|
||||
403: () => import("@/views/(builtin)/403/index.vue"),
|
||||
404: () => import("@/views/(builtin)/404/index.vue"),
|
||||
500: () => import("@/views/(builtin)/500/index.vue"),
|
||||
Home: () => import("@/views/home/index.vue"),
|
||||
IframeUrl: () => import("@/views/(builtin)/iframe/[url].vue"),
|
||||
Login: () => import("@/views/(builtin)/login/index.vue"),
|
||||
ManageApi: () => import("@/views/manage/api/index.vue"),
|
||||
ManageDictionary: () => import("@/views/manage/dictionary/index.vue"),
|
||||
ManageMenu: () => import("@/views/manage/menu/index.vue"),
|
||||
ManageOrganization: () => import("@/views/manage/organization/index.vue"),
|
||||
ManagePermission: () => import("@/views/manage/permission/index.vue"),
|
||||
ManageRole: () => import("@/views/manage/role/index.vue"),
|
||||
ManageRoute: () => import("@/views/manage/route/index.vue"),
|
||||
ManageUser: () => import("@/views/manage/user/index.vue"),
|
||||
Wip: () => import("@/views/(builtin)/wip/index.vue"),
|
||||
};
|
||||
@@ -1,166 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// biome-ignore lint: disable
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
import type { AutoRouterRoute } from '@elegant-router/types';
|
||||
|
||||
export const routes: AutoRouterRoute[] = [
|
||||
{
|
||||
name: 'Root',
|
||||
path: '/',
|
||||
redirect: '/home',
|
||||
meta: {
|
||||
title: "Root"
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'NotFound',
|
||||
path: '/:pathMatch(.*)*',
|
||||
layout: 'base',
|
||||
component: '404',
|
||||
meta: {
|
||||
title: "NotFound"
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '403',
|
||||
path: '/403',
|
||||
layout: 'base',
|
||||
component: '403',
|
||||
meta: {
|
||||
title: "403",
|
||||
constant: true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '404',
|
||||
path: '/404',
|
||||
layout: 'base',
|
||||
component: '404',
|
||||
meta: {
|
||||
title: "404",
|
||||
constant: true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '500',
|
||||
path: '/500',
|
||||
layout: 'base',
|
||||
component: '500',
|
||||
meta: {
|
||||
title: "500",
|
||||
constant: true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Home',
|
||||
path: '/home',
|
||||
layout: 'base',
|
||||
component: 'Home',
|
||||
meta: {
|
||||
title: "Home"
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'IframeUrl',
|
||||
path: '/iframe/:url',
|
||||
layout: 'base',
|
||||
component: 'IframeUrl',
|
||||
meta: {
|
||||
title: "IframeUrl"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Login',
|
||||
path: '/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?',
|
||||
layout: 'base',
|
||||
component: 'Login',
|
||||
meta: {
|
||||
title: "Login",
|
||||
constant: true
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ManageApi',
|
||||
path: '/manage/api',
|
||||
layout: 'base',
|
||||
component: 'ManageApi',
|
||||
meta: {
|
||||
title: "ManageApi"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ManageDictionary',
|
||||
path: '/manage/dictionary',
|
||||
layout: 'base',
|
||||
component: 'ManageDictionary',
|
||||
meta: {
|
||||
title: "ManageDictionary"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ManageMenu',
|
||||
path: '/manage/menu',
|
||||
layout: 'base',
|
||||
component: 'ManageMenu',
|
||||
meta: {
|
||||
title: "ManageMenu"
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ManageOrganization',
|
||||
path: '/manage/organization',
|
||||
layout: 'base',
|
||||
component: 'ManageOrganization',
|
||||
meta: {
|
||||
title: "ManageOrganization"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ManagePermission',
|
||||
path: '/manage/permission',
|
||||
layout: 'base',
|
||||
component: 'ManagePermission',
|
||||
meta: {
|
||||
title: "ManagePermission"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ManageRole',
|
||||
path: '/manage/role',
|
||||
layout: 'base',
|
||||
component: 'ManageRole',
|
||||
meta: {
|
||||
title: "ManageRole"
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ManageRoute',
|
||||
path: '/manage/route',
|
||||
layout: 'base',
|
||||
component: 'ManageRoute',
|
||||
meta: {
|
||||
title: "ManageRoute"
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ManageUser',
|
||||
path: '/manage/user',
|
||||
layout: 'base',
|
||||
component: 'ManageUser',
|
||||
meta: {
|
||||
title: "ManageUser"
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Wip',
|
||||
path: '/wip',
|
||||
layout: 'base',
|
||||
component: 'Wip',
|
||||
meta: {
|
||||
title: "Wip"
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -1,32 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
/* oxlint-disable */
|
||||
// biome-ignore lint: disable
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
import type { RouteKey, RoutePathMap } from '@elegant-router/types';
|
||||
|
||||
const routePathMap: RoutePathMap = {
|
||||
"Root": "/",
|
||||
"NotFound": "/:pathMatch(.*)*",
|
||||
"403": "/403",
|
||||
"404": "/404",
|
||||
"500": "/500",
|
||||
"Home": "/home",
|
||||
"IframeUrl": "/iframe/:url",
|
||||
"Login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
|
||||
"ManageApi": "/manage/api",
|
||||
"ManageDictionary": "/manage/dictionary",
|
||||
"ManageMenu": "/manage/menu",
|
||||
"ManageOrganization": "/manage/organization",
|
||||
"ManagePermission": "/manage/permission",
|
||||
"ManageRole": "/manage/role",
|
||||
"ManageRoute": "/manage/route",
|
||||
"ManageUser": "/manage/user",
|
||||
"Wip": "/wip",
|
||||
};
|
||||
|
||||
export function getRoutePath(key: RouteKey) {
|
||||
return routePathMap[key];
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
/* oxlint-disable */
|
||||
// biome-ignore lint: disable
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import type {
|
||||
AutoRouterRedirect,
|
||||
AutoRouterRoute,
|
||||
AutoRouterSingleView,
|
||||
RawRouteComponent,
|
||||
RouteFileKey,
|
||||
RouteLayoutKey
|
||||
} from '@elegant-router/types';
|
||||
|
||||
export function transformToVueRoutes(
|
||||
routes: AutoRouterRoute[],
|
||||
layouts: Record<RouteLayoutKey, RawRouteComponent>,
|
||||
views: Record<RouteFileKey, RawRouteComponent>
|
||||
) {
|
||||
const { redirects, groupedRoutes } = getFormattedRoutes(routes);
|
||||
|
||||
const vueRoutes: RouteRecordRaw[] = [...redirects];
|
||||
|
||||
groupedRoutes.forEach((items, layout) => {
|
||||
const layoutRoute: RouteRecordRaw = {
|
||||
path: `/${layout}-layout`,
|
||||
component: layouts[layout],
|
||||
children: items.map(item => {
|
||||
const { layout: _, component, ...rest } = item;
|
||||
|
||||
return {
|
||||
component: views[component],
|
||||
...rest
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
vueRoutes.push(layoutRoute);
|
||||
});
|
||||
|
||||
return vueRoutes;
|
||||
}
|
||||
|
||||
function getFormattedRoutes(routes: AutoRouterRoute[]) {
|
||||
const groupedRoutes = new Map<RouteLayoutKey, AutoRouterSingleView[]>();
|
||||
const redirects: AutoRouterRedirect[] = [];
|
||||
|
||||
routes.forEach(route => {
|
||||
if (isAutoRouterRedirect(route)) {
|
||||
redirects.push(route);
|
||||
return;
|
||||
}
|
||||
|
||||
const items = groupedRoutes.get(route.layout) || [];
|
||||
items.push(route);
|
||||
groupedRoutes.set(route.layout, items);
|
||||
});
|
||||
|
||||
return {
|
||||
redirects,
|
||||
groupedRoutes
|
||||
};
|
||||
}
|
||||
|
||||
function isAutoRouterRedirect(route: AutoRouterRoute): route is AutoRouterRedirect {
|
||||
return 'redirect' in route;
|
||||
}
|
||||
24
src/router/elegant/imports.ts
Normal file
24
src/router/elegant/imports.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
import type { RouteComponent } from "vue-router";
|
||||
import type { LastLevelRouteKey, RouteLayout } from "@elegant-router/types";
|
||||
|
||||
import BaseLayout from "@/layouts/base-layout/index.vue";
|
||||
import BlankLayout from "@/layouts/blank-layout/index.vue";
|
||||
|
||||
export const layouts: Record<RouteLayout, RouteComponent | (() => Promise<RouteComponent>)> = {
|
||||
base: BaseLayout,
|
||||
blank: BlankLayout,
|
||||
};
|
||||
|
||||
export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<RouteComponent>)> = {
|
||||
403: () => import("@/views/_builtin/403/index.vue"),
|
||||
404: () => import("@/views/_builtin/404/index.vue"),
|
||||
500: () => import("@/views/_builtin/500/index.vue"),
|
||||
"iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"),
|
||||
login: () => import("@/views/_builtin/login/index.vue"),
|
||||
home: () => import("@/views/home/index.vue"),
|
||||
};
|
||||
78
src/router/elegant/routes.ts
Normal file
78
src/router/elegant/routes.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
import type { GeneratedRoute } from '@elegant-router/types';
|
||||
|
||||
export const generatedRoutes: GeneratedRoute[] = [
|
||||
{
|
||||
name: '403',
|
||||
path: '/403',
|
||||
component: 'layout.blank$view.403',
|
||||
meta: {
|
||||
title: '403',
|
||||
i18nKey: 'route.403',
|
||||
constant: true,
|
||||
hideInMenu: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '404',
|
||||
path: '/404',
|
||||
component: 'layout.blank$view.404',
|
||||
meta: {
|
||||
title: '404',
|
||||
i18nKey: 'route.404',
|
||||
constant: true,
|
||||
hideInMenu: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '500',
|
||||
path: '/500',
|
||||
component: 'layout.blank$view.500',
|
||||
meta: {
|
||||
title: '500',
|
||||
i18nKey: 'route.500',
|
||||
constant: true,
|
||||
hideInMenu: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'home',
|
||||
path: '/home',
|
||||
component: 'layout.base$view.home',
|
||||
meta: {
|
||||
title: 'home',
|
||||
i18nKey: 'route.home',
|
||||
icon: 'mdi:monitor-dashboard',
|
||||
order: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'iframe-page',
|
||||
path: '/iframe-page/:url',
|
||||
component: 'layout.base$view.iframe-page',
|
||||
props: true,
|
||||
meta: {
|
||||
title: 'iframe-page',
|
||||
i18nKey: 'route.iframe-page',
|
||||
constant: true,
|
||||
hideInMenu: true,
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'login',
|
||||
path: '/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?',
|
||||
component: 'layout.blank$view.login',
|
||||
props: true,
|
||||
meta: {
|
||||
title: 'login',
|
||||
i18nKey: 'route.login',
|
||||
constant: true,
|
||||
hideInMenu: true
|
||||
}
|
||||
}
|
||||
];
|
||||
192
src/router/elegant/transform.ts
Normal file
192
src/router/elegant/transform.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
import type { RouteRecordRaw, RouteComponent } from 'vue-router';
|
||||
import type { ElegantConstRoute } from '@elegant-router/vue';
|
||||
import type { RouteMap, RouteKey, RoutePath } from '@elegant-router/types';
|
||||
|
||||
/**
|
||||
* transform elegant const routes to vue routes
|
||||
* @param routes elegant const routes
|
||||
* @param layouts layout components
|
||||
* @param views view components
|
||||
*/
|
||||
export function transformElegantRoutesToVueRoutes(
|
||||
routes: ElegantConstRoute[],
|
||||
layouts: Record<string, RouteComponent | (() => Promise<RouteComponent>)>,
|
||||
views: Record<string, RouteComponent | (() => Promise<RouteComponent>)>
|
||||
) {
|
||||
return routes.flatMap(route => transformElegantRouteToVueRoute(route, layouts, views));
|
||||
}
|
||||
|
||||
/**
|
||||
* transform elegant route to vue route
|
||||
* @param route elegant const route
|
||||
* @param layouts layout components
|
||||
* @param views view components
|
||||
*/
|
||||
function transformElegantRouteToVueRoute(
|
||||
route: ElegantConstRoute,
|
||||
layouts: Record<string, RouteComponent | (() => Promise<RouteComponent>)>,
|
||||
views: Record<string, RouteComponent | (() => Promise<RouteComponent>)>
|
||||
) {
|
||||
const LAYOUT_PREFIX = 'layout.';
|
||||
const VIEW_PREFIX = 'view.';
|
||||
const ROUTE_DEGREE_SPLITTER = '_';
|
||||
const FIRST_LEVEL_ROUTE_COMPONENT_SPLIT = '$';
|
||||
|
||||
function isLayout(component: string) {
|
||||
return component.startsWith(LAYOUT_PREFIX);
|
||||
}
|
||||
|
||||
function getLayoutName(component: string) {
|
||||
const layout = component.replace(LAYOUT_PREFIX, '');
|
||||
|
||||
if(!layouts[layout]) {
|
||||
throw new Error(`Layout component "${layout}" not found`);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
function isView(component: string) {
|
||||
return component.startsWith(VIEW_PREFIX);
|
||||
}
|
||||
|
||||
function getViewName(component: string) {
|
||||
const view = component.replace(VIEW_PREFIX, '');
|
||||
|
||||
if(!views[view]) {
|
||||
throw new Error(`View component "${view}" not found`);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
function isFirstLevelRoute(item: ElegantConstRoute) {
|
||||
return !item.name.includes(ROUTE_DEGREE_SPLITTER);
|
||||
}
|
||||
|
||||
function isSingleLevelRoute(item: ElegantConstRoute) {
|
||||
return isFirstLevelRoute(item) && !item.children?.length;
|
||||
}
|
||||
|
||||
function getSingleLevelRouteComponent(component: string) {
|
||||
const [layout, view] = component.split(FIRST_LEVEL_ROUTE_COMPONENT_SPLIT);
|
||||
|
||||
return {
|
||||
layout: getLayoutName(layout),
|
||||
view: getViewName(view)
|
||||
};
|
||||
}
|
||||
|
||||
const vueRoutes: RouteRecordRaw[] = [];
|
||||
|
||||
// add props: true to route
|
||||
if (route.path.includes(':') && !route.props) {
|
||||
route.props = true;
|
||||
}
|
||||
|
||||
const { name, path, component, children, ...rest } = route;
|
||||
|
||||
const vueRoute = { name, path, ...rest } as RouteRecordRaw;
|
||||
|
||||
try {
|
||||
if (component) {
|
||||
if (isSingleLevelRoute(route)) {
|
||||
const { layout, view } = getSingleLevelRouteComponent(component);
|
||||
|
||||
const singleLevelRoute: RouteRecordRaw = {
|
||||
path,
|
||||
component: layouts[layout],
|
||||
meta: {
|
||||
title: route.meta?.title || ''
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name,
|
||||
path: '',
|
||||
component: views[view],
|
||||
...rest
|
||||
} as RouteRecordRaw
|
||||
]
|
||||
};
|
||||
|
||||
return [singleLevelRoute];
|
||||
}
|
||||
|
||||
if (isLayout(component)) {
|
||||
const layoutName = getLayoutName(component);
|
||||
|
||||
vueRoute.component = layouts[layoutName];
|
||||
}
|
||||
|
||||
if (isView(component)) {
|
||||
const viewName = getViewName(component);
|
||||
|
||||
vueRoute.component = views[viewName];
|
||||
}
|
||||
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`Error transforming route "${route.name}": ${error.toString()}`);
|
||||
return [];
|
||||
}
|
||||
|
||||
// add redirect to child
|
||||
if (children?.length && !vueRoute.redirect) {
|
||||
vueRoute.redirect = {
|
||||
name: children[0].name
|
||||
};
|
||||
}
|
||||
|
||||
if (children?.length) {
|
||||
const childRoutes = children.flatMap(child => transformElegantRouteToVueRoute(child, layouts, views));
|
||||
|
||||
if(isFirstLevelRoute(route)) {
|
||||
vueRoute.children = childRoutes;
|
||||
} else {
|
||||
vueRoutes.push(...childRoutes);
|
||||
}
|
||||
}
|
||||
|
||||
vueRoutes.unshift(vueRoute);
|
||||
|
||||
return vueRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* map of route name and route path
|
||||
*/
|
||||
const routeMap: RouteMap = {
|
||||
"root": "/",
|
||||
"not-found": "/:pathMatch(.*)*",
|
||||
"403": "/403",
|
||||
"404": "/404",
|
||||
"500": "/500",
|
||||
"home": "/home",
|
||||
"iframe-page": "/iframe-page/:url",
|
||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?"
|
||||
};
|
||||
|
||||
/**
|
||||
* get route path by route name
|
||||
* @param name route name
|
||||
*/
|
||||
export function getRoutePath<T extends RouteKey>(name: T) {
|
||||
return routeMap[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* get route name by route path
|
||||
* @param path route path
|
||||
*/
|
||||
export function getRouteName(path: RoutePath) {
|
||||
const routeEntries = Object.entries(routeMap) as [RouteKey, RoutePath][];
|
||||
|
||||
const routeName: RouteKey | null = routeEntries.find(([, routePath]) => routePath === path)?.[0] || null;
|
||||
|
||||
return routeName;
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
import type { App } from 'vue';
|
||||
import { createMemoryHistory, createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
|
||||
import type { RouterHistory } from 'vue-router';
|
||||
import {
|
||||
type RouterHistory,
|
||||
createMemoryHistory,
|
||||
createRouter,
|
||||
createWebHashHistory,
|
||||
createWebHistory
|
||||
} from 'vue-router';
|
||||
import { createBuiltinVueRoutes } from './routes/builtin';
|
||||
import { createRouterGuard } from './guard';
|
||||
|
||||
const { VITE_ROUTER_HISTORY_MODE = 'history', VITE_BASE_URL } = import.meta.env;
|
||||
@@ -13,7 +19,7 @@ const historyCreatorMap: Record<Env.RouterHistoryMode, (base?: string) => Router
|
||||
|
||||
export const router = createRouter({
|
||||
history: historyCreatorMap[VITE_ROUTER_HISTORY_MODE](VITE_BASE_URL),
|
||||
routes: []
|
||||
routes: createBuiltinVueRoutes()
|
||||
});
|
||||
|
||||
/** Setup Vue Router */
|
||||
|
||||
31
src/router/routes/builtin.ts
Normal file
31
src/router/routes/builtin.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import type { CustomRoute } from '@elegant-router/types';
|
||||
import { layouts, views } from '../elegant/imports';
|
||||
import { getRoutePath, transformElegantRoutesToVueRoutes } from '../elegant/transform';
|
||||
|
||||
export const ROOT_ROUTE: CustomRoute = {
|
||||
name: 'root',
|
||||
path: '/',
|
||||
redirect: getRoutePath(import.meta.env.VITE_ROUTE_HOME) || '/home',
|
||||
meta: {
|
||||
title: 'root',
|
||||
constant: true
|
||||
}
|
||||
};
|
||||
|
||||
const NOT_FOUND_ROUTE: CustomRoute = {
|
||||
name: 'not-found',
|
||||
path: '/:pathMatch(.*)*',
|
||||
component: 'layout.blank$view.404',
|
||||
meta: {
|
||||
title: 'not-found',
|
||||
constant: true
|
||||
}
|
||||
};
|
||||
|
||||
/** builtin routes, it must be constant and setup in vue-router */
|
||||
const builtinRoutes: CustomRoute[] = [ROOT_ROUTE, NOT_FOUND_ROUTE];
|
||||
|
||||
/** create builtin vue routes */
|
||||
export function createBuiltinVueRoutes() {
|
||||
return transformElegantRoutesToVueRoutes(builtinRoutes, layouts, views);
|
||||
}
|
||||
@@ -1,14 +1,22 @@
|
||||
import type { AutoRouterRoute } from '@elegant-router/types';
|
||||
import { routes } from '../_generated/routes';
|
||||
import { layouts, views } from '../_generated/imports';
|
||||
import { transformToVueRoutes } from '../_generated/transformer';
|
||||
import type { CustomRoute, ElegantConstRoute, ElegantRoute } from '@elegant-router/types';
|
||||
import { generatedRoutes } from '../elegant/routes';
|
||||
import { layouts, views } from '../elegant/imports';
|
||||
import { transformElegantRoutesToVueRoutes } from '../elegant/transform';
|
||||
|
||||
/**
|
||||
* custom routes
|
||||
*
|
||||
* @link https://github.com/soybeanjs/elegant-router?tab=readme-ov-file#custom-route
|
||||
*/
|
||||
const customRoutes: CustomRoute[] = [];
|
||||
|
||||
/** create routes when the auth route mode is static */
|
||||
export function createStaticRoutes() {
|
||||
const constantRoutes: AutoRouterRoute[] = [];
|
||||
const authRoutes: AutoRouterRoute[] = [];
|
||||
const constantRoutes: ElegantRoute[] = [];
|
||||
|
||||
routes.forEach(item => {
|
||||
const authRoutes: ElegantRoute[] = [];
|
||||
|
||||
[...customRoutes, ...generatedRoutes].forEach(item => {
|
||||
if (item.meta?.constant) {
|
||||
constantRoutes.push(item);
|
||||
} else {
|
||||
@@ -25,8 +33,8 @@ export function createStaticRoutes() {
|
||||
/**
|
||||
* Get auth vue routes
|
||||
*
|
||||
* @param authRoutes Elegant routes
|
||||
* @param routes Elegant routes
|
||||
*/
|
||||
export function getAuthVueRoutes(authRoutes: AutoRouterRoute[]) {
|
||||
return transformToVueRoutes(authRoutes, layouts, views);
|
||||
export function getAuthVueRoutes(routes: ElegantConstRoute[]) {
|
||||
return transformElegantRoutesToVueRoutes(routes, layouts, views);
|
||||
}
|
||||
|
||||
@@ -46,10 +46,7 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
||||
});
|
||||
|
||||
setReloadFlag(true);
|
||||
|
||||
if (themeStore.resetCacheStrategy === 'refresh') {
|
||||
routeStore.resetRouteCache();
|
||||
}
|
||||
routeStore.resetRouteCache();
|
||||
}
|
||||
|
||||
const locale = ref<App.I18n.LangType>(localStg.get('lang') || 'zh-CN');
|
||||
|
||||
@@ -112,10 +112,8 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
await switchRouteByTab(nextTab);
|
||||
}
|
||||
|
||||
// reset route cache if cache strategy is close
|
||||
if (themeStore.resetCacheStrategy === 'close') {
|
||||
routeStore.resetRouteCache(removedTabRouteKey);
|
||||
}
|
||||
// reset route cache
|
||||
routeStore.resetRouteCache(removedTabRouteKey);
|
||||
}
|
||||
|
||||
/** remove active tab */
|
||||
@@ -147,10 +145,8 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
const tabsToRemove = tabs.value.filter(tab => !remainTabIds.includes(tab.id));
|
||||
const routeKeysToReset: RouteKey[] = [];
|
||||
|
||||
if (themeStore.resetCacheStrategy === 'close') {
|
||||
for (const tab of tabsToRemove) {
|
||||
routeKeysToReset.push(tab.routeKey);
|
||||
}
|
||||
for (const tab of tabsToRemove) {
|
||||
routeKeysToReset.push(tab.routeKey);
|
||||
}
|
||||
|
||||
const removedTabsIds = tabsToRemove.map(tab => tab.id);
|
||||
|
||||
@@ -53,7 +53,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
});
|
||||
|
||||
/** Naive theme */
|
||||
const naiveTheme = computed(() => getNaiveTheme(themeColors.value, settings.value.recommendColor));
|
||||
const naiveTheme = computed(() => getNaiveTheme(themeColors.value, settings.value));
|
||||
|
||||
/**
|
||||
* Settings json
|
||||
|
||||
@@ -236,22 +236,23 @@ function getNaiveThemeColors(colors: App.Theme.ThemeColor, recommended = false)
|
||||
/**
|
||||
* Get naive theme
|
||||
*
|
||||
* @param colors Theme colors
|
||||
* @param [recommended=false] Use recommended color. Default is `false`
|
||||
* @param settings Theme settings object.
|
||||
* @param settings.recommendColor Whether to use recommended color palette.
|
||||
* @param settings.themeRadius Border radius to use in the theme (in px).
|
||||
*/
|
||||
export function getNaiveTheme(colors: App.Theme.ThemeColor, recommended = false) {
|
||||
export function getNaiveTheme(colors: App.Theme.ThemeColor, settings: App.Theme.ThemeSetting) {
|
||||
const { primary: colorLoading } = colors;
|
||||
|
||||
const theme: GlobalThemeOverrides = {
|
||||
common: {
|
||||
...getNaiveThemeColors(colors, recommended),
|
||||
borderRadius: '6px'
|
||||
...getNaiveThemeColors(colors, settings.recommendColor),
|
||||
borderRadius: `${settings.themeRadius}px`
|
||||
},
|
||||
LoadingBar: {
|
||||
colorLoading
|
||||
},
|
||||
Tag: {
|
||||
borderRadius: '6px'
|
||||
borderRadius: `${settings.themeRadius}px`
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
text-autospace: normal;
|
||||
}
|
||||
|
||||
html {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
@mixin scrollbar($size: 7px, $color: rgba(0, 0, 0, 0.5)) {
|
||||
@mixin scrollbar($size: 7px, $color: rgba(0, 0, 0, 0.5), $dark-color: rgba(255, 255, 255, 0.5)) {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: $color transparent;
|
||||
|
||||
// Dark theme override
|
||||
.dark & {
|
||||
// guide safari use light color scrollbar
|
||||
color-scheme: dark;
|
||||
scrollbar-color: $dark-color transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: $color;
|
||||
border-radius: $size;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"warning": "#d4bb9d",
|
||||
"error": "#c49a9a"
|
||||
},
|
||||
"themeRadius": 6,
|
||||
"isInfoFollowPrimary": true,
|
||||
"resetCacheStrategy": "refresh",
|
||||
"layout": {
|
||||
"mode": "vertical-mix",
|
||||
"scrollMode": "wrapper"
|
||||
@@ -41,7 +41,8 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 48,
|
||||
"mode": "chrome"
|
||||
"mode": "chrome",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"warning": "#faad14",
|
||||
"error": "#f5222d"
|
||||
},
|
||||
"themeRadius": 6,
|
||||
"isInfoFollowPrimary": true,
|
||||
"resetCacheStrategy": "close",
|
||||
"layout": {
|
||||
"mode": "vertical",
|
||||
"scrollMode": "content"
|
||||
@@ -41,7 +41,8 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 36,
|
||||
"mode": "button"
|
||||
"mode": "button",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"warning": "#faad14",
|
||||
"error": "#f5222d"
|
||||
},
|
||||
"themeRadius": 6,
|
||||
"isInfoFollowPrimary": true,
|
||||
"resetCacheStrategy": "close",
|
||||
"layout": {
|
||||
"mode": "vertical",
|
||||
"scrollMode": "content"
|
||||
@@ -41,7 +41,8 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 44,
|
||||
"mode": "chrome"
|
||||
"mode": "chrome",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"warning": "#faad14",
|
||||
"error": "#f5222d"
|
||||
},
|
||||
"themeRadius": 6,
|
||||
"isInfoFollowPrimary": true,
|
||||
"resetCacheStrategy": "close",
|
||||
"layout": {
|
||||
"mode": "vertical",
|
||||
"scrollMode": "content"
|
||||
@@ -41,7 +41,8 @@
|
||||
"visible": true,
|
||||
"cache": true,
|
||||
"height": 44,
|
||||
"mode": "chrome"
|
||||
"mode": "chrome",
|
||||
"closeTabByMiddleClick": false
|
||||
},
|
||||
"fixedHeaderAndTab": true,
|
||||
"sider": {
|
||||
|
||||
@@ -5,6 +5,7 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
||||
colourWeakness: false,
|
||||
recommendColor: false,
|
||||
themeColor: '#646cff',
|
||||
themeRadius: 6,
|
||||
otherColor: {
|
||||
info: '#2080f0',
|
||||
success: '#52c41a',
|
||||
@@ -12,7 +13,6 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
||||
error: '#f5222d'
|
||||
},
|
||||
isInfoFollowPrimary: true,
|
||||
resetCacheStrategy: 'refresh',
|
||||
layout: {
|
||||
mode: 'vertical',
|
||||
scrollMode: 'content'
|
||||
@@ -38,7 +38,8 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
||||
visible: true,
|
||||
cache: true,
|
||||
height: 44,
|
||||
mode: 'chrome'
|
||||
mode: 'chrome',
|
||||
closeTabByMiddleClick: false
|
||||
},
|
||||
fixedHeaderAndTab: true,
|
||||
sider: {
|
||||
|
||||
14
src/typings/app.d.ts
vendored
14
src/typings/app.d.ts
vendored
@@ -16,12 +16,12 @@ declare namespace App {
|
||||
recommendColor: boolean;
|
||||
/** Theme color */
|
||||
themeColor: string;
|
||||
/** Theme radius */
|
||||
themeRadius: number;
|
||||
/** Other color */
|
||||
otherColor: OtherColor;
|
||||
/** Whether info color is followed by the primary color */
|
||||
isInfoFollowPrimary: boolean;
|
||||
/** Reset cache strategy */
|
||||
resetCacheStrategy: UnionKey.ResetCacheStrategy;
|
||||
/** Layout */
|
||||
layout: {
|
||||
/** Layout mode */
|
||||
@@ -71,6 +71,8 @@ declare namespace App {
|
||||
height: number;
|
||||
/** Tab mode */
|
||||
mode: UnionKey.ThemeTabMode;
|
||||
/** Whether to close tab by middle click */
|
||||
closeTabByMiddleClick: boolean;
|
||||
};
|
||||
/** Fixed header and tab */
|
||||
fixedHeaderAndTab: boolean;
|
||||
@@ -376,9 +378,12 @@ declare namespace App {
|
||||
themeColor: {
|
||||
title: string;
|
||||
followPrimary: string;
|
||||
} & Theme.ThemeColor;
|
||||
} & Record<Theme.ThemeColorKey, string>;
|
||||
recommendColor: string;
|
||||
recommendColorDesc: string;
|
||||
themeRadius: {
|
||||
title: string;
|
||||
};
|
||||
preset: {
|
||||
title: string;
|
||||
apply: string;
|
||||
@@ -402,6 +407,8 @@ declare namespace App {
|
||||
cacheTip: string;
|
||||
height: string;
|
||||
mode: { title: string } & Record<UnionKey.ThemeTabMode, string>;
|
||||
closeByMiddleClick: string;
|
||||
closeByMiddleClickTip: string;
|
||||
};
|
||||
header: {
|
||||
title: string;
|
||||
@@ -436,7 +443,6 @@ declare namespace App {
|
||||
};
|
||||
fixedHeaderAndTab: string;
|
||||
};
|
||||
resetCacheStrategy: { title: string } & Record<UnionKey.ResetCacheStrategy, string>;
|
||||
};
|
||||
general: {
|
||||
title: string;
|
||||
|
||||
83
src/typings/components.d.ts
vendored
83
src/typings/components.d.ts
vendored
@@ -1,8 +1,12 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
// biome-ignore lint: disable
|
||||
// oxlint-disable
|
||||
// ------
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
// biome-ignore lint: disable
|
||||
import { GlobalComponents } from 'vue'
|
||||
|
||||
export {}
|
||||
|
||||
/* prettier-ignore */
|
||||
@@ -66,7 +70,6 @@ declare module 'vue' {
|
||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
||||
NTab: typeof import('naive-ui')['NTab']
|
||||
NTabs: typeof import('naive-ui')['NTabs']
|
||||
NTag: typeof import('naive-ui')['NTag']
|
||||
NThing: typeof import('naive-ui')['NThing']
|
||||
NTooltip: typeof import('naive-ui')['NTooltip']
|
||||
NWatermark: typeof import('naive-ui')['NWatermark']
|
||||
@@ -83,3 +86,79 @@ declare module 'vue' {
|
||||
WaveBg: typeof import('./../components/custom/wave-bg.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
// For TSX support
|
||||
declare global {
|
||||
const AppProvider: typeof import('./../components/common/app-provider.vue')['default']
|
||||
const BetterScroll: typeof import('./../components/custom/better-scroll.vue')['default']
|
||||
const ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default']
|
||||
const CountTo: typeof import('./../components/custom/count-to.vue')['default']
|
||||
const DarkModeContainer: typeof import('./../components/common/dark-mode-container.vue')['default']
|
||||
const ExceptionBase: typeof import('./../components/common/exception-base.vue')['default']
|
||||
const FullScreen: typeof import('./../components/common/full-screen.vue')['default']
|
||||
const IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
|
||||
const IconAntDesignReloadOutlined: typeof import('~icons/ant-design/reload-outlined')['default']
|
||||
const IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default']
|
||||
const IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default']
|
||||
const IconLocalBanner: typeof import('~icons/local/banner')['default']
|
||||
const IconLocalLogo: typeof import('~icons/local/logo')['default']
|
||||
const IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
|
||||
const IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
|
||||
const IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
|
||||
const IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
|
||||
const IconTooltip: typeof import('./../components/common/icon-tooltip.vue')['default']
|
||||
const IconUilSearch: typeof import('~icons/uil/search')['default']
|
||||
const LangSwitch: typeof import('./../components/common/lang-switch.vue')['default']
|
||||
const LookForward: typeof import('./../components/custom/look-forward.vue')['default']
|
||||
const MenuToggler: typeof import('./../components/common/menu-toggler.vue')['default']
|
||||
const NAlert: typeof import('naive-ui')['NAlert']
|
||||
const NBadge: typeof import('naive-ui')['NBadge']
|
||||
const NBreadcrumb: typeof import('naive-ui')['NBreadcrumb']
|
||||
const NBreadcrumbItem: typeof import('naive-ui')['NBreadcrumbItem']
|
||||
const NButton: typeof import('naive-ui')['NButton']
|
||||
const NCard: typeof import('naive-ui')['NCard']
|
||||
const NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||
const NColorPicker: typeof import('naive-ui')['NColorPicker']
|
||||
const NDialogProvider: typeof import('naive-ui')['NDialogProvider']
|
||||
const NDivider: typeof import('naive-ui')['NDivider']
|
||||
const NDrawer: typeof import('naive-ui')['NDrawer']
|
||||
const NDrawerContent: typeof import('naive-ui')['NDrawerContent']
|
||||
const NDropdown: typeof import('naive-ui')['NDropdown']
|
||||
const NEmpty: typeof import('naive-ui')['NEmpty']
|
||||
const NForm: typeof import('naive-ui')['NForm']
|
||||
const NFormItem: typeof import('naive-ui')['NFormItem']
|
||||
const NGi: typeof import('naive-ui')['NGi']
|
||||
const NGrid: typeof import('naive-ui')['NGrid']
|
||||
const NInput: typeof import('naive-ui')['NInput']
|
||||
const NInputGroup: typeof import('naive-ui')['NInputGroup']
|
||||
const NInputNumber: typeof import('naive-ui')['NInputNumber']
|
||||
const NList: typeof import('naive-ui')['NList']
|
||||
const NListItem: typeof import('naive-ui')['NListItem']
|
||||
const NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
|
||||
const NMenu: typeof import('naive-ui')['NMenu']
|
||||
const NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||
const NModal: typeof import('naive-ui')['NModal']
|
||||
const NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
|
||||
const NPopover: typeof import('naive-ui')['NPopover']
|
||||
const NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||
const NSelect: typeof import('naive-ui')['NSelect']
|
||||
const NSpace: typeof import('naive-ui')['NSpace']
|
||||
const NStatistic: typeof import('naive-ui')['NStatistic']
|
||||
const NSwitch: typeof import('naive-ui')['NSwitch']
|
||||
const NTab: typeof import('naive-ui')['NTab']
|
||||
const NTabs: typeof import('naive-ui')['NTabs']
|
||||
const NThing: typeof import('naive-ui')['NThing']
|
||||
const NTooltip: typeof import('naive-ui')['NTooltip']
|
||||
const NWatermark: typeof import('naive-ui')['NWatermark']
|
||||
const PinToggler: typeof import('./../components/common/pin-toggler.vue')['default']
|
||||
const ReloadButton: typeof import('./../components/common/reload-button.vue')['default']
|
||||
const RouterLink: typeof import('vue-router')['RouterLink']
|
||||
const RouterView: typeof import('vue-router')['RouterView']
|
||||
const SoybeanAvatar: typeof import('./../components/custom/soybean-avatar.vue')['default']
|
||||
const SvgIcon: typeof import('./../components/custom/svg-icon.vue')['default']
|
||||
const SystemLogo: typeof import('./../components/common/system-logo.vue')['default']
|
||||
const TableColumnSetting: typeof import('./../components/advanced/table-column-setting.vue')['default']
|
||||
const TableHeaderOperation: typeof import('./../components/advanced/table-header-operation.vue')['default']
|
||||
const ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default']
|
||||
const WaveBg: typeof import('./../components/custom/wave-bg.vue')['default']
|
||||
}
|
||||
240
src/typings/elegant-router.d.ts
vendored
240
src/typings/elegant-router.d.ts
vendored
@@ -1,104 +1,240 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
/* oxlint-disable */
|
||||
// biome-ignore lint: disable
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
declare module "@elegant-router/types" {
|
||||
type RouteRecordSingleView = import("vue-router").RouteRecordSingleView;
|
||||
type RouteRecordRedirect = import("vue-router").RouteRecordRedirect;
|
||||
type RouteComponent = import("vue-router").RouteComponent;
|
||||
|
||||
type Lazy<T> = () => Promise<T>;
|
||||
|
||||
export type RawRouteComponent = RouteComponent | Lazy<RouteComponent>;
|
||||
type ElegantConstRoute = import('@elegant-router/vue').ElegantConstRoute;
|
||||
|
||||
/**
|
||||
* route layout key
|
||||
* route layout
|
||||
*/
|
||||
export type RouteLayoutKey = "base" | "blank";
|
||||
export type RouteLayout = "base" | "blank";
|
||||
|
||||
/**
|
||||
* route path map
|
||||
* route map
|
||||
*/
|
||||
export type RoutePathMap = {
|
||||
"Root": "/";
|
||||
"NotFound": "/:pathMatch(.*)*";
|
||||
export type RouteMap = {
|
||||
"root": "/";
|
||||
"not-found": "/:pathMatch(.*)*";
|
||||
"403": "/403";
|
||||
"404": "/404";
|
||||
"500": "/500";
|
||||
"Home": "/home";
|
||||
"IframeUrl": "/iframe/:url";
|
||||
"Login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
||||
"ManageApi": "/manage/api";
|
||||
"ManageDictionary": "/manage/dictionary";
|
||||
"ManageMenu": "/manage/menu";
|
||||
"ManageOrganization": "/manage/organization";
|
||||
"ManagePermission": "/manage/permission";
|
||||
"ManageRole": "/manage/role";
|
||||
"ManageRoute": "/manage/route";
|
||||
"ManageUser": "/manage/user";
|
||||
"Wip": "/wip";
|
||||
"home": "/home";
|
||||
"iframe-page": "/iframe-page/:url";
|
||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
||||
};
|
||||
|
||||
/**
|
||||
* route key
|
||||
*/
|
||||
export type RouteKey = keyof RoutePathMap;
|
||||
export type RouteKey = keyof RouteMap;
|
||||
|
||||
/**
|
||||
* route path
|
||||
*/
|
||||
export type RoutePath = RoutePathMap[RouteKey];
|
||||
export type RoutePath = RouteMap[RouteKey];
|
||||
|
||||
/**
|
||||
* root route key
|
||||
* custom route key
|
||||
*/
|
||||
export type RootRouteKey = 'Root';
|
||||
export type CustomRouteKey = Extract<
|
||||
RouteKey,
|
||||
| "root"
|
||||
| "not-found"
|
||||
>;
|
||||
|
||||
/**
|
||||
* not found route key
|
||||
* the generated route key
|
||||
*/
|
||||
export type NotFoundRouteKey = 'NotFound';
|
||||
export type GeneratedRouteKey = Exclude<RouteKey, CustomRouteKey>;
|
||||
|
||||
/**
|
||||
* builtin route key
|
||||
* the first level route key, which contain the layout of the route
|
||||
*/
|
||||
export type BuiltinRouteKey = RootRouteKey | NotFoundRouteKey;
|
||||
export type FirstLevelRouteKey = Extract<
|
||||
RouteKey,
|
||||
| "403"
|
||||
| "404"
|
||||
| "500"
|
||||
| "home"
|
||||
| "iframe-page"
|
||||
| "login"
|
||||
>;
|
||||
|
||||
/**
|
||||
* reuse route key
|
||||
* the custom first level route key
|
||||
*/
|
||||
export type ReuseRouteKey = never;
|
||||
export type CustomFirstLevelRouteKey = Extract<
|
||||
CustomRouteKey,
|
||||
| "root"
|
||||
| "not-found"
|
||||
>;
|
||||
|
||||
/**
|
||||
* the route file key, which has it's own file
|
||||
* the last level route key, which has the page file
|
||||
*/
|
||||
export type RouteFileKey = Exclude<RouteKey, BuiltinRouteKey | ReuseRouteKey>;
|
||||
export type LastLevelRouteKey = Extract<
|
||||
RouteKey,
|
||||
| "403"
|
||||
| "404"
|
||||
| "500"
|
||||
| "iframe-page"
|
||||
| "login"
|
||||
| "home"
|
||||
>;
|
||||
|
||||
/**
|
||||
* mapped name and path
|
||||
* the custom last level route key
|
||||
*/
|
||||
type MappedNamePath = {
|
||||
[K in RouteKey]: { name: K; path: RoutePathMap[K] };
|
||||
}[RouteKey];
|
||||
export type CustomLastLevelRouteKey = Extract<
|
||||
CustomRouteKey,
|
||||
| "root"
|
||||
| "not-found"
|
||||
>;
|
||||
|
||||
/**
|
||||
* auto router single view
|
||||
* the single level route key
|
||||
*/
|
||||
export type AutoRouterSingleView = Omit<RouteRecordSingleView, 'component' | 'name' | 'path'> & {
|
||||
component: RouteFileKey;
|
||||
layout: RouteLayoutKey;
|
||||
} & MappedNamePath;
|
||||
export type SingleLevelRouteKey = FirstLevelRouteKey & LastLevelRouteKey;
|
||||
|
||||
/**
|
||||
* auto router redirect
|
||||
* the custom single level route key
|
||||
*/
|
||||
export type AutoRouterRedirect = Omit<RouteRecordRedirect, 'children' | 'name' | 'path'> & MappedNamePath;
|
||||
export type CustomSingleLevelRouteKey = CustomFirstLevelRouteKey & CustomLastLevelRouteKey;
|
||||
|
||||
/**
|
||||
* auto router route
|
||||
* the first level route key, but not the single level
|
||||
*/
|
||||
export type FirstLevelRouteNotSingleKey = Exclude<FirstLevelRouteKey, SingleLevelRouteKey>;
|
||||
|
||||
/**
|
||||
* the custom first level route key, but not the single level
|
||||
*/
|
||||
export type AutoRouterRoute = AutoRouterSingleView | AutoRouterRedirect;
|
||||
export type CustomFirstLevelRouteNotSingleKey = Exclude<CustomFirstLevelRouteKey, CustomSingleLevelRouteKey>;
|
||||
|
||||
/**
|
||||
* the center level route key
|
||||
*/
|
||||
export type CenterLevelRouteKey = Exclude<GeneratedRouteKey, FirstLevelRouteKey | LastLevelRouteKey>;
|
||||
|
||||
/**
|
||||
* the custom center level route key
|
||||
*/
|
||||
export type CustomCenterLevelRouteKey = Exclude<CustomRouteKey, CustomFirstLevelRouteKey | CustomLastLevelRouteKey>;
|
||||
|
||||
/**
|
||||
* the center level route key
|
||||
*/
|
||||
type GetChildRouteKey<K extends RouteKey, T extends RouteKey = RouteKey> = T extends `${K}_${infer R}`
|
||||
? R extends `${string}_${string}`
|
||||
? never
|
||||
: T
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the single level route
|
||||
*/
|
||||
type SingleLevelRoute<K extends SingleLevelRouteKey = SingleLevelRouteKey> = K extends string
|
||||
? Omit<ElegantConstRoute, 'children'> & {
|
||||
name: K;
|
||||
path: RouteMap[K];
|
||||
component: `layout.${RouteLayout}$view.${K}`;
|
||||
}
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the last level route
|
||||
*/
|
||||
type LastLevelRoute<K extends GeneratedRouteKey> = K extends LastLevelRouteKey
|
||||
? Omit<ElegantConstRoute, 'children'> & {
|
||||
name: K;
|
||||
path: RouteMap[K];
|
||||
component: `view.${K}`;
|
||||
}
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the center level route
|
||||
*/
|
||||
type CenterLevelRoute<K extends GeneratedRouteKey> = K extends CenterLevelRouteKey
|
||||
? Omit<ElegantConstRoute, 'component'> & {
|
||||
name: K;
|
||||
path: RouteMap[K];
|
||||
children: (CenterLevelRoute<GetChildRouteKey<K>> | LastLevelRoute<GetChildRouteKey<K>>)[];
|
||||
}
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the multi level route
|
||||
*/
|
||||
type MultiLevelRoute<K extends FirstLevelRouteNotSingleKey = FirstLevelRouteNotSingleKey> = K extends string
|
||||
? ElegantConstRoute & {
|
||||
name: K;
|
||||
path: RouteMap[K];
|
||||
component: `layout.${RouteLayout}`;
|
||||
children: (CenterLevelRoute<GetChildRouteKey<K>> | LastLevelRoute<GetChildRouteKey<K>>)[];
|
||||
}
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the custom first level route
|
||||
*/
|
||||
type CustomSingleLevelRoute<K extends CustomFirstLevelRouteKey = CustomFirstLevelRouteKey> = K extends string
|
||||
? Omit<ElegantConstRoute, 'children'> & {
|
||||
name: K;
|
||||
path: RouteMap[K];
|
||||
component?: `layout.${RouteLayout}$view.${LastLevelRouteKey}`;
|
||||
}
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the custom last level route
|
||||
*/
|
||||
type CustomLastLevelRoute<K extends CustomRouteKey> = K extends CustomLastLevelRouteKey
|
||||
? Omit<ElegantConstRoute, 'children'> & {
|
||||
name: K;
|
||||
path: RouteMap[K];
|
||||
component?: `view.${LastLevelRouteKey}`;
|
||||
}
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the custom center level route
|
||||
*/
|
||||
type CustomCenterLevelRoute<K extends CustomRouteKey> = K extends CustomCenterLevelRouteKey
|
||||
? Omit<ElegantConstRoute, 'component'> & {
|
||||
name: K;
|
||||
path: RouteMap[K];
|
||||
children: (CustomCenterLevelRoute<GetChildRouteKey<K>> | CustomLastLevelRoute<GetChildRouteKey<K>>)[];
|
||||
}
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the custom multi level route
|
||||
*/
|
||||
type CustomMultiLevelRoute<K extends CustomFirstLevelRouteNotSingleKey = CustomFirstLevelRouteNotSingleKey> =
|
||||
K extends string
|
||||
? ElegantConstRoute & {
|
||||
name: K;
|
||||
path: RouteMap[K];
|
||||
component: `layout.${RouteLayout}`;
|
||||
children: (CustomCenterLevelRoute<GetChildRouteKey<K>> | CustomLastLevelRoute<GetChildRouteKey<K>>)[];
|
||||
}
|
||||
: never;
|
||||
|
||||
/**
|
||||
* the custom route
|
||||
*/
|
||||
type CustomRoute = CustomSingleLevelRoute | CustomMultiLevelRoute;
|
||||
|
||||
/**
|
||||
* the generated route
|
||||
*/
|
||||
type GeneratedRoute = SingleLevelRoute | MultiLevelRoute;
|
||||
|
||||
/**
|
||||
* the elegant route
|
||||
*/
|
||||
type ElegantRoute = GeneratedRoute | CustomRoute;
|
||||
}
|
||||
|
||||
4
src/typings/router.d.ts
vendored
4
src/typings/router.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
export {};
|
||||
import 'vue-router';
|
||||
|
||||
declare module 'vue-router' {
|
||||
export interface RouteMeta {
|
||||
interface RouteMeta {
|
||||
/**
|
||||
* Title of the route
|
||||
*
|
||||
|
||||
44
src/typings/typed-router.d.ts
vendored
44
src/typings/typed-router.d.ts
vendored
@@ -1,44 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
/* prettier-ignore */
|
||||
/* oxlint-disable */
|
||||
// biome-ignore lint: disable
|
||||
// Generated by elegant-router
|
||||
// Read more: https://github.com/soybeanjs/elegant-router
|
||||
|
||||
export {}
|
||||
|
||||
declare module "vue-router" {
|
||||
type RouteNamedMap = import("vue-router/auto-routes").RouteNamedMap;
|
||||
|
||||
export interface TypesConfig {
|
||||
RouteNamedMap: RouteNamedMap;
|
||||
}
|
||||
}
|
||||
|
||||
declare module "vue-router/auto-routes" {
|
||||
import type { RouteParamsRawGeneric, RouteParamsGeneric, RouteMeta, RouteRecordInfo, ParamValue, ParamValueZeroOrOne } from "vue-router";
|
||||
|
||||
/**
|
||||
* route named map
|
||||
*/
|
||||
export interface RouteNamedMap {
|
||||
"Root": RouteRecordInfo<"Root", "/", Record<never, never>, Record<never, never>>;
|
||||
"NotFound": RouteRecordInfo<"NotFound", "/:pathMatch(.*)*", Record<never, never>, Record<never, never>>;
|
||||
"403": RouteRecordInfo<"403", "/403", Record<never, never>, Record<never, never>>;
|
||||
"404": RouteRecordInfo<"404", "/404", Record<never, never>, Record<never, never>>;
|
||||
"500": RouteRecordInfo<"500", "/500", Record<never, never>, Record<never, never>>;
|
||||
"Home": RouteRecordInfo<"Home", "/home", Record<never, never>, Record<never, never>>;
|
||||
"IframeUrl": RouteRecordInfo<"IframeUrl", "/iframe/:url", { url: ParamValue<true> }, { url: ParamValue<false> }>;
|
||||
"Login": RouteRecordInfo<"Login", "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?", { module?: ParamValueZeroOrOne<true> }, { module?: ParamValueZeroOrOne<false> }>;
|
||||
"ManageApi": RouteRecordInfo<"ManageApi", "/manage/api", Record<never, never>, Record<never, never>>;
|
||||
"ManageDictionary": RouteRecordInfo<"ManageDictionary", "/manage/dictionary", Record<never, never>, Record<never, never>>;
|
||||
"ManageMenu": RouteRecordInfo<"ManageMenu", "/manage/menu", Record<never, never>, Record<never, never>>;
|
||||
"ManageOrganization": RouteRecordInfo<"ManageOrganization", "/manage/organization", Record<never, never>, Record<never, never>>;
|
||||
"ManagePermission": RouteRecordInfo<"ManagePermission", "/manage/permission", Record<never, never>, Record<never, never>>;
|
||||
"ManageRole": RouteRecordInfo<"ManageRole", "/manage/role", Record<never, never>, Record<never, never>>;
|
||||
"ManageRoute": RouteRecordInfo<"ManageRoute", "/manage/route", Record<never, never>, Record<never, never>>;
|
||||
"ManageUser": RouteRecordInfo<"ManageUser", "/manage/user", Record<never, never>, Record<never, never>>;
|
||||
"Wip": RouteRecordInfo<"Wip", "/wip", Record<never, never>, Record<never, never>>
|
||||
}
|
||||
}
|
||||
8
src/typings/union-key.d.ts
vendored
8
src/typings/union-key.d.ts
vendored
@@ -14,14 +14,6 @@ declare namespace UnionKey {
|
||||
/** Theme scheme */
|
||||
type ThemeScheme = 'light' | 'dark' | 'auto';
|
||||
|
||||
/**
|
||||
* Reset cache strategy
|
||||
*
|
||||
* - close: re-cache when close page
|
||||
* - refresh: re-cache when refresh page
|
||||
*/
|
||||
type ResetCacheStrategy = 'close' | 'refresh';
|
||||
|
||||
/**
|
||||
* The layout mode
|
||||
*
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<LookForward />
|
||||
</template>
|
||||
@@ -23,7 +23,7 @@ const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
interface LoginModule {
|
||||
label: string;
|
||||
label: App.I18n.I18nKey;
|
||||
component: Component;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { createReusableTemplate } from '@vueuse/core';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({
|
||||
@@ -72,6 +73,8 @@ interface GradientBgProps {
|
||||
|
||||
const [DefineGradientBg, GradientBg] = createReusableTemplate<GradientBgProps>();
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
function getGradientColor(color: CardData['color']) {
|
||||
return `linear-gradient(to bottom right, ${color.start}, ${color.end})`;
|
||||
}
|
||||
@@ -81,7 +84,10 @@ function getGradientColor(color: CardData['color']) {
|
||||
<NCard :bordered="false" size="small" class="card-wrapper">
|
||||
<!-- define component start: GradientBg -->
|
||||
<DefineGradientBg v-slot="{ $slots, gradientColor }">
|
||||
<div class="rd-8px px-16px pb-4px pt-8px text-white" :style="{ backgroundImage: gradientColor }">
|
||||
<div
|
||||
class="px-16px pb-4px pt-8px text-white"
|
||||
:style="{ backgroundImage: gradientColor, borderRadius: themeStore.themeRadius + 'px' }"
|
||||
>
|
||||
<component :is="$slots.default" />
|
||||
</div>
|
||||
</DefineGradientBg>
|
||||
|
||||
@@ -21,13 +21,14 @@ const { domRef, updateOptions } = useEcharts(() => ({
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: [$t('page.home.downloadCount'), $t('page.home.registerCount')]
|
||||
data: [$t('page.home.downloadCount'), $t('page.home.registerCount')],
|
||||
top: '0'
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
top: '15%'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>ManageApi</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>ManageDictionary</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>ManageMenu</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>ManageOrganization</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>ManagePermission</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>ManageRole</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>ManageRoute</div>
|
||||
</template>
|
||||
@@ -1,5 +0,0 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>ManageUser</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user