mirror of
https://github.com/KwiTsukasa/kt-template-admin.git
synced 2026-05-27 16:35:47 +08:00
chore(admin): 精简后台模板并隐藏未接入模块
This commit is contained in:
parent
1f3f32fd94
commit
3e5a60089b
@ -1,5 +0,0 @@
|
|||||||
# Changesets
|
|
||||||
|
|
||||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
|
||||||
|
|
||||||
We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
|
|
||||||
"changelog": [
|
|
||||||
"@changesets/changelog-github",
|
|
||||||
{ "repo": "vbenjs/vue-vben-admin" }
|
|
||||||
],
|
|
||||||
"commit": false,
|
|
||||||
"fixed": [["@vben-core/*", "@vben/*"]],
|
|
||||||
"snapshot": {
|
|
||||||
"prereleaseTemplate": "{tag}-{datetime}"
|
|
||||||
},
|
|
||||||
"privatePackages": { "version": true, "tag": true },
|
|
||||||
"linked": [],
|
|
||||||
"access": "public",
|
|
||||||
"baseBranch": "main",
|
|
||||||
"updateInternalDependencies": "patch",
|
|
||||||
"ignore": []
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export { default } from '@vben/commitlint-config';
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
ports:
|
|
||||||
- port: 5555
|
|
||||||
onOpen: open-preview
|
|
||||||
tasks:
|
|
||||||
- init: npm i -g corepack && pnpm install
|
|
||||||
command: pnpm run dev:play
|
|
||||||
@ -1 +1 @@
|
|||||||
node scripts/validate-commit-msg.mjs "$1"
|
node internal/commit/validate-commit-msg.mjs "$1"
|
||||||
|
|||||||
157
README.ja-JP.md
157
README.ja-JP.md
@ -1,157 +0,0 @@
|
|||||||
<div align="center">
|
|
||||||
<a href="https://github.com/anncwb/vue-vben-admin">
|
|
||||||
<img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp">
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
[](LICENSE)
|
|
||||||
|
|
||||||
<h1>Vue Vben Admin</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
[](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin)    
|
|
||||||
|
|
||||||
**日本語** | [English](./README.md) | [中文](./README.zh-CN.md)
|
|
||||||
|
|
||||||
## 紹介
|
|
||||||
|
|
||||||
Vue Vben Adminは、最新の`vue3`、`vite`、`TypeScript`などの主流技術を使用して開発された、無料でオープンソースの中・後端テンプレートです。すぐに使える中・後端のフロントエンドソリューションとして、学習の参考にもなります。
|
|
||||||
|
|
||||||
## アップグレード通知
|
|
||||||
|
|
||||||
これは最新バージョン `5.0` であり、以前のバージョンとは互換性がありません。新しいプロジェクトを開始する場合は、最新バージョンを使用することをお勧めします。古いバージョンを表示したい場合は、[v2ブランチ](https://github.com/vbenjs/vue-vben-admin/tree/v2)を使用してください。
|
|
||||||
|
|
||||||
## 特徴
|
|
||||||
|
|
||||||
- **最新技術スタック**:Vue 3やViteなどの最先端フロントエンド技術で開発
|
|
||||||
- **TypeScript**:アプリケーション規模のJavaScriptのための言語
|
|
||||||
- **テーマ**:複数のテーマカラーが利用可能で、カスタマイズオプションも豊富
|
|
||||||
- **国際化**:完全な内蔵国際化サポート
|
|
||||||
- **権限管理**:動的ルートベースの権限生成ソリューションを内蔵
|
|
||||||
|
|
||||||
## プレビュー
|
|
||||||
|
|
||||||
- [Vben Admin](https://vben.pro/) - フルバージョンの中国語サイト
|
|
||||||
|
|
||||||
テストアカウント:vben/123456
|
|
||||||
|
|
||||||
<div align="center">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
### Gitpodを使用
|
|
||||||
|
|
||||||
Gitpod(GitHub用の無料オンライン開発環境)でプロジェクトを開き、すぐにコーディングを開始します。
|
|
||||||
|
|
||||||
[](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
|
|
||||||
|
|
||||||
## ドキュメント
|
|
||||||
|
|
||||||
[ドキュメント](https://doc.vben.pro/)
|
|
||||||
|
|
||||||
## インストールと使用
|
|
||||||
|
|
||||||
1. プロジェクトコードを取得
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 依存関係のインストール
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd vue-vben-admin
|
|
||||||
npm i -g corepack
|
|
||||||
pnpm install
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 実行
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm dev
|
|
||||||
```
|
|
||||||
|
|
||||||
4. ビルド
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm build
|
|
||||||
```
|
|
||||||
|
|
||||||
## 変更ログ
|
|
||||||
|
|
||||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
|
||||||
|
|
||||||
## 貢献方法
|
|
||||||
|
|
||||||
ご参加をお待ちしておりますするか、Pull Requestを送信してください。
|
|
||||||
|
|
||||||
**Pull Request プロセス:**
|
|
||||||
|
|
||||||
1. コードをフォーク
|
|
||||||
2. 自分のブランチを作成:`git checkout -b feat/xxxx`
|
|
||||||
3. 変更をコミット:`git commit -am 'feat(function): add xxxxx'`
|
|
||||||
4. ブランチをプッシュ:`git push origin feat/xxxx`
|
|
||||||
5. `pull request`を送信
|
|
||||||
|
|
||||||
## Git貢献提出規則
|
|
||||||
|
|
||||||
参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 規則 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
|
||||||
|
|
||||||
- `feat` 新機能の追加
|
|
||||||
- `fix` 問題/バグの修正
|
|
||||||
- `style` コードスタイルに関連し、実行結果に影響しない
|
|
||||||
- `perf` 最適化/パフォーマンス向上
|
|
||||||
- `refactor` リファクタリング
|
|
||||||
- `revert` 変更の取り消し
|
|
||||||
- `test` テスト関連
|
|
||||||
- `docs` ドキュメント/注釈
|
|
||||||
- `chore` 依存関係の更新/スキャフォールディング設定の変更など
|
|
||||||
- `ci` 継続的インテグレーション
|
|
||||||
- `types` 型定義ファイルの変更
|
|
||||||
|
|
||||||
## ブラウザサポート
|
|
||||||
|
|
||||||
ローカル開発には `Chrome 80+` ブラウザを推奨します
|
|
||||||
|
|
||||||
モダンブラウザをサポートし、IEはサポートしません
|
|
||||||
|
|
||||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
|
||||||
| :-: | :-: | :-: | :-: |
|
|
||||||
| 最新2バージョン | 最新2バージョン | 最新2バージョン | 最新2バージョン |
|
|
||||||
|
|
||||||
## メンテナー
|
|
||||||
|
|
||||||
[@Vben](https://github.com/anncwb)
|
|
||||||
|
|
||||||
## スター歴史
|
|
||||||
|
|
||||||
[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
|
|
||||||
|
|
||||||
## 寄付
|
|
||||||
|
|
||||||
このプロジェクトが役に立つと思われた場合、作者にコーヒーを一杯おごってサポートを示すことができます!
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
|
||||||
|
|
||||||
## 貢献者
|
|
||||||
|
|
||||||
<a href="https://openomy.app/github/vbenjs/vue-vben-admin" target="_blank" style="display: block; width: 100%;" align="center">
|
|
||||||
<img src="https://openomy.app/svg?repo=vbenjs/vue-vben-admin&chart=bubble&latestMonth=3" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
|
||||||
<img alt="Contributors" src="https://contrib.rocks/image?repo=vbenjs/vue-vben-admin" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## Discord
|
|
||||||
|
|
||||||
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
|
|
||||||
|
|
||||||
## ライセンス
|
|
||||||
|
|
||||||
[MIT © Vben-2020](./LICENSE)
|
|
||||||
198
README.md
198
README.md
@ -1,157 +1,67 @@
|
|||||||
<div align="center">
|
# KT Template Admin
|
||||||
<a href="https://github.com/anncwb/vue-vben-admin">
|
|
||||||
<img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp">
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
[](LICENSE)
|
`kt-template-admin` 是 KT 后台管理端项目,基于 Vben 5.6.0 精简后只保留 `antdv-next` 应用,接口统一接入 `kt-template-online-api`,生产发布走 Jenkins 静态构建和 Nginx 反向代理。
|
||||||
|
|
||||||
<h1>Vue Vben Admin</h1>
|
## 项目结构
|
||||||
</div>
|
|
||||||
|
|
||||||
[](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) [](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml) [](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml) [](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml) [](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml)
|
```text
|
||||||
|
apps/web-antdv-next 后台管理端入口
|
||||||
**English** | [中文](./README.zh-CN.md) | [日本語](./README.ja-JP.md)
|
internal 构建、Vite、Lint 等内部配置包
|
||||||
|
packages Vben 运行时依赖的核心包和组件包
|
||||||
## Introduction
|
deploy/nginx-admin.conf Admin 静态站点和后端 /api 反向代理配置
|
||||||
|
Jenkinsfile Jenkins 静态发布流水线
|
||||||
Vue Vben Admin is a free and open source middle and back-end template. Using the latest `vue3`, `vite`, `TypeScript` and other mainstream technology development, the out-of-the-box middle and back-end front-end solutions can also be used for learning reference.
|
|
||||||
|
|
||||||
## Upgrade Notice
|
|
||||||
|
|
||||||
This is the latest version, 5.0, and it is not compatible with previous versions. If you are starting a new project, it is recommended to use the latest version. If you wish to view the old version, please use the [v2 branch](https://github.com/vbenjs/vue-vben-admin/tree/v2).
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **Latest Technology Stack**: Developed with cutting-edge front-end technologies like Vue 3 and Vite
|
|
||||||
- **TypeScript**: A language for application-scale JavaScript
|
|
||||||
- **Themes**: Multiple theme colors available with customizable options
|
|
||||||
- **Internationalization**: Comprehensive built-in internationalization support
|
|
||||||
- **Permissions**: Built-in solution for dynamic route-based permission generation
|
|
||||||
|
|
||||||
## Preview
|
|
||||||
|
|
||||||
- [Vben Admin](https://vben.pro/) - Full version Chinese site
|
|
||||||
|
|
||||||
Test Account: vben/123456
|
|
||||||
|
|
||||||
<div align="center">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
### Use Gitpod
|
|
||||||
|
|
||||||
Open the project in Gitpod (free online dev environment for GitHub) and start coding immediately.
|
|
||||||
|
|
||||||
[](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
|
|
||||||
[Document](https://doc.vben.pro/)
|
|
||||||
|
|
||||||
## Install and Use
|
|
||||||
|
|
||||||
1. Get the project code
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Install dependencies
|
## 环境要求
|
||||||
|
|
||||||
|
- Node.js `22.22.0`
|
||||||
|
- pnpm `10.28.2`
|
||||||
|
|
||||||
|
建议通过 Corepack 固定 pnpm 版本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
corepack enable
|
||||||
|
corepack prepare pnpm@10.28.2 --activate
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常用命令
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd vue-vben-admin
|
|
||||||
npm i -g corepack
|
|
||||||
pnpm install
|
pnpm install
|
||||||
|
pnpm run dev
|
||||||
|
pnpm run verify:commit
|
||||||
|
pnpm run build:antdv-next
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Run
|
## 环境变量
|
||||||
|
|
||||||
```bash
|
本地开发和 Jenkins 构建主要使用:
|
||||||
pnpm dev
|
|
||||||
|
- `VITE_GLOB_API_URL`:后端 API 前缀,本地和生产默认使用 `/api`
|
||||||
|
- `VITE_BASE`:Vite base,默认 `/`
|
||||||
|
- `VITE_ROUTER_HISTORY`:路由模式,可选 `hash` 或 `html5`
|
||||||
|
- `VITE_COMPRESS`:构建压缩方式,可选 `none`、`gzip`、`brotli`
|
||||||
|
|
||||||
|
真实环境变量不提交,示例配置以 `.env.example` 为准。
|
||||||
|
|
||||||
|
## 部署说明
|
||||||
|
|
||||||
|
Jenkins 使用 `Jenkinsfile` 执行:
|
||||||
|
|
||||||
|
1. 安装依赖
|
||||||
|
2. `pnpm run verify:commit`
|
||||||
|
3. `pnpm run build:antdv-next`
|
||||||
|
4. 将 `apps/web-antdv-next/dist` 原子发布到 Nginx 挂载的 Admin 静态目录
|
||||||
|
|
||||||
|
Nginx 配置见 `deploy/nginx-admin.conf`,默认监听 `5999`,静态根目录为 `/usr/share/nginx/html/admin`,并将浏览器侧 `/api/*` 转发到后端 `192.168.31.224:48085`。配置保留 gzip、静态资源长缓存、入口 HTML 不缓存和 SPA 回退。
|
||||||
|
|
||||||
|
## 提交规范
|
||||||
|
|
||||||
|
Husky 会在提交前执行 lint 和类型校验,并在 `commit-msg` 阶段校验提交信息格式:
|
||||||
|
|
||||||
|
```text
|
||||||
|
feat(admin): 增加后台菜单配置
|
||||||
|
fix(api): 修复登录态刷新
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Build
|
要求使用英文类型前缀,描述部分包含中文。
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm build
|
|
||||||
```
|
|
||||||
|
|
||||||
## Change Log
|
|
||||||
|
|
||||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
|
||||||
|
|
||||||
## How to Contribute
|
|
||||||
|
|
||||||
You are very welcome to join! [Raise an issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) or submit a Pull Request.
|
|
||||||
|
|
||||||
**Pull Request Process:**
|
|
||||||
|
|
||||||
1. Fork the code
|
|
||||||
2. Create your branch: `git checkout -b feat/xxxx`
|
|
||||||
3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
|
|
||||||
4. Push your branch: `git push origin feat/xxxx`
|
|
||||||
5. Submit `pull request`
|
|
||||||
|
|
||||||
## Git Contribution Submission Specification
|
|
||||||
|
|
||||||
Reference [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) specification ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
|
||||||
|
|
||||||
- `feat` Add new features
|
|
||||||
- `fix` Fix the problem/BUG
|
|
||||||
- `style` The code style is related and does not affect the running result
|
|
||||||
- `perf` Optimization/performance improvement
|
|
||||||
- `refactor` Refactor
|
|
||||||
- `revert` Undo edit
|
|
||||||
- `test` Test related
|
|
||||||
- `docs` Documentation/notes
|
|
||||||
- `chore` Dependency update/scaffolding configuration modification etc.
|
|
||||||
- `ci` Continuous integration
|
|
||||||
- `types` Type definition file changes
|
|
||||||
|
|
||||||
## Browser Support
|
|
||||||
|
|
||||||
The `Chrome 80+` browser is recommended for local development
|
|
||||||
|
|
||||||
Support modern browsers, not IE
|
|
||||||
|
|
||||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
|
||||||
| :-: | :-: | :-: | :-: |
|
|
||||||
| last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
|
||||||
|
|
||||||
## Maintainer
|
|
||||||
|
|
||||||
[@Vben](https://github.com/anncwb)
|
|
||||||
|
|
||||||
## Star History
|
|
||||||
|
|
||||||
[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support!
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aee;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
<a href="https://openomy.app/github/vbenjs/vue-vben-admin" target="_blank" style="display: block; width: 100%;" align="center">
|
|
||||||
<img src="https://openomy.app/svg?repo=vbenjs/vue-vben-admin&chart=bubble&latestMonth=3" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
|
||||||
<img alt="Contributors" src="https://contrib.rocks/image?repo=vbenjs/vue-vben-admin" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## Discord
|
|
||||||
|
|
||||||
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[MIT © Vben-2020](./LICENSE)
|
|
||||||
|
|||||||
157
README.zh-CN.md
157
README.zh-CN.md
@ -1,157 +0,0 @@
|
|||||||
<div align="center">
|
|
||||||
<a href="https://github.com/anncwb/vue-vben-admin">
|
|
||||||
<img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp">
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
[](LICENSE)
|
|
||||||
|
|
||||||
<h1>Vue Vben Admin</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
[](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin)    
|
|
||||||
|
|
||||||
**中文** | [English](./README.md) | [日本語](./README.ja-JP.md)
|
|
||||||
|
|
||||||
## 简介
|
|
||||||
|
|
||||||
Vue Vben Admin 是 Vue Vben Admin 的升级版本。作为一个免费开源的中后台模板,它采用了最新的 Vue 3、Vite、TypeScript 等主流技术开发,开箱即用,可用于中后台前端开发,也适合学习参考。
|
|
||||||
|
|
||||||
## 升级提示
|
|
||||||
|
|
||||||
该版本为最新版本 `5.0`,与其他版本不兼容,如果你是新项目,建议使用最新版本。如果你想查看旧版本,请使用 [v2 分支](https://github.com/vbenjs/vue-vben-admin/tree/v2)
|
|
||||||
|
|
||||||
## 特性
|
|
||||||
|
|
||||||
- **最新技术栈**:使用 Vue3/vite 等前端前沿技术开发
|
|
||||||
- **TypeScript**:应用程序级 JavaScript 的语言
|
|
||||||
- **主题**:提供多套主题色彩,可配置自定义主题
|
|
||||||
- **国际化**:内置完善的国际化方案
|
|
||||||
- **权限**:内置完善的动态路由权限生成方案
|
|
||||||
|
|
||||||
## 预览
|
|
||||||
|
|
||||||
- [Vben Admin](https://vben.pro/) - 完整版中文站点
|
|
||||||
|
|
||||||
测试账号:vben/123456
|
|
||||||
|
|
||||||
<div align="center">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
|
|
||||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
### 使用 Gitpod
|
|
||||||
|
|
||||||
在 Gitpod(适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码。
|
|
||||||
|
|
||||||
[](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
|
|
||||||
|
|
||||||
## 文档
|
|
||||||
|
|
||||||
[文档地址](https://doc.vben.pro/)
|
|
||||||
|
|
||||||
## 安装使用
|
|
||||||
|
|
||||||
1. 获取项目代码
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 安装依赖
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd vue-vben-admin
|
|
||||||
npm i -g corepack
|
|
||||||
pnpm install
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 运行
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm dev
|
|
||||||
```
|
|
||||||
|
|
||||||
4. 打包
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm build
|
|
||||||
```
|
|
||||||
|
|
||||||
## 更新日志
|
|
||||||
|
|
||||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
|
||||||
|
|
||||||
## 如何贡献
|
|
||||||
|
|
||||||
非常欢迎你的加入 或者提交一个 Pull Request。
|
|
||||||
|
|
||||||
**Pull Request 流程:**
|
|
||||||
|
|
||||||
1. Fork 代码
|
|
||||||
2. 创建自己的分支:`git checkout -b feature/xxxx`
|
|
||||||
3. 提交你的修改:`git commit -am 'feat(function): add xxxxx'`
|
|
||||||
4. 推送您的分支:`git push origin feature/xxxx`
|
|
||||||
5. 提交 `pull request`
|
|
||||||
|
|
||||||
## Git 贡献提交规范
|
|
||||||
|
|
||||||
参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
|
||||||
|
|
||||||
- `feat` 增加新功能
|
|
||||||
- `fix` 修复问题/BUG
|
|
||||||
- `style` 代码风格相关无影响运行结果的
|
|
||||||
- `perf` 优化/性能提升
|
|
||||||
- `refactor` 重构
|
|
||||||
- `revert` 撤销修改
|
|
||||||
- `test` 测试相关
|
|
||||||
- `docs` 文档/注释
|
|
||||||
- `chore` 依赖更新/脚手架配置修改等
|
|
||||||
- `ci` 持续集成
|
|
||||||
- `types` 类型定义文件更改
|
|
||||||
|
|
||||||
## 浏览器支持
|
|
||||||
|
|
||||||
本地开发推荐使用 `Chrome 80+` 浏览器
|
|
||||||
|
|
||||||
支持现代浏览器,不支持 IE
|
|
||||||
|
|
||||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
|
||||||
| :-: | :-: | :-: | :-: |
|
|
||||||
| last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
|
||||||
|
|
||||||
## 维护者
|
|
||||||
|
|
||||||
[@Vben](https://github.com/anncwb)
|
|
||||||
|
|
||||||
## Star 历史
|
|
||||||
|
|
||||||
[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
|
|
||||||
|
|
||||||
## 捐赠
|
|
||||||
|
|
||||||
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
|
||||||
|
|
||||||
## 贡献者
|
|
||||||
|
|
||||||
<a href="https://openomy.app/github/vbenjs/vue-vben-admin" target="_blank" style="display: block; width: 100%;" align="center">
|
|
||||||
<img src="https://openomy.app/svg?repo=vbenjs/vue-vben-admin&chart=bubble&latestMonth=3" target="_blank" alt="Contribution Leaderboard" style="display: block; width: 100%;" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
|
||||||
<img alt="Contributors" src="https://contrib.rocks/image?repo=vbenjs/vue-vben-admin" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## Discord
|
|
||||||
|
|
||||||
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
|
|
||||||
|
|
||||||
## 许可证
|
|
||||||
|
|
||||||
[MIT © Vben-2020](./LICENSE)
|
|
||||||
@ -2,9 +2,52 @@ import type { RouteRecordStringComponent } from '@vben/types';
|
|||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
const SUPPORTED_ADMIN_MENU_NAMES = new Set([
|
||||||
|
'System',
|
||||||
|
'SystemDept',
|
||||||
|
'SystemDeptCreate',
|
||||||
|
'SystemDeptDelete',
|
||||||
|
'SystemDeptEdit',
|
||||||
|
'SystemMenu',
|
||||||
|
'SystemMenuCreate',
|
||||||
|
'SystemMenuDelete',
|
||||||
|
'SystemMenuEdit',
|
||||||
|
'SystemRole',
|
||||||
|
'SystemRoleCreate',
|
||||||
|
'SystemRoleDelete',
|
||||||
|
'SystemRoleEdit',
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function isSupportedAdminMenuName(name?: null | string | symbol) {
|
||||||
|
return typeof name === 'string' && SUPPORTED_ADMIN_MENU_NAMES.has(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterSupportedAdminMenus(
|
||||||
|
menus: RouteRecordStringComponent[],
|
||||||
|
): RouteRecordStringComponent[] {
|
||||||
|
return menus
|
||||||
|
.map((menu) => {
|
||||||
|
const children = menu.children
|
||||||
|
? filterSupportedAdminMenus(menu.children)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...menu,
|
||||||
|
...(children && children.length > 0 ? { children } : {}),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(
|
||||||
|
(menu) => isSupportedAdminMenuName(menu.name) || !!menu.children?.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户所有菜单
|
* 获取用户所有菜单
|
||||||
*/
|
*/
|
||||||
export async function getAllMenusApi() {
|
export async function getAllMenusApi() {
|
||||||
return requestClient.get<RouteRecordStringComponent[]>('/menu/all');
|
const menus =
|
||||||
|
await requestClient.get<RouteRecordStringComponent[]>('/menu/all');
|
||||||
|
|
||||||
|
// 只暴露当前后端真实接口已经支撑的后台菜单,模板演示入口等后续补接口后再放开。
|
||||||
|
return filterSupportedAdminMenus(menus);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import type { Recordable } from '@vben/types';
|
|||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
import { isSupportedAdminMenuName } from '../core/menu';
|
||||||
|
|
||||||
export namespace SystemMenuApi {
|
export namespace SystemMenuApi {
|
||||||
/** 徽标颜色集合 */
|
/** 徽标颜色集合 */
|
||||||
export const BadgeVariants = [
|
export const BadgeVariants = [
|
||||||
@ -90,13 +92,35 @@ export namespace SystemMenuApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filterSupportedSystemMenus(
|
||||||
|
menus: SystemMenuApi.SystemMenu[],
|
||||||
|
): SystemMenuApi.SystemMenu[] {
|
||||||
|
return menus
|
||||||
|
.map((menu) => {
|
||||||
|
const children = menu.children
|
||||||
|
? filterSupportedSystemMenus(menu.children)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...menu,
|
||||||
|
...(children && children.length > 0 ? { children } : {}),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(
|
||||||
|
(menu) => isSupportedAdminMenuName(menu.name) || !!menu.children?.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取菜单数据列表
|
* 获取菜单数据列表
|
||||||
*/
|
*/
|
||||||
async function getMenuList() {
|
async function getMenuList() {
|
||||||
return requestClient.get<Array<SystemMenuApi.SystemMenu>>(
|
const menus =
|
||||||
'/system/menu/list',
|
await requestClient.get<Array<SystemMenuApi.SystemMenu>>(
|
||||||
);
|
'/system/menu/list',
|
||||||
|
);
|
||||||
|
|
||||||
|
return filterSupportedSystemMenus(menus);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isMenuNameExists(
|
async function isMenuNameExists(
|
||||||
|
|||||||
@ -1,24 +1,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { NotificationItem } from '@vben/layouts';
|
import { computed, onBeforeMount, watch } from 'vue';
|
||||||
|
|
||||||
import { computed, onBeforeMount, ref, watch } from 'vue';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
|
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
|
||||||
import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
|
|
||||||
import { useWatermark } from '@vben/hooks';
|
import { useWatermark } from '@vben/hooks';
|
||||||
import { BookOpenText, CircleHelp, SvgGithubIcon } from '@vben/icons';
|
import { BasicLayout, LockScreen, UserDropdown } from '@vben/layouts';
|
||||||
import {
|
|
||||||
BasicLayout,
|
|
||||||
LockScreen,
|
|
||||||
Notification,
|
|
||||||
UserDropdown,
|
|
||||||
} from '@vben/layouts';
|
|
||||||
import { preferences } from '@vben/preferences';
|
import { preferences } from '@vben/preferences';
|
||||||
import { useAccessStore, useTabbarStore, useUserStore } from '@vben/stores';
|
import { useAccessStore, useTabbarStore, useUserStore } from '@vben/stores';
|
||||||
import { openWindow } from '@vben/utils';
|
|
||||||
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
import { useAuthStore } from '#/store';
|
import { useAuthStore } from '#/store';
|
||||||
import LoginForm from '#/views/_core/authentication/login.vue';
|
import LoginForm from '#/views/_core/authentication/login.vue';
|
||||||
|
|
||||||
@ -35,104 +23,10 @@ setMenuList([
|
|||||||
'close-all',
|
'close-all',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const notifications = ref<NotificationItem[]>([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
avatar: 'https://avatar.vercel.sh/vercel.svg?text=VB',
|
|
||||||
date: '3小时前',
|
|
||||||
isRead: true,
|
|
||||||
message: '描述信息描述信息描述信息',
|
|
||||||
title: '收到了 14 份新周报',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
avatar: 'https://avatar.vercel.sh/1',
|
|
||||||
date: '刚刚',
|
|
||||||
isRead: false,
|
|
||||||
message: '描述信息描述信息描述信息',
|
|
||||||
title: '朱偏右 回复了你',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
avatar: 'https://avatar.vercel.sh/1',
|
|
||||||
date: '2024-01-01',
|
|
||||||
isRead: false,
|
|
||||||
message: '描述信息描述信息描述信息',
|
|
||||||
title: '曲丽丽 评论了你',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
avatar: 'https://avatar.vercel.sh/satori',
|
|
||||||
date: '1天前',
|
|
||||||
isRead: false,
|
|
||||||
message: '描述信息描述信息描述信息',
|
|
||||||
title: '代办提醒',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
avatar: 'https://avatar.vercel.sh/satori',
|
|
||||||
date: '1天前',
|
|
||||||
isRead: false,
|
|
||||||
message: '描述信息描述信息描述信息',
|
|
||||||
title: '跳转Workspace示例',
|
|
||||||
link: '/workspace',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
avatar: 'https://avatar.vercel.sh/satori',
|
|
||||||
date: '1天前',
|
|
||||||
isRead: false,
|
|
||||||
message: '描述信息描述信息描述信息',
|
|
||||||
title: '跳转外部链接示例',
|
|
||||||
link: 'https://doc.vben.pro',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const accessStore = useAccessStore();
|
const accessStore = useAccessStore();
|
||||||
const { destroyWatermark, updateWatermark } = useWatermark();
|
const { destroyWatermark, updateWatermark } = useWatermark();
|
||||||
const showDot = computed(() =>
|
|
||||||
notifications.value.some((item) => !item.isRead),
|
|
||||||
);
|
|
||||||
|
|
||||||
const menus = computed(() => [
|
|
||||||
{
|
|
||||||
handler: () => {
|
|
||||||
router.push({ name: 'Profile' });
|
|
||||||
},
|
|
||||||
icon: 'lucide:user',
|
|
||||||
text: $t('page.auth.profile'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handler: () => {
|
|
||||||
openWindow(VBEN_DOC_URL, {
|
|
||||||
target: '_blank',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon: BookOpenText,
|
|
||||||
text: $t('ui.widgets.document'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handler: () => {
|
|
||||||
openWindow(VBEN_GITHUB_URL, {
|
|
||||||
target: '_blank',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon: SvgGithubIcon,
|
|
||||||
text: 'GitHub',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
handler: () => {
|
|
||||||
openWindow(`${VBEN_GITHUB_URL}/issues`, {
|
|
||||||
target: '_blank',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon: CircleHelp,
|
|
||||||
text: $t('ui.widgets.qa'),
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const avatar = computed(() => {
|
const avatar = computed(() => {
|
||||||
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
|
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
|
||||||
@ -142,25 +36,6 @@ async function handleLogout() {
|
|||||||
await authStore.logout(false);
|
await authStore.logout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleNoticeClear() {
|
|
||||||
notifications.value = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
function markRead(id: number | string) {
|
|
||||||
const item = notifications.value.find((item) => item.id === id);
|
|
||||||
if (item) {
|
|
||||||
item.isRead = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove(id: number | string) {
|
|
||||||
notifications.value = notifications.value.filter((item) => item.id !== id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMakeAll() {
|
|
||||||
notifications.value.forEach((item) => (item.isRead = true));
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleClickLogo() {}
|
function handleClickLogo() {}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -199,24 +74,12 @@ onBeforeMount(() => {
|
|||||||
<template #user-dropdown>
|
<template #user-dropdown>
|
||||||
<UserDropdown
|
<UserDropdown
|
||||||
:avatar
|
:avatar
|
||||||
:menus
|
:description="userStore.userInfo?.username"
|
||||||
:text="userStore.userInfo?.realName"
|
:text="userStore.userInfo?.realName"
|
||||||
description="ann.vben@gmail.com"
|
|
||||||
tag-text="Pro"
|
|
||||||
trigger="both"
|
trigger="both"
|
||||||
@logout="handleLogout"
|
@logout="handleLogout"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #notification>
|
|
||||||
<Notification
|
|
||||||
:dot="showDot"
|
|
||||||
:notifications="notifications"
|
|
||||||
@clear="handleNoticeClear"
|
|
||||||
@read="(item) => item.id && markRead(item.id)"
|
|
||||||
@remove="(item) => item.id && remove(item.id)"
|
|
||||||
@make-all="handleMakeAll"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<AuthenticationLoginExpiredModal
|
<AuthenticationLoginExpiredModal
|
||||||
v-model:open="accessStore.loginExpired"
|
v-model:open="accessStore.loginExpired"
|
||||||
|
|||||||
@ -8,7 +8,12 @@ import { defineOverridesPreferences } from '@vben/preferences';
|
|||||||
export const overridesPreferences = defineOverridesPreferences({
|
export const overridesPreferences = defineOverridesPreferences({
|
||||||
// overrides
|
// overrides
|
||||||
app: {
|
app: {
|
||||||
|
accessMode: 'backend',
|
||||||
|
defaultHomePath: '/system/role',
|
||||||
enableRefreshToken: true,
|
enableRefreshToken: true,
|
||||||
name: import.meta.env.VITE_APP_TITLE,
|
name: import.meta.env.VITE_APP_TITLE,
|
||||||
},
|
},
|
||||||
|
widget: {
|
||||||
|
notification: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -42,6 +42,7 @@ const componentKeys: string[] = Object.keys(
|
|||||||
.map((v) => {
|
.map((v) => {
|
||||||
const path = v.replace('../../views/', '/');
|
const path = v.replace('../../views/', '/');
|
||||||
return path.endsWith('.vue') ? path.slice(0, -4) : path;
|
return path.endsWith('.vue') ? path.slice(0, -4) : path;
|
||||||
});
|
})
|
||||||
|
.filter((path) => path.startsWith('/system/'));
|
||||||
|
|
||||||
export { accessRoutes, componentKeys, coreRouteNames, routes };
|
export { accessRoutes, componentKeys, coreRouteNames, routes };
|
||||||
|
|||||||
81
cspell.json
81
cspell.json
@ -1,81 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
|
|
||||||
"version": "0.2",
|
|
||||||
"language": "en,en-US",
|
|
||||||
"allowCompoundWords": true,
|
|
||||||
"words": [
|
|
||||||
"acmr",
|
|
||||||
"antd",
|
|
||||||
"antdv",
|
|
||||||
"archiver",
|
|
||||||
"astro",
|
|
||||||
"axios",
|
|
||||||
"brotli",
|
|
||||||
"cascader",
|
|
||||||
"clsx",
|
|
||||||
"defu",
|
|
||||||
"demi",
|
|
||||||
"dotenv",
|
|
||||||
"echarts",
|
|
||||||
"ependencies",
|
|
||||||
"esbuild",
|
|
||||||
"esno",
|
|
||||||
"etag",
|
|
||||||
"execa",
|
|
||||||
"iconify",
|
|
||||||
"iconoir",
|
|
||||||
"intlify",
|
|
||||||
"isequal",
|
|
||||||
"jspm",
|
|
||||||
"lockb",
|
|
||||||
"lucide",
|
|
||||||
"minh",
|
|
||||||
"minw",
|
|
||||||
"mkdist",
|
|
||||||
"mockjs",
|
|
||||||
"naiveui",
|
|
||||||
"napi",
|
|
||||||
"nocheck",
|
|
||||||
"nolebase",
|
|
||||||
"noopener",
|
|
||||||
"noreferrer",
|
|
||||||
"nprogress",
|
|
||||||
"nuxt",
|
|
||||||
"pinia",
|
|
||||||
"prefixs",
|
|
||||||
"publint",
|
|
||||||
"qrcode",
|
|
||||||
"reka",
|
|
||||||
"rollup",
|
|
||||||
"shadcn",
|
|
||||||
"sonner",
|
|
||||||
"sortablejs",
|
|
||||||
"styl",
|
|
||||||
"taze",
|
|
||||||
"tdesign",
|
|
||||||
"ui-kit",
|
|
||||||
"uicons",
|
|
||||||
"unplugin",
|
|
||||||
"unref",
|
|
||||||
"vben",
|
|
||||||
"vbenjs",
|
|
||||||
"vite",
|
|
||||||
"vitejs",
|
|
||||||
"vitepress",
|
|
||||||
"vitest",
|
|
||||||
"vnode",
|
|
||||||
"vueuse",
|
|
||||||
"yxxx"
|
|
||||||
],
|
|
||||||
"ignorePaths": [
|
|
||||||
"**/*-dist/**",
|
|
||||||
"**/*.log",
|
|
||||||
"**/*.spec.ts",
|
|
||||||
"**/*.test.ts",
|
|
||||||
"**/__tests__/**",
|
|
||||||
"**/dist/**",
|
|
||||||
"**/icons/**",
|
|
||||||
"**/node_modules/**",
|
|
||||||
"pnpm-lock.yaml"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
35
deploy/nginx-admin.conf
Normal file
35
deploy/nginx-admin.conf
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
server {
|
||||||
|
listen 5999;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html/admin;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
|
||||||
|
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control "no-store";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://192.168.31.224:48085/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,153 +0,0 @@
|
|||||||
import { execSync } from 'node:child_process';
|
|
||||||
|
|
||||||
import { getPackagesSync } from '@vben/node-utils';
|
|
||||||
|
|
||||||
const { packages } = getPackagesSync();
|
|
||||||
|
|
||||||
const allowedScopes = [
|
|
||||||
...packages.map((pkg) => pkg.packageJson.name),
|
|
||||||
'project',
|
|
||||||
'style',
|
|
||||||
'lint',
|
|
||||||
'ci',
|
|
||||||
'dev',
|
|
||||||
'deploy',
|
|
||||||
'other',
|
|
||||||
];
|
|
||||||
|
|
||||||
// precomputed scope
|
|
||||||
const scopeComplete = execSync('git status --porcelain || true')
|
|
||||||
.toString()
|
|
||||||
.trim()
|
|
||||||
.split('\n')
|
|
||||||
.find((r) => ~r.indexOf('M src'))
|
|
||||||
?.replaceAll(/(\/)/g, '%%')
|
|
||||||
?.match(/src%%((\w|-)*)/)?.[1]
|
|
||||||
?.replace(/s$/, '');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {import('cz-git').UserConfig}
|
|
||||||
*/
|
|
||||||
const userConfig = {
|
|
||||||
extends: ['@commitlint/config-conventional'],
|
|
||||||
plugins: ['commitlint-plugin-function-rules'],
|
|
||||||
prompt: {
|
|
||||||
/** @use `pnpm commit :f` */
|
|
||||||
alias: {
|
|
||||||
b: 'build: bump dependencies',
|
|
||||||
c: 'chore: update config',
|
|
||||||
f: 'docs: fix typos',
|
|
||||||
r: 'docs: update README',
|
|
||||||
s: 'style: update code format',
|
|
||||||
},
|
|
||||||
allowCustomIssuePrefixs: false,
|
|
||||||
// scopes: [...scopes, 'mock'],
|
|
||||||
allowEmptyIssuePrefixs: false,
|
|
||||||
customScopesAlign: scopeComplete ? 'bottom' : 'top',
|
|
||||||
defaultScope: scopeComplete,
|
|
||||||
// English
|
|
||||||
typesAppend: [
|
|
||||||
{ name: 'workflow: workflow improvements', value: 'workflow' },
|
|
||||||
{ name: 'types: type definition file changes', value: 'types' },
|
|
||||||
],
|
|
||||||
|
|
||||||
// 中英文对照版
|
|
||||||
// messages: {
|
|
||||||
// type: '选择你要提交的类型 :',
|
|
||||||
// scope: '选择一个提交范围 (可选):',
|
|
||||||
// customScope: '请输入自定义的提交范围 :',
|
|
||||||
// subject: '填写简短精炼的变更描述 :\n',
|
|
||||||
// body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
|
|
||||||
// breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
|
|
||||||
// footerPrefixsSelect: '选择关联issue前缀 (可选):',
|
|
||||||
// customFooterPrefixs: '输入自定义issue前缀 :',
|
|
||||||
// footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
|
|
||||||
// confirmCommit: '是否提交或修改commit ?',
|
|
||||||
// },
|
|
||||||
// types: [
|
|
||||||
// { value: 'feat', name: 'feat: 新增功能' },
|
|
||||||
// { value: 'fix', name: 'fix: 修复缺陷' },
|
|
||||||
// { value: 'docs', name: 'docs: 文档变更' },
|
|
||||||
// { value: 'style', name: 'style: 代码格式' },
|
|
||||||
// { value: 'refactor', name: 'refactor: 代码重构' },
|
|
||||||
// { value: 'perf', name: 'perf: 性能优化' },
|
|
||||||
// { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
|
|
||||||
// { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
|
|
||||||
// { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
|
|
||||||
// { value: 'revert', name: 'revert: 回滚 commit' },
|
|
||||||
// { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
|
|
||||||
// { value: 'wip', name: 'wip: 正在开发中' },
|
|
||||||
// { value: 'workflow', name: 'workflow: 工作流程改进' },
|
|
||||||
// { value: 'types', name: 'types: 类型定义文件修改' },
|
|
||||||
// ],
|
|
||||||
// emptyScopesAlias: 'empty: 不填写',
|
|
||||||
// customScopesAlias: 'custom: 自定义',
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
/**
|
|
||||||
* type[scope]: [function] description
|
|
||||||
*
|
|
||||||
* ^^^^^^^^^^^^^^ empty line.
|
|
||||||
* - Something here
|
|
||||||
*/
|
|
||||||
'body-leading-blank': [2, 'always'],
|
|
||||||
/**
|
|
||||||
* type[scope]: [function] description
|
|
||||||
*
|
|
||||||
* - something here
|
|
||||||
*
|
|
||||||
* ^^^^^^^^^^^^^^
|
|
||||||
*/
|
|
||||||
'footer-leading-blank': [1, 'always'],
|
|
||||||
/**
|
|
||||||
* type[scope]: [function] description
|
|
||||||
* ^^^^^
|
|
||||||
*/
|
|
||||||
'function-rules/scope-enum': [
|
|
||||||
2, // level: error
|
|
||||||
'always',
|
|
||||||
(parsed) => {
|
|
||||||
if (!parsed.scope || allowedScopes.includes(parsed.scope)) {
|
|
||||||
return [true];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [false, `scope must be one of ${allowedScopes.join(', ')}`];
|
|
||||||
},
|
|
||||||
],
|
|
||||||
/**
|
|
||||||
* type[scope]: [function] description [No more than 108 characters]
|
|
||||||
* ^^^^^
|
|
||||||
*/
|
|
||||||
'header-max-length': [2, 'always', 108],
|
|
||||||
|
|
||||||
'scope-enum': [0],
|
|
||||||
'subject-case': [0],
|
|
||||||
'subject-empty': [2, 'never'],
|
|
||||||
'type-empty': [2, 'never'],
|
|
||||||
/**
|
|
||||||
* type[scope]: [function] description
|
|
||||||
* ^^^^
|
|
||||||
*/
|
|
||||||
'type-enum': [
|
|
||||||
2,
|
|
||||||
'always',
|
|
||||||
[
|
|
||||||
'feat',
|
|
||||||
'fix',
|
|
||||||
'perf',
|
|
||||||
'style',
|
|
||||||
'docs',
|
|
||||||
'test',
|
|
||||||
'refactor',
|
|
||||||
'build',
|
|
||||||
'ci',
|
|
||||||
'chore',
|
|
||||||
'revert',
|
|
||||||
'types',
|
|
||||||
'release',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default userConfig;
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@vben/commitlint-config",
|
|
||||||
"version": "5.6.0",
|
|
||||||
"private": true,
|
|
||||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
|
||||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
|
|
||||||
"directory": "internal/lint-configs/commitlint-config"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"type": "module",
|
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"main": "./index.mjs",
|
|
||||||
"module": "./index.mjs",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"import": "./index.mjs",
|
|
||||||
"default": "./index.mjs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@commitlint/cli": "catalog:",
|
|
||||||
"@commitlint/config-conventional": "catalog:",
|
|
||||||
"@vben/node-utils": "workspace:*",
|
|
||||||
"commitlint-plugin-function-rules": "catalog:",
|
|
||||||
"cz-git": "catalog:",
|
|
||||||
"czg": "catalog:"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -27,7 +27,6 @@ export async function ignores(): Promise<Linter.Config[]> {
|
|||||||
'**/.nuxt',
|
'**/.nuxt',
|
||||||
'**/.next',
|
'**/.next',
|
||||||
'**/.vercel',
|
'**/.vercel',
|
||||||
'**/.changeset',
|
|
||||||
'**/.idea',
|
'**/.idea',
|
||||||
'**/.cache',
|
'**/.cache',
|
||||||
'**/.output',
|
'**/.output',
|
||||||
|
|||||||
@ -48,7 +48,6 @@ export async function jsonc(): Promise<Linter.Config[]> {
|
|||||||
},
|
},
|
||||||
sortTsconfig(),
|
sortTsconfig(),
|
||||||
sortPackageJson(),
|
sortPackageJson(),
|
||||||
sortCspellJson(),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,21 +130,6 @@ function sortPackageJson(): Linter.Config {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortCspellJson(): Linter.Config {
|
|
||||||
return {
|
|
||||||
files: ['**/cspell.json', '**/.cspell.json'],
|
|
||||||
rules: {
|
|
||||||
'jsonc/sort-array-values': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
order: { type: 'asc' },
|
|
||||||
pathPattern: '^words$|^ignorePaths$',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortTsconfig(): Linter.Config {
|
function sortTsconfig(): Linter.Config {
|
||||||
return {
|
return {
|
||||||
files: [
|
files: [
|
||||||
|
|||||||
@ -45,10 +45,7 @@ export async function node(): Promise<Linter.Config[]> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: ['internal/**/*.?([cm])[jt]s?(x)'],
|
||||||
'scripts/**/*.?([cm])[jt]s?(x)',
|
|
||||||
'internal/**/*.?([cm])[jt]s?(x)',
|
|
||||||
],
|
|
||||||
rules: {
|
rules: {
|
||||||
'n/prefer-global/process': 'off',
|
'n/prefer-global/process': 'off',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -33,10 +33,7 @@ export async function unicorn(): Promise<Linter.Config[]> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: [
|
files: ['internal/**/*.?([cm])[jt]s?(x)'],
|
||||||
'scripts/**/*.?([cm])[jt]s?(x)',
|
|
||||||
'internal/**/*.?([cm])[jt]s?(x)',
|
|
||||||
],
|
|
||||||
rules: {
|
rules: {
|
||||||
'unicorn/no-process-exit': 'off',
|
'unicorn/no-process-exit': 'off',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -158,7 +158,7 @@ const customConfig: Linter.Config[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['internal/**/**', 'scripts/**/**'],
|
files: ['internal/**/**'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': 'off',
|
'no-console': 'off',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -28,7 +28,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@changesets/git": "catalog:",
|
|
||||||
"@manypkg/get-packages": "catalog:",
|
"@manypkg/get-packages": "catalog:",
|
||||||
"chalk": "catalog:",
|
"chalk": "catalog:",
|
||||||
"consola": "catalog:",
|
"consola": "catalog:",
|
||||||
|
|||||||
@ -2,8 +2,6 @@ import path from 'node:path';
|
|||||||
|
|
||||||
import { execa } from 'execa';
|
import { execa } from 'execa';
|
||||||
|
|
||||||
export * from '@changesets/git';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取暂存区文件
|
* 获取暂存区文件
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -2,7 +2,6 @@ export * from './constants';
|
|||||||
export * from './date';
|
export * from './date';
|
||||||
export * from './fs';
|
export * from './fs';
|
||||||
export * from './git';
|
export * from './git';
|
||||||
export { getStagedFiles, add as gitAdd } from './git';
|
|
||||||
export { generatorContentHash } from './hash';
|
export { generatorContentHash } from './hash';
|
||||||
export * from './monorepo';
|
export * from './monorepo';
|
||||||
export { toPosixPath } from './path';
|
export { toPosixPath } from './path';
|
||||||
|
|||||||
60
package.json
60
package.json
@ -1,83 +1,45 @@
|
|||||||
{
|
{
|
||||||
"name": "vben-admin-monorepo",
|
"name": "kt-template-admin",
|
||||||
"version": "5.5.9",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"keywords": [
|
|
||||||
"monorepo",
|
|
||||||
"turbo",
|
|
||||||
"vben",
|
|
||||||
"vben admin",
|
|
||||||
"vben pro",
|
|
||||||
"vue",
|
|
||||||
"vue admin",
|
|
||||||
"vue vben admin",
|
|
||||||
"vue vben admin pro",
|
|
||||||
"vue3"
|
|
||||||
],
|
|
||||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
|
||||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
|
||||||
"repository": "vbenjs/vue-vben-admin.git",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": {
|
|
||||||
"name": "vben",
|
|
||||||
"email": "ann.vben@gmail.com",
|
|
||||||
"url": "https://github.com/anncwb"
|
|
||||||
},
|
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
|
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
|
||||||
"build:analyze": "turbo build:analyze",
|
"build:analyze": "turbo build:analyze",
|
||||||
"build:antdv-next": "pnpm run build --filter=@vben/web-antdv-next",
|
"build:antdv-next": "pnpm run build --filter=@vben/web-antdv-next",
|
||||||
"build:docker": "./scripts/deploy/build-local-docker-image.sh",
|
"check": "pnpm run check:type",
|
||||||
"changeset": "pnpm exec changeset",
|
|
||||||
"check": "pnpm run check:circular && pnpm run check:dep && pnpm run check:type && pnpm check:cspell",
|
|
||||||
"check:circular": "vsh check-circular",
|
|
||||||
"check:cspell": "cspell lint **/*.ts **/README.md .changeset/*.md --no-progress",
|
|
||||||
"check:dep": "vsh check-dep",
|
|
||||||
"check:type": "turbo run typecheck",
|
"check:type": "turbo run typecheck",
|
||||||
"clean": "node ./scripts/clean.mjs",
|
"clean": "rimraf .turbo apps/*/dist apps/*/dist.zip packages/**/dist packages/**/dist.zip internal/**/dist internal/**/dist.zip",
|
||||||
"commit": "czg",
|
"dev": "pnpm run dev:antdv-next",
|
||||||
"dev": "turbo-run dev",
|
|
||||||
"dev:antdv-next": "pnpm -F @vben/web-antdv-next run dev",
|
"dev:antdv-next": "pnpm -F @vben/web-antdv-next run dev",
|
||||||
"format": "vsh lint --format",
|
"format": "eslint apps/web-antdv-next internal --cache --fix && prettier . --write --cache --log-level warn && stylelint \"**/*.{vue,css,less,scss}\" --cache --fix",
|
||||||
"lint": "vsh lint",
|
"lint": "eslint apps/web-antdv-next internal --cache && prettier . --ignore-unknown --check --cache && stylelint \"**/*.{vue,css,less,scss}\" --cache",
|
||||||
"lint:commit": "eslint apps/web-antdv-next scripts/validate-commit-msg.mjs --cache",
|
"lint:commit": "eslint apps/web-antdv-next internal/commit/validate-commit-msg.mjs --cache",
|
||||||
"postinstall": "pnpm -r run stub --if-present",
|
"postinstall": "pnpm -r run stub --if-present",
|
||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
"preview": "turbo-run preview",
|
"preview": "pnpm -F @vben/web-antdv-next run preview",
|
||||||
"publint": "vsh publint",
|
"reinstall": "pnpm run clean && rimraf pnpm-lock.yaml && pnpm install",
|
||||||
"reinstall": "pnpm clean --del-lock && pnpm install",
|
|
||||||
"test:unit": "vitest run --dom",
|
|
||||||
"verify:commit": "pnpm run lint:commit && pnpm -F @vben/web-antdv-next run typecheck",
|
"verify:commit": "pnpm run lint:commit && pnpm -F @vben/web-antdv-next run typecheck",
|
||||||
"test:e2e": "turbo run test:e2e",
|
"test:e2e": "turbo run test:e2e"
|
||||||
"update:deps": "npx taze -r -w",
|
|
||||||
"version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile",
|
|
||||||
"catalog": "pnpx codemod pnpm/catalog"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@changesets/changelog-github": "catalog:",
|
|
||||||
"@changesets/cli": "catalog:",
|
|
||||||
"@playwright/test": "catalog:",
|
"@playwright/test": "catalog:",
|
||||||
"@types/node": "catalog:",
|
"@types/node": "catalog:",
|
||||||
"@vben/commitlint-config": "workspace:*",
|
|
||||||
"@vben/eslint-config": "workspace:*",
|
"@vben/eslint-config": "workspace:*",
|
||||||
"@vben/prettier-config": "workspace:*",
|
"@vben/prettier-config": "workspace:*",
|
||||||
"@vben/stylelint-config": "workspace:*",
|
"@vben/stylelint-config": "workspace:*",
|
||||||
"@vben/tailwind-config": "workspace:*",
|
"@vben/tailwind-config": "workspace:*",
|
||||||
"@vben/tsconfig": "workspace:*",
|
"@vben/tsconfig": "workspace:*",
|
||||||
"@vben/turbo-run": "workspace:*",
|
|
||||||
"@vben/vite-config": "workspace:*",
|
"@vben/vite-config": "workspace:*",
|
||||||
"@vben/vsh": "workspace:*",
|
|
||||||
"@vitejs/plugin-vue": "catalog:",
|
"@vitejs/plugin-vue": "catalog:",
|
||||||
"@vitejs/plugin-vue-jsx": "catalog:",
|
"@vitejs/plugin-vue-jsx": "catalog:",
|
||||||
"@vue/test-utils": "catalog:",
|
"@vue/test-utils": "catalog:",
|
||||||
"autoprefixer": "catalog:",
|
"autoprefixer": "catalog:",
|
||||||
"cross-env": "catalog:",
|
"cross-env": "catalog:",
|
||||||
"cspell": "catalog:",
|
|
||||||
"happy-dom": "catalog:",
|
"happy-dom": "catalog:",
|
||||||
"husky": "catalog:",
|
"husky": "catalog:",
|
||||||
"is-ci": "catalog:",
|
|
||||||
"playwright": "catalog:",
|
"playwright": "catalog:",
|
||||||
"rimraf": "catalog:",
|
"rimraf": "catalog:",
|
||||||
"tailwindcss": "catalog:",
|
"tailwindcss": "catalog:",
|
||||||
|
|||||||
2451
pnpm-lock.yaml
2451
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,6 @@ packages:
|
|||||||
- packages/effects/*
|
- packages/effects/*
|
||||||
- packages/business/*
|
- packages/business/*
|
||||||
- apps/*
|
- apps/*
|
||||||
- scripts/*
|
|
||||||
|
|
||||||
overrides:
|
overrides:
|
||||||
'@ast-grep/napi': 'catalog:'
|
'@ast-grep/napi': 'catalog:'
|
||||||
@ -21,12 +20,6 @@ overrides:
|
|||||||
vue: 'catalog:'
|
vue: 'catalog:'
|
||||||
catalog:
|
catalog:
|
||||||
'@ast-grep/napi': ^0.39.9
|
'@ast-grep/napi': ^0.39.9
|
||||||
'@changesets/changelog-github': ^0.5.2
|
|
||||||
'@changesets/cli': ^2.29.8
|
|
||||||
'@changesets/git': ^3.0.4
|
|
||||||
'@clack/prompts': ^0.11.0
|
|
||||||
'@commitlint/cli': ^19.8.1
|
|
||||||
'@commitlint/config-conventional': ^19.8.1
|
|
||||||
'@ctrl/tinycolor': ^4.2.0
|
'@ctrl/tinycolor': ^4.2.0
|
||||||
'@eslint/js': ^9.39.2
|
'@eslint/js': ^9.39.2
|
||||||
'@faker-js/faker': ^9.9.0
|
'@faker-js/faker': ^9.9.0
|
||||||
@ -71,22 +64,15 @@ catalog:
|
|||||||
autoprefixer: ^10.4.24
|
autoprefixer: ^10.4.24
|
||||||
axios: ^1.13.4
|
axios: ^1.13.4
|
||||||
axios-mock-adapter: ^2.1.0
|
axios-mock-adapter: ^2.1.0
|
||||||
cac: ^6.7.14
|
|
||||||
chalk: ^5.6.2
|
chalk: ^5.6.2
|
||||||
cheerio: ^1.2.0
|
cheerio: ^1.2.0
|
||||||
circular-dependency-scanner: ^2.3.0
|
|
||||||
class-variance-authority: ^0.7.1
|
class-variance-authority: ^0.7.1
|
||||||
clsx: ^2.1.1
|
clsx: ^2.1.1
|
||||||
commitlint-plugin-function-rules: ^4.3.1
|
|
||||||
consola: ^3.4.2
|
consola: ^3.4.2
|
||||||
cross-env: ^10.1.0
|
cross-env: ^10.1.0
|
||||||
cspell: ^9.6.4
|
|
||||||
cssnano: ^7.1.2
|
cssnano: ^7.1.2
|
||||||
cz-git: ^1.12.0
|
|
||||||
czg: ^1.12.0
|
|
||||||
dayjs: ^1.11.19
|
dayjs: ^1.11.19
|
||||||
defu: ^6.1.4
|
defu: ^6.1.4
|
||||||
depcheck: ^1.4.7
|
|
||||||
dotenv: ^16.6.1
|
dotenv: ^16.6.1
|
||||||
echarts: ^6.0.0
|
echarts: ^6.0.0
|
||||||
es-toolkit: ^1.44.0
|
es-toolkit: ^1.44.0
|
||||||
@ -117,7 +103,6 @@ catalog:
|
|||||||
happy-dom: ^17.6.3
|
happy-dom: ^17.6.3
|
||||||
husky: ^9.1.7
|
husky: ^9.1.7
|
||||||
html-minifier-terser: ^7.2.0
|
html-minifier-terser: ^7.2.0
|
||||||
is-ci: ^4.1.0
|
|
||||||
jiti: ^2.6.1
|
jiti: ^2.6.1
|
||||||
json-bigint: ^1.0.0
|
json-bigint: ^1.0.0
|
||||||
jsonc-eslint-parser: ^2.4.2
|
jsonc-eslint-parser: ^2.4.2
|
||||||
@ -140,7 +125,6 @@ catalog:
|
|||||||
postcss-scss: ^4.0.9
|
postcss-scss: ^4.0.9
|
||||||
prettier: ^3.8.1
|
prettier: ^3.8.1
|
||||||
prettier-plugin-tailwindcss: ^0.7.2
|
prettier-plugin-tailwindcss: ^0.7.2
|
||||||
publint: ^0.3.17
|
|
||||||
qrcode: ^1.5.4
|
qrcode: ^1.5.4
|
||||||
qs: ^6.14.1
|
qs: ^6.14.1
|
||||||
reka-ui: ^2.7.0
|
reka-ui: ^2.7.0
|
||||||
|
|||||||
@ -1,141 +0,0 @@
|
|||||||
import { promises as fs } from 'node:fs';
|
|
||||||
import { join, normalize } from 'node:path';
|
|
||||||
|
|
||||||
const rootDir = process.cwd();
|
|
||||||
|
|
||||||
// 控制并发数量,避免创建过多的并发任务
|
|
||||||
const CONCURRENCY_LIMIT = 10;
|
|
||||||
|
|
||||||
// 需要跳过的目录,避免进入这些目录进行清理
|
|
||||||
const SKIP_DIRS = new Set(['.DS_Store', '.git', '.idea', '.vscode']);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理单个文件/目录项
|
|
||||||
* @param {string} currentDir - 当前目录路径
|
|
||||||
* @param {string} item - 文件/目录名
|
|
||||||
* @param {string[]} targets - 要删除的目标列表
|
|
||||||
* @param {number} _depth - 当前递归深度
|
|
||||||
* @returns {Promise<boolean>} - 是否需要进一步递归处理
|
|
||||||
*/
|
|
||||||
async function processItem(currentDir, item, targets, _depth) {
|
|
||||||
// 跳过特殊目录
|
|
||||||
if (SKIP_DIRS.has(item)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const itemPath = normalize(join(currentDir, item));
|
|
||||||
|
|
||||||
if (targets.includes(item)) {
|
|
||||||
// 匹配到目标目录或文件时直接删除
|
|
||||||
await fs.rm(itemPath, { force: true, recursive: true });
|
|
||||||
console.log(`✅ Deleted: ${itemPath}`);
|
|
||||||
return false; // 已删除,无需递归
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 readdir 的 withFileTypes 选项,避免额外的 lstat 调用
|
|
||||||
return true; // 可能需要递归,由调用方决定
|
|
||||||
} catch (error) {
|
|
||||||
// 更详细的错误信息
|
|
||||||
if (error.code === 'ENOENT') {
|
|
||||||
// 文件不存在,可能已被删除,这是正常情况
|
|
||||||
return false;
|
|
||||||
} else if (error.code === 'EPERM' || error.code === 'EACCES') {
|
|
||||||
console.error(`❌ Permission denied: ${item} in ${currentDir}`);
|
|
||||||
} else {
|
|
||||||
console.error(
|
|
||||||
`❌ Error handling item ${item} in ${currentDir}: ${error.message}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 递归查找并删除目标目录(并发优化版本)
|
|
||||||
* @param {string} currentDir - 当前遍历的目录路径
|
|
||||||
* @param {string[]} targets - 要删除的目标列表
|
|
||||||
* @param {number} depth - 当前递归深度,避免过深递归
|
|
||||||
*/
|
|
||||||
async function cleanTargetsRecursively(currentDir, targets, depth = 0) {
|
|
||||||
// 限制递归深度,避免无限递归
|
|
||||||
if (depth > 10) {
|
|
||||||
console.warn(`Max recursion depth reached at: ${currentDir}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dirents;
|
|
||||||
try {
|
|
||||||
// 使用 withFileTypes 选项,一次性获取文件类型信息,避免后续 lstat 调用
|
|
||||||
dirents = await fs.readdir(currentDir, { withFileTypes: true });
|
|
||||||
} catch (error) {
|
|
||||||
// 如果无法读取目录,可能已被删除或权限不足
|
|
||||||
console.warn(`Cannot read directory ${currentDir}: ${error.message}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分批处理,控制并发数量
|
|
||||||
for (let i = 0; i < dirents.length; i += CONCURRENCY_LIMIT) {
|
|
||||||
const batch = dirents.slice(i, i + CONCURRENCY_LIMIT);
|
|
||||||
|
|
||||||
const tasks = batch.map(async (dirent) => {
|
|
||||||
const item = dirent.name;
|
|
||||||
const shouldRecurse = await processItem(currentDir, item, targets, depth);
|
|
||||||
|
|
||||||
// 如果是目录且没有被删除,则递归处理
|
|
||||||
if (shouldRecurse && dirent.isDirectory()) {
|
|
||||||
const itemPath = normalize(join(currentDir, item));
|
|
||||||
return cleanTargetsRecursively(itemPath, targets, depth + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 并发执行当前批次的任务
|
|
||||||
const results = await Promise.allSettled(tasks);
|
|
||||||
|
|
||||||
// 检查是否有失败的任务(可选:用于调试)
|
|
||||||
const failedTasks = results.filter(
|
|
||||||
(result) => result.status === 'rejected',
|
|
||||||
);
|
|
||||||
if (failedTasks.length > 0) {
|
|
||||||
console.warn(
|
|
||||||
`${failedTasks.length} tasks failed in batch starting at index ${i} in directory: ${currentDir}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(async function startCleanup() {
|
|
||||||
// 要删除的目录及文件名称
|
|
||||||
const targets = ['node_modules', 'dist', '.turbo', 'dist.zip'];
|
|
||||||
const deleteLockFile = process.argv.includes('--del-lock');
|
|
||||||
const cleanupTargets = [...targets];
|
|
||||||
|
|
||||||
if (deleteLockFile) {
|
|
||||||
cleanupTargets.push('pnpm-lock.yaml');
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`🚀 Starting cleanup of targets: ${cleanupTargets.join(', ')} from root: ${rootDir}`,
|
|
||||||
);
|
|
||||||
|
|
||||||
const startTime = Date.now();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 先统计要删除的目标数量
|
|
||||||
console.log('📊 Scanning for cleanup targets...');
|
|
||||||
|
|
||||||
await cleanTargetsRecursively(rootDir, cleanupTargets);
|
|
||||||
|
|
||||||
const endTime = Date.now();
|
|
||||||
const duration = (endTime - startTime) / 1000;
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`✨ Cleanup process completed successfully in ${duration.toFixed(2)}s`,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`💥 Unexpected error during cleanup: ${error.message}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
FROM node:22-slim AS builder
|
|
||||||
|
|
||||||
# --max-old-space-size
|
|
||||||
ENV PNPM_HOME="/pnpm"
|
|
||||||
ENV PATH="$PNPM_HOME:$PATH"
|
|
||||||
ENV NODE_OPTIONS=--max-old-space-size=8192
|
|
||||||
ENV TZ=Asia/Shanghai
|
|
||||||
|
|
||||||
RUN npm i -g corepack
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# copy package.json and pnpm-lock.yaml to workspace
|
|
||||||
COPY . /app
|
|
||||||
|
|
||||||
# 安装依赖
|
|
||||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
|
||||||
RUN pnpm run build --filter=\!./docs
|
|
||||||
|
|
||||||
RUN echo "Builder Success 🎉"
|
|
||||||
|
|
||||||
FROM nginx:stable-alpine AS production
|
|
||||||
|
|
||||||
# 配置 nginx
|
|
||||||
RUN echo "types { application/javascript js mjs; }" > /etc/nginx/conf.d/mjs.conf \
|
|
||||||
&& rm -rf /etc/nginx/conf.d/default.conf
|
|
||||||
|
|
||||||
# 复制构建产物
|
|
||||||
COPY --from=builder /app/playground/dist /usr/share/nginx/html
|
|
||||||
|
|
||||||
# 复制 nginx 配置
|
|
||||||
COPY --from=builder /app/scripts/deploy/nginx.conf /etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
|
|
||||||
# 启动 nginx
|
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
|
||||||
LOG_FILE=${SCRIPT_DIR}/build-local-docker-image.log
|
|
||||||
ERROR=""
|
|
||||||
IMAGE_NAME="vben-admin-local"
|
|
||||||
|
|
||||||
function stop_and_remove_container() {
|
|
||||||
# Stop and remove the existing container
|
|
||||||
docker stop ${IMAGE_NAME} >/dev/null 2>&1
|
|
||||||
docker rm ${IMAGE_NAME} >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove_image() {
|
|
||||||
# Remove the existing image
|
|
||||||
docker rmi vben-admin-pro >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
function install_dependencies() {
|
|
||||||
# Install all dependencies
|
|
||||||
cd ${SCRIPT_DIR}
|
|
||||||
pnpm install || ERROR="install_dependencies failed"
|
|
||||||
}
|
|
||||||
|
|
||||||
function build_image() {
|
|
||||||
# build docker
|
|
||||||
docker build ../../ -f Dockerfile -t ${IMAGE_NAME} || ERROR="build_image failed"
|
|
||||||
}
|
|
||||||
|
|
||||||
function log_message() {
|
|
||||||
if [[ ${ERROR} != "" ]];
|
|
||||||
then
|
|
||||||
>&2 echo "build failed, Please check build-local-docker-image.log for more details"
|
|
||||||
>&2 echo "ERROR: ${ERROR}"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "docker image with tag '${IMAGE_NAME}' built sussessfully. Use below sample command to run the container"
|
|
||||||
echo ""
|
|
||||||
echo "docker run -d -p 8010:8080 --name ${IMAGE_NAME} ${IMAGE_NAME}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Info: Stopping and removing existing container and image" | tee ${LOG_FILE}
|
|
||||||
stop_and_remove_container
|
|
||||||
remove_image
|
|
||||||
|
|
||||||
echo "Info: Installing dependencies" | tee -a ${LOG_FILE}
|
|
||||||
install_dependencies 1>> ${LOG_FILE} 2>> ${LOG_FILE}
|
|
||||||
|
|
||||||
if [[ ${ERROR} == "" ]]; then
|
|
||||||
echo "Info: Building docker image" | tee -a ${LOG_FILE}
|
|
||||||
build_image 1>> ${LOG_FILE} 2>> ${LOG_FILE}
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_message | tee -a ${LOG_FILE}
|
|
||||||
@ -1,75 +0,0 @@
|
|||||||
|
|
||||||
#user nobody;
|
|
||||||
worker_processes 1;
|
|
||||||
|
|
||||||
#error_log logs/error.log;
|
|
||||||
#error_log logs/error.log notice;
|
|
||||||
#error_log logs/error.log info;
|
|
||||||
|
|
||||||
#pid logs/nginx.pid;
|
|
||||||
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
http {
|
|
||||||
include mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
types {
|
|
||||||
application/javascript js mjs;
|
|
||||||
text/css css;
|
|
||||||
text/html html;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendfile on;
|
|
||||||
# tcp_nopush on;
|
|
||||||
|
|
||||||
#keepalive_timeout 0;
|
|
||||||
# keepalive_timeout 65;
|
|
||||||
|
|
||||||
# gzip on;
|
|
||||||
# gzip_buffers 32 16k;
|
|
||||||
# gzip_comp_level 6;
|
|
||||||
# gzip_min_length 1k;
|
|
||||||
# gzip_static on;
|
|
||||||
# gzip_types text/plain
|
|
||||||
# text/css
|
|
||||||
# application/javascript
|
|
||||||
# application/json
|
|
||||||
# application/x-javascript
|
|
||||||
# text/xml
|
|
||||||
# application/xml
|
|
||||||
# application/xml+rss
|
|
||||||
# text/javascript; #设置压缩的文件类型
|
|
||||||
# gzip_vary on;
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 8080;
|
|
||||||
server_name localhost;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
index index.html;
|
|
||||||
# Enable CORS
|
|
||||||
add_header 'Access-Control-Allow-Origin' '*';
|
|
||||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
|
||||||
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
|
|
||||||
if ($request_method = 'OPTIONS') {
|
|
||||||
add_header 'Access-Control-Max-Age' 1728000;
|
|
||||||
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
|
||||||
add_header 'Content-Length' 0;
|
|
||||||
return 204;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
|
||||||
|
|
||||||
location = /50x.html {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
# @vben/turbo-run
|
|
||||||
|
|
||||||
`turbo-run` 是一个命令行工具,允许你在多个包中并行运行命令。它提供了一个交互式的界面,让你可以选择要运行命令的包。
|
|
||||||
|
|
||||||
## 特性
|
|
||||||
|
|
||||||
- 🚀 交互式选择要运行的包
|
|
||||||
- 📦 支持 monorepo 项目结构
|
|
||||||
- 🔍 自动检测可用的命令
|
|
||||||
- 🎯 精确过滤目标包
|
|
||||||
|
|
||||||
## 安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm add -D @vben/turbo-run
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用方法
|
|
||||||
|
|
||||||
基本语法:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
turbo-run [script]
|
|
||||||
```
|
|
||||||
|
|
||||||
例如,如果你想运行 `dev` 命令:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
turbo-run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
工具会自动检测哪些包有 `dev` 命令,并提供一个交互式界面让你选择要运行的包。
|
|
||||||
|
|
||||||
## 示例
|
|
||||||
|
|
||||||
假设你的项目中有以下包:
|
|
||||||
|
|
||||||
- `@vben/app`
|
|
||||||
- `@vben/admin`
|
|
||||||
- `@vben/website`
|
|
||||||
|
|
||||||
当你运行:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
turbo-run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
工具会:
|
|
||||||
|
|
||||||
1. 检测哪些包有 `dev` 命令
|
|
||||||
2. 显示一个交互式选择界面
|
|
||||||
3. 让你选择要运行命令的包
|
|
||||||
4. 使用 `pnpm --filter` 在选定的包中运行命令
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
- 确保你的项目使用 pnpm 作为包管理器
|
|
||||||
- 确保目标包在 `package.json` 中定义了相应的脚本命令
|
|
||||||
- 该工具需要在 monorepo 项目的根目录下运行
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
import('../dist/index.mjs');
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
import { defineBuildConfig } from 'unbuild';
|
|
||||||
|
|
||||||
export default defineBuildConfig({
|
|
||||||
clean: true,
|
|
||||||
declaration: true,
|
|
||||||
entries: ['src/index'],
|
|
||||||
});
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@vben/turbo-run",
|
|
||||||
"version": "5.6.0",
|
|
||||||
"private": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"stub": "pnpm unbuild --stub"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"bin": {
|
|
||||||
"turbo-run": "./bin/turbo-run.mjs"
|
|
||||||
},
|
|
||||||
"main": "./dist/index.mjs",
|
|
||||||
"module": "./dist/index.mjs",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"default": "./dist/index.mjs"
|
|
||||||
},
|
|
||||||
"./package.json": "./package.json"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@clack/prompts": "catalog:",
|
|
||||||
"@vben/node-utils": "workspace:*",
|
|
||||||
"cac": "catalog:"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
import { colors, consola } from '@vben/node-utils';
|
|
||||||
|
|
||||||
import { cac } from 'cac';
|
|
||||||
|
|
||||||
import { run } from './run';
|
|
||||||
|
|
||||||
try {
|
|
||||||
const turboRun = cac('turbo-run');
|
|
||||||
|
|
||||||
turboRun
|
|
||||||
.command('[script]')
|
|
||||||
.usage(`Run turbo interactively.`)
|
|
||||||
.action(async (command: string) => {
|
|
||||||
run({ command });
|
|
||||||
});
|
|
||||||
|
|
||||||
// Invalid command
|
|
||||||
turboRun.on('command:*', () => {
|
|
||||||
consola.error(colors.red('Invalid command!'));
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
turboRun.usage('turbo-run');
|
|
||||||
turboRun.help();
|
|
||||||
turboRun.parse();
|
|
||||||
} catch (error) {
|
|
||||||
consola.error(error);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
import { execaCommand, getPackages } from '@vben/node-utils';
|
|
||||||
|
|
||||||
import { cancel, isCancel, select } from '@clack/prompts';
|
|
||||||
|
|
||||||
interface RunOptions {
|
|
||||||
command?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function run(options: RunOptions) {
|
|
||||||
const { command } = options;
|
|
||||||
if (!command) {
|
|
||||||
console.error('Please enter the command to run');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
const { packages } = await getPackages();
|
|
||||||
// const appPkgs = await findApps(process.cwd(), packages);
|
|
||||||
// const websitePkg = packages.find(
|
|
||||||
// (item) => item.packageJson.name === '@vben/website',
|
|
||||||
// );
|
|
||||||
|
|
||||||
// 只显示有对应命令的包
|
|
||||||
const selectPkgs = packages.filter((pkg) => {
|
|
||||||
return (pkg?.packageJson as Record<string, any>)?.scripts?.[command];
|
|
||||||
});
|
|
||||||
|
|
||||||
let selectPkg: string | symbol;
|
|
||||||
if (selectPkgs.length > 1) {
|
|
||||||
selectPkg = await select<string>({
|
|
||||||
message: `Select the app you need to run [${command}]:`,
|
|
||||||
options: selectPkgs.map((item) => ({
|
|
||||||
label: item?.packageJson.name,
|
|
||||||
value: item?.packageJson.name,
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isCancel(selectPkg) || !selectPkg) {
|
|
||||||
cancel('👋 Has cancelled');
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
selectPkg = selectPkgs[0]?.packageJson?.name ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!selectPkg) {
|
|
||||||
console.error('No app found');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
execaCommand(`pnpm --filter=${selectPkg} run ${command}`, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 过滤app包
|
|
||||||
* @param root
|
|
||||||
* @param packages
|
|
||||||
*/
|
|
||||||
// async function findApps(root: string, packages: Package[]) {
|
|
||||||
// // apps内的
|
|
||||||
// const appPackages = packages.filter((pkg) => {
|
|
||||||
// const viteConfigExists = fs.existsSync(join(pkg.dir, 'vite.config.mts'));
|
|
||||||
// return pkg.dir.startsWith(join(root, 'apps')) && viteConfigExists;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return appPackages;
|
|
||||||
// }
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "@vben/tsconfig/node.json",
|
|
||||||
"include": ["src"],
|
|
||||||
"exclude": ["node_modules"]
|
|
||||||
}
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
# @vben/vsh
|
|
||||||
|
|
||||||
一个 Shell 脚本工具集合,用于 Vue Vben Admin 项目的开发和管理。
|
|
||||||
|
|
||||||
## 功能特性
|
|
||||||
|
|
||||||
- 🚀 基于 Node.js 的现代化 Shell 工具
|
|
||||||
- 📦 支持模块化开发和按需加载
|
|
||||||
- 🔍 提供依赖检查和分析功能
|
|
||||||
- 🔄 支持循环依赖扫描
|
|
||||||
- 📝 提供包发布检查功能
|
|
||||||
|
|
||||||
## 安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 使用 pnpm 安装
|
|
||||||
pnpm add -D @vben/vsh
|
|
||||||
|
|
||||||
# 或者使用 npm
|
|
||||||
npm install -D @vben/vsh
|
|
||||||
|
|
||||||
# 或者使用 yarn
|
|
||||||
yarn add -D @vben/vsh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用方法
|
|
||||||
|
|
||||||
### 全局安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 全局安装
|
|
||||||
pnpm add -g @vben/vsh
|
|
||||||
|
|
||||||
# 使用 vsh 命令
|
|
||||||
vsh [command]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 本地使用
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 在 package.json 中添加脚本
|
|
||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"vsh": "vsh"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 运行命令
|
|
||||||
pnpm vsh [command]
|
|
||||||
```
|
|
||||||
|
|
||||||
## 命令列表
|
|
||||||
|
|
||||||
- `vsh check-deps`: 检查项目依赖
|
|
||||||
- `vsh scan-circular`: 扫描循环依赖
|
|
||||||
- `vsh publish-check`: 检查包发布配置
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
import('../dist/index.mjs');
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
import { defineBuildConfig } from 'unbuild';
|
|
||||||
|
|
||||||
export default defineBuildConfig({
|
|
||||||
clean: true,
|
|
||||||
declaration: true,
|
|
||||||
entries: ['src/index'],
|
|
||||||
});
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@vben/vsh",
|
|
||||||
"version": "5.6.0",
|
|
||||||
"private": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"stub": "pnpm unbuild --stub"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"dist"
|
|
||||||
],
|
|
||||||
"bin": {
|
|
||||||
"vsh": "./bin/vsh.mjs"
|
|
||||||
},
|
|
||||||
"main": "./dist/index.mjs",
|
|
||||||
"module": "./dist/index.mjs",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"default": "./dist/index.mjs"
|
|
||||||
},
|
|
||||||
"./package.json": "./package.json"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@vben/node-utils": "workspace:*",
|
|
||||||
"cac": "catalog:",
|
|
||||||
"circular-dependency-scanner": "catalog:",
|
|
||||||
"depcheck": "catalog:",
|
|
||||||
"publint": "catalog:"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,170 +0,0 @@
|
|||||||
import type { CAC } from 'cac';
|
|
||||||
|
|
||||||
import { extname } from 'node:path';
|
|
||||||
|
|
||||||
import { getStagedFiles } from '@vben/node-utils';
|
|
||||||
|
|
||||||
import { circularDepsDetect } from 'circular-dependency-scanner';
|
|
||||||
|
|
||||||
// 默认配置
|
|
||||||
const DEFAULT_CONFIG = {
|
|
||||||
allowedExtensions: ['.cjs', '.js', '.jsx', '.mjs', '.ts', '.tsx', '.vue'],
|
|
||||||
ignoreDirs: [
|
|
||||||
'dist',
|
|
||||||
'.turbo',
|
|
||||||
'output',
|
|
||||||
'.cache',
|
|
||||||
'scripts',
|
|
||||||
'internal',
|
|
||||||
'packages/effects/request/src/',
|
|
||||||
'packages/@core/ui-kit/menu-ui/src/',
|
|
||||||
'packages/@core/ui-kit/popup-ui/src/',
|
|
||||||
],
|
|
||||||
threshold: 0, // 循环依赖的阈值
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
// 类型定义
|
|
||||||
type CircularDependencyResult = string[];
|
|
||||||
|
|
||||||
interface CheckCircularConfig {
|
|
||||||
allowedExtensions?: string[];
|
|
||||||
ignoreDirs?: string[];
|
|
||||||
threshold?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CommandOptions {
|
|
||||||
config?: CheckCircularConfig;
|
|
||||||
staged: boolean;
|
|
||||||
verbose: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存机制
|
|
||||||
const cache = new Map<string, CircularDependencyResult[]>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化循环依赖的输出
|
|
||||||
* @param circles - 循环依赖结果
|
|
||||||
*/
|
|
||||||
function formatCircles(circles: CircularDependencyResult[]): void {
|
|
||||||
if (circles.length === 0) {
|
|
||||||
console.log('✅ No circular dependencies found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('⚠️ Circular dependencies found:');
|
|
||||||
circles.forEach((circle, index) => {
|
|
||||||
console.log(`\nCircular dependency #${index + 1}:`);
|
|
||||||
circle.forEach((file) => console.log(` → ${file}`));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查项目中的循环依赖
|
|
||||||
* @param options - 检查选项
|
|
||||||
* @param options.staged - 是否只检查暂存区文件
|
|
||||||
* @param options.verbose - 是否显示详细信息
|
|
||||||
* @param options.config - 自定义配置
|
|
||||||
* @returns Promise<void>
|
|
||||||
*/
|
|
||||||
async function checkCircular({
|
|
||||||
config = {},
|
|
||||||
staged,
|
|
||||||
verbose,
|
|
||||||
}: CommandOptions): Promise<void> {
|
|
||||||
try {
|
|
||||||
// 合并配置
|
|
||||||
const finalConfig = {
|
|
||||||
...DEFAULT_CONFIG,
|
|
||||||
...config,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 生成忽略模式
|
|
||||||
const ignorePattern = `**/{${finalConfig.ignoreDirs.join(',')}}/**`;
|
|
||||||
|
|
||||||
// 检查缓存
|
|
||||||
const cacheKey = `${staged}-${process.cwd()}-${ignorePattern}`;
|
|
||||||
if (cache.has(cacheKey)) {
|
|
||||||
const cachedResults = cache.get(cacheKey);
|
|
||||||
if (cachedResults) {
|
|
||||||
verbose && formatCircles(cachedResults);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测循环依赖
|
|
||||||
const results = await circularDepsDetect({
|
|
||||||
absolute: staged,
|
|
||||||
cwd: process.cwd(),
|
|
||||||
ignore: [ignorePattern],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (staged) {
|
|
||||||
let files = await getStagedFiles();
|
|
||||||
const allowedExtensions = new Set(finalConfig.allowedExtensions);
|
|
||||||
|
|
||||||
// 过滤文件列表
|
|
||||||
files = files.filter((file) => allowedExtensions.has(extname(file)));
|
|
||||||
|
|
||||||
const circularFiles: CircularDependencyResult[] = [];
|
|
||||||
|
|
||||||
for (const file of files) {
|
|
||||||
for (const result of results) {
|
|
||||||
const resultFiles = result.flat();
|
|
||||||
if (resultFiles.includes(file)) {
|
|
||||||
circularFiles.push(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新缓存
|
|
||||||
cache.set(cacheKey, circularFiles);
|
|
||||||
verbose && formatCircles(circularFiles);
|
|
||||||
} else {
|
|
||||||
// 更新缓存
|
|
||||||
cache.set(cacheKey, results);
|
|
||||||
verbose && formatCircles(results);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果发现循环依赖,只输出警告信息
|
|
||||||
if (results.length > 0) {
|
|
||||||
console.log(
|
|
||||||
'\n⚠️ Warning: Circular dependencies found, please check and fix',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(
|
|
||||||
'❌ Error checking circular dependencies:',
|
|
||||||
error instanceof Error ? error.message : error,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定义检查循环依赖的命令
|
|
||||||
* @param cac - CAC实例
|
|
||||||
*/
|
|
||||||
function defineCheckCircularCommand(cac: CAC): void {
|
|
||||||
cac
|
|
||||||
.command('check-circular')
|
|
||||||
.option('--staged', 'Only check staged files')
|
|
||||||
.option('--verbose', 'Show detailed information')
|
|
||||||
.option('--threshold <number>', 'Threshold for circular dependencies', {
|
|
||||||
default: 0,
|
|
||||||
})
|
|
||||||
.option('--ignore-dirs <dirs>', 'Directories to ignore, comma separated')
|
|
||||||
.usage('Analyze project circular dependencies')
|
|
||||||
.action(async ({ ignoreDirs, staged, threshold, verbose }) => {
|
|
||||||
const config: CheckCircularConfig = {
|
|
||||||
threshold: Number(threshold),
|
|
||||||
...(ignoreDirs && { ignoreDirs: ignoreDirs.split(',') }),
|
|
||||||
};
|
|
||||||
|
|
||||||
await checkCircular({
|
|
||||||
config,
|
|
||||||
staged,
|
|
||||||
verbose: verbose ?? true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { type CheckCircularConfig, defineCheckCircularCommand };
|
|
||||||
@ -1,193 +0,0 @@
|
|||||||
import type { CAC } from 'cac';
|
|
||||||
|
|
||||||
import { getPackages } from '@vben/node-utils';
|
|
||||||
|
|
||||||
import depcheck from 'depcheck';
|
|
||||||
|
|
||||||
// 默认配置
|
|
||||||
const DEFAULT_CONFIG = {
|
|
||||||
// 需要忽略的依赖匹配
|
|
||||||
ignoreMatches: [
|
|
||||||
'vite',
|
|
||||||
'vitest',
|
|
||||||
'unbuild',
|
|
||||||
'@vben/tsconfig',
|
|
||||||
'@vben/vite-config',
|
|
||||||
'@vben/tailwind-config',
|
|
||||||
'@types/*',
|
|
||||||
'@vben-core/design',
|
|
||||||
],
|
|
||||||
// 需要忽略的包
|
|
||||||
ignorePackages: [
|
|
||||||
'@vben/commitlint-config',
|
|
||||||
'@vben/eslint-config',
|
|
||||||
'@vben/node-utils',
|
|
||||||
'@vben/prettier-config',
|
|
||||||
'@vben/stylelint-config',
|
|
||||||
'@vben/tailwind-config',
|
|
||||||
'@vben/tsconfig',
|
|
||||||
'@vben/vite-config',
|
|
||||||
'@vben/vsh',
|
|
||||||
],
|
|
||||||
// 需要忽略的文件模式
|
|
||||||
ignorePatterns: ['dist', 'node_modules', 'public'],
|
|
||||||
};
|
|
||||||
|
|
||||||
interface DepcheckResult {
|
|
||||||
dependencies: string[];
|
|
||||||
devDependencies: string[];
|
|
||||||
missing: Record<string, string[]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DepcheckConfig {
|
|
||||||
ignoreMatches?: string[];
|
|
||||||
ignorePackages?: string[];
|
|
||||||
ignorePatterns?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PackageInfo {
|
|
||||||
dir: string;
|
|
||||||
packageJson: {
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清理依赖检查结果
|
|
||||||
* @param unused - 依赖检查结果
|
|
||||||
*/
|
|
||||||
function cleanDepcheckResult(unused: DepcheckResult): void {
|
|
||||||
// 删除file:前缀的依赖提示,该依赖是本地依赖
|
|
||||||
Reflect.deleteProperty(unused.missing, 'file:');
|
|
||||||
|
|
||||||
// 清理路径依赖
|
|
||||||
Object.keys(unused.missing).forEach((key) => {
|
|
||||||
unused.missing[key] = (unused.missing[key] || []).filter(
|
|
||||||
(item: string) => !item.startsWith('/'),
|
|
||||||
);
|
|
||||||
if (unused.missing[key].length === 0) {
|
|
||||||
Reflect.deleteProperty(unused.missing, key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化依赖检查结果
|
|
||||||
* @param pkgName - 包名
|
|
||||||
* @param unused - 依赖检查结果
|
|
||||||
*/
|
|
||||||
function formatDepcheckResult(pkgName: string, unused: DepcheckResult): void {
|
|
||||||
const hasIssues =
|
|
||||||
Object.keys(unused.missing).length > 0 ||
|
|
||||||
unused.dependencies.length > 0 ||
|
|
||||||
unused.devDependencies.length > 0;
|
|
||||||
|
|
||||||
if (!hasIssues) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('\n📦 Package:', pkgName);
|
|
||||||
|
|
||||||
if (Object.keys(unused.missing).length > 0) {
|
|
||||||
console.log('❌ Missing dependencies:');
|
|
||||||
Object.entries(unused.missing).forEach(([dep, files]) => {
|
|
||||||
console.log(` - ${dep}:`);
|
|
||||||
files.forEach((file) => console.log(` → ${file}`));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unused.dependencies.length > 0) {
|
|
||||||
console.log('⚠️ Unused dependencies:');
|
|
||||||
unused.dependencies.forEach((dep) => console.log(` - ${dep}`));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unused.devDependencies.length > 0) {
|
|
||||||
console.log('⚠️ Unused devDependencies:');
|
|
||||||
unused.devDependencies.forEach((dep) => console.log(` - ${dep}`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 运行依赖检查
|
|
||||||
* @param config - 配置选项
|
|
||||||
*/
|
|
||||||
async function runDepcheck(config: DepcheckConfig = {}): Promise<void> {
|
|
||||||
try {
|
|
||||||
const finalConfig = {
|
|
||||||
...DEFAULT_CONFIG,
|
|
||||||
...config,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { packages } = await getPackages();
|
|
||||||
|
|
||||||
let hasIssues = false;
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
packages.map(async (pkg: PackageInfo) => {
|
|
||||||
// 跳过需要忽略的包
|
|
||||||
if (finalConfig.ignorePackages.includes(pkg.packageJson.name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unused = await depcheck(pkg.dir, {
|
|
||||||
ignoreMatches: finalConfig.ignoreMatches,
|
|
||||||
ignorePatterns: finalConfig.ignorePatterns,
|
|
||||||
});
|
|
||||||
|
|
||||||
cleanDepcheckResult(unused);
|
|
||||||
|
|
||||||
const pkgHasIssues =
|
|
||||||
Object.keys(unused.missing).length > 0 ||
|
|
||||||
unused.dependencies.length > 0 ||
|
|
||||||
unused.devDependencies.length > 0;
|
|
||||||
|
|
||||||
if (pkgHasIssues) {
|
|
||||||
hasIssues = true;
|
|
||||||
formatDepcheckResult(pkg.packageJson.name, unused);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!hasIssues) {
|
|
||||||
console.log('\n✅ Dependency check completed, no issues found');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(
|
|
||||||
'❌ Dependency check failed:',
|
|
||||||
error instanceof Error ? error.message : error,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定义依赖检查命令
|
|
||||||
* @param cac - CAC实例
|
|
||||||
*/
|
|
||||||
function defineDepcheckCommand(cac: CAC): void {
|
|
||||||
cac
|
|
||||||
.command('check-dep')
|
|
||||||
.option(
|
|
||||||
'--ignore-packages <packages>',
|
|
||||||
'Packages to ignore, comma separated',
|
|
||||||
)
|
|
||||||
.option(
|
|
||||||
'--ignore-matches <matches>',
|
|
||||||
'Dependency patterns to ignore, comma separated',
|
|
||||||
)
|
|
||||||
.option(
|
|
||||||
'--ignore-patterns <patterns>',
|
|
||||||
'File patterns to ignore, comma separated',
|
|
||||||
)
|
|
||||||
.usage('Analyze project dependencies')
|
|
||||||
.action(async ({ ignoreMatches, ignorePackages, ignorePatterns }) => {
|
|
||||||
const config: DepcheckConfig = {
|
|
||||||
...(ignorePackages && { ignorePackages: ignorePackages.split(',') }),
|
|
||||||
...(ignoreMatches && { ignoreMatches: ignoreMatches.split(',') }),
|
|
||||||
...(ignorePatterns && { ignorePatterns: ignorePatterns.split(',') }),
|
|
||||||
};
|
|
||||||
|
|
||||||
await runDepcheck(config);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { defineDepcheckCommand, type DepcheckConfig };
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
import type { CAC } from 'cac';
|
|
||||||
|
|
||||||
import { join, relative } from 'node:path';
|
|
||||||
|
|
||||||
import {
|
|
||||||
colors,
|
|
||||||
consola,
|
|
||||||
findMonorepoRoot,
|
|
||||||
getPackages,
|
|
||||||
gitAdd,
|
|
||||||
outputJSON,
|
|
||||||
prettierFormat,
|
|
||||||
toPosixPath,
|
|
||||||
} from '@vben/node-utils';
|
|
||||||
|
|
||||||
const CODE_WORKSPACE_FILE = join('vben-admin.code-workspace');
|
|
||||||
|
|
||||||
interface CodeWorkspaceCommandOptions {
|
|
||||||
autoCommit?: boolean;
|
|
||||||
spaces?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createCodeWorkspace({
|
|
||||||
autoCommit = false,
|
|
||||||
spaces = 2,
|
|
||||||
}: CodeWorkspaceCommandOptions) {
|
|
||||||
const { packages, rootDir } = await getPackages();
|
|
||||||
|
|
||||||
let folders = packages.map((pkg) => {
|
|
||||||
const { dir, packageJson } = pkg;
|
|
||||||
return {
|
|
||||||
name: packageJson.name,
|
|
||||||
path: toPosixPath(relative(rootDir, dir)),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
folders = folders.filter(Boolean);
|
|
||||||
|
|
||||||
const monorepoRoot = findMonorepoRoot();
|
|
||||||
const outputPath = join(monorepoRoot, CODE_WORKSPACE_FILE);
|
|
||||||
await outputJSON(outputPath, { folders }, spaces);
|
|
||||||
|
|
||||||
await prettierFormat(outputPath);
|
|
||||||
if (autoCommit) {
|
|
||||||
await gitAdd(CODE_WORKSPACE_FILE, monorepoRoot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runCodeWorkspace({
|
|
||||||
autoCommit,
|
|
||||||
spaces,
|
|
||||||
}: CodeWorkspaceCommandOptions) {
|
|
||||||
await createCodeWorkspace({
|
|
||||||
autoCommit,
|
|
||||||
spaces,
|
|
||||||
});
|
|
||||||
if (autoCommit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
consola.log('');
|
|
||||||
consola.success(colors.green(`${CODE_WORKSPACE_FILE} is updated!`));
|
|
||||||
consola.log('');
|
|
||||||
}
|
|
||||||
|
|
||||||
function defineCodeWorkspaceCommand(cac: CAC) {
|
|
||||||
cac
|
|
||||||
.command('code-workspace')
|
|
||||||
.usage('Update the `.code-workspace` file')
|
|
||||||
.option('--spaces [number]', '.code-workspace JSON file spaces.', {
|
|
||||||
default: 2,
|
|
||||||
})
|
|
||||||
.option('--auto-commit', 'auto commit .code-workspace JSON file.', {
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
.action(runCodeWorkspace);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { defineCodeWorkspaceCommand };
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
import { colors, consola } from '@vben/node-utils';
|
|
||||||
|
|
||||||
import { cac } from 'cac';
|
|
||||||
|
|
||||||
import { version } from '../package.json';
|
|
||||||
import { defineCheckCircularCommand } from './check-circular';
|
|
||||||
import { defineDepcheckCommand } from './check-dep';
|
|
||||||
import { defineCodeWorkspaceCommand } from './code-workspace';
|
|
||||||
import { defineLintCommand } from './lint';
|
|
||||||
import { definePubLintCommand } from './publint';
|
|
||||||
|
|
||||||
// 命令描述
|
|
||||||
const COMMAND_DESCRIPTIONS = {
|
|
||||||
'check-circular': 'Check for circular dependencies',
|
|
||||||
'check-dep': 'Check for unused dependencies',
|
|
||||||
'code-workspace': 'Manage VS Code workspace settings',
|
|
||||||
lint: 'Run linting on the project',
|
|
||||||
publint: 'Check package.json files for publishing standards',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize and run the CLI
|
|
||||||
*/
|
|
||||||
async function main(): Promise<void> {
|
|
||||||
try {
|
|
||||||
const vsh = cac('vsh');
|
|
||||||
|
|
||||||
// Register commands
|
|
||||||
defineLintCommand(vsh);
|
|
||||||
definePubLintCommand(vsh);
|
|
||||||
defineCodeWorkspaceCommand(vsh);
|
|
||||||
defineCheckCircularCommand(vsh);
|
|
||||||
defineDepcheckCommand(vsh);
|
|
||||||
|
|
||||||
// Handle invalid commands
|
|
||||||
vsh.on('command:*', ([cmd]) => {
|
|
||||||
consola.error(
|
|
||||||
colors.red(`Invalid command: ${cmd}`),
|
|
||||||
'\n',
|
|
||||||
colors.yellow('Available commands:'),
|
|
||||||
'\n',
|
|
||||||
Object.entries(COMMAND_DESCRIPTIONS)
|
|
||||||
.map(([cmd, desc]) => ` ${colors.cyan(cmd)} - ${desc}`)
|
|
||||||
.join('\n'),
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set up CLI
|
|
||||||
vsh.usage('vsh <command> [options]');
|
|
||||||
vsh.help();
|
|
||||||
vsh.version(version);
|
|
||||||
|
|
||||||
// Parse arguments
|
|
||||||
vsh.parse();
|
|
||||||
} catch (error) {
|
|
||||||
consola.error(
|
|
||||||
colors.red('An unexpected error occurred:'),
|
|
||||||
'\n',
|
|
||||||
error instanceof Error ? error.message : error,
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the CLI
|
|
||||||
main().catch((error) => {
|
|
||||||
consola.error(
|
|
||||||
colors.red('Failed to start CLI:'),
|
|
||||||
'\n',
|
|
||||||
error instanceof Error ? error.message : error,
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
import type { CAC } from 'cac';
|
|
||||||
|
|
||||||
import { execaCommand } from '@vben/node-utils';
|
|
||||||
|
|
||||||
interface LintCommandOptions {
|
|
||||||
/**
|
|
||||||
* Format lint problem.
|
|
||||||
*/
|
|
||||||
format?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runLint({ format }: LintCommandOptions) {
|
|
||||||
// process.env.FORCE_COLOR = '3';
|
|
||||||
|
|
||||||
if (format) {
|
|
||||||
await execaCommand(`stylelint "**/*.{vue,css,less,scss}" --cache --fix`, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
});
|
|
||||||
await execaCommand(`eslint . --cache --fix`, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
});
|
|
||||||
await execaCommand(`prettier . --write --cache --log-level warn`, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await Promise.all([
|
|
||||||
execaCommand(`eslint . --cache`, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
}),
|
|
||||||
execaCommand(`prettier . --ignore-unknown --check --cache`, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
}),
|
|
||||||
execaCommand(`stylelint "**/*.{vue,css,less,scss}" --cache`, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function defineLintCommand(cac: CAC) {
|
|
||||||
cac
|
|
||||||
.command('lint')
|
|
||||||
.usage('Batch execute project lint check.')
|
|
||||||
.option('--format', 'Format lint problem.')
|
|
||||||
.action(runLint);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { defineLintCommand };
|
|
||||||
@ -1,185 +0,0 @@
|
|||||||
import type { CAC } from 'cac';
|
|
||||||
import type { Result } from 'publint';
|
|
||||||
|
|
||||||
import { basename, dirname, join } from 'node:path';
|
|
||||||
|
|
||||||
import {
|
|
||||||
colors,
|
|
||||||
consola,
|
|
||||||
ensureFile,
|
|
||||||
findMonorepoRoot,
|
|
||||||
generatorContentHash,
|
|
||||||
getPackages,
|
|
||||||
outputJSON,
|
|
||||||
readJSON,
|
|
||||||
UNICODE,
|
|
||||||
} from '@vben/node-utils';
|
|
||||||
|
|
||||||
import { publint } from 'publint';
|
|
||||||
import { formatMessage } from 'publint/utils';
|
|
||||||
|
|
||||||
const CACHE_FILE = join(
|
|
||||||
'node_modules',
|
|
||||||
'.cache',
|
|
||||||
'publint',
|
|
||||||
'.pkglintcache.json',
|
|
||||||
);
|
|
||||||
|
|
||||||
interface PubLintCommandOptions {
|
|
||||||
/**
|
|
||||||
* Only errors are checked, no program exit is performed
|
|
||||||
*/
|
|
||||||
check?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get files that require lint
|
|
||||||
* @param files
|
|
||||||
*/
|
|
||||||
async function getLintFiles(files: string[] = []) {
|
|
||||||
const lintFiles: string[] = [];
|
|
||||||
|
|
||||||
if (files?.length > 0) {
|
|
||||||
return files.filter((file) => basename(file) === 'package.json');
|
|
||||||
}
|
|
||||||
|
|
||||||
const { packages } = await getPackages();
|
|
||||||
|
|
||||||
for (const { dir } of packages) {
|
|
||||||
lintFiles.push(join(dir, 'package.json'));
|
|
||||||
}
|
|
||||||
return lintFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCacheFile() {
|
|
||||||
const root = findMonorepoRoot();
|
|
||||||
return join(root, CACHE_FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readCache(cacheFile: string) {
|
|
||||||
try {
|
|
||||||
await ensureFile(cacheFile);
|
|
||||||
return await readJSON(cacheFile);
|
|
||||||
} catch {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runPublint(files: string[], { check }: PubLintCommandOptions) {
|
|
||||||
const lintFiles = await getLintFiles(files);
|
|
||||||
const cacheFile = getCacheFile();
|
|
||||||
|
|
||||||
const cacheData = await readCache(cacheFile);
|
|
||||||
const cache: Record<string, { hash: string; result: Result }> = cacheData;
|
|
||||||
|
|
||||||
const results = await Promise.all(
|
|
||||||
lintFiles.map(async (file) => {
|
|
||||||
try {
|
|
||||||
const pkgJson = await readJSON(file);
|
|
||||||
|
|
||||||
if (pkgJson.private) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reflect.deleteProperty(pkgJson, 'dependencies');
|
|
||||||
Reflect.deleteProperty(pkgJson, 'devDependencies');
|
|
||||||
Reflect.deleteProperty(pkgJson, 'peerDependencies');
|
|
||||||
const content = JSON.stringify(pkgJson);
|
|
||||||
const hash = generatorContentHash(content);
|
|
||||||
|
|
||||||
const publintResult: Result =
|
|
||||||
cache?.[file]?.hash === hash
|
|
||||||
? (cache?.[file]?.result ?? [])
|
|
||||||
: await publint({
|
|
||||||
level: 'suggestion',
|
|
||||||
pkgDir: dirname(file),
|
|
||||||
strict: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
cache[file] = {
|
|
||||||
hash,
|
|
||||||
result: publintResult,
|
|
||||||
};
|
|
||||||
|
|
||||||
return { pkgJson, pkgPath: file, publintResult };
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
await outputJSON(cacheFile, cache);
|
|
||||||
printResult(results, check);
|
|
||||||
}
|
|
||||||
|
|
||||||
function printResult(
|
|
||||||
results: Array<null | {
|
|
||||||
pkgJson: Record<string, number | string>;
|
|
||||||
pkgPath: string;
|
|
||||||
publintResult: Result;
|
|
||||||
}>,
|
|
||||||
check?: boolean,
|
|
||||||
) {
|
|
||||||
let errorCount = 0;
|
|
||||||
let warningCount = 0;
|
|
||||||
let suggestionsCount = 0;
|
|
||||||
|
|
||||||
for (const result of results) {
|
|
||||||
if (!result) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const { pkgJson, pkgPath, publintResult } = result;
|
|
||||||
const messages = publintResult?.messages ?? [];
|
|
||||||
if (messages?.length < 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
consola.log('');
|
|
||||||
consola.log(pkgPath);
|
|
||||||
for (const message of messages) {
|
|
||||||
switch (message.type) {
|
|
||||||
case 'error': {
|
|
||||||
errorCount++;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'suggestion': {
|
|
||||||
suggestionsCount++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'warning': {
|
|
||||||
warningCount++;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// No default
|
|
||||||
}
|
|
||||||
const ruleUrl = `https://publint.dev/rules#${message.code.toLocaleLowerCase()}`;
|
|
||||||
consola.log(
|
|
||||||
` ${formatMessage(message, pkgJson)}${colors.dim(` ${ruleUrl}`)}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalCount = warningCount + errorCount + suggestionsCount;
|
|
||||||
if (totalCount > 0) {
|
|
||||||
consola.error(
|
|
||||||
colors.red(
|
|
||||||
`${UNICODE.FAILURE} ${totalCount} problem (${errorCount} errors, ${warningCount} warnings, ${suggestionsCount} suggestions)`,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
!check && process.exit(1);
|
|
||||||
} else {
|
|
||||||
consola.log(colors.green(`${UNICODE.SUCCESS} No problem`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function definePubLintCommand(cac: CAC) {
|
|
||||||
cac
|
|
||||||
.command('publint [...files]')
|
|
||||||
.usage('Check if the monorepo package conforms to the publint standard.')
|
|
||||||
.option('--check', 'Only errors are checked, no program exit is performed.')
|
|
||||||
.action(runPublint);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { definePubLintCommand };
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "@vben/tsconfig/node.json",
|
|
||||||
"include": ["src"],
|
|
||||||
"exclude": ["node_modules"]
|
|
||||||
}
|
|
||||||
@ -293,5 +293,5 @@ import { useAuthStore } from '#/store';
|
|||||||
- **常用功能**: `references/features/features.md` - 水印、缓存、动态标题等
|
- **常用功能**: `references/features/features.md` - 水印、缓存、动态标题等
|
||||||
|
|
||||||
### 构建部署 (references/deployment/)
|
### 构建部署 (references/deployment/)
|
||||||
- **构建部署**: `references/deployment/deploy.md` - 构建配置、Nginx、Docker
|
- **构建部署**: `references/deployment/deploy.md` - 构建配置、Jenkins、Nginx
|
||||||
- **常见问题**: `references/deployment/faq.md` - 依赖安装、打包部署、错误排查
|
- **常见问题**: `references/deployment/faq.md` - 依赖安装、打包部署、错误排查
|
||||||
|
|||||||
@ -97,40 +97,6 @@ server {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker 部署
|
|
||||||
|
|
||||||
```dockerfile
|
|
||||||
# Dockerfile
|
|
||||||
FROM node:20-alpine as builder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package.json pnpm-lock.yaml ./
|
|
||||||
RUN npm install -g pnpm && pnpm install --frozen-lockfile
|
|
||||||
COPY . .
|
|
||||||
RUN pnpm build:antd
|
|
||||||
|
|
||||||
FROM nginx:alpine
|
|
||||||
COPY --from=builder /app/apps/web-antd/dist /usr/share/nginx/html
|
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
||||||
EXPOSE 80
|
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# docker-compose.yml
|
|
||||||
version: '3'
|
|
||||||
services:
|
|
||||||
web:
|
|
||||||
build: .
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
backend:
|
|
||||||
image: your-backend-image
|
|
||||||
ports:
|
|
||||||
- "8080:8080"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 动态配置
|
## 动态配置
|
||||||
|
|
||||||
打包后可通过修改 `_app.config.js` 动态修改配置:
|
打包后可通过修改 `_app.config.js` 动态修改配置:
|
||||||
|
|||||||
6
tea.yaml
6
tea.yaml
@ -1,6 +0,0 @@
|
|||||||
# https://tea.xyz/what-is-this-file
|
|
||||||
---
|
|
||||||
version: 1.0.0
|
|
||||||
codeOwners:
|
|
||||||
- '0xB33cc732DFc15Cd39eF50Fb165c876E24417E48f'
|
|
||||||
quorum: 1
|
|
||||||
@ -8,9 +8,7 @@
|
|||||||
"internal/node-utils/src/**/*.ts",
|
"internal/node-utils/src/**/*.ts",
|
||||||
"internal/tailwind-config/src/**/*.ts",
|
"internal/tailwind-config/src/**/*.ts",
|
||||||
"internal/vite-config/*.json",
|
"internal/vite-config/*.json",
|
||||||
"internal/vite-config/src/**/*.ts",
|
"internal/vite-config/src/**/*.ts"
|
||||||
"scripts/*/src/**/*.ts",
|
|
||||||
"scripts/*/src/**/*.json"
|
|
||||||
],
|
],
|
||||||
"globalEnv": ["NODE_ENV"],
|
"globalEnv": ["NODE_ENV"],
|
||||||
"tasks": {
|
"tasks": {
|
||||||
|
|||||||
@ -1,152 +0,0 @@
|
|||||||
{
|
|
||||||
"folders": [
|
|
||||||
{
|
|
||||||
"name": "@vben/web-antdv-next",
|
|
||||||
"path": "apps/web-antdv-next",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/commitlint-config",
|
|
||||||
"path": "internal/lint-configs/commitlint-config",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/eslint-config",
|
|
||||||
"path": "internal/lint-configs/eslint-config",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/prettier-config",
|
|
||||||
"path": "internal/lint-configs/prettier-config",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/stylelint-config",
|
|
||||||
"path": "internal/lint-configs/stylelint-config",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/node-utils",
|
|
||||||
"path": "internal/node-utils",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/tailwind-config",
|
|
||||||
"path": "internal/tailwind-config",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/tsconfig",
|
|
||||||
"path": "internal/tsconfig",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/vite-config",
|
|
||||||
"path": "internal/vite-config",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/design",
|
|
||||||
"path": "packages/@core/base/design",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/icons",
|
|
||||||
"path": "packages/@core/base/icons",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/shared",
|
|
||||||
"path": "packages/@core/base/shared",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/typings",
|
|
||||||
"path": "packages/@core/base/typings",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/composables",
|
|
||||||
"path": "packages/@core/composables",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/preferences",
|
|
||||||
"path": "packages/@core/preferences",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/form-ui",
|
|
||||||
"path": "packages/@core/ui-kit/form-ui",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/layout-ui",
|
|
||||||
"path": "packages/@core/ui-kit/layout-ui",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/menu-ui",
|
|
||||||
"path": "packages/@core/ui-kit/menu-ui",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/popup-ui",
|
|
||||||
"path": "packages/@core/ui-kit/popup-ui",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/shadcn-ui",
|
|
||||||
"path": "packages/@core/ui-kit/shadcn-ui",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben-core/tabs-ui",
|
|
||||||
"path": "packages/@core/ui-kit/tabs-ui",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/constants",
|
|
||||||
"path": "packages/constants",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/access",
|
|
||||||
"path": "packages/effects/access",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/common-ui",
|
|
||||||
"path": "packages/effects/common-ui",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/hooks",
|
|
||||||
"path": "packages/effects/hooks",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/layouts",
|
|
||||||
"path": "packages/effects/layouts",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/plugins",
|
|
||||||
"path": "packages/effects/plugins",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/request",
|
|
||||||
"path": "packages/effects/request",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/icons",
|
|
||||||
"path": "packages/icons",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/locales",
|
|
||||||
"path": "packages/locales",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/preferences",
|
|
||||||
"path": "packages/preferences",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/stores",
|
|
||||||
"path": "packages/stores",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/styles",
|
|
||||||
"path": "packages/styles",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/types",
|
|
||||||
"path": "packages/types",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/utils",
|
|
||||||
"path": "packages/utils",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/turbo-run",
|
|
||||||
"path": "scripts/turbo-run",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "@vben/vsh",
|
|
||||||
"path": "scripts/vsh",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user