mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-18 01:36:37 +08:00
chore(projects): merge main to v1.1.0
This commit is contained in:
commit
ebe55af7d5
1
.npmrc
1
.npmrc
@ -1,3 +1,4 @@
|
|||||||
registry=https://registry.npmmirror.com/
|
registry=https://registry.npmmirror.com/
|
||||||
shamefully-hoist=true
|
shamefully-hoist=true
|
||||||
ignore-workspace-root-check=true
|
ignore-workspace-root-check=true
|
||||||
|
link-workspace-packages=true
|
||||||
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -13,7 +13,6 @@
|
|||||||
"i18n-ally.keystyle": "nested",
|
"i18n-ally.keystyle": "nested",
|
||||||
"i18n-ally.localesPaths": ["src/locales/langs"],
|
"i18n-ally.localesPaths": ["src/locales/langs"],
|
||||||
"prettier.enable": false,
|
"prettier.enable": false,
|
||||||
"unocss.root": ["./"],
|
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
"vue.server.hybridMode": true
|
"unocss.root": ["./"]
|
||||||
}
|
}
|
||||||
|
107
CHANGELOG.md
107
CHANGELOG.md
@ -1,6 +1,113 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
|
||||||
|
## [v1.0.9](https://github.com/soybeanjs/soybean-admin/compare/v1.0.8...v1.0.9) (2024-05-05)
|
||||||
|
|
||||||
|
### 🚀 Features
|
||||||
|
|
||||||
|
- **packages**: @sa/scripts: add new commit type `optimize` and commit scope `packages` - by @honghuangdc [<samp>(fbc2e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/fbc2e61)
|
||||||
|
|
||||||
|
### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- **projects**: fix manage page drawer operate about data reset. fixed #415, fixed #417 - by @honghuangdc in https://github.com/soybeanjs/soybean-admin/issues/415 and https://github.com/soybeanjs/soybean-admin/issues/417 [<samp>(f4513)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f4513e1)
|
||||||
|
|
||||||
|
### 📖 Documentation
|
||||||
|
|
||||||
|
- **projects**:
|
||||||
|
- add ecosystem to README.md - by @honghuangdc [<samp>(d0f17)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d0f17a4)
|
||||||
|
- add PanisAdmin to README - by **paynezhuang** [<samp>(ce2a7)</samp>](https://github.com/soybeanjs/soybean-admin/commit/ce2a75b)
|
||||||
|
|
||||||
|
### 🏡 Chore
|
||||||
|
|
||||||
|
- **deps**:
|
||||||
|
- update deps - by @honghuangdc [<samp>(413a8)</samp>](https://github.com/soybeanjs/soybean-admin/commit/413a8b2)
|
||||||
|
- update deps - by @honghuangdc [<samp>(734ef)</samp>](https://github.com/soybeanjs/soybean-admin/commit/734ef98)
|
||||||
|
- **projects**:
|
||||||
|
- update .npmrc - by @honghuangdc [<samp>(52188)</samp>](https://github.com/soybeanjs/soybean-admin/commit/52188d8)
|
||||||
|
- update vscode settings - by @honghuangdc [<samp>(c137b)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c137b97)
|
||||||
|
|
||||||
|
### ❤️ Contributors
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
[paynezhuang](mailto:paynezhuang@gmail.com)
|
||||||
|
|
||||||
|
## [v1.0.8](https://github.com/soybeanjs/soybean-admin/compare/v1.0.7...v1.0.8) (2024-04-27)
|
||||||
|
|
||||||
|
### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- **components**:
|
||||||
|
- fix PinToggler label. fixed #407 - by @honghuangdc in https://github.com/soybeanjs/soybean-admin/issues/407 [<samp>(c0ed1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c0ed1f2)
|
||||||
|
- **projects**:
|
||||||
|
- text level low. #409 - by **alleycharming** in https://github.com/soybeanjs/soybean-admin/issues/409 [<samp>(3ddb1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3ddb17a)
|
||||||
|
- fix tab fixedIndex as null case - by **paynezhuang** [<samp>(4708e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/4708ede)
|
||||||
|
- recovery the layout config before is mobile. fixed #408, fixed #361 - by @honghuangdc in https://github.com/soybeanjs/soybean-admin/issues/408 and https://github.com/soybeanjs/soybean-admin/issues/361 [<samp>(dae2a)</samp>](https://github.com/soybeanjs/soybean-admin/commit/dae2aa5)
|
||||||
|
|
||||||
|
### 🔥 Performance
|
||||||
|
|
||||||
|
- **projects**: perf judgement the fixed tab - by @honghuangdc [<samp>(b3e9b)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b3e9bba)
|
||||||
|
|
||||||
|
### 💅 Refactors
|
||||||
|
|
||||||
|
- **projects**: `Soybean Admin` to `SoybeanAdmin` - by @honghuangdc [<samp>(a8dbc)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a8dbc03)
|
||||||
|
|
||||||
|
### ❤️ Contributors
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
[paynezhuang](mailto:paynezhuang@gmail.com), [alleycharming](mailto:alleycharming@gmail.com)
|
||||||
|
|
||||||
|
## [v1.0.7](https://github.com/soybeanjs/soybean-admin/compare/v1.0.6...v1.0.7) (2024-04-25)
|
||||||
|
|
||||||
|
### 🚀 Features
|
||||||
|
|
||||||
|
- **projects**: support iframe page with diffrent url of custom route - by @honghuangdc [<samp>(da12d)</samp>](https://github.com/soybeanjs/soybean-admin/commit/da12d4a)
|
||||||
|
|
||||||
|
### 🏡 Chore
|
||||||
|
|
||||||
|
- **deps**: update deps - by @honghuangdc [<samp>(fbd80)</samp>](https://github.com/soybeanjs/soybean-admin/commit/fbd80c2)
|
||||||
|
|
||||||
|
### ❤️ Contributors
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
|
||||||
|
## [v1.0.6](https://github.com/soybeanjs/soybean-admin/compare/v1.0.5...v1.0.6) (2024-04-25)
|
||||||
|
|
||||||
|
### 🚀 Features
|
||||||
|
|
||||||
|
- **hooks**: add state hooks: useRef, useState, useSignal - by @honghuangdc [<samp>(09f64)</samp>](https://github.com/soybeanjs/soybean-admin/commit/09f6464)
|
||||||
|
|
||||||
|
### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- **projects**:
|
||||||
|
- added responseType judgment. #396 - by **alleycharming** in https://github.com/soybeanjs/soybean-admin/issues/396 [<samp>(82eab)</samp>](https://github.com/soybeanjs/soybean-admin/commit/82eabab)
|
||||||
|
- supply $t import statement - by @honghuangdc [<samp>(b2660)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b266035)
|
||||||
|
- fix mix-menu blank. fixed #389 & cache mixMenuFixed - by @honghuangdc in https://github.com/soybeanjs/soybean-admin/issues/389 [<samp>(93c7f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/93c7ff7)
|
||||||
|
|
||||||
|
### 🔥 Performance
|
||||||
|
|
||||||
|
- **hooks**:
|
||||||
|
- perf useSignal - by @honghuangdc [<samp>(5d45c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5d45cef)
|
||||||
|
- **projects**:
|
||||||
|
- remove useless prop `title` of `NDrawer` - by @honghuangdc [<samp>(fdde6)</samp>](https://github.com/soybeanjs/soybean-admin/commit/fdde679)
|
||||||
|
- add tsconfig.json for @sa/color-palette - by @honghuangdc [<samp>(d460e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d460e5c)
|
||||||
|
|
||||||
|
### 💅 Refactors
|
||||||
|
|
||||||
|
- **hooks**: refactor useSignal, useComputed - by @honghuangdc [<samp>(3b5e4)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3b5e4b3)
|
||||||
|
- **projects**: useMixMenuContext replace useMixMenu - by @honghuangdc [<samp>(1e142)</samp>](https://github.com/soybeanjs/soybean-admin/commit/1e14293)
|
||||||
|
|
||||||
|
### 🏡 Chore
|
||||||
|
|
||||||
|
- **deps**:
|
||||||
|
- update deps - by @honghuangdc [<samp>(e57bf)</samp>](https://github.com/soybeanjs/soybean-admin/commit/e57bf0b)
|
||||||
|
- **projects**:
|
||||||
|
- use `engines` replace `packageManager` - by @honghuangdc [<samp>(dcd51)</samp>](https://github.com/soybeanjs/soybean-admin/commit/dcd51f4)
|
||||||
|
- update pnpm version requirement - by @honghuangdc [<samp>(19e65)</samp>](https://github.com/soybeanjs/soybean-admin/commit/19e65c1)
|
||||||
|
|
||||||
|
### ❤️ Contributors
|
||||||
|
|
||||||
|
[](https://github.com/honghuangdc)
|
||||||
|
[alleycharming](mailto:alleycharming@gmail.com)
|
||||||
|
|
||||||
## [v1.0.5](https://github.com/honghuangdc/soybean-admin/compare/v1.0.4...v1.0.5) (2024-04-24)
|
## [v1.0.5](https://github.com/honghuangdc/soybean-admin/compare/v1.0.4...v1.0.5) (2024-04-24)
|
||||||
|
|
||||||
### 📖 Documentation
|
### 📖 Documentation
|
||||||
|
@ -106,6 +106,15 @@ pnpm dev
|
|||||||
pnpm build
|
pnpm build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Ecosystem
|
||||||
|
|
||||||
|
- [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).
|
||||||
|
- [MalusAdmin](https://github.com/pridejoy/MalusAdmin): A backend management framework developed based on Vue3/TypeScript/NaiveUI and NET7 & Sqlsugar. It is implemented in the most original and simplest way, with a fresh and elegant front-end, a clear and elegant backend structure, and powerful functions.
|
||||||
|
- [PanisAdmin](https://github.com/paynezhuang/panis-admin): Adopting SpringBoot 3, SaToken, MySQL and other frameworks to develop and modify [soybean-admin](https://github.com/soybeanjs/soybean-admin) for the second time, adapting dynamic menu/button-level authorization. Retaining the original flavor, fresh and elegant, high-value back-end management system scaffold.
|
||||||
|
|
||||||
|
|
||||||
## How to Contribute
|
## How to Contribute
|
||||||
|
|
||||||
We warmly welcome and appreciate all forms of contributions. If you have any ideas or suggestions, please feel free to share them by submitting [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) or creating GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new).
|
We warmly welcome and appreciate all forms of contributions. If you have any ideas or suggestions, please feel free to share them by submitting [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) or creating GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new).
|
||||||
|
@ -105,6 +105,15 @@ pnpm dev
|
|||||||
pnpm build
|
pnpm build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 周边生态
|
||||||
|
|
||||||
|
- [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) 开发的简单权限系统。
|
||||||
|
- [MalusAdmin](https://github.com/pridejoy/MalusAdmin): 基于 Vue3/TypeScript/NaiveUI 和 NET7 & Sqlsugar 开发的后台管理框架。采用最原生最简洁的方式来实现, 前端清新优雅高颜值,后端 结构清晰,优雅易懂,功能强大。
|
||||||
|
- [PanisAdmin](https://github.com/paynezhuang/panis-admin): 采用SpringBoot3、SaToken、MySQL等框架开发,二次修改 [soybean-admin](https://github.com/soybeanjs/soybean-admin),适配动态菜单/按钮级别的鉴权,保留原汁原味、清新优雅、高颜值的后台管理系统脚手架。
|
||||||
|
|
||||||
|
|
||||||
## 如何贡献
|
## 如何贡献
|
||||||
|
|
||||||
我们热烈欢迎并感谢所有形式的贡献。如果您有任何想法或建议,欢迎通过提交 [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) 或创建 GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new) 来分享。
|
我们热烈欢迎并感谢所有形式的贡献。如果您有任何想法或建议,欢迎通过提交 [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) 或创建 GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new) 来分享。
|
||||||
@ -126,6 +135,7 @@ pnpm build
|
|||||||
|
|
||||||
[Soybean](https://github.com/honghuangdc)
|
[Soybean](https://github.com/honghuangdc)
|
||||||
|
|
||||||
|
|
||||||
## 贡献者
|
## 贡献者
|
||||||
|
|
||||||
感谢以下贡献者的贡献。如果您想为本项目做出贡献,请参考 [如何贡献](#如何贡献)。
|
感谢以下贡献者的贡献。如果您想为本项目做出贡献,请参考 [如何贡献](#如何贡献)。
|
||||||
|
@ -9,7 +9,18 @@ export function setupElegantRouter() {
|
|||||||
blank: 'src/layouts/blank-layout/index.vue'
|
blank: 'src/layouts/blank-layout/index.vue'
|
||||||
},
|
},
|
||||||
customRoutes: {
|
customRoutes: {
|
||||||
names: ['exception_403', 'exception_404', 'exception_500']
|
names: [
|
||||||
|
'exception_403',
|
||||||
|
'exception_404',
|
||||||
|
'exception_500',
|
||||||
|
'document_project',
|
||||||
|
'document_project-link',
|
||||||
|
'document_vue',
|
||||||
|
'document_vite',
|
||||||
|
'document_unocss',
|
||||||
|
'document_naive',
|
||||||
|
'document_antd'
|
||||||
|
]
|
||||||
},
|
},
|
||||||
routePathTransformer(routeName, routePath) {
|
routePathTransformer(routeName, routePath) {
|
||||||
const key = routeName as RouteKey;
|
const key = routeName as RouteKey;
|
||||||
|
@ -7,7 +7,7 @@ export default defineConfig(
|
|||||||
'vue/multi-word-component-names': [
|
'vue/multi-word-component-names': [
|
||||||
'warn',
|
'warn',
|
||||||
{
|
{
|
||||||
ignores: ['index', 'App', '[id]']
|
ignores: ['index', 'App', '[id]', '[url]']
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'vue/component-name-in-template-casing': [
|
'vue/component-name-in-template-casing': [
|
||||||
|
35
package.json
35
package.json
@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "soybean-admin",
|
"name": "soybean-admin",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"packageManager": "pnpm@9.0.5",
|
|
||||||
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Soybean",
|
"name": "Soybean",
|
||||||
@ -27,6 +26,10 @@
|
|||||||
"ant-design-vue v4",
|
"ant-design-vue v4",
|
||||||
"UnoCSS"
|
"UnoCSS"
|
||||||
],
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.12.0",
|
||||||
|
"pnpm": ">=8.7.0"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build --mode prod",
|
"build": "vite build --mode prod",
|
||||||
"build:test": "vite build --mode test",
|
"build:test": "vite build --mode test",
|
||||||
@ -52,25 +55,25 @@
|
|||||||
"@sa/utils": "workspace:*",
|
"@sa/utils": "workspace:*",
|
||||||
"@vueuse/core": "10.9.0",
|
"@vueuse/core": "10.9.0",
|
||||||
"clipboard": "2.0.11",
|
"clipboard": "2.0.11",
|
||||||
"dayjs": "1.11.10",
|
"dayjs": "1.11.11",
|
||||||
"echarts": "5.5.0",
|
"echarts": "5.5.0",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "4.17.21",
|
||||||
"naive-ui": "2.38.1",
|
"naive-ui": "2.38.2",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"pinia": "2.1.7",
|
"pinia": "2.1.7",
|
||||||
"vue": "3.4.25",
|
"vue": "3.4.26",
|
||||||
"vue-draggable-plus": "0.4.0",
|
"vue-draggable-plus": "0.4.0",
|
||||||
"vue-i18n": "9.13.1",
|
"vue-i18n": "9.13.1",
|
||||||
"vue-router": "4.3.2"
|
"vue-router": "4.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@elegant-router/vue": "0.3.6",
|
"@elegant-router/vue": "0.3.6",
|
||||||
"@iconify/json": "2.2.204",
|
"@iconify/json": "2.2.206",
|
||||||
"@sa/scripts": "workspace:*",
|
"@sa/scripts": "workspace:*",
|
||||||
"@sa/uno-preset": "workspace:*",
|
"@sa/uno-preset": "workspace:*",
|
||||||
"@soybeanjs/eslint-config": "1.3.2",
|
"@soybeanjs/eslint-config": "1.3.4",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "4.17.12",
|
||||||
"@types/node": "20.12.7",
|
"@types/node": "20.12.8",
|
||||||
"@types/nprogress": "0.2.3",
|
"@types/nprogress": "0.2.3",
|
||||||
"@unocss/eslint-config": "0.59.4",
|
"@unocss/eslint-config": "0.59.4",
|
||||||
"@unocss/preset-icons": "0.59.4",
|
"@unocss/preset-icons": "0.59.4",
|
||||||
@ -80,21 +83,21 @@
|
|||||||
"@unocss/vite": "0.59.4",
|
"@unocss/vite": "0.59.4",
|
||||||
"@vitejs/plugin-vue": "5.0.4",
|
"@vitejs/plugin-vue": "5.0.4",
|
||||||
"@vitejs/plugin-vue-jsx": "3.1.0",
|
"@vitejs/plugin-vue-jsx": "3.1.0",
|
||||||
"eslint": "9.1.1",
|
"eslint": "9.2.0",
|
||||||
"eslint-plugin-vue": "9.25.0",
|
"eslint-plugin-vue": "9.25.0",
|
||||||
"lint-staged": "15.2.2",
|
"lint-staged": "15.2.2",
|
||||||
"sass": "1.75.0",
|
"sass": "1.76.0",
|
||||||
"simple-git-hooks": "2.11.1",
|
"simple-git-hooks": "2.11.1",
|
||||||
"tsx": "4.7.3",
|
"tsx": "4.9.1",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.4.5",
|
||||||
"unplugin-icons": "0.18.5",
|
"unplugin-icons": "0.19.0",
|
||||||
"unplugin-vue-components": "0.26.0",
|
"unplugin-vue-components": "0.27.0",
|
||||||
"vite": "5.2.10",
|
"vite": "5.2.11",
|
||||||
"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": "7.1.2",
|
"vite-plugin-vue-devtools": "7.1.3",
|
||||||
"vue-eslint-parser": "9.4.2",
|
"vue-eslint-parser": "9.4.2",
|
||||||
"vue-tsc": "2.0.14"
|
"vue-tsc": "2.0.16"
|
||||||
},
|
},
|
||||||
"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/axios",
|
"name": "@sa/axios",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -48,7 +48,9 @@ function createCommonRequest<ResponseData = any>(
|
|||||||
|
|
||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
async response => {
|
async response => {
|
||||||
if (opts.isBackendSuccess(response)) {
|
const responseType: ResponseType = (response.config?.responseType as ResponseType) || 'json';
|
||||||
|
|
||||||
|
if (responseType !== 'json' || opts.isBackendSuccess(response)) {
|
||||||
return Promise.resolve(response);
|
return Promise.resolve(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/color",
|
"name": "@sa/color",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/hooks",
|
"name": "@sa/hooks",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -7,4 +7,5 @@ import useHookTable from './use-table';
|
|||||||
|
|
||||||
export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useHookTable };
|
export { useBoolean, useLoading, useCountDown, useContext, useSvgIconRender, useHookTable };
|
||||||
|
|
||||||
|
export * from './use-signal';
|
||||||
export * from './use-table';
|
export * from './use-table';
|
||||||
|
144
packages/hooks/src/use-signal.ts
Normal file
144
packages/hooks/src/use-signal.ts
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import { computed, ref, shallowRef, triggerRef } from 'vue';
|
||||||
|
import type {
|
||||||
|
ComputedGetter,
|
||||||
|
DebuggerOptions,
|
||||||
|
Ref,
|
||||||
|
ShallowRef,
|
||||||
|
WritableComputedOptions,
|
||||||
|
WritableComputedRef
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
type Updater<T> = (value: T) => T;
|
||||||
|
type Mutator<T> = (value: T) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal is a reactive value that can be set, updated or mutated
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```ts
|
||||||
|
* const count = useSignal(0);
|
||||||
|
*
|
||||||
|
* // `watchEffect`
|
||||||
|
* watchEffect(() => {
|
||||||
|
* console.log(count());
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // watch
|
||||||
|
* watch(count, value => {
|
||||||
|
* console.log(value);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // useComputed
|
||||||
|
* const double = useComputed(() => count() * 2);
|
||||||
|
* const writeableDouble = useComputed({
|
||||||
|
* get: () => count() * 2,
|
||||||
|
* set: value => count.set(value / 2)
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export interface Signal<T> {
|
||||||
|
(): Readonly<T>;
|
||||||
|
/**
|
||||||
|
* Set the value of the signal
|
||||||
|
*
|
||||||
|
* It recommend use `set` for primitive values
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
set(value: T): void;
|
||||||
|
/**
|
||||||
|
* Update the value of the signal using an updater function
|
||||||
|
*
|
||||||
|
* It recommend use `update` for non-primitive values, only the first level of the object will be reactive.
|
||||||
|
*
|
||||||
|
* @param updater
|
||||||
|
*/
|
||||||
|
update(updater: Updater<T>): void;
|
||||||
|
/**
|
||||||
|
* Mutate the value of the signal using a mutator function
|
||||||
|
*
|
||||||
|
* this action will call `triggerRef`, so the value will be tracked on `watchEffect`.
|
||||||
|
*
|
||||||
|
* It recommend use `mutate` for non-primitive values, all levels of the object will be reactive.
|
||||||
|
*
|
||||||
|
* @param mutator
|
||||||
|
*/
|
||||||
|
mutate(mutator: Mutator<T>): void;
|
||||||
|
/**
|
||||||
|
* Get the reference of the signal
|
||||||
|
*
|
||||||
|
* Sometimes it can be useful to make `v-model` work with the signal
|
||||||
|
*
|
||||||
|
* ```vue
|
||||||
|
* <template>
|
||||||
|
* <input v-model="model.count" />
|
||||||
|
* </template>;
|
||||||
|
*
|
||||||
|
* <script setup lang="ts">
|
||||||
|
* const state = useSignal({ count: 0 }, { useRef: true });
|
||||||
|
*
|
||||||
|
* const model = state.getRef();
|
||||||
|
* </script>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
getRef(): Readonly<ShallowRef<Readonly<T>>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReadonlySignal<T> {
|
||||||
|
(): Readonly<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SignalOptions {
|
||||||
|
/**
|
||||||
|
* Whether to use `ref` to store the value
|
||||||
|
*
|
||||||
|
* @default false use `sharedRef` to store the value
|
||||||
|
*/
|
||||||
|
useRef?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSignal<T>(initialValue: T, options?: SignalOptions): Signal<T> {
|
||||||
|
const { useRef } = options || {};
|
||||||
|
|
||||||
|
const state = useRef ? (ref(initialValue) as Ref<T>) : shallowRef(initialValue);
|
||||||
|
|
||||||
|
return createSignal(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useComputed<T>(getter: ComputedGetter<T>, debugOptions?: DebuggerOptions): ReadonlySignal<T>;
|
||||||
|
export function useComputed<T>(options: WritableComputedOptions<T>, debugOptions?: DebuggerOptions): Signal<T>;
|
||||||
|
export function useComputed<T>(
|
||||||
|
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>,
|
||||||
|
debugOptions?: DebuggerOptions
|
||||||
|
) {
|
||||||
|
const isGetter = typeof getterOrOptions === 'function';
|
||||||
|
|
||||||
|
const computedValue = computed(getterOrOptions as any, debugOptions);
|
||||||
|
|
||||||
|
if (isGetter) {
|
||||||
|
return () => computedValue.value as ReadonlySignal<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createSignal(computedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSignal<T>(state: ShallowRef<T> | WritableComputedRef<T>): Signal<T> {
|
||||||
|
const signal = () => state.value;
|
||||||
|
|
||||||
|
signal.set = (value: T) => {
|
||||||
|
state.value = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.update = (updater: Updater<T>) => {
|
||||||
|
state.value = updater(state.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.mutate = (mutator: Mutator<T>) => {
|
||||||
|
mutator(state.value);
|
||||||
|
triggerRef(state);
|
||||||
|
};
|
||||||
|
|
||||||
|
signal.getRef = () => state as Readonly<ShallowRef<Readonly<T>>>;
|
||||||
|
|
||||||
|
return signal;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/materials",
|
"name": "@sa/materials",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/fetch",
|
"name": "@sa/fetch",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/scripts",
|
"name": "@sa/scripts",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"bin": {
|
"bin": {
|
||||||
"sa": "./bin.ts"
|
"sa": "./bin.ts"
|
||||||
},
|
},
|
||||||
@ -13,15 +13,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@soybeanjs/changelog": "0.3.22",
|
"@soybeanjs/changelog": "0.3.23",
|
||||||
"bumpp": "9.4.0",
|
"bumpp": "9.4.1",
|
||||||
"c12": "1.10.0",
|
"c12": "1.10.0",
|
||||||
"cac": "6.7.14",
|
"cac": "6.7.14",
|
||||||
"consola": "3.2.3",
|
"consola": "3.2.3",
|
||||||
"enquirer": "2.4.1",
|
"enquirer": "2.4.1",
|
||||||
"execa": "8.0.1",
|
"execa": "8.0.1",
|
||||||
"kolorist": "1.8.0",
|
"kolorist": "1.8.0",
|
||||||
"npm-check-updates": "16.14.19",
|
"npm-check-updates": "16.14.20",
|
||||||
"rimraf": "5.0.5"
|
"rimraf": "5.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ const defaultOptions: CliOption = {
|
|||||||
['style', 'Changes that do not affect the meaning of the code'],
|
['style', 'Changes that do not affect the meaning of the code'],
|
||||||
['refactor', 'A code change that neither fixes a bug nor adds a feature'],
|
['refactor', 'A code change that neither fixes a bug nor adds a feature'],
|
||||||
['perf', 'A code change that improves performance'],
|
['perf', 'A code change that improves performance'],
|
||||||
|
['optimize', 'A code change that optimizes code quality'],
|
||||||
['test', 'Adding missing tests or correcting existing tests'],
|
['test', 'Adding missing tests or correcting existing tests'],
|
||||||
['build', 'Changes that affect the build system or external dependencies'],
|
['build', 'Changes that affect the build system or external dependencies'],
|
||||||
['ci', 'Changes to our CI configuration files and scripts'],
|
['ci', 'Changes to our CI configuration files and scripts'],
|
||||||
@ -27,6 +28,7 @@ const defaultOptions: CliOption = {
|
|||||||
],
|
],
|
||||||
gitCommitScopes: [
|
gitCommitScopes: [
|
||||||
['projects', 'project'],
|
['projects', 'project'],
|
||||||
|
['packages', 'packages'],
|
||||||
['components', 'components'],
|
['components', 'components'],
|
||||||
['hooks', 'hook functions'],
|
['hooks', 'hook functions'],
|
||||||
['utils', 'utils functions'],
|
['utils', 'utils functions'],
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/uno-preset",
|
"name": "@sa/uno-preset",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@sa/utils",
|
"name": "@sa/utils",
|
||||||
"version": "1.0.5",
|
"version": "1.0.9",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
|
1616
pnpm-lock.yaml
1616
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'TableHeaderOperation'
|
name: 'TableHeaderOperation'
|
||||||
});
|
});
|
||||||
|
@ -36,7 +36,11 @@ const icon = computed(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ButtonIcon :tooltip-content="collapsed ? $t('icon.expand') : $t('icon.collapse')" tooltip-placement="bottom-start">
|
<ButtonIcon
|
||||||
|
:tooltip-content="collapsed ? $t('icon.expand') : $t('icon.collapse')"
|
||||||
|
tooltip-placement="bottom-start"
|
||||||
|
:z-index="99"
|
||||||
|
>
|
||||||
<SvgIcon :icon="icon" />
|
<SvgIcon :icon="icon" />
|
||||||
</ButtonIcon>
|
</ButtonIcon>
|
||||||
</template>
|
</template>
|
||||||
|
@ -15,7 +15,7 @@ const icon = computed(() => (props.pin ? 'mdi-pin-off' : 'mdi-pin'));
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
:tooltip-content="pin ? $t('icon.pin') : $t('icon.unpin')"
|
:tooltip-content="pin ? $t('icon.unpin') : $t('icon.pin')"
|
||||||
tooltip-placement="bottom-start"
|
tooltip-placement="bottom-start"
|
||||||
:z-index="100"
|
:z-index="100"
|
||||||
>
|
>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { computed, effectScope, onScopeDispose, reactive, ref, watch } from 'vue';
|
import { computed, effectScope, onScopeDispose, reactive, ref, watch } from 'vue';
|
||||||
import type { Ref } from 'vue';
|
import type { Ref } from 'vue';
|
||||||
import type { PaginationProps } from 'naive-ui';
|
import type { PaginationProps } from 'naive-ui';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
import { useBoolean, useHookTable } from '@sa/hooks';
|
import { useBoolean, useHookTable } from '@sa/hooks';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
import { $t } from '@/locales';
|
import { $t } from '@/locales';
|
||||||
@ -194,7 +195,8 @@ export function useTableOperate<T extends TableData = TableData>(data: Ref<T[]>,
|
|||||||
|
|
||||||
function handleEdit(id: T['id']) {
|
function handleEdit(id: T['id']) {
|
||||||
operateType.value = 'edit';
|
operateType.value = 'edit';
|
||||||
editingData.value = data.value.find(item => item.id === id) || null;
|
const findItem = data.value.find(item => item.id === id) || null;
|
||||||
|
editingData.value = cloneDeep(findItem);
|
||||||
|
|
||||||
openDrawer();
|
openDrawer();
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ defineOptions({
|
|||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
|
const { menus } = setupMixMenuContext();
|
||||||
|
|
||||||
const layoutMode = computed(() => {
|
const layoutMode = computed(() => {
|
||||||
const vertical: LayoutMode = 'vertical';
|
const vertical: LayoutMode = 'vertical';
|
||||||
@ -65,7 +66,7 @@ function getSiderWidth() {
|
|||||||
|
|
||||||
let w = isVerticalMix.value || isHorizontalMix.value ? mixWidth : width;
|
let w = isVerticalMix.value || isHorizontalMix.value ? mixWidth : width;
|
||||||
|
|
||||||
if (isVerticalMix.value && appStore.mixSiderFixed) {
|
if (isVerticalMix.value && appStore.mixSiderFixed && menus.value.length) {
|
||||||
w += mixChildMenuWidth;
|
w += mixChildMenuWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,14 +78,12 @@ function getSiderCollapsedWidth() {
|
|||||||
|
|
||||||
let w = isVerticalMix.value || isHorizontalMix.value ? mixCollapsedWidth : collapsedWidth;
|
let w = isVerticalMix.value || isHorizontalMix.value ? mixCollapsedWidth : collapsedWidth;
|
||||||
|
|
||||||
if (isVerticalMix.value && appStore.mixSiderFixed) {
|
if (isVerticalMix.value && appStore.mixSiderFixed && menus.value.length) {
|
||||||
w += mixChildMenuWidth;
|
w += mixChildMenuWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupMixMenuContext();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,4 +1,47 @@
|
|||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import { useContext } from '@sa/hooks';
|
import { useContext } from '@sa/hooks';
|
||||||
import { useMixMenu } from '../hooks';
|
import { useRouteStore } from '@/store/modules/route';
|
||||||
|
|
||||||
export const { setupStore: setupMixMenuContext, useStore: useMixMenuContext } = useContext('mix-menu', useMixMenu);
|
export const { setupStore: setupMixMenuContext, useStore: useMixMenuContext } = useContext('mix-menu', useMixMenu);
|
||||||
|
|
||||||
|
function useMixMenu() {
|
||||||
|
const route = useRoute();
|
||||||
|
const routeStore = useRouteStore();
|
||||||
|
|
||||||
|
const activeFirstLevelMenuKey = ref('');
|
||||||
|
|
||||||
|
function setActiveFirstLevelMenuKey(key: string) {
|
||||||
|
activeFirstLevelMenuKey.value = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActiveFirstLevelMenuKey() {
|
||||||
|
const { hideInMenu, activeMenu } = route.meta;
|
||||||
|
const name = route.name as string;
|
||||||
|
|
||||||
|
const routeName = (hideInMenu ? activeMenu : name) || name;
|
||||||
|
|
||||||
|
const [firstLevelRouteName] = routeName.split('_');
|
||||||
|
|
||||||
|
setActiveFirstLevelMenuKey(firstLevelRouteName);
|
||||||
|
}
|
||||||
|
|
||||||
|
const menus = computed(
|
||||||
|
() => routeStore.menus.find(menu => menu.key === activeFirstLevelMenuKey.value)?.children || []
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.name,
|
||||||
|
() => {
|
||||||
|
getActiveFirstLevelMenuKey();
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
activeFirstLevelMenuKey,
|
||||||
|
setActiveFirstLevelMenuKey,
|
||||||
|
getActiveFirstLevelMenuKey,
|
||||||
|
menus
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
import { computed, ref, watch } from 'vue';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import { useRouteStore } from '@/store/modules/route';
|
|
||||||
|
|
||||||
export function useMixMenu() {
|
|
||||||
const route = useRoute();
|
|
||||||
const routeStore = useRouteStore();
|
|
||||||
|
|
||||||
const activeFirstLevelMenuKey = ref('');
|
|
||||||
|
|
||||||
function setActiveFirstLevelMenuKey(key: string) {
|
|
||||||
activeFirstLevelMenuKey.value = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getActiveFirstLevelMenuKey() {
|
|
||||||
const { hideInMenu, activeMenu } = route.meta;
|
|
||||||
const name = route.name as string;
|
|
||||||
|
|
||||||
const routeName = (hideInMenu ? activeMenu : name) || name;
|
|
||||||
|
|
||||||
const [firstLevelRouteName] = routeName.split('_');
|
|
||||||
|
|
||||||
setActiveFirstLevelMenuKey(firstLevelRouteName);
|
|
||||||
}
|
|
||||||
|
|
||||||
const menus = computed(
|
|
||||||
() => routeStore.menus.find(menu => menu.key === activeFirstLevelMenuKey.value)?.children || []
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => route.name,
|
|
||||||
() => {
|
|
||||||
getActiveFirstLevelMenuKey();
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
activeFirstLevelMenuKey,
|
|
||||||
setActiveFirstLevelMenuKey,
|
|
||||||
getActiveFirstLevelMenuKey,
|
|
||||||
menus
|
|
||||||
};
|
|
||||||
}
|
|
@ -2,10 +2,10 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useBoolean } from '@sa/hooks';
|
import { useBoolean } from '@sa/hooks';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
import { useRouteStore } from '@/store/modules/route';
|
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
import { useRouterPush } from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
import { useMixMenu } from '../../hooks';
|
import { $t } from '@/locales';
|
||||||
|
import { useMixMenuContext } from '../../context';
|
||||||
import FirstLevelMenu from './first-level-menu.vue';
|
import FirstLevelMenu from './first-level-menu.vue';
|
||||||
import BaseMenu from './base-menu.vue';
|
import BaseMenu from './base-menu.vue';
|
||||||
|
|
||||||
@ -15,16 +15,15 @@ defineOptions({
|
|||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
const routeStore = useRouteStore();
|
|
||||||
const { routerPushByKey } = useRouterPush();
|
const { routerPushByKey } = useRouterPush();
|
||||||
const { bool: drawerVisible, setBool: setDrawerVisible } = useBoolean();
|
const { bool: drawerVisible, setBool: setDrawerVisible } = useBoolean();
|
||||||
const { activeFirstLevelMenuKey, setActiveFirstLevelMenuKey, getActiveFirstLevelMenuKey } = useMixMenu();
|
const { menus, activeFirstLevelMenuKey, setActiveFirstLevelMenuKey, getActiveFirstLevelMenuKey } = useMixMenuContext();
|
||||||
|
|
||||||
const siderInverted = computed(() => !themeStore.darkMode && themeStore.sider.inverted);
|
const siderInverted = computed(() => !themeStore.darkMode && themeStore.sider.inverted);
|
||||||
|
|
||||||
const menus = computed(() => routeStore.menus.find(menu => menu.key === activeFirstLevelMenuKey.value)?.children || []);
|
const hasMenus = computed(() => menus.value.length > 0);
|
||||||
|
|
||||||
const showDrawer = computed(() => (drawerVisible.value && menus.value.length) || appStore.mixSiderFixed);
|
const showDrawer = computed(() => hasMenus.value && (drawerVisible.value || appStore.mixSiderFixed));
|
||||||
|
|
||||||
function handleSelectMixMenu(menu: App.Global.Menu) {
|
function handleSelectMixMenu(menu: App.Global.Menu) {
|
||||||
setActiveFirstLevelMenuKey(menu.key);
|
setActiveFirstLevelMenuKey(menu.key);
|
||||||
@ -49,7 +48,7 @@ function handleResetActiveMenu() {
|
|||||||
</FirstLevelMenu>
|
</FirstLevelMenu>
|
||||||
<div
|
<div
|
||||||
class="relative h-full transition-width-300"
|
class="relative h-full transition-width-300"
|
||||||
:style="{ width: appStore.mixSiderFixed ? themeStore.sider.mixChildMenuWidth + 'px' : '0px' }"
|
:style="{ width: appStore.mixSiderFixed && hasMenus ? themeStore.sider.mixChildMenuWidth + 'px' : '0px' }"
|
||||||
>
|
>
|
||||||
<DarkModeContainer
|
<DarkModeContainer
|
||||||
class="absolute-lt h-full flex-col-stretch nowrap-hidden shadow-sm transition-all-300"
|
class="absolute-lt h-full flex-col-stretch nowrap-hidden shadow-sm transition-all-300"
|
||||||
|
@ -140,7 +140,16 @@ const local: App.I18n.Schema = {
|
|||||||
403: 'No Permission',
|
403: 'No Permission',
|
||||||
404: 'Page Not Found',
|
404: 'Page Not Found',
|
||||||
500: 'Server Error',
|
500: 'Server Error',
|
||||||
|
'iframe-page': 'Iframe',
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
|
document: 'Document',
|
||||||
|
document_project: 'Project Document',
|
||||||
|
'document_project-link': 'Project Document(External Link)',
|
||||||
|
document_vue: 'Vue Document',
|
||||||
|
document_vite: 'Vite Document',
|
||||||
|
document_unocss: 'UnoCSS Document',
|
||||||
|
document_naive: 'Naive UI Document',
|
||||||
|
document_antd: 'Ant Design Vue Document',
|
||||||
'user-center': 'User Center',
|
'user-center': 'User Center',
|
||||||
about: 'About',
|
about: 'About',
|
||||||
function: 'System Function',
|
function: 'System Function',
|
||||||
|
@ -140,7 +140,16 @@ const local: App.I18n.Schema = {
|
|||||||
403: '无权限',
|
403: '无权限',
|
||||||
404: '页面不存在',
|
404: '页面不存在',
|
||||||
500: '服务器错误',
|
500: '服务器错误',
|
||||||
|
'iframe-page': '外链页面',
|
||||||
home: '首页',
|
home: '首页',
|
||||||
|
document: '文档',
|
||||||
|
document_project: '项目文档',
|
||||||
|
'document_project-link': '项目文档(外链)',
|
||||||
|
document_vue: 'Vue文档',
|
||||||
|
document_vite: 'Vite文档',
|
||||||
|
document_unocss: 'UnoCSS文档',
|
||||||
|
document_naive: 'Naive UI文档',
|
||||||
|
document_antd: 'Ant Design Vue文档',
|
||||||
'user-center': '个人中心',
|
'user-center': '个人中心',
|
||||||
about: '关于',
|
about: '关于',
|
||||||
function: '系统功能',
|
function: '系统功能',
|
||||||
|
@ -18,6 +18,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
403: () => import("@/views/_builtin/403/index.vue"),
|
403: () => import("@/views/_builtin/403/index.vue"),
|
||||||
404: () => import("@/views/_builtin/404/index.vue"),
|
404: () => import("@/views/_builtin/404/index.vue"),
|
||||||
500: () => import("@/views/_builtin/500/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"),
|
login: () => import("@/views/_builtin/login/index.vue"),
|
||||||
about: () => import("@/views/about/index.vue"),
|
about: () => import("@/views/about/index.vue"),
|
||||||
"function_hide-child_one": () => import("@/views/function/hide-child/one/index.vue"),
|
"function_hide-child_one": () => import("@/views/function/hide-child/one/index.vue"),
|
||||||
|
@ -179,6 +179,19 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
order: 1
|
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',
|
name: 'login',
|
||||||
path: '/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?',
|
path: '/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?',
|
||||||
|
@ -147,6 +147,14 @@ const routeMap: RouteMap = {
|
|||||||
"exception_403": "/exception/403",
|
"exception_403": "/exception/403",
|
||||||
"exception_404": "/exception/404",
|
"exception_404": "/exception/404",
|
||||||
"exception_500": "/exception/500",
|
"exception_500": "/exception/500",
|
||||||
|
"document": "/document",
|
||||||
|
"document_project": "/document/project",
|
||||||
|
"document_project-link": "/document/project-link",
|
||||||
|
"document_vue": "/document/vue",
|
||||||
|
"document_vite": "/document/vite",
|
||||||
|
"document_unocss": "/document/unocss",
|
||||||
|
"document_naive": "/document/naive",
|
||||||
|
"document_antd": "/document/antd",
|
||||||
"403": "/403",
|
"403": "/403",
|
||||||
"404": "/404",
|
"404": "/404",
|
||||||
"500": "/500",
|
"500": "/500",
|
||||||
@ -162,6 +170,7 @@ const routeMap: RouteMap = {
|
|||||||
"function_tab": "/function/tab",
|
"function_tab": "/function/tab",
|
||||||
"function_toggle-auth": "/function/toggle-auth",
|
"function_toggle-auth": "/function/toggle-auth",
|
||||||
"home": "/home",
|
"home": "/home",
|
||||||
|
"iframe-page": "/iframe-page/:url",
|
||||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
|
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
|
||||||
"manage": "/manage",
|
"manage": "/manage",
|
||||||
"manage_menu": "/manage/menu",
|
"manage_menu": "/manage/menu",
|
||||||
|
@ -51,6 +51,115 @@ const customRoutes: CustomRoute[] = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document',
|
||||||
|
path: '/document',
|
||||||
|
component: 'layout.base',
|
||||||
|
meta: {
|
||||||
|
title: 'document',
|
||||||
|
i18nKey: 'route.document',
|
||||||
|
order: 2,
|
||||||
|
icon: 'mdi:file-document-multiple-outline'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'document_antd',
|
||||||
|
path: '/document/antd',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://antdv.com/components/overview-cn'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_antd',
|
||||||
|
i18nKey: 'route.document_antd',
|
||||||
|
order: 7,
|
||||||
|
icon: 'logos:ant-design'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_naive',
|
||||||
|
path: '/document/naive',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://www.naiveui.com/zh-CN/os-theme/docs/introduction'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_naive',
|
||||||
|
i18nKey: 'route.document_naive',
|
||||||
|
order: 6,
|
||||||
|
icon: 'logos:naiveui'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_project',
|
||||||
|
path: '/document/project',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://docs.soybeanjs.cn/zh'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_project',
|
||||||
|
i18nKey: 'route.document_project',
|
||||||
|
order: 1,
|
||||||
|
localIcon: 'logo'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_project-link',
|
||||||
|
path: '/document/project-link',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
meta: {
|
||||||
|
title: 'document_project-link',
|
||||||
|
i18nKey: 'route.document_project-link',
|
||||||
|
order: 2,
|
||||||
|
localIcon: 'logo',
|
||||||
|
href: 'https://docs.soybeanjs.cn/zh'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_unocss',
|
||||||
|
path: '/document/unocss',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://unocss.dev/'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_unocss',
|
||||||
|
i18nKey: 'route.document_unocss',
|
||||||
|
order: 5,
|
||||||
|
icon: 'logos:unocss'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_vite',
|
||||||
|
path: '/document/vite',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://cn.vitejs.dev/'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_vite',
|
||||||
|
i18nKey: 'route.document_vite',
|
||||||
|
order: 4,
|
||||||
|
icon: 'logos:vitejs'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'document_vue',
|
||||||
|
path: '/document/vue',
|
||||||
|
component: 'view.iframe-page',
|
||||||
|
props: {
|
||||||
|
url: 'https://cn.vuejs.org/'
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'document_vue',
|
||||||
|
i18nKey: 'route.document_vue',
|
||||||
|
order: 3,
|
||||||
|
icon: 'logos:vue'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { effectScope, onScopeDispose, ref, watch } from 'vue';
|
import { effectScope, nextTick, onScopeDispose, ref, watch } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { breakpointsTailwind, useBreakpoints, useTitle } from '@vueuse/core';
|
import { breakpointsTailwind, useBreakpoints, useEventListener, useTitle } from '@vueuse/core';
|
||||||
import { useBoolean } from '@sa/hooks';
|
import { useBoolean } from '@sa/hooks';
|
||||||
import { SetupStoreId } from '@/enum';
|
import { SetupStoreId } from '@/enum';
|
||||||
import { router } from '@/router';
|
import { router } from '@/router';
|
||||||
@ -22,7 +22,11 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
const { bool: fullContent, toggle: toggleFullContent } = useBoolean();
|
const { bool: fullContent, toggle: toggleFullContent } = useBoolean();
|
||||||
const { bool: contentXScrollable, setBool: setContentXScrollable } = useBoolean();
|
const { bool: contentXScrollable, setBool: setContentXScrollable } = useBoolean();
|
||||||
const { bool: siderCollapse, setBool: setSiderCollapse, toggle: toggleSiderCollapse } = useBoolean();
|
const { bool: siderCollapse, setBool: setSiderCollapse, toggle: toggleSiderCollapse } = useBoolean();
|
||||||
const { bool: mixSiderFixed, setBool: setMixSiderFixed, toggle: toggleMixSiderFixed } = useBoolean();
|
const {
|
||||||
|
bool: mixSiderFixed,
|
||||||
|
setBool: setMixSiderFixed,
|
||||||
|
toggle: toggleMixSiderFixed
|
||||||
|
} = useBoolean(localStg.get('mixSiderFixed') === 'Y');
|
||||||
|
|
||||||
/** Is mobile layout */
|
/** Is mobile layout */
|
||||||
const isMobile = breakpoints.smaller('sm');
|
const isMobile = breakpoints.smaller('sm');
|
||||||
@ -83,9 +87,26 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
isMobile,
|
isMobile,
|
||||||
newValue => {
|
newValue => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
setSiderCollapse(true);
|
// backup theme setting before is mobile
|
||||||
|
localStg.set('backupThemeSettingBeforeIsMobile', {
|
||||||
|
layout: themeStore.layout.mode,
|
||||||
|
siderCollapse: siderCollapse.value
|
||||||
|
});
|
||||||
|
|
||||||
themeStore.setThemeLayout('vertical');
|
themeStore.setThemeLayout('vertical');
|
||||||
|
setSiderCollapse(true);
|
||||||
|
} else {
|
||||||
|
// when is not mobile, recover the backup theme setting
|
||||||
|
const backup = localStg.get('backupThemeSettingBeforeIsMobile');
|
||||||
|
|
||||||
|
if (backup) {
|
||||||
|
nextTick(() => {
|
||||||
|
themeStore.setThemeLayout(backup.layout);
|
||||||
|
setSiderCollapse(backup.siderCollapse);
|
||||||
|
|
||||||
|
localStg.remove('backupThemeSettingBeforeIsMobile');
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
@ -107,6 +128,11 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// cache mixSiderFixed
|
||||||
|
useEventListener(window, 'beforeunload', () => {
|
||||||
|
localStg.set('mixSiderFixed', mixSiderFixed.value ? 'Y' : 'N');
|
||||||
|
});
|
||||||
|
|
||||||
/** On scope dispose */
|
/** On scope dispose */
|
||||||
onScopeDispose(() => {
|
onScopeDispose(() => {
|
||||||
scope.stop();
|
scope.stop();
|
||||||
|
@ -16,17 +16,24 @@ export function getAllTabs(tabs: App.Global.Tab[], homeTab?: App.Global.Tab) {
|
|||||||
|
|
||||||
const filterHomeTabs = tabs.filter(tab => tab.id !== homeTab.id);
|
const filterHomeTabs = tabs.filter(tab => tab.id !== homeTab.id);
|
||||||
|
|
||||||
const fixedTabs = filterHomeTabs
|
const fixedTabs = filterHomeTabs.filter(isFixedTab).sort((a, b) => a.fixedIndex! - b.fixedIndex!);
|
||||||
.filter(tab => tab.fixedIndex !== undefined)
|
|
||||||
.sort((a, b) => a.fixedIndex! - b.fixedIndex!);
|
|
||||||
|
|
||||||
const remainTabs = filterHomeTabs.filter(tab => tab.fixedIndex === undefined);
|
const remainTabs = filterHomeTabs.filter(tab => !isFixedTab(tab));
|
||||||
|
|
||||||
const allTabs = [homeTab, ...fixedTabs, ...remainTabs];
|
const allTabs = [homeTab, ...fixedTabs, ...remainTabs];
|
||||||
|
|
||||||
return updateTabsLabel(allTabs);
|
return updateTabsLabel(allTabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is fixed tab
|
||||||
|
*
|
||||||
|
* @param tab
|
||||||
|
*/
|
||||||
|
function isFixedTab(tab: App.Global.Tab) {
|
||||||
|
return tab.fixedIndex !== undefined && tab.fixedIndex !== null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get tab id by route
|
* Get tab id by route
|
||||||
*
|
*
|
||||||
@ -177,7 +184,7 @@ export function extractTabsByAllRoutes(router: Router, tabs: App.Global.Tab[]) {
|
|||||||
* @param tabs
|
* @param tabs
|
||||||
*/
|
*/
|
||||||
export function getFixedTabs(tabs: App.Global.Tab[]) {
|
export function getFixedTabs(tabs: App.Global.Tab[]) {
|
||||||
return tabs.filter(tab => tab.fixedIndex !== undefined);
|
return tabs.filter(isFixedTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
2
src/typings/app.d.ts
vendored
2
src/typings/app.d.ts
vendored
@ -202,7 +202,7 @@ declare namespace App {
|
|||||||
/** The tab route full path */
|
/** The tab route full path */
|
||||||
fullPath: string;
|
fullPath: string;
|
||||||
/** The tab fixed index */
|
/** The tab fixed index */
|
||||||
fixedIndex?: number;
|
fixedIndex?: number | null;
|
||||||
/**
|
/**
|
||||||
* Tab icon
|
* Tab icon
|
||||||
*
|
*
|
||||||
|
2
src/typings/components.d.ts
vendored
2
src/typings/components.d.ts
vendored
@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
/* prettier-ignore */
|
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
// Generated by unplugin-vue-components
|
// Generated by unplugin-vue-components
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
export {}
|
export {}
|
||||||
|
|
||||||
|
/* prettier-ignore */
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
AppProvider: typeof import('./../components/common/app-provider.vue')['default']
|
AppProvider: typeof import('./../components/common/app-provider.vue')['default']
|
||||||
|
27
src/typings/elegant-router.d.ts
vendored
27
src/typings/elegant-router.d.ts
vendored
@ -21,6 +21,14 @@ declare module "@elegant-router/types" {
|
|||||||
"exception_403": "/exception/403";
|
"exception_403": "/exception/403";
|
||||||
"exception_404": "/exception/404";
|
"exception_404": "/exception/404";
|
||||||
"exception_500": "/exception/500";
|
"exception_500": "/exception/500";
|
||||||
|
"document": "/document";
|
||||||
|
"document_project": "/document/project";
|
||||||
|
"document_project-link": "/document/project-link";
|
||||||
|
"document_vue": "/document/vue";
|
||||||
|
"document_vite": "/document/vite";
|
||||||
|
"document_unocss": "/document/unocss";
|
||||||
|
"document_naive": "/document/naive";
|
||||||
|
"document_antd": "/document/antd";
|
||||||
"403": "/403";
|
"403": "/403";
|
||||||
"404": "/404";
|
"404": "/404";
|
||||||
"500": "/500";
|
"500": "/500";
|
||||||
@ -36,6 +44,7 @@ declare module "@elegant-router/types" {
|
|||||||
"function_tab": "/function/tab";
|
"function_tab": "/function/tab";
|
||||||
"function_toggle-auth": "/function/toggle-auth";
|
"function_toggle-auth": "/function/toggle-auth";
|
||||||
"home": "/home";
|
"home": "/home";
|
||||||
|
"iframe-page": "/iframe-page/:url";
|
||||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
||||||
"manage": "/manage";
|
"manage": "/manage";
|
||||||
"manage_menu": "/manage/menu";
|
"manage_menu": "/manage/menu";
|
||||||
@ -72,6 +81,14 @@ declare module "@elegant-router/types" {
|
|||||||
| "exception_403"
|
| "exception_403"
|
||||||
| "exception_404"
|
| "exception_404"
|
||||||
| "exception_500"
|
| "exception_500"
|
||||||
|
| "document"
|
||||||
|
| "document_project"
|
||||||
|
| "document_project-link"
|
||||||
|
| "document_vue"
|
||||||
|
| "document_vite"
|
||||||
|
| "document_unocss"
|
||||||
|
| "document_naive"
|
||||||
|
| "document_antd"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,6 +107,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "about"
|
| "about"
|
||||||
| "function"
|
| "function"
|
||||||
| "home"
|
| "home"
|
||||||
|
| "iframe-page"
|
||||||
| "login"
|
| "login"
|
||||||
| "manage"
|
| "manage"
|
||||||
| "multi-menu"
|
| "multi-menu"
|
||||||
@ -104,6 +122,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "root"
|
| "root"
|
||||||
| "not-found"
|
| "not-found"
|
||||||
| "exception"
|
| "exception"
|
||||||
|
| "document"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,6 +133,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "403"
|
| "403"
|
||||||
| "404"
|
| "404"
|
||||||
| "500"
|
| "500"
|
||||||
|
| "iframe-page"
|
||||||
| "login"
|
| "login"
|
||||||
| "about"
|
| "about"
|
||||||
| "function_hide-child_one"
|
| "function_hide-child_one"
|
||||||
@ -144,6 +164,13 @@ declare module "@elegant-router/types" {
|
|||||||
| "exception_403"
|
| "exception_403"
|
||||||
| "exception_404"
|
| "exception_404"
|
||||||
| "exception_500"
|
| "exception_500"
|
||||||
|
| "document_project"
|
||||||
|
| "document_project-link"
|
||||||
|
| "document_vue"
|
||||||
|
| "document_vite"
|
||||||
|
| "document_unocss"
|
||||||
|
| "document_naive"
|
||||||
|
| "document_antd"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
2
src/typings/router.d.ts
vendored
2
src/typings/router.d.ts
vendored
@ -58,7 +58,7 @@ declare module 'vue-router' {
|
|||||||
/** By default, the same route path will use one tab, if set to true, it will use multiple tabs */
|
/** By default, the same route path will use one tab, if set to true, it will use multiple tabs */
|
||||||
multiTab?: boolean;
|
multiTab?: boolean;
|
||||||
/** If set, the route will be fixed in tabs, and the value is the order of fixed tabs */
|
/** If set, the route will be fixed in tabs, and the value is the order of fixed tabs */
|
||||||
fixedIndexInTab?: number;
|
fixedIndexInTab?: number | null;
|
||||||
/** if set query parameters, it will be automatically carried when entering the route */
|
/** if set query parameters, it will be automatically carried when entering the route */
|
||||||
query?: Record<string, string>;
|
query?: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
7
src/typings/storage.d.ts
vendored
7
src/typings/storage.d.ts
vendored
@ -14,6 +14,8 @@ declare namespace StorageType {
|
|||||||
lang: App.I18n.LangType;
|
lang: App.I18n.LangType;
|
||||||
/** The token */
|
/** The token */
|
||||||
token: string;
|
token: string;
|
||||||
|
/** Fixed sider with mix-menu */
|
||||||
|
mixSiderFixed: CommonType.YesOrNo;
|
||||||
/** The refresh token */
|
/** The refresh token */
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
/** The user info */
|
/** The user info */
|
||||||
@ -30,5 +32,10 @@ declare namespace StorageType {
|
|||||||
overrideThemeFlag: string;
|
overrideThemeFlag: string;
|
||||||
/** The global tabs */
|
/** The global tabs */
|
||||||
globalTabs: App.Global.Tab[];
|
globalTabs: App.Global.Tab[];
|
||||||
|
/** The backup theme setting before is mobile */
|
||||||
|
backupThemeSettingBeforeIsMobile: {
|
||||||
|
layout: UnionKey.ThemeLayoutMode;
|
||||||
|
siderCollapse: boolean;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
src/views/_builtin/iframe-page/[url].vue
Normal file
25
src/views/_builtin/iframe-page/[url].vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onActivated, onMounted } from 'vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineProps<Props>();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log('mounted');
|
||||||
|
});
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
console.log('activated');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="h-full">
|
||||||
|
<iframe id="iframePage" class="size-full" :src="url"></iframe>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@ -187,20 +187,18 @@ async function getRoleOptions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleUpdateModel() {
|
function handleInitModel() {
|
||||||
if (props.operateType === 'add') {
|
|
||||||
Object.assign(model, createDefaultModel());
|
Object.assign(model, createDefaultModel());
|
||||||
|
|
||||||
return;
|
if (!props.rowData) return;
|
||||||
}
|
|
||||||
|
|
||||||
if (props.operateType === 'addChild' && props.rowData) {
|
if (props.operateType === 'addChild') {
|
||||||
const { id } = props.rowData;
|
const { id } = props.rowData;
|
||||||
|
|
||||||
Object.assign(model, createDefaultModel(), { parentId: id });
|
Object.assign(model, { parentId: id });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.operateType === 'edit' && props.rowData) {
|
if (props.operateType === 'edit') {
|
||||||
const { component, query, ...rest } = props.rowData;
|
const { component, query, ...rest } = props.rowData;
|
||||||
|
|
||||||
const { layout, page } = getLayoutAndPage(component);
|
const { layout, page } = getLayoutAndPage(component);
|
||||||
@ -233,7 +231,7 @@ async function handleSubmit() {
|
|||||||
|
|
||||||
watch(visible, () => {
|
watch(visible, () => {
|
||||||
if (visible.value) {
|
if (visible.value) {
|
||||||
handleUpdateModel();
|
handleInitModel();
|
||||||
restoreValidation();
|
restoreValidation();
|
||||||
getRoleOptions();
|
getRoleOptions();
|
||||||
}
|
}
|
||||||
@ -241,9 +239,9 @@ watch(visible, () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NDrawer v-model:show="visible" display-directive="show" :width="400">
|
<NModal v-model:show="visible" :title="title" preset="card" class="w-720px">
|
||||||
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
<NScrollbar class="h-400px">
|
||||||
<NForm ref="formRef" :model="model" :rules="rules" label-placement="left" :label-width="80">
|
<NForm ref="formRef" :model="model" :rules="rules" label-placement="left" :label-width="100">
|
||||||
<NGrid>
|
<NGrid>
|
||||||
<NFormItemGi span="12" :label="$t('page.manage.menu.menuType')" path="menuType">
|
<NFormItemGi span="12" :label="$t('page.manage.menu.menuType')" path="menuType">
|
||||||
<NRadioGroup v-model:value="model.menuType" :disabled="disabledMenuType">
|
<NRadioGroup v-model:value="model.menuType" :disabled="disabledMenuType">
|
||||||
@ -384,14 +382,14 @@ watch(visible, () => {
|
|||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
</NGrid>
|
</NGrid>
|
||||||
</NForm>
|
</NForm>
|
||||||
|
</NScrollbar>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<NSpace :size="16">
|
<NSpace justify="end" :size="16">
|
||||||
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
||||||
<NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
|
<NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</template>
|
</template>
|
||||||
</NDrawerContent>
|
</NModal>
|
||||||
</NDrawer>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -68,11 +68,8 @@ const roleId = computed(() => props.rowData?.id || -1);
|
|||||||
|
|
||||||
const isEdit = computed(() => props.operateType === 'edit');
|
const isEdit = computed(() => props.operateType === 'edit');
|
||||||
|
|
||||||
function handleUpdateModelWhenEdit() {
|
function handleInitModel() {
|
||||||
if (props.operateType === 'add') {
|
|
||||||
Object.assign(model, createDefaultModel());
|
Object.assign(model, createDefaultModel());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.operateType === 'edit' && props.rowData) {
|
if (props.operateType === 'edit' && props.rowData) {
|
||||||
Object.assign(model, props.rowData);
|
Object.assign(model, props.rowData);
|
||||||
@ -93,14 +90,14 @@ async function handleSubmit() {
|
|||||||
|
|
||||||
watch(visible, () => {
|
watch(visible, () => {
|
||||||
if (visible.value) {
|
if (visible.value) {
|
||||||
handleUpdateModelWhenEdit();
|
handleInitModel();
|
||||||
restoreValidation();
|
restoreValidation();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="360">
|
<NDrawer v-model:show="visible" display-directive="show" :width="360">
|
||||||
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
||||||
<NForm ref="formRef" :model="model" :rules="rules">
|
<NForm ref="formRef" :model="model" :rules="rules">
|
||||||
<NFormItem :label="$t('page.manage.role.roleName')" path="roleName">
|
<NFormItem :label="$t('page.manage.role.roleName')" path="roleName">
|
||||||
|
@ -89,11 +89,8 @@ async function getRoleOptions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleUpdateModelWhenEdit() {
|
function handleInitModel() {
|
||||||
if (props.operateType === 'add') {
|
|
||||||
Object.assign(model, createDefaultModel());
|
Object.assign(model, createDefaultModel());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.operateType === 'edit' && props.rowData) {
|
if (props.operateType === 'edit' && props.rowData) {
|
||||||
Object.assign(model, props.rowData);
|
Object.assign(model, props.rowData);
|
||||||
@ -114,7 +111,7 @@ async function handleSubmit() {
|
|||||||
|
|
||||||
watch(visible, () => {
|
watch(visible, () => {
|
||||||
if (visible.value) {
|
if (visible.value) {
|
||||||
handleUpdateModelWhenEdit();
|
handleInitModel();
|
||||||
restoreValidation();
|
restoreValidation();
|
||||||
getRoleOptions();
|
getRoleOptions();
|
||||||
}
|
}
|
||||||
@ -122,7 +119,7 @@ watch(visible, () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="360">
|
<NDrawer v-model:show="visible" display-directive="show" :width="360">
|
||||||
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
||||||
<NForm ref="formRef" :model="model" :rules="rules">
|
<NForm ref="formRef" :model="model" :rules="rules">
|
||||||
<NFormItem :label="$t('page.manage.user.userName')" path="userName">
|
<NFormItem :label="$t('page.manage.user.userName')" path="userName">
|
||||||
|
Loading…
Reference in New Issue
Block a user