mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-11-22 00:16:47 +08:00
Compare commits
16 Commits
6eaec8705d
...
v2.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56ad0df974 | ||
|
|
6cbf5705bb | ||
|
|
87a66a4236 | ||
|
|
3549c4dbd5 | ||
|
|
24c6df528b | ||
|
|
dac5075be9 | ||
|
|
a8d1e5d266 | ||
|
|
345aa2932f | ||
|
|
d5a3a25d3d | ||
|
|
d567c057a8 | ||
|
|
91fae50260 | ||
|
|
61fa4b7f3b | ||
|
|
ef7acc626f | ||
|
|
2a0c9f1b41 | ||
|
|
5be864a80b | ||
|
|
b041fdd864 |
111
CHANGELOG.md
111
CHANGELOG.md
@@ -1,6 +1,117 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
|
||||||
|
## [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)
|
## [v1.3.15](https://github.com/soybeanjs/soybean-admin/compare/v1.3.14...v1.3.15) (2025-06-24)
|
||||||
|
|
||||||
### 🚀 Features
|
### 🚀 Features
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
[](https://gitcode.com/soybeanjs/soybean-admin)
|
[](https://gitcode.com/soybeanjs/soybean-admin)
|
||||||
[](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")
|
[](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]
|
> [!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!
|
> 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!
|
||||||
|
|||||||
@@ -13,7 +13,10 @@
|
|||||||
[](https://gitcode.com/soybeanjs/soybean-admin)
|
[](https://gitcode.com/soybeanjs/soybean-admin)
|
||||||
[](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")
|
[](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]
|
> [!NOTE]
|
||||||
> 如果您觉得 `SoybeanAdmin`对您有所帮助,或者您喜欢我们的项目,请在 GitHub 上给我们一个 ⭐️。您的支持是我们持续改进和增加新功能的动力!感谢您的支持!
|
> 如果您觉得 `SoybeanAdmin`对您有所帮助,或者您喜欢我们的项目,请在 GitHub 上给我们一个 ⭐️。您的支持是我们持续改进和增加新功能的动力!感谢您的支持!
|
||||||
|
|||||||
52
package.json
52
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "soybean-admin",
|
"name": "soybean-admin",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"description": "A fresh and elegant admin template, based on Vue3、Vite7、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite7、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
"description": "A fresh and elegant admin template, based on Vue3、Vite7、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite7、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Soybean",
|
"name": "Soybean",
|
||||||
@@ -54,53 +54,53 @@
|
|||||||
"@sa/hooks": "workspace:*",
|
"@sa/hooks": "workspace:*",
|
||||||
"@sa/materials": "workspace:*",
|
"@sa/materials": "workspace:*",
|
||||||
"@sa/utils": "workspace:*",
|
"@sa/utils": "workspace:*",
|
||||||
"@vueuse/core": "13.8.0",
|
"@vueuse/core": "14.0.0",
|
||||||
"clipboard": "2.0.11",
|
"clipboard": "2.0.11",
|
||||||
"dayjs": "1.11.14",
|
"dayjs": "1.11.18",
|
||||||
"defu": "6.1.4",
|
"defu": "6.1.4",
|
||||||
"echarts": "6.0.0",
|
"echarts": "6.0.0",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
"naive-ui": "2.42.0",
|
"naive-ui": "2.43.1",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"pinia": "3.0.3",
|
"pinia": "3.0.3",
|
||||||
"tailwind-merge": "3.3.1",
|
"tailwind-merge": "3.3.1",
|
||||||
"vue": "3.5.20",
|
"vue": "3.5.22",
|
||||||
"vue-draggable-plus": "0.6.0",
|
"vue-draggable-plus": "0.6.0",
|
||||||
"vue-i18n": "11.1.11",
|
"vue-i18n": "11.1.12",
|
||||||
"vue-router": "4.5.1"
|
"vue-router": "4.6.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@elegant-router/vue": "0.3.8",
|
"@elegant-router/vue": "0.3.8",
|
||||||
"@iconify/json": "2.2.378",
|
"@iconify/json": "2.2.400",
|
||||||
"@sa/scripts": "workspace:*",
|
"@sa/scripts": "workspace:*",
|
||||||
"@sa/uno-preset": "workspace:*",
|
"@sa/uno-preset": "workspace:*",
|
||||||
"@soybeanjs/eslint-config": "1.7.1",
|
"@soybeanjs/eslint-config": "1.7.1",
|
||||||
"@types/node": "24.3.0",
|
"@types/node": "24.9.1",
|
||||||
"@types/nprogress": "0.2.3",
|
"@types/nprogress": "0.2.3",
|
||||||
"@unocss/eslint-config": "66.4.2",
|
"@unocss/eslint-config": "66.5.4",
|
||||||
"@unocss/preset-icons": "66.4.2",
|
"@unocss/preset-icons": "66.5.4",
|
||||||
"@unocss/preset-uno": "66.4.2",
|
"@unocss/preset-uno": "66.5.4",
|
||||||
"@unocss/transformer-directives": "66.4.2",
|
"@unocss/transformer-directives": "66.5.4",
|
||||||
"@unocss/transformer-variant-group": "66.4.2",
|
"@unocss/transformer-variant-group": "66.5.4",
|
||||||
"@unocss/vite": "66.4.2",
|
"@unocss/vite": "66.5.4",
|
||||||
"@vitejs/plugin-vue": "6.0.1",
|
"@vitejs/plugin-vue": "6.0.1",
|
||||||
"@vitejs/plugin-vue-jsx": "5.1.0",
|
"@vitejs/plugin-vue-jsx": "5.1.1",
|
||||||
"consola": "3.4.2",
|
"consola": "3.4.2",
|
||||||
"eslint": "9.34.0",
|
"eslint": "9.38.0",
|
||||||
"eslint-plugin-vue": "10.4.0",
|
"eslint-plugin-vue": "10.5.1",
|
||||||
"kolorist": "1.8.0",
|
"kolorist": "1.8.0",
|
||||||
"sass": "1.91.0",
|
"sass": "1.93.2",
|
||||||
"simple-git-hooks": "2.13.1",
|
"simple-git-hooks": "2.13.1",
|
||||||
"tsx": "4.20.5",
|
"tsx": "4.20.6",
|
||||||
"typescript": "5.9.2",
|
"typescript": "5.9.3",
|
||||||
"unplugin-icons": "22.2.0",
|
"unplugin-icons": "22.5.0",
|
||||||
"unplugin-vue-components": "29.0.0",
|
"unplugin-vue-components": "30.0.0",
|
||||||
"vite": "7.1.3",
|
"vite": "7.1.12",
|
||||||
"vite-plugin-progress": "0.0.7",
|
"vite-plugin-progress": "0.0.7",
|
||||||
"vite-plugin-svg-icons": "2.0.1",
|
"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-eslint-parser": "10.2.0",
|
||||||
"vue-tsc": "3.0.6"
|
"vue-tsc": "3.1.2"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
"commit-msg": "pnpm sa git-commit-verify",
|
"commit-msg": "pnpm sa git-commit-verify",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/alova",
|
"name": "@sa/alova",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
"./fetch": "./src/fetch.ts",
|
"./fetch": "./src/fetch.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/axios",
|
"name": "@sa/axios",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sa/utils": "workspace:*",
|
"@sa/utils": "workspace:*",
|
||||||
"axios": "1.11.0",
|
"axios": "1.12.2",
|
||||||
"axios-retry": "4.5.0",
|
"axios-retry": "4.5.0",
|
||||||
"qs": "6.14.0"
|
"qs": "6.14.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig } f
|
|||||||
import axiosRetry from 'axios-retry';
|
import axiosRetry from 'axios-retry';
|
||||||
import { nanoid } from '@sa/utils';
|
import { nanoid } from '@sa/utils';
|
||||||
import { createAxiosConfig, createDefaultOptions, createRetryOptions } from './options';
|
import { createAxiosConfig, createDefaultOptions, createRetryOptions } from './options';
|
||||||
|
import { transformResponse } from './shared';
|
||||||
import { BACKEND_ERROR_CODE, REQUEST_ID_KEY } from './constant';
|
import { BACKEND_ERROR_CODE, REQUEST_ID_KEY } from './constant';
|
||||||
import type {
|
import type {
|
||||||
CustomAxiosRequestConfig,
|
CustomAxiosRequestConfig,
|
||||||
@@ -53,6 +54,8 @@ function createCommonRequest<
|
|||||||
async response => {
|
async response => {
|
||||||
const responseType: ResponseType = (response.config?.responseType as ResponseType) || 'json';
|
const responseType: ResponseType = (response.config?.responseType as ResponseType) || 'json';
|
||||||
|
|
||||||
|
await transformResponse(response);
|
||||||
|
|
||||||
if (responseType !== 'json' || opts.isBackendSuccess(response)) {
|
if (responseType !== 'json' || opts.isBackendSuccess(response)) {
|
||||||
return Promise.resolve(response);
|
return Promise.resolve(response);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { AxiosHeaderValue, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
import type { AxiosHeaderValue, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||||
|
import type { ResponseType } from './type';
|
||||||
|
|
||||||
export function getContentType(config: InternalAxiosRequestConfig) {
|
export function getContentType(config: InternalAxiosRequestConfig) {
|
||||||
const contentType: AxiosHeaderValue = config.headers?.['Content-Type'] || 'application/json';
|
const contentType: AxiosHeaderValue = config.headers?.['Content-Type'] || 'application/json';
|
||||||
@@ -26,3 +27,53 @@ export function isResponseJson(response: AxiosResponse) {
|
|||||||
|
|
||||||
return responseType === 'json' || responseType === undefined;
|
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",
|
"name": "@sa/color",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/hooks",
|
"name": "@sa/hooks",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/materials",
|
"name": "@sa/materials",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -95,3 +95,27 @@
|
|||||||
.chrome-tab_dark .chrome-tab-divider {
|
.chrome-tab_dark .chrome-tab-divider {
|
||||||
background-color: rgba(255, 255, 255, 0.9);
|
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_dark': string;
|
||||||
readonly 'chrome-tab-divider': string;
|
readonly 'chrome-tab-divider': string;
|
||||||
readonly 'svg-close': 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;
|
export default styles;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import type { PageTabMode, PageTabProps } from '../../types';
|
|||||||
import { ACTIVE_COLOR, createTabCssVars } from './shared';
|
import { ACTIVE_COLOR, createTabCssVars } from './shared';
|
||||||
import ChromeTab from './chrome-tab.vue';
|
import ChromeTab from './chrome-tab.vue';
|
||||||
import ButtonTab from './button-tab.vue';
|
import ButtonTab from './button-tab.vue';
|
||||||
|
import SliderTab from './slider-tab.vue';
|
||||||
import SvgClose from './svg-close.vue';
|
import SvgClose from './svg-close.vue';
|
||||||
import style from './index.module.css';
|
import style from './index.module.css';
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ interface Emits {
|
|||||||
const emit = defineEmits<Emits>();
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
const activeTabComponent = computed(() => {
|
const activeTabComponent = computed(() => {
|
||||||
const { mode, chromeClass, buttonClass } = props;
|
const { mode, chromeClass, buttonClass, sliderClass } = props;
|
||||||
|
|
||||||
const tabComponentMap = {
|
const tabComponentMap = {
|
||||||
chrome: {
|
chrome: {
|
||||||
@@ -36,6 +37,10 @@ const activeTabComponent = computed(() => {
|
|||||||
button: {
|
button: {
|
||||||
component: ButtonTab,
|
component: ButtonTab,
|
||||||
class: buttonClass
|
class: buttonClass
|
||||||
|
},
|
||||||
|
slider: {
|
||||||
|
component: SliderTab,
|
||||||
|
class: sliderClass
|
||||||
}
|
}
|
||||||
} satisfies Record<PageTabMode, { component: Component; class?: string }>;
|
} satisfies Record<PageTabMode, { component: Component; class?: string }>;
|
||||||
|
|
||||||
@@ -45,7 +50,7 @@ const activeTabComponent = computed(() => {
|
|||||||
const cssVars = computed(() => createTabCssVars(props.activeColor));
|
const cssVars = computed(() => createTabCssVars(props.activeColor));
|
||||||
|
|
||||||
const bindProps = computed(() => {
|
const bindProps = computed(() => {
|
||||||
const { chromeClass: _chromeCls, buttonClass: _btnCls, ...rest } = props;
|
const { chromeClass: _chromeCls, buttonClass: _btnCls, sliderClass: _sliderCls, ...rest } = props;
|
||||||
|
|
||||||
return rest;
|
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
|
* @default chrome
|
||||||
*/
|
*/
|
||||||
export type PageTabMode = 'button' | 'chrome';
|
export type PageTabMode = 'button' | 'chrome' | 'slider';
|
||||||
|
|
||||||
export interface PageTabProps {
|
export interface PageTabProps {
|
||||||
/** Whether is dark mode */
|
/** Whether is dark mode */
|
||||||
@@ -262,6 +262,8 @@ export interface PageTabProps {
|
|||||||
buttonClass?: string;
|
buttonClass?: string;
|
||||||
/** The class of the chrome tab */
|
/** The class of the chrome tab */
|
||||||
chromeClass?: string;
|
chromeClass?: string;
|
||||||
|
/** The class of the title tab */
|
||||||
|
sliderClass?: string;
|
||||||
/** Whether the tab is active */
|
/** Whether the tab is active */
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
/** The color of the active tab */
|
/** The color of the active tab */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/scripts",
|
"name": "@sa/scripts",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"bin": {
|
"bin": {
|
||||||
"sa": "./bin.ts"
|
"sa": "./bin.ts"
|
||||||
},
|
},
|
||||||
@@ -13,15 +13,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@soybeanjs/changelog": "0.3.24",
|
"@soybeanjs/changelog": "0.3.25",
|
||||||
"bumpp": "10.2.3",
|
"bumpp": "10.3.1",
|
||||||
"c12": "3.2.0",
|
"c12": "3.3.1",
|
||||||
"cac": "6.7.14",
|
"cac": "6.7.14",
|
||||||
"consola": "3.4.2",
|
"consola": "3.4.2",
|
||||||
"enquirer": "2.4.1",
|
"enquirer": "2.4.1",
|
||||||
"execa": "9.6.0",
|
"execa": "9.6.0",
|
||||||
"kolorist": "1.8.0",
|
"kolorist": "1.8.0",
|
||||||
"npm-check-updates": "18.0.3",
|
"npm-check-updates": "19.1.1",
|
||||||
"picomatch": "4.0.3",
|
"picomatch": "4.0.3",
|
||||||
"rimraf": "6.0.1"
|
"rimraf": "6.0.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/uno-preset",
|
"name": "@sa/uno-preset",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/utils",
|
"name": "@sa/utils",
|
||||||
"version": "1.3.15",
|
"version": "2.0.0-beta.1",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"crypto-js": "4.2.0",
|
"crypto-js": "4.2.0",
|
||||||
"klona": "2.0.6",
|
"klona": "2.0.6",
|
||||||
"localforage": "1.10.0",
|
"localforage": "1.10.0",
|
||||||
"nanoid": "5.1.5"
|
"nanoid": "5.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/crypto-js": "4.2.2"
|
"@types/crypto-js": "4.2.2"
|
||||||
|
|||||||
2399
pnpm-lock.yaml
generated
2399
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> = {
|
export const themeTabModeRecord: Record<UnionKey.ThemeTabMode, App.I18n.I18nKey> = {
|
||||||
chrome: 'theme.layout.tab.mode.chrome',
|
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);
|
export const themeTabModeOptions = transformRecordToOption(themeTabModeRecord);
|
||||||
@@ -57,13 +58,6 @@ export const themePageAnimationModeRecord: Record<UnionKey.ThemePageAnimateMode,
|
|||||||
|
|
||||||
export const themePageAnimationModeOptions = transformRecordToOption(themePageAnimationModeRecord);
|
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 DARK_CLASS = 'dark';
|
||||||
|
|
||||||
export const watermarkTimeFormatOptions = [
|
export const watermarkTimeFormatOptions = [
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ const tabRef = ref<HTMLElement>();
|
|||||||
const isPCFlag = isPC();
|
const isPCFlag = isPC();
|
||||||
|
|
||||||
const TAB_DATA_ID = 'data-tab-id';
|
const TAB_DATA_ID = 'data-tab-id';
|
||||||
|
const MIDDLE_MOUSE_BUTTON = 1;
|
||||||
|
|
||||||
type TabNamedNodeMap = NamedNodeMap & {
|
type TabNamedNodeMap = NamedNodeMap & {
|
||||||
[TAB_DATA_ID]: Attr;
|
[TAB_DATA_ID]: Attr;
|
||||||
@@ -84,6 +85,20 @@ function handleCloseTab(tab: App.Global.Tab) {
|
|||||||
tabStore.removeTab(tab.id);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
appStore.reloadPage(500);
|
appStore.reloadPage(500);
|
||||||
}
|
}
|
||||||
@@ -169,7 +184,9 @@ init();
|
|||||||
<div
|
<div
|
||||||
ref="tabRef"
|
ref="tabRef"
|
||||||
class="h-full flex pr-18px"
|
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
|
<PageTab
|
||||||
v-for="tab in tabStore.tabs"
|
v-for="tab in tabStore.tabs"
|
||||||
@@ -181,6 +198,7 @@ init();
|
|||||||
:active-color="themeStore.themeColor"
|
:active-color="themeStore.themeColor"
|
||||||
:closable="!tabStore.isTabRetain(tab.id)"
|
:closable="!tabStore.isTabRetain(tab.id)"
|
||||||
@pointerdown="tabStore.switchRouteByTab(tab)"
|
@pointerdown="tabStore.switchRouteByTab(tab)"
|
||||||
|
@mousedown="handleMousedown($event, tab)"
|
||||||
@close="handleCloseTab(tab)"
|
@close="handleCloseTab(tab)"
|
||||||
@contextmenu="handleContextMenu($event, tab.id)"
|
@contextmenu="handleContextMenu($event, tab.id)"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ThemeSchema from './modules/theme-schema.vue';
|
import ThemeSchema from './modules/theme-schema.vue';
|
||||||
import ThemeColor from './modules/theme-color.vue';
|
import ThemeColor from './modules/theme-color.vue';
|
||||||
|
import ThemeRadius from './modules/theme-radius.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'AppearanceSettings'
|
name: 'AppearanceSettings'
|
||||||
@@ -11,6 +12,7 @@ defineOptions({
|
|||||||
<div class="flex-col-stretch gap-16px">
|
<div class="flex-col-stretch gap-16px">
|
||||||
<ThemeSchema />
|
<ThemeSchema />
|
||||||
<ThemeColor />
|
<ThemeColor />
|
||||||
|
<ThemeRadius />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</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">
|
<script setup lang="ts">
|
||||||
import { resetCacheStrategyOptions, themeTabModeOptions } from '@/constants/app';
|
import { themeTabModeOptions } from '@/constants/app';
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
import { translateOptions } from '@/utils/common';
|
import { translateOptions } from '@/utils/common';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
@@ -15,14 +15,6 @@ const themeStore = useThemeStore();
|
|||||||
<template>
|
<template>
|
||||||
<NDivider>{{ $t('theme.layout.tab.title') }}</NDivider>
|
<NDivider>{{ $t('theme.layout.tab.title') }}</NDivider>
|
||||||
<TransitionGroup tag="div" name="setting-list" class="flex-col-stretch gap-12px">
|
<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')">
|
<SettingItem key="1" :label="$t('theme.layout.tab.visible')">
|
||||||
<NSwitch v-model:value="themeStore.tab.visible" />
|
<NSwitch v-model:value="themeStore.tab.visible" />
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
@@ -43,6 +35,12 @@ const themeStore = useThemeStore();
|
|||||||
class="w-120px"
|
class="w-120px"
|
||||||
/>
|
/>
|
||||||
</SettingItem>
|
</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>
|
</TransitionGroup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ type ThemePreset = Pick<
|
|||||||
| 'colourWeakness'
|
| 'colourWeakness'
|
||||||
| 'recommendColor'
|
| 'recommendColor'
|
||||||
| 'themeColor'
|
| 'themeColor'
|
||||||
|
| 'themeRadius'
|
||||||
| 'otherColor'
|
| 'otherColor'
|
||||||
| 'isInfoFollowPrimary'
|
| 'isInfoFollowPrimary'
|
||||||
| 'resetCacheStrategy'
|
|
||||||
| 'layout'
|
| 'layout'
|
||||||
| 'page'
|
| 'page'
|
||||||
| 'header'
|
| 'header'
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ const local: App.I18n.Schema = {
|
|||||||
error: 'Error',
|
error: 'Error',
|
||||||
followPrimary: 'Follow Primary'
|
followPrimary: 'Follow Primary'
|
||||||
},
|
},
|
||||||
|
themeRadius: {
|
||||||
|
title: 'Theme Radius'
|
||||||
|
},
|
||||||
recommendColor: 'Apply Recommended Color Algorithm',
|
recommendColor: 'Apply Recommended Color Algorithm',
|
||||||
recommendColorDesc: 'The recommended color algorithm refers to',
|
recommendColorDesc: 'The recommended color algorithm refers to',
|
||||||
preset: {
|
preset: {
|
||||||
@@ -135,9 +138,12 @@ const local: App.I18n.Schema = {
|
|||||||
height: 'Tab Height',
|
height: 'Tab Height',
|
||||||
mode: {
|
mode: {
|
||||||
title: 'Tab Mode',
|
title: 'Tab Mode',
|
||||||
|
slider: 'Slider',
|
||||||
chrome: 'Chrome',
|
chrome: 'Chrome',
|
||||||
button: 'Button'
|
button: 'Button'
|
||||||
}
|
},
|
||||||
|
closeByMiddleClick: 'Close Tab by Middle Click',
|
||||||
|
closeByMiddleClickTip: 'Enable closing tabs by clicking with the middle mouse button'
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
title: 'Header Settings',
|
title: 'Header Settings',
|
||||||
@@ -185,11 +191,6 @@ const local: App.I18n.Schema = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
fixedHeaderAndTab: 'Fixed Header And Tab'
|
fixedHeaderAndTab: 'Fixed Header And Tab'
|
||||||
},
|
|
||||||
resetCacheStrategy: {
|
|
||||||
title: 'Reset Cache Strategy',
|
|
||||||
close: 'Close Page',
|
|
||||||
refresh: 'Refresh Page'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
general: {
|
general: {
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ const local: App.I18n.Schema = {
|
|||||||
error: '错误色',
|
error: '错误色',
|
||||||
followPrimary: '跟随主色'
|
followPrimary: '跟随主色'
|
||||||
},
|
},
|
||||||
|
themeRadius: {
|
||||||
|
title: '主题圆角'
|
||||||
|
},
|
||||||
recommendColor: '应用推荐算法的颜色',
|
recommendColor: '应用推荐算法的颜色',
|
||||||
recommendColorDesc: '推荐颜色的算法参照',
|
recommendColorDesc: '推荐颜色的算法参照',
|
||||||
preset: {
|
preset: {
|
||||||
@@ -132,9 +135,12 @@ const local: App.I18n.Schema = {
|
|||||||
height: '标签栏高度',
|
height: '标签栏高度',
|
||||||
mode: {
|
mode: {
|
||||||
title: '标签栏风格',
|
title: '标签栏风格',
|
||||||
|
slider: '滑块风格',
|
||||||
chrome: '谷歌风格',
|
chrome: '谷歌风格',
|
||||||
button: '按钮风格'
|
button: '按钮风格'
|
||||||
}
|
},
|
||||||
|
closeByMiddleClick: '鼠标中键关闭标签页',
|
||||||
|
closeByMiddleClickTip: '启用后可以使用鼠标中键点击标签页进行关闭'
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
title: '头部设置',
|
title: '头部设置',
|
||||||
@@ -158,7 +164,7 @@ const local: App.I18n.Schema = {
|
|||||||
visible: '显示底部',
|
visible: '显示底部',
|
||||||
fixed: '固定底部',
|
fixed: '固定底部',
|
||||||
height: '底部高度',
|
height: '底部高度',
|
||||||
right: '底部局右'
|
right: '底部居右'
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
title: '内容区域设置',
|
title: '内容区域设置',
|
||||||
@@ -182,11 +188,6 @@ const local: App.I18n.Schema = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
fixedHeaderAndTab: '固定头部和标签栏'
|
fixedHeaderAndTab: '固定头部和标签栏'
|
||||||
},
|
|
||||||
resetCacheStrategy: {
|
|
||||||
title: '重置缓存策略',
|
|
||||||
close: '关闭页面',
|
|
||||||
refresh: '刷新页面'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
general: {
|
general: {
|
||||||
|
|||||||
@@ -46,11 +46,8 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setReloadFlag(true);
|
setReloadFlag(true);
|
||||||
|
|
||||||
if (themeStore.resetCacheStrategy === 'refresh') {
|
|
||||||
routeStore.resetRouteCache();
|
routeStore.resetRouteCache();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const locale = ref<App.I18n.LangType>(localStg.get('lang') || 'zh-CN');
|
const locale = ref<App.I18n.LangType>(localStg.get('lang') || 'zh-CN');
|
||||||
|
|
||||||
|
|||||||
@@ -112,11 +112,9 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
|||||||
await switchRouteByTab(nextTab);
|
await switchRouteByTab(nextTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset route cache if cache strategy is close
|
// reset route cache
|
||||||
if (themeStore.resetCacheStrategy === 'close') {
|
|
||||||
routeStore.resetRouteCache(removedTabRouteKey);
|
routeStore.resetRouteCache(removedTabRouteKey);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** remove active tab */
|
/** remove active tab */
|
||||||
async function removeActiveTab() {
|
async function removeActiveTab() {
|
||||||
@@ -147,11 +145,9 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
|||||||
const tabsToRemove = tabs.value.filter(tab => !remainTabIds.includes(tab.id));
|
const tabsToRemove = tabs.value.filter(tab => !remainTabIds.includes(tab.id));
|
||||||
const routeKeysToReset: RouteKey[] = [];
|
const routeKeysToReset: RouteKey[] = [];
|
||||||
|
|
||||||
if (themeStore.resetCacheStrategy === 'close') {
|
|
||||||
for (const tab of tabsToRemove) {
|
for (const tab of tabsToRemove) {
|
||||||
routeKeysToReset.push(tab.routeKey);
|
routeKeysToReset.push(tab.routeKey);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const removedTabsIds = tabsToRemove.map(tab => tab.id);
|
const removedTabsIds = tabsToRemove.map(tab => tab.id);
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/** Naive theme */
|
/** Naive theme */
|
||||||
const naiveTheme = computed(() => getNaiveTheme(themeColors.value, settings.value.recommendColor));
|
const naiveTheme = computed(() => getNaiveTheme(themeColors.value, settings.value));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings json
|
* Settings json
|
||||||
|
|||||||
@@ -236,22 +236,23 @@ function getNaiveThemeColors(colors: App.Theme.ThemeColor, recommended = false)
|
|||||||
/**
|
/**
|
||||||
* Get naive theme
|
* Get naive theme
|
||||||
*
|
*
|
||||||
* @param colors Theme colors
|
* @param settings Theme settings object.
|
||||||
* @param [recommended=false] Use recommended color. Default is `false`
|
* @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 { primary: colorLoading } = colors;
|
||||||
|
|
||||||
const theme: GlobalThemeOverrides = {
|
const theme: GlobalThemeOverrides = {
|
||||||
common: {
|
common: {
|
||||||
...getNaiveThemeColors(colors, recommended),
|
...getNaiveThemeColors(colors, settings.recommendColor),
|
||||||
borderRadius: '6px'
|
borderRadius: `${settings.themeRadius}px`
|
||||||
},
|
},
|
||||||
LoadingBar: {
|
LoadingBar: {
|
||||||
colorLoading
|
colorLoading
|
||||||
},
|
},
|
||||||
Tag: {
|
Tag: {
|
||||||
borderRadius: '6px'
|
borderRadius: `${settings.themeRadius}px`
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ html,
|
|||||||
body,
|
body,
|
||||||
#app {
|
#app {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
text-autospace: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
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-width: thin;
|
||||||
scrollbar-color: $color transparent;
|
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 {
|
&::-webkit-scrollbar-thumb {
|
||||||
background-color: $color;
|
background-color: $color;
|
||||||
border-radius: $size;
|
border-radius: $size;
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
"warning": "#d4bb9d",
|
"warning": "#d4bb9d",
|
||||||
"error": "#c49a9a"
|
"error": "#c49a9a"
|
||||||
},
|
},
|
||||||
|
"themeRadius": 6,
|
||||||
"isInfoFollowPrimary": true,
|
"isInfoFollowPrimary": true,
|
||||||
"resetCacheStrategy": "refresh",
|
|
||||||
"layout": {
|
"layout": {
|
||||||
"mode": "vertical-mix",
|
"mode": "vertical-mix",
|
||||||
"scrollMode": "wrapper"
|
"scrollMode": "wrapper"
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
"warning": "#faad14",
|
"warning": "#faad14",
|
||||||
"error": "#f5222d"
|
"error": "#f5222d"
|
||||||
},
|
},
|
||||||
|
"themeRadius": 6,
|
||||||
"isInfoFollowPrimary": true,
|
"isInfoFollowPrimary": true,
|
||||||
"resetCacheStrategy": "close",
|
|
||||||
"layout": {
|
"layout": {
|
||||||
"mode": "vertical",
|
"mode": "vertical",
|
||||||
"scrollMode": "content"
|
"scrollMode": "content"
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
"warning": "#faad14",
|
"warning": "#faad14",
|
||||||
"error": "#f5222d"
|
"error": "#f5222d"
|
||||||
},
|
},
|
||||||
|
"themeRadius": 6,
|
||||||
"isInfoFollowPrimary": true,
|
"isInfoFollowPrimary": true,
|
||||||
"resetCacheStrategy": "close",
|
|
||||||
"layout": {
|
"layout": {
|
||||||
"mode": "vertical",
|
"mode": "vertical",
|
||||||
"scrollMode": "content"
|
"scrollMode": "content"
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
"warning": "#faad14",
|
"warning": "#faad14",
|
||||||
"error": "#f5222d"
|
"error": "#f5222d"
|
||||||
},
|
},
|
||||||
|
"themeRadius": 6,
|
||||||
"isInfoFollowPrimary": true,
|
"isInfoFollowPrimary": true,
|
||||||
"resetCacheStrategy": "close",
|
|
||||||
"layout": {
|
"layout": {
|
||||||
"mode": "vertical",
|
"mode": "vertical",
|
||||||
"scrollMode": "content"
|
"scrollMode": "content"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
|||||||
colourWeakness: false,
|
colourWeakness: false,
|
||||||
recommendColor: false,
|
recommendColor: false,
|
||||||
themeColor: '#646cff',
|
themeColor: '#646cff',
|
||||||
|
themeRadius: 6,
|
||||||
otherColor: {
|
otherColor: {
|
||||||
info: '#2080f0',
|
info: '#2080f0',
|
||||||
success: '#52c41a',
|
success: '#52c41a',
|
||||||
@@ -12,7 +13,6 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
|||||||
error: '#f5222d'
|
error: '#f5222d'
|
||||||
},
|
},
|
||||||
isInfoFollowPrimary: true,
|
isInfoFollowPrimary: true,
|
||||||
resetCacheStrategy: 'refresh',
|
|
||||||
layout: {
|
layout: {
|
||||||
mode: 'vertical',
|
mode: 'vertical',
|
||||||
scrollMode: 'content'
|
scrollMode: 'content'
|
||||||
@@ -38,7 +38,8 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
|||||||
visible: true,
|
visible: true,
|
||||||
cache: true,
|
cache: true,
|
||||||
height: 44,
|
height: 44,
|
||||||
mode: 'chrome'
|
mode: 'chrome',
|
||||||
|
closeTabByMiddleClick: false
|
||||||
},
|
},
|
||||||
fixedHeaderAndTab: true,
|
fixedHeaderAndTab: true,
|
||||||
sider: {
|
sider: {
|
||||||
|
|||||||
14
src/typings/app.d.ts
vendored
14
src/typings/app.d.ts
vendored
@@ -16,12 +16,12 @@ declare namespace App {
|
|||||||
recommendColor: boolean;
|
recommendColor: boolean;
|
||||||
/** Theme color */
|
/** Theme color */
|
||||||
themeColor: string;
|
themeColor: string;
|
||||||
|
/** Theme radius */
|
||||||
|
themeRadius: number;
|
||||||
/** Other color */
|
/** Other color */
|
||||||
otherColor: OtherColor;
|
otherColor: OtherColor;
|
||||||
/** Whether info color is followed by the primary color */
|
/** Whether info color is followed by the primary color */
|
||||||
isInfoFollowPrimary: boolean;
|
isInfoFollowPrimary: boolean;
|
||||||
/** Reset cache strategy */
|
|
||||||
resetCacheStrategy: UnionKey.ResetCacheStrategy;
|
|
||||||
/** Layout */
|
/** Layout */
|
||||||
layout: {
|
layout: {
|
||||||
/** Layout mode */
|
/** Layout mode */
|
||||||
@@ -71,6 +71,8 @@ declare namespace App {
|
|||||||
height: number;
|
height: number;
|
||||||
/** Tab mode */
|
/** Tab mode */
|
||||||
mode: UnionKey.ThemeTabMode;
|
mode: UnionKey.ThemeTabMode;
|
||||||
|
/** Whether to close tab by middle click */
|
||||||
|
closeTabByMiddleClick: boolean;
|
||||||
};
|
};
|
||||||
/** Fixed header and tab */
|
/** Fixed header and tab */
|
||||||
fixedHeaderAndTab: boolean;
|
fixedHeaderAndTab: boolean;
|
||||||
@@ -376,9 +378,12 @@ declare namespace App {
|
|||||||
themeColor: {
|
themeColor: {
|
||||||
title: string;
|
title: string;
|
||||||
followPrimary: string;
|
followPrimary: string;
|
||||||
} & Theme.ThemeColor;
|
} & Record<Theme.ThemeColorKey, string>;
|
||||||
recommendColor: string;
|
recommendColor: string;
|
||||||
recommendColorDesc: string;
|
recommendColorDesc: string;
|
||||||
|
themeRadius: {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
preset: {
|
preset: {
|
||||||
title: string;
|
title: string;
|
||||||
apply: string;
|
apply: string;
|
||||||
@@ -402,6 +407,8 @@ declare namespace App {
|
|||||||
cacheTip: string;
|
cacheTip: string;
|
||||||
height: string;
|
height: string;
|
||||||
mode: { title: string } & Record<UnionKey.ThemeTabMode, string>;
|
mode: { title: string } & Record<UnionKey.ThemeTabMode, string>;
|
||||||
|
closeByMiddleClick: string;
|
||||||
|
closeByMiddleClickTip: string;
|
||||||
};
|
};
|
||||||
header: {
|
header: {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -436,7 +443,6 @@ declare namespace App {
|
|||||||
};
|
};
|
||||||
fixedHeaderAndTab: string;
|
fixedHeaderAndTab: string;
|
||||||
};
|
};
|
||||||
resetCacheStrategy: { title: string } & Record<UnionKey.ResetCacheStrategy, string>;
|
|
||||||
};
|
};
|
||||||
general: {
|
general: {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
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 */
|
/** Theme scheme */
|
||||||
type ThemeScheme = 'light' | 'dark' | 'auto';
|
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
|
* The layout mode
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const appStore = useAppStore();
|
|||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
|
|
||||||
interface LoginModule {
|
interface LoginModule {
|
||||||
label: string;
|
label: App.I18n.I18nKey;
|
||||||
component: Component;
|
component: Component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { createReusableTemplate } from '@vueuse/core';
|
import { createReusableTemplate } from '@vueuse/core';
|
||||||
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@@ -72,6 +73,8 @@ interface GradientBgProps {
|
|||||||
|
|
||||||
const [DefineGradientBg, GradientBg] = createReusableTemplate<GradientBgProps>();
|
const [DefineGradientBg, GradientBg] = createReusableTemplate<GradientBgProps>();
|
||||||
|
|
||||||
|
const themeStore = useThemeStore();
|
||||||
|
|
||||||
function getGradientColor(color: CardData['color']) {
|
function getGradientColor(color: CardData['color']) {
|
||||||
return `linear-gradient(to bottom right, ${color.start}, ${color.end})`;
|
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">
|
<NCard :bordered="false" size="small" class="card-wrapper">
|
||||||
<!-- define component start: GradientBg -->
|
<!-- define component start: GradientBg -->
|
||||||
<DefineGradientBg v-slot="{ $slots, gradientColor }">
|
<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" />
|
<component :is="$slots.default" />
|
||||||
</div>
|
</div>
|
||||||
</DefineGradientBg>
|
</DefineGradientBg>
|
||||||
|
|||||||
Reference in New Issue
Block a user