Merge branch 'main' into example

This commit is contained in:
soybeanfe
2026-03-09 12:58:17 +08:00
45 changed files with 3178 additions and 2286 deletions

View File

@@ -1,7 +1,7 @@
name: 🐞 Bug提交
description: 在使用软件或功能的过程中遇到了错误
title: '[Bug]: '
labels: [ "bug?" ]
labels: ['bug?']
body:
- type: markdown

View File

@@ -1,7 +1,7 @@
name: 🐞 Bug Report
description: Encountered an error while using the software or feature
title: '[Bug]: '
labels: [ "bug?" ]
labels: ['bug?']
body:
- type: markdown

View File

@@ -1,9 +1,9 @@
---
name: 🚀 功能请求
description: 提出一个想法以帮助我们改进W&B
title: "[功能]: "
title: '[功能]: '
labels:
- "功能请求"
- '功能请求'
body:
- type: markdown

View File

@@ -1,9 +1,9 @@
---
name: 🚀 Feature Request
description: Suggest an idea to help us improve W&B
title: "[Feature]: "
title: '[Feature]: '
labels:
- "feature_request"
- 'feature_request'
body:
- type: markdown

34
.github/workflows/opencode.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: opencode
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
opencode:
if: |
contains(github.event.comment.body, ' /oc') ||
startsWith(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, ' /opencode') ||
startsWith(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: read
issues: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Run opencode
uses: anomalyco/opencode/github@latest
env:
GOOGLE_GENERATIVE_AI_API_KEY: ${{ secrets.GOOGLE_GENERATIVE_AI_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
with:
model: google/gemini-3-pro-preview

View File

@@ -6,7 +6,7 @@ permissions:
on:
push:
tags:
- "v*"
- 'v*'
jobs:
release:

11
.oxfmtrc.json Normal file
View File

@@ -0,0 +1,11 @@
{
"ignorePatterns": ["src/typings/components.d.ts", "src/typings/elegant-router.d.ts", "src/router/elegant"],
"printWidth": 120,
"singleQuote": true,
"trailingComma": "none",
"arrowParens": "avoid",
"htmlWhitespaceSensitivity": "ignore",
"experimentalSortPackageJson": {
"sortScripts": true
}
}

14
.oxlintrc.json Normal file
View File

@@ -0,0 +1,14 @@
{
"categories": {
"correctness": "error",
"suspicious": "error"
},
"plugins": ["eslint", "typescript", "unicorn", "oxc", "import", "vue"],
"rules": {
"import/no-unassigned-import": "off",
"unicorn/consistent-function-scoping": "off",
"unicorn/no-array-sort": "off",
"unicorn/no-array-reverse": "off",
"unicorn/require-module-specifiers": "off"
}
}

19
.vscode/settings.json vendored
View File

@@ -1,21 +1,11 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never"
"source.fixAll.oxc": "explicit"
},
"editor.formatOnSave": false,
"eslint.validate": [
"html",
"css",
"scss",
"json",
"jsonc",
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue"
],
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"eslint.validate": ["vue"],
"i18n-ally.displayLanguage": "zh-cn",
"i18n-ally.enabledParsers": ["ts"],
"i18n-ally.enabledFrameworks": ["vue"],
@@ -26,6 +16,5 @@
"moduleResolution": "node"
},
"prettier.enable": false,
"typescript.tsdk": "node_modules/typescript/lib",
"unocss.root": ["./"]
}

View File

@@ -1,5 +1,60 @@
# Changelog
## [v2.1.0](https://github.com/soybeanjs/soybean-admin/compare/v2.0.2...v2.1.0) (2026-03-09)
###    🚨 Breaking Changes
- **projects**: integrate oxlint and oxfmt &nbsp;-&nbsp; by **soybeanfe** [<samp>(6ff74)</samp>](https://github.com/soybeanjs/soybean-admin/commit/6ff74c0c)
### &nbsp;&nbsp;&nbsp;🚀 Features
- **components**:
- Column settings support fixed columns. &nbsp;-&nbsp; by @m-xlsea [<samp>(70658)</samp>](https://github.com/soybeanjs/soybean-admin/commit/70658643)
- Add “Select All” to TableColumnSetting &nbsp;-&nbsp; by @wenyuanw [<samp>(0081b)</samp>](https://github.com/soybeanjs/soybean-admin/commit/0081b9c0)
- **logo**:
- use new logo &nbsp;-&nbsp; by @soybeanjs [<samp>(5aac5)</samp>](https://github.com/soybeanjs/soybean-admin/commit/5aac540a)
- **projects**:
- add the plugin: vite-plugin-vue-transition-root-validator, to optimize the development experience. &nbsp;-&nbsp; by **Azir-11** [<samp>(30e3c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/30e3cdc7)
- **types**:
- Added type definition `force` to router push options. &nbsp;-&nbsp; by @m-xlsea [<samp>(a3794)</samp>](https://github.com/soybeanjs/soybean-admin/commit/a37949f2)
- **workflows**:
- add opencode workflow for issue and PR comment triggers &nbsp;-&nbsp; by @soybeanjs [<samp>(dacee)</samp>](https://github.com/soybeanjs/soybean-admin/commit/dacee143)
### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes
- **projects**:
- fix the long list TableColumnSetting component exceeds the viewport. &nbsp;-&nbsp; by **skyfeiz** [<samp>(cbfb9)</samp>](https://github.com/soybeanjs/soybean-admin/commit/cbfb932f)
- fix NButton props conflicts. &nbsp;-&nbsp; by **skyfeiz** [<samp>(54107)</samp>](https://github.com/soybeanjs/soybean-admin/commit/54107aca)
- ensure HTML lang attribute is updated when setting locale &nbsp;-&nbsp; by @pan0xc [<samp>(f96c3)</samp>](https://github.com/soybeanjs/soybean-admin/commit/f96c3c9e)
- correct HTML lang attribute to standard format &nbsp;-&nbsp; by @pan0xc [<samp>(b520d)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b520db3e)
- **router**:
- simplify route guard logic and remove unnecessary next calls &nbsp;-&nbsp; by **soybeanfe** [<samp>(3c2cb)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3c2cbb74)
### &nbsp;&nbsp;&nbsp;🛠 Optimizations
- **projects**:
- modify the injection location of the token. &nbsp;-&nbsp; by **Azir-11** [<samp>(9d48c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9d48ca5f)
- optimize unocss config &nbsp;-&nbsp; by **soybeanfe** [<samp>(6fc6f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/6fc6f1c9)
### &nbsp;&nbsp;&nbsp;📖 Documentation
- **projects**: V2 has been released. &nbsp;-&nbsp; by **skyfeiz** [<samp>(d7394)</samp>](https://github.com/soybeanjs/soybean-admin/commit/d73947a5)
### &nbsp;&nbsp;&nbsp;🏡 Chore
- **deps**:
- update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(232e1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/232e1ac4)
- update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(2a023)</samp>](https://github.com/soybeanjs/soybean-admin/commit/2a0231da)
- update deps &nbsp;-&nbsp; by **soybeanfe** [<samp>(b867c)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b867c290)
### &nbsp;&nbsp;&nbsp;🎨 Styles
- **projects**: fix lint code and format code &nbsp;-&nbsp; by **soybeanfe** [<samp>(781a1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/781a18f4)
### &nbsp;&nbsp;&nbsp;❤️ Contributors
[![pan0xc](https://github.com/pan0xc.png?size=48)](https://github.com/pan0xc)&nbsp;&nbsp;[![m-xlsea](https://github.com/m-xlsea.png?size=48)](https://github.com/m-xlsea)&nbsp;&nbsp;[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)&nbsp;&nbsp;[![wenyuanw](https://github.com/wenyuanw.png?size=48)](https://github.com/wenyuanw)&nbsp;&nbsp;
[soybeanfe](mailto:honghuangdc@gmail.com),&nbsp;[Azir-11](mailto:2075125282@qq.com),&nbsp;[skyfeiz](mailto:webzhangfei@163.com),&nbsp;
## [v2.0.2](https://github.com/soybeanjs/soybean-admin/compare/v2.0.1...v2.0.2) (2025-12-23)
@@ -25,7 +80,7 @@
- update QQ group image in README &nbsp;-&nbsp; by @soybeanjs [<samp>(46081)</samp>](https://github.com/soybeanjs/soybean-admin/commit/46081c36)
- **projects**:
- support theme presets to only set partial content. &nbsp;-&nbsp; by **Azir-11** [<samp>(9da84)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9da847fb)
- support theme perset to override component library presets. &nbsp;-&nbsp; by **Azir-11** [<samp>(60517)</samp>](https://github.com/soybeanjs/soybean-admin/commit/605173a1)
- support theme perset to override component library presets. &nbsp;-&nbsp; by **Azir-11** [<samp>(60517)</samp>](https://github.com/soybeanjs/soybean-admin/commit/605173a1)
- support pinning and unpinning of tabs &nbsp;-&nbsp; by **hooke** [<samp>(b8a76)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b8a767d7)
- hybrid layout mode auto select first deepest child menu &nbsp;-&nbsp; by @paynezhuang [<samp>(94019)</samp>](https://github.com/soybeanjs/soybean-admin/commit/9401925f)
@@ -425,13 +480,13 @@
### &nbsp;&nbsp;&nbsp;🏡 Chore
- **deps**:
- add vscode recommend plugin close #738 &nbsp;-&nbsp; by @tu6ge in https://github.com/soybeanjs/soybean-admin/issues/739 and https://github.com/soybeanjs/soybean-admin/issues/738 [<samp>(61244)</samp>](https://github.com/soybeanjs/soybean-admin/commit/61244f0f)
- add vscode recommend plugin close #738 &nbsp;-&nbsp; by @tu6ge in https://github.com/soybeanjs/soybean-admin/issues/739 and https://github.com/soybeanjs/soybean-admin/issues/738 [<samp>(61244)</samp>](https://github.com/soybeanjs/soybean-admin/commit/61244f0f)
- update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(41b5f)</samp>](https://github.com/soybeanjs/soybean-admin/commit/41b5f493)
- update deps &nbsp;-&nbsp; by @soybeanjs [<samp>(3e4e1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/3e4e17ab)
### &nbsp;&nbsp;&nbsp;🤖 CI
- **hooks**: remove lint-staged in git hook. close #724 &nbsp;-&nbsp; by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/743 and https://github.com/soybeanjs/soybean-admin/issues/724 [<samp>(c3abc)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c3abc3df)
- **hooks**: remove lint-staged in git hook. close #724 &nbsp;-&nbsp; by @Azir-11 in https://github.com/soybeanjs/soybean-admin/issues/743 and https://github.com/soybeanjs/soybean-admin/issues/724 [<samp>(c3abc)</samp>](https://github.com/soybeanjs/soybean-admin/commit/c3abc3df)
### &nbsp;&nbsp;&nbsp;❤️ Contributors
@@ -551,7 +606,7 @@
### &nbsp;&nbsp;&nbsp;📖 Documentation
- **projects**: ✏️ add element-plus version link &nbsp;-&nbsp; by **一寸灰** in https://github.com/honghuangdc/soybean-admin/issues/679 [<samp>(5c6ab)</samp>](https://github.com/honghuangdc/soybean-admin/commit/5c6ab0b)
- **projects**: ✏️ add element-plus version link &nbsp;-&nbsp; by **一寸灰** in https://github.com/honghuangdc/soybean-admin/issues/679 [<samp>(5c6ab)</samp>](https://github.com/honghuangdc/soybean-admin/commit/5c6ab0b)
### &nbsp;&nbsp;&nbsp;🏡 Chore
@@ -593,7 +648,6 @@
### &nbsp;&nbsp;&nbsp;❤️ Contributors
[Soybean](mailto:soybeanjs@outlook.com),&nbsp;[青菜白玉汤](mailto:79054161+Azir-11@users.noreply.github.com)
## [v1.3.8](https://github.com/soybeanjs/soybean-admin/compare/v1.3.7...v1.3.8) (2024-10-25)
@@ -1640,7 +1694,7 @@
- Optimize internationalized menu search code &nbsp;-&nbsp; by **燕博文** [<samp>(8c1ef)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8c1ef4b)
- Optimize menu search code &nbsp;-&nbsp; by **燕博文** [<samp>(296a2)</samp>](https://github.com/soybeanjs/soybean-admin/commit/296a2d2)
- perf count-to &nbsp;-&nbsp; by @honghuangdc [<samp>(b2c61)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b2c61f0)
- components name is converted to uppercase &nbsp;-&nbsp; by **燕博文** [<samp>(04aa1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/04aa10b)
- components name is converted to uppercase &nbsp;-&nbsp; by **燕博文** [<samp>(04aa1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/04aa10b)
- perf global-search &nbsp;-&nbsp; by @honghuangdc [<samp>(72745)</samp>](https://github.com/soybeanjs/soybean-admin/commit/7274522)
- **projects**:
- perf code &nbsp;-&nbsp; by @honghuangdc [<samp>(8081e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8081e19)
@@ -1917,7 +1971,7 @@
- Optimize internationalized menu search code &nbsp;-&nbsp; by **燕博文** [<samp>(8c1ef)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8c1ef4b)
- Optimize menu search code &nbsp;-&nbsp; by **燕博文** [<samp>(296a2)</samp>](https://github.com/soybeanjs/soybean-admin/commit/296a2d2)
- perf count-to &nbsp;-&nbsp; by @honghuangdc [<samp>(b2c61)</samp>](https://github.com/soybeanjs/soybean-admin/commit/b2c61f0)
- components name is converted to uppercase &nbsp;-&nbsp; by **燕博文** [<samp>(04aa1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/04aa10b)
- components name is converted to uppercase &nbsp;-&nbsp; by **燕博文** [<samp>(04aa1)</samp>](https://github.com/soybeanjs/soybean-admin/commit/04aa10b)
- perf global-search &nbsp;-&nbsp; by @honghuangdc [<samp>(72745)</samp>](https://github.com/soybeanjs/soybean-admin/commit/7274522)
- **projects**:
- perf code &nbsp;-&nbsp; by @honghuangdc [<samp>(8081e)</samp>](https://github.com/soybeanjs/soybean-admin/commit/8081e19)
@@ -3312,6 +3366,3 @@
### &nbsp;&nbsp;&nbsp;❤️ Contributors
[![honghuangdc](https://github.com/honghuangdc.png?size=48)](https://github.com/honghuangdc)&nbsp;&nbsp;[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)&nbsp;&nbsp;

View File

@@ -143,7 +143,6 @@
[![honghuangdc](https://github.com/honghuangdc.png?size=48)](https://github.com/honghuangdc)&nbsp;&nbsp;[![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)&nbsp;&nbsp;
[Azir](mailto:2075125282@qq.com),&nbsp;
## [v1.3.0](https://github.com/soybeanjs/soybean-admin/compare/v1.2.8...v1.3.0) (2024-07-22)
### &nbsp;&nbsp;&nbsp;🚨 破坏性变更
@@ -182,7 +181,6 @@
[![honghuangdc](https://github.com/honghuangdc.png?size=48)](https://github.com/honghuangdc)&nbsp;&nbsp;[![mmdapl](https://github.com/mmdapl.png?size=48)](https://github.com/mmdapl)&nbsp;&nbsp;[![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)&nbsp;&nbsp;
## [v1.2.8](https://github.com/soybeanjs/soybean-admin/compare/v1.2.7...v1.2.8) (2024-07-20)
### &nbsp;&nbsp;&nbsp;🐞 修复
@@ -210,7 +208,6 @@
[![honghuangdc](https://github.com/honghuangdc.png?size=48)](https://github.com/honghuangdc)&nbsp;&nbsp;
[dodu2014](mailto:dodu@live.cn)
## [v1.2.7](https://github.com/honghuangdc/soybean-admin/compare/v1.2.6...v1.2.7) (2024-07-12)
### &nbsp;&nbsp;&nbsp;🛠 优化
@@ -294,7 +291,6 @@
[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)&nbsp;&nbsp;[![Azir-11](https://github.com/Azir-11.png?size=48)](https://github.com/Azir-11)&nbsp;&nbsp;
[CHENZL](mailto:zlong5568863@qq.com)
## [v1.2.4](https://github.com/soybeanjs/soybean-admin/compare/v1.2.3...v1.2.4) (2024-06-14)
### &nbsp;&nbsp;&nbsp;🛠 优化
@@ -372,7 +368,6 @@
[![soybeanjs](https://github.com/soybeanjs.png?size=48)](https://github.com/soybeanjs)&nbsp;&nbsp;
## [v1.2.0](https://github.com/soybeanjs/soybean-admin/compare/v1.1.5...v1.2.0) (2024-06-06)
### &nbsp;&nbsp;&nbsp;🚀 功能
@@ -593,7 +588,6 @@
[![honghuangdc](https://github.com/honghuangdc.png?size=48)](https://github.com/honghuangdc)&nbsp;&nbsp;
[paynezhuang](mailto:paynezhuang@gmail.com)
## [v1.1.0-beta.1](https://github.com/soybeanjs/soybean-admin/compare/v1.0.9...v1.1.0-beta.1) (2024-05-07)
### &nbsp;&nbsp;&nbsp;🚀 功能

View File

@@ -23,14 +23,10 @@
> [!NOTE]
> The `SoybeanAdmin` quick start series videos have been uploaded to [Bilibili](https://www.bilibili.com/video/BV1YKdRYXELC) Go online [click here](https://www.bilibili.com/video/BV1YKdRYXELC) Go check it out
> [!WARNING]
> `SoybeanAdmin` is planning to develop a `V2` version, see [plan list](https://github.com/soybeanjs/soybean-admin/issues/767)
## Introduction
[`SoybeanAdmin`](https://github.com/soybeanjs/soybean-admin) is a clean, elegant, beautiful and powerful admin template, based on the latest front-end technology stack, including Vue3, Vite7, TypeScript, Pinia and UnoCSS. It has built-in rich theme configuration and components, strict code specifications, and an automated file routing system. In addition, it also uses the online mock data solution based on ApiFox. `SoybeanAdmin` provides you with a one-stop admin solution, no additional configuration, and out of the box. It is also a best practice for learning cutting-edge technologies quickly.
## Features
- **Cutting-edge technology application**: using the latest popular technology stack such as Vue3, Vite7, TypeScript, Pinia and UnoCSS.
@@ -45,7 +41,6 @@
- **Command line tool**: built-in efficient command line tool, git commit, delete file, release, etc.
- **Mobile adaptation**: perfectly support mobile terminal to realize adaptive layout.
## Version
- **NaiveUI Version:**
@@ -72,7 +67,6 @@
- [Gitee Repository](https://gitee.com/honghuangdc/soybean-admin/tree/legacy)
- [Gitcode Repository](https://gitcode.com/soybeanjs/soybean-admin/tree/legacy)
## Documentation
- [Link](https://docs.soybeanjs.cn)
@@ -92,7 +86,6 @@
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-10.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-mobile.png)
## Usage
**Environment Preparation**
@@ -119,6 +112,7 @@ git clone https://gitcode.com/soybeanjs/soybean-admin.git
```bash
pnpm i
```
> Since this project uses the pnpm monorepo management method, please do not use npm or yarn to install dependencies.
**Start Project**
@@ -153,7 +147,6 @@ Refer to the [Code Synchronization](https://docs.soybeanjs.cn/guide/sync) docume
More ecosystem please refer to [Ecosystem](https://docs.soybeanjs.cn/awesome) document.
## 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).
@@ -167,8 +160,8 @@ This project has built-in `commit` command, you can execute `pnpm commit` to gen
It is recommended to use the latest version of Chrome in development for a better experience.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="IE" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) |
| --- | --- | --- | --- | --- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## OpenSource Author

View File

@@ -23,9 +23,6 @@
> [!NOTE]
> `SoybeanAdmin` 快速上手系列视频已在 [Bilibili](https://www.bilibili.com/video/BV1YKdRYXELC) 上线 [点击这里](https://www.bilibili.com/video/BV1YKdRYXELC) 前往查看
> [!WARNING]
> `SoybeanAdmin` 正在计划开发 `V2` 版本,详情见[计划清单](https://github.com/soybeanjs/soybean-admin/issues/767)
## 简介
[`SoybeanAdmin`](https://github.com/soybeanjs/soybean-admin) 是一个清新优雅、高颜值且功能强大的后台管理模板,基于最新的前端技术栈,包括 Vue3, Vite7, TypeScript, Pinia 和 UnoCSS。它内置了丰富的主题配置和组件代码规范严谨实现了自动化的文件路由系统。此外它还采用了基于 ApiFox 的在线Mock数据方案。`SoybeanAdmin` 为您提供了一站式的后台管理解决方案,无需额外配置,开箱即用。同样是一个快速学习前沿技术的最佳实践。
@@ -44,7 +41,6 @@
- **命令行工具**内置高效的命令行工具git提交、删除文件、发布等。
- **移动端适配**:完美支持移动端,实现自适应布局。
## 版本
- **NaiveUI 版本:**
@@ -68,13 +64,11 @@
- [Gitee 仓库](https://gitee.com/honghuangdc/soybean-admin/tree/legacy)
- [Gitcode 仓库](https://gitcode.com/soybeanjs/soybean-admin/tree/legacy)
## 文档
- [地址](https://docs.soybeanjs.cn)
- [旧版文档](https://legacy-docs.soybeanjs.cn)
## 合作事项
我们非常感谢大家对 [`SoybeanAdmin`](https://github.com/soybeanjs/soybean-admin) 的支持!为了进一步回馈社区,并助力企业和开发者实现个性化需求,我们现提供多种合作服务,期待与您携手共赢。
@@ -99,11 +93,10 @@
- **Email**: [soybeanjs@outlook.com](mailto:soybeanjs@outlook.com)
- **GitHub Issues**: 欢迎通过 [GitHub Issues](https://github.com/soybeanjs/soybean-admin/issues/new) 联系我们,进行初步的合作洽谈。
- **商务合作微信**: honghuangdc
- **商务合作微信**: honghuangdc
期待与您开展深入合作,共同推动 SoybeanAdmin 项目及其在更多领域的成功应用!
## 示例图片
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-01.png)
@@ -118,7 +111,6 @@
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-10.png)
![](https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean-admin-v1-mobile.png)
## 使用
**环境准备**
@@ -145,6 +137,7 @@ git clone https://gitcode.com/soybeanjs/soybean-admin.git
```bash
pnpm i
```
> 由于本项目采用了 pnpm monorepo 的管理方式,因此请不要使用 npm 或 yarn 来安装依赖。
**启动项目**
@@ -179,29 +172,26 @@ pnpm build
更多周边生态请翻阅 [周边生态](https://docs.soybeanjs.cn/zh/awesome) 文档。
## 如何贡献
我们热烈欢迎并感谢所有形式的贡献。如果您有任何想法或建议,欢迎通过提交 [pull requests](https://github.com/soybeanjs/soybean-admin/pulls) 或创建 GitHub [issue](https://github.com/soybeanjs/soybean-admin/issues/new) 来分享。
## Git 提交规范
本项目已内置 `commit` 命令,您可以通过执行 `pnpm commit` 来生成符合 [Conventional Commits]([conventionalcommits](https://www.conventionalcommits.org/)) 规范的提交信息。在提交PR时请务必使用 `commit` 命令来创建提交信息,以确保信息的规范性。
本项目已内置 `commit` 命令,您可以通过执行 `pnpm commit` 来生成符合 [Conventional Commits](<[conventionalcommits](https://www.conventionalcommits.org/)>) 规范的提交信息。在提交PR时请务必使用 `commit` 命令来创建提交信息,以确保信息的规范性。
## 浏览器支持
推荐使用最新版的 Chrome 浏览器进行开发,以获得更好的体验。
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="IE" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) |
| --- | --- | --- | --- | --- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 开源作者
[Soybean](https://github.com/honghuangdc)
## 贡献者
感谢以下贡献者的贡献。如果您想为本项目做出贡献,请参考 [如何贡献](#如何贡献)。

View File

@@ -2,6 +2,7 @@ import type { PluginOption } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import progress from 'vite-plugin-progress';
import vueRootValidator from 'vite-plugin-vue-transition-root-validator';
import { setupElegantRouter } from './router';
import { setupUnocss } from './unocss';
import { setupUnplugin } from './unplugin';
@@ -17,7 +18,8 @@ export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
setupUnocss(viteEnv),
...setupUnplugin(viteEnv),
progress(),
setupHtmlPlugin(buildTime)
setupHtmlPlugin(buildTime),
vueRootValidator()
];
return plugins;

View File

@@ -1,7 +1,7 @@
import process from 'node:process';
import path from 'node:path';
import unocss from '@unocss/vite';
import presetIcons from '@unocss/preset-icons';
import { presetIcons } from 'unocss';
import unocss from 'unocss/vite';
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders';
export function setupUnocss(viteEnv: Env.ImportMeta) {

View File

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

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="zh-cmn-Hans">
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.svg" />

View File

@@ -1,35 +1,31 @@
{
"name": "soybean-admin",
"type": "module",
"version": "2.0.2",
"version": "2.1.0",
"description": "A fresh and elegant admin template, based on Vue3、Vite7、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite7、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
"keywords": [
"TypeScript",
"UnoCSS",
"Vite7",
"Vue3 admin ",
"ant-design-vue v4",
"naive-ui",
"naive-ui-admin",
"vue-admin-template"
],
"homepage": "https://github.com/soybeanjs/soybean-admin",
"bugs": {
"url": "https://github.com/soybeanjs/soybean-admin/issues"
},
"license": "MIT",
"author": {
"name": "Soybean",
"email": "soybeanjs@outlook.com",
"url": "https://github.com/soybeanjs"
},
"license": "MIT",
"homepage": "https://github.com/soybeanjs/soybean-admin",
"repository": {
"url": "https://github.com/soybeanjs/soybean-admin.git"
},
"bugs": {
"url": "https://github.com/soybeanjs/soybean-admin/issues"
},
"keywords": [
"Vue3 admin ",
"vue-admin-template",
"Vite7",
"TypeScript",
"naive-ui",
"naive-ui-admin",
"ant-design-vue v4",
"UnoCSS"
],
"engines": {
"node": ">=20.19.0",
"pnpm": ">=10.5.0"
},
"type": "module",
"scripts": {
"build": "vite build --mode prod",
"build:test": "vite build --mode test",
@@ -38,8 +34,9 @@
"commit:zh": "sa git-commit -l=zh-cn",
"dev": "vite --mode test",
"dev:prod": "vite --mode prod",
"fmt": "oxfmt",
"gen-route": "sa gen-route",
"lint": "eslint . --fix",
"lint": "oxlint --fix && eslint --fix .",
"prepare": "simple-git-hooks",
"preview": "vite preview",
"release": "sa release",
@@ -48,8 +45,8 @@
},
"dependencies": {
"@antv/data-set": "0.11.8",
"@antv/g2": "5.4.7",
"@antv/g6": "5.0.50",
"@antv/g2": "5.4.8",
"@antv/g6": "5.0.51",
"@better-scroll/core": "2.5.1",
"@iconify/vue": "5.0.0",
"@sa/alova": "workspace:*",
@@ -58,36 +55,36 @@
"@sa/hooks": "workspace:*",
"@sa/materials": "workspace:*",
"@sa/utils": "workspace:*",
"@visactor/vchart": "2.0.11",
"@visactor/vchart-theme": "1.12.2",
"@visactor/vtable-editors": "1.22.8",
"@visactor/vtable-gantt": "1.22.8",
"@visactor/vue-vtable": "1.22.8",
"@vueuse/components": "14.1.0",
"@vueuse/core": "14.1.0",
"@visactor/vchart": "2.0.19",
"@visactor/vchart-theme": "1.12.3",
"@visactor/vtable-editors": "1.23.3",
"@visactor/vtable-gantt": "1.23.3",
"@visactor/vue-vtable": "1.23.3",
"@vueuse/components": "14.2.1",
"@vueuse/core": "14.2.1",
"clipboard": "2.0.11",
"dayjs": "1.11.19",
"defu": "6.1.4",
"dhtmlx-gantt": "9.1.1",
"dompurify": "3.3.1",
"dhtmlx-gantt": "9.1.2",
"dompurify": "3.3.2",
"echarts": "6.0.0",
"jsbarcode": "3.12.1",
"jsbarcode": "3.12.3",
"json5": "2.2.3",
"naive-ui": "2.43.2",
"naive-ui": "2.44.1",
"nprogress": "0.2.0",
"pinia": "3.0.4",
"pinyin-pro": "3.27.0",
"pinyin-pro": "3.28.0",
"print-js": "1.6.0",
"pro-naive-ui": "3.2.0",
"swiper": "12.0.3",
"tailwind-merge": "3.4.0",
"pro-naive-ui": "3.2.2",
"swiper": "12.1.2",
"tailwind-merge": "3.5.0",
"typeit": "8.8.7",
"vditor": "3.11.2",
"vue": "3.5.26",
"vue-draggable-plus": "0.6.0",
"vue-i18n": "11.2.7",
"vue-pdf-embed": "2.1.3",
"vue-router": "4.6.4",
"vue": "3.5.29",
"vue-draggable-plus": "0.6.1",
"vue-i18n": "11.3.0",
"vue-pdf-embed": "2.1.4",
"vue-router": "5.0.3",
"wangeditor": "4.7.15",
"xgplayer": "3.0.23",
"xlsx": "0.18.5"
@@ -95,43 +92,43 @@
"devDependencies": {
"@amap/amap-jsapi-types": "0.0.15",
"@elegant-router/vue": "0.3.8",
"@iconify/json": "2.2.417",
"@iconify/json": "2.2.447",
"@sa/scripts": "workspace:*",
"@sa/uno-preset": "workspace:*",
"@soybeanjs/eslint-config": "1.7.4",
"@soybeanjs/eslint-config-vue": "^0.0.2",
"@types/bmapgl": "0.0.7",
"@types/node": "25.0.3",
"@types/node": "25.3.5",
"@types/nprogress": "0.2.3",
"@unocss/eslint-config": "66.5.10",
"@unocss/preset-icons": "66.5.10",
"@unocss/preset-uno": "66.5.10",
"@unocss/transformer-directives": "66.5.10",
"@unocss/transformer-variant-group": "66.5.10",
"@unocss/vite": "66.5.10",
"@vitejs/plugin-vue": "6.0.3",
"@vitejs/plugin-vue-jsx": "5.1.2",
"@vitejs/plugin-vue": "6.0.4",
"@vitejs/plugin-vue-jsx": "5.1.4",
"consola": "3.4.2",
"eslint": "9.39.2",
"eslint-plugin-vue": "10.6.2",
"eslint": "10.0.3",
"kolorist": "1.8.0",
"lint-staged": "16.2.7",
"oxfmt": "^0.36.0",
"oxlint": "^1.51.0",
"pro-naive-ui-resolver": "1.0.2",
"sass": "1.97.1",
"sass": "1.97.3",
"simple-git-hooks": "2.13.1",
"tsx": "4.21.0",
"typescript": "5.9.3",
"unplugin-icons": "22.5.0",
"unplugin-vue-components": "30.0.0",
"vite": "7.3.0",
"unocss": "^66.6.6",
"unplugin-icons": "23.0.1",
"unplugin-vue-components": "31.0.0",
"vite": "7.3.1",
"vite-plugin-progress": "0.0.7",
"vite-plugin-svg-icons": "2.0.1",
"vite-plugin-vue-devtools": "8.0.5",
"vue-eslint-parser": "10.2.0",
"vue-tsc": "3.2.1"
"vite-plugin-vue-devtools": "8.0.7",
"vite-plugin-vue-transition-root-validator": "^0.1.0",
"vue-eslint-parser": "10.4.0",
"vue-tsc": "3.2.5"
},
"simple-git-hooks": {
"commit-msg": "pnpm sa git-commit-verify",
"pre-commit": "pnpm typecheck && pnpm lint && git diff --exit-code"
"pre-commit": "pnpm typecheck && pnpm lint && pnpm fmt && git diff --exit-code"
},
"engines": {
"node": ">=20.19.0",
"pnpm": ">=10.5.0"
},
"website": "https://admin.soybeanjs.cn"
}

View File

@@ -1,20 +1,22 @@
{
"name": "@sa/alova",
"version": "2.0.2",
"version": "2.1.0",
"typesVersions": {
"*": {
"*": [
"./src/*"
]
}
},
"exports": {
".": "./src/index.ts",
"./fetch": "./src/fetch.ts",
"./client": "./src/client.ts",
"./mock": "./src/mock.ts"
},
"typesVersions": {
"*": {
"*": ["./src/*"]
}
},
"dependencies": {
"@alova/mock": "2.0.18",
"@alova/mock": "2.0.19",
"@sa/utils": "workspace:*",
"alova": "3.4.1"
"alova": "3.5.1"
}
}

View File

@@ -1,21 +1,23 @@
{
"name": "@sa/axios",
"version": "2.0.2",
"version": "2.1.0",
"typesVersions": {
"*": {
"*": [
"./src/*"
]
}
},
"exports": {
".": "./src/index.ts"
},
"typesVersions": {
"*": {
"*": ["./src/*"]
}
},
"dependencies": {
"@sa/utils": "workspace:*",
"axios": "1.13.2",
"axios": "1.13.6",
"axios-retry": "4.5.0",
"qs": "6.14.0"
"qs": "6.15.0"
},
"devDependencies": {
"@types/qs": "6.14.0"
"@types/qs": "6.15.0"
}
}

View File

@@ -1,14 +1,16 @@
{
"name": "@sa/color",
"version": "2.0.2",
"exports": {
".": "./src/index.ts"
},
"version": "2.1.0",
"typesVersions": {
"*": {
"*": ["./src/*"]
"*": [
"./src/*"
]
}
},
"exports": {
".": "./src/index.ts"
},
"dependencies": {
"@sa/utils": "workspace:*",
"colord": "2.9.3"

View File

@@ -1,14 +1,16 @@
{
"name": "@sa/hooks",
"version": "2.0.2",
"exports": {
".": "./src/index.ts"
},
"version": "2.1.0",
"typesVersions": {
"*": {
"*": ["./src/*"]
"*": [
"./src/*"
]
}
},
"exports": {
".": "./src/index.ts"
},
"dependencies": {
"@sa/axios": "workspace:*",
"@sa/utils": "workspace:*"

View File

@@ -23,6 +23,7 @@ export type TableColumnCheck = {
title: TableColumnCheckTitle;
checked: boolean;
visible: boolean;
fixed: 'left' | 'right' | 'unFixed';
};
export interface UseTableOptions<ResponseData, ApiData, Column, Pagination extends boolean> {
@@ -78,12 +79,14 @@ export default function useTable<ResponseData, ApiData, Column, Pagination exten
function reloadColumns() {
const checkMap = new Map(columnChecks.value.map(col => [col.key, col.checked]));
const fixedMap = new Map(columnChecks.value.map(col => [col.key, col.fixed]));
const defaultChecks = getColumnChecks(columns());
columnChecks.value = defaultChecks.map(col => ({
...col,
checked: checkMap.get(col.key) ?? col.checked
checked: checkMap.get(col.key) ?? col.checked,
fixed: (fixedMap.get(col.key) !== 'unFixed' ? fixedMap.get(col.key) : undefined) ?? col.fixed
}));
}

View File

@@ -1,14 +1,16 @@
{
"name": "@sa/materials",
"version": "2.0.2",
"exports": {
".": "./src/index.ts"
},
"version": "2.1.0",
"typesVersions": {
"*": {
"*": ["./src/*"]
"*": [
"./src/*"
]
}
},
"exports": {
".": "./src/index.ts"
},
"dependencies": {
"@sa/utils": "workspace:*",
"simplebar-vue": "2.4.2"

View File

@@ -1,28 +1,30 @@
{
"name": "@sa/scripts",
"version": "2.0.2",
"version": "2.1.0",
"bin": {
"sa": "./bin.ts"
},
"typesVersions": {
"*": {
"*": [
"./src/*"
]
}
},
"exports": {
".": "./src/index.ts"
},
"typesVersions": {
"*": {
"*": ["./src/*"]
}
},
"devDependencies": {
"@soybeanjs/changelog": "0.3.25",
"bumpp": "10.3.2",
"@soybeanjs/changelog": "0.4.3",
"bumpp": "10.4.1",
"c12": "3.3.3",
"cac": "6.7.14",
"consola": "3.4.2",
"enquirer": "2.4.1",
"execa": "9.6.1",
"kolorist": "1.8.0",
"npm-check-updates": "19.2.0",
"npm-check-updates": "19.6.3",
"picomatch": "4.0.3",
"rimraf": "6.1.2"
"rimraf": "6.1.3"
}
}

View File

@@ -1,4 +1,4 @@
import cac from 'cac';
import { cac } from 'cac';
import { blue, lightGreen } from 'kolorist';
import { version } from '../package.json';
import { cleanup, genChangelog, generateRoute, gitCommit, gitCommitVerify, release, updatePkg } from './commands';

View File

@@ -1,12 +1,14 @@
{
"name": "@sa/uno-preset",
"version": "2.0.2",
"exports": {
".": "./src/index.ts"
},
"version": "2.1.0",
"typesVersions": {
"*": {
"*": ["./src/*"]
"*": [
"./src/*"
]
}
},
"exports": {
".": "./src/index.ts"
}
}

View File

@@ -1,7 +1,7 @@
// @unocss-include
import type { Preset } from '@unocss/core';
import type { Theme } from '@unocss/preset-uno';
import type { Theme } from '@unocss/preset-mini';
export function presetSoybeanAdmin(): Preset<Theme> {
const preset: Preset<Theme> = {

View File

@@ -1,14 +1,16 @@
{
"name": "@sa/utils",
"version": "2.0.2",
"exports": {
".": "./src/index.ts"
},
"version": "2.1.0",
"typesVersions": {
"*": {
"*": ["./src/*"]
"*": [
"./src/*"
]
}
},
"exports": {
".": "./src/index.ts"
},
"dependencies": {
"colord": "2.9.3",
"crypto-js": "4.2.0",

4743
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,2 @@
packages:
- "packages/*"
- 'packages/*'

View File

@@ -1,4 +1,5 @@
<script setup lang="ts" generic="T extends Record<string, unknown>, K = never">
import { computed } from 'vue';
import { VueDraggable } from 'vue-draggable-plus';
import { $t } from '@/locales';
@@ -9,6 +10,53 @@ defineOptions({
const columns = defineModel<NaiveUI.TableColumnCheck[]>('columns', {
required: true
});
const tooltipRecord: Record<NaiveUI.TableColumnFixed, App.I18n.I18nKey> = {
left: 'datatable.fixed.right',
right: 'datatable.fixed.unFixed',
unFixed: 'datatable.fixed.left'
};
function handleFixed(column: NaiveUI.TableColumnCheck) {
const fixedOptions: NaiveUI.TableColumnFixed[] = ['left', 'right', 'unFixed'];
const index = fixedOptions.findIndex(item => item === column.fixed);
const nextIndex = index === fixedOptions.length - 1 ? 0 : index + 1;
column.fixed = fixedOptions[nextIndex];
}
const visibleStats = computed(() => {
let total = 0;
let checked = 0;
columns.value.forEach(column => {
if (!column.visible) return;
total += 1;
if (column.checked) checked += 1;
});
return { total, checked };
});
const selectAllChecked = computed(() => {
const { total, checked } = visibleStats.value;
return total > 0 && checked === total;
});
const selectAllIndeterminate = computed(() => {
const { total, checked } = visibleStats.value;
return checked > 0 && checked < total;
});
function toggleSelectAll(checked: boolean) {
columns.value.forEach(column => {
if (!column.visible) return;
column.checked = checked;
});
}
</script>
<template>
@@ -21,22 +69,48 @@ const columns = defineModel<NaiveUI.TableColumnCheck[]>('columns', {
{{ $t('common.columnSetting') }}
</NButton>
</template>
<VueDraggable v-model="columns" :animation="150" filter=".none_draggable">
<div
v-for="item in columns"
:key="item.key"
class="h-36px flex-y-center rd-4px hover:(bg-primary bg-opacity-20)"
:class="{ hidden: !item.visible }"
>
<icon-mdi-drag class="mr-8px h-full cursor-move text-icon" />
<NCheckbox v-model:checked="item.checked" class="none_draggable flex-1">
<template v-if="typeof item.title === 'function'">
<component :is="item.title" />
</template>
<template v-else>{{ item.title }}</template>
<div>
<div class="h-36px flex-y-center rd-4px pl-26px hover:(bg-primary bg-opacity-20)">
<NCheckbox
:checked="selectAllChecked"
:indeterminate="selectAllIndeterminate"
:disabled="visibleStats.total === 0"
class="flex-1"
@update:checked="toggleSelectAll"
>
{{ $t('common.selectAll') }}
</NCheckbox>
</div>
</VueDraggable>
<NDivider class="!my-4px" />
<VueDraggable v-model="columns" :animation="150" filter=".none_draggable" class="max-h-[200px] overflow-y-auto">
<div
v-for="item in columns"
:key="item.key"
class="h-36px flex-y-center justify-between gap-6px"
:class="{ hidden: !item.visible }"
>
<div class="h-full flex-y-center flex-1 rd-4px hover:(bg-primary bg-opacity-20)">
<icon-mdi-drag class="mr-8px h-full cursor-move text-icon" />
<NCheckbox v-model:checked="item.checked" class="none_draggable flex-1">
<template v-if="typeof item.title === 'function'">
<component :is="item.title" />
</template>
<template v-else>{{ item.title }}</template>
</NCheckbox>
</div>
<ButtonIcon
:disabled="!item.checked"
:focusable="false"
:tooltip-content="$t(tooltipRecord[item.fixed!])"
@click="handleFixed(item)"
>
<icon-octicon-pin-16 v-if="item.fixed === 'unFixed'" />
<icon-octicon-pin-16 v-else-if="item.fixed === 'left'" class="rotate-270" />
<icon-octicon-pin-slash-16 v-else />
</ButtonIcon>
</div>
</VueDraggable>
</div>
</NPopover>
</template>

View File

@@ -265,6 +265,7 @@ function getColumnChecks<Column extends NaiveUI.TableColumn<any>>(
key: column.key as string,
title: column.title!,
checked: true,
fixed: column.fixed ?? 'unFixed',
visible: getColumnVisible?.(column) ?? true
});
} else if (column.type === 'selection') {
@@ -272,6 +273,7 @@ function getColumnChecks<Column extends NaiveUI.TableColumn<any>>(
key: SELECTION_KEY,
title: $t('common.check'),
checked: true,
fixed: column.fixed ?? 'unFixed',
visible: getColumnVisible?.(column) ?? false
});
} else if (column.type === 'expand') {
@@ -279,6 +281,7 @@ function getColumnChecks<Column extends NaiveUI.TableColumn<any>>(
key: EXPAND_KEY,
title: $t('common.expandColumn'),
checked: true,
fixed: column.fixed ?? 'unFixed',
visible: getColumnVisible?.(column) ?? false
});
}
@@ -300,7 +303,14 @@ function getColumns<Column extends NaiveUI.TableColumn<any>>(cols: Column[], che
}
});
const filteredColumns = checks.filter(item => item.checked).map(check => columnMap.get(check.key) as Column);
const filteredColumns = checks
.filter(item => item.checked)
.map(check => {
return {
...columnMap.get(check.key),
fixed: check.fixed
} as Column;
});
return filteredColumns;
}

View File

@@ -23,4 +23,10 @@ export const $t = i18n.global.t as App.I18n.$T;
export function setLocale(locale: App.I18n.LangType) {
i18n.global.locale.value = locale;
document?.querySelector('html')?.setAttribute('lang', locale);
}
export function getLocale(): App.I18n.LangType {
return i18n.global.locale.value as App.I18n.LangType;
}

View File

@@ -15,6 +15,7 @@ const local: App.I18n.Schema = {
cancel: 'Cancel',
close: 'Close',
check: 'Check',
selectAll: 'Select All',
expandColumn: 'Expand Column',
columnSetting: 'Column Setting',
config: 'Config',
@@ -689,7 +690,12 @@ const local: App.I18n.Schema = {
unpin: 'Unpin'
},
datatable: {
itemCount: 'Total {total} items'
itemCount: 'Total {total} items',
fixed: {
left: 'Left Fixed',
right: 'Right Fixed',
unFixed: 'Unfixed'
}
}
};

View File

@@ -15,6 +15,7 @@ const local: App.I18n.Schema = {
cancel: '取消',
close: '关闭',
check: '勾选',
selectAll: '全选',
expandColumn: '展开列',
columnSetting: '列设置',
config: '配置',
@@ -685,7 +686,12 @@ const local: App.I18n.Schema = {
unpin: '取消固定'
},
datatable: {
itemCount: '共 {total} 条'
itemCount: '共 {total} 条',
fixed: {
left: '左固定',
right: '右固定',
unFixed: '取消固定'
}
}
};

View File

@@ -8,9 +8,10 @@ import {
setupNProgress,
setupProNaiveComponents
} from './plugins';
import { setupVueRootValidator } from 'vite-plugin-vue-transition-root-validator/client';
import { setupStore } from './store';
import { setupRouter } from './router';
import { setupI18n } from './locales';
import { getLocale, setupI18n } from './locales';
import App from './App.vue';
async function setupApp() {
@@ -34,6 +35,10 @@ async function setupApp() {
setupAppVersionNotification();
setupVueRootValidator(app, {
lang: getLocale() === 'zh-CN' ? 'zh' : 'en'
});
app.mount('#app');
}

View File

@@ -1,11 +1,11 @@
import type { Router } from 'vue-router';
export function createProgressGuard(router: Router) {
router.beforeEach((_to, _from, next) => {
router.beforeEach(() => {
window.NProgress?.start?.();
next();
return;
});
router.afterEach(_to => {
router.afterEach(() => {
window.NProgress?.done?.();
});
}

View File

@@ -1,10 +1,4 @@
import type {
LocationQueryRaw,
NavigationGuardNext,
RouteLocationNormalized,
RouteLocationRaw,
Router
} from 'vue-router';
import type { LocationQueryRaw, RouteLocationNormalized, RouteLocationRaw, Router } from 'vue-router';
import type { RouteKey, RoutePath } from '@elegant-router/types';
import { useAuthStore } from '@/store/modules/auth';
import { useRouteStore } from '@/store/modules/route';
@@ -17,12 +11,11 @@ import { getRouteName } from '@/router/elegant/transform';
* @param router router instance
*/
export function createRouteGuard(router: Router) {
router.beforeEach(async (to, from, next) => {
router.beforeEach(async (to, from) => {
const location = await initRoute(to);
if (location) {
next(location);
return;
return location;
}
const authStore = useAuthStore();
@@ -40,30 +33,27 @@ export function createRouteGuard(router: Router) {
// if it is login route when logged in, then switch to the root page
if (to.name === loginRoute && isLogin) {
next({ name: rootRoute });
return;
return { name: rootRoute };
}
// if the route does not need login, then it is allowed to access directly
if (!needLogin) {
handleRouteSwitch(to, from, next);
handleRouteSwitch(to, from);
return;
}
// the route need login but the user is not logged in, then switch to the login page
if (!isLogin) {
next({ name: loginRoute, query: { redirect: to.fullPath } });
return;
return { name: loginRoute, query: { redirect: to.fullPath } };
}
// if the user is logged in but does not have authorization, then switch to the 403 page
if (!hasAuth) {
next({ name: noAuthorizationRoute });
return;
return { name: noAuthorizationRoute };
}
// switch route normally
handleRouteSwitch(to, from, next);
handleRouteSwitch(to, from);
});
}
@@ -161,17 +151,13 @@ async function initRoute(to: RouteLocationNormalized): Promise<RouteLocationRaw
return null;
}
function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
function handleRouteSwitch(to: RouteLocationNormalized, from: RouteLocationNormalized) {
// route with href
if (to.meta.href) {
window.open(to.meta.href, '_blank');
next({ path: from.fullPath, replace: true, query: from.query, hash: to.hash });
return;
return { path: from.fullPath, replace: true, query: from.query, hash: to.hash };
}
next();
}
function getRouteQueryOfLoginRoute(to: RouteLocationNormalized, routeHome: RouteKey) {

View File

@@ -19,7 +19,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
const { toLogin, redirectFromLogin } = useRouterPush(false);
const { loading: loginLoading, startLoading, endLoading } = useLoading();
const token = ref(getToken());
const token = ref('');
const userInfo: Api.Auth.UserInfo = reactive({
userId: '',
@@ -159,9 +159,10 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
}
async function initUserInfo() {
const hasToken = getToken();
const maybeToken = getToken();
if (hasToken) {
if (maybeToken) {
token.value = maybeToken;
const pass = await getUserInfo();
if (!pass) {

View File

@@ -196,6 +196,7 @@ declare namespace App {
type RouterPushOptions = {
query?: Record<string, string>;
params?: Record<string, string>;
force?: boolean;
};
/** The global header props */
@@ -326,6 +327,7 @@ declare namespace App {
cancel: string;
close: string;
check: string;
selectAll: string;
expandColumn: string;
columnSetting: string;
config: string;
@@ -838,6 +840,11 @@ declare namespace App {
};
datatable: {
itemCount: string;
fixed: {
left: string;
right: string;
unFixed: string;
};
};
};

View File

@@ -53,6 +53,8 @@ declare module 'vue' {
NCollapseItem: typeof import('naive-ui')['NCollapseItem']
NColorPicker: typeof import('naive-ui')['NColorPicker']
NDataTable: typeof import('naive-ui')['NDataTable']
NDescriptions: typeof import('naive-ui')['NDescriptions']
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDivider: typeof import('naive-ui')['NDivider']
NDrawer: typeof import('naive-ui')['NDrawer']
@@ -85,6 +87,7 @@ declare module 'vue' {
NSwitch: typeof import('naive-ui')['NSwitch']
NTab: typeof import('naive-ui')['NTab']
NTabs: typeof import('naive-ui')['NTabs']
NTag: typeof import('naive-ui')['NTag']
NThing: typeof import('naive-ui')['NThing']
NTooltip: typeof import('naive-ui')['NTooltip']
NWatermark: typeof import('naive-ui')['NWatermark']
@@ -146,6 +149,8 @@ declare global {
const NCollapseItem: typeof import('naive-ui')['NCollapseItem']
const NColorPicker: typeof import('naive-ui')['NColorPicker']
const NDataTable: typeof import('naive-ui')['NDataTable']
const NDescriptions: typeof import('naive-ui')['NDescriptions']
const NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
const NDialogProvider: typeof import('naive-ui')['NDialogProvider']
const NDivider: typeof import('naive-ui')['NDivider']
const NDrawer: typeof import('naive-ui')['NDrawer']
@@ -178,6 +183,7 @@ declare global {
const NSwitch: typeof import('naive-ui')['NSwitch']
const NTab: typeof import('naive-ui')['NTab']
const NTabs: typeof import('naive-ui')['NTabs']
const NTag: typeof import('naive-ui')['NTag']
const NThing: typeof import('naive-ui')['NThing']
const NTooltip: typeof import('naive-ui')['NTooltip']
const NWatermark: typeof import('naive-ui')['NWatermark']
@@ -193,4 +199,4 @@ declare global {
const ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default']
const WaveBg: typeof import('./../components/custom/wave-bg.vue')['default']
const WebSiteLink: typeof import('./../components/custom/web-site-link.vue')['default']
}
}

View File

@@ -7,6 +7,7 @@ declare namespace NaiveUI {
type DataTableSelectionColumn<T> = import('naive-ui').DataTableSelectionColumn<T>;
type TableColumnGroup<T> = import('naive-ui/es/data-table/src/interface').TableColumnGroup<T>;
type TableColumnCheck = import('@sa/hooks').TableColumnCheck;
type TableColumnFixed = import('@sa/hooks').TableColumnCheck['fixed'];
type SetTableColumnKey<C, T> = Omit<C, 'key'> & { key: keyof T | (string & {}) };

View File

@@ -12,7 +12,8 @@ const domRef = ref<HTMLDivElement | null>(null);
async function renderMap() {
await load(true);
if (!domRef.value) return;
// eslint-disable-next-line no-new
// oxlint-disable-next-line no-new
new TMap.Map(domRef.value, {
center: new TMap.LatLng(39.98412, 116.307484),
zoom: 11,

View File

@@ -1,12 +1,8 @@
import { defineConfig } from '@unocss/vite';
import transformerDirectives from '@unocss/transformer-directives';
import transformerVariantGroup from '@unocss/transformer-variant-group';
import presetWind3 from '@unocss/preset-wind3';
import type { Theme } from '@unocss/preset-uno';
import { defineConfig, transformerDirectives, transformerVariantGroup, presetWind3 } from 'unocss';
import { presetSoybeanAdmin } from '@sa/uno-preset';
import { themeVars } from './src/theme/vars';
export default defineConfig<Theme>({
export default defineConfig({
content: {
pipeline: {
exclude: ['node_modules', 'dist']