This commit is contained in:
dap 2024-08-08 08:03:04 +08:00
commit f2f7225c1f
71 changed files with 1219 additions and 1210 deletions

View File

@ -7,9 +7,16 @@ on:
permissions:
contents: read
pull-requests: write
jobs:
update_release_draft:
permissions:
# write permission is required to create a github release
contents: write
# write permission is required for autolabeler
# otherwise, read permission is required at least
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v6

View File

@ -189,5 +189,7 @@
},
"commentTranslate.hover.enabled": false,
"i18n-ally.keystyle": "nested",
"commentTranslate.multiLineMerge": true
"commentTranslate.multiLineMerge": true,
"vue.server.hybridMode": true,
"typescript.tsdk": "node_modules/typescript/lib"
}

146
README.ja-JP.md Normal file
View File

@ -0,0 +1,146 @@
<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.5/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
<h1>Vue Vben Admin</h1>
</div>
**日本語** | [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
<p 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">
</p>
### Gitpodを使用
GitpodGitHub用の無料オンライン開発環境でプロジェクトを開き、すぐにコーディングを開始します。
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
## ドキュメント
[ドキュメント](https://doc.vben.pro/)
## インストールと使用
- プロジェクトコードを取得
```bash
git clone https://github.com/vbenjs/vue-vben-admin.git
```
- 依存関係のインストール
```bash
cd vue-vben-admin
corepack enable
pnpm install
```
- 実行
```bash
pnpm dev
```
- ビルド
```bash
pnpm build
```
## 変更ログ
[CHANGELOG](./CHANGELOG.zh_CN.md)
## 貢献方法
ご参加をお待ちしております![Issueを提出](https://github.com/anncwb/vue-vben-admin/issues/new/choose)するか、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` 型定義ファイルの変更
- `wip` 開発中
## ブラウザサポート
ローカル開発には`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>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)
## 寄付
このプロジェクトが役に立つと思われた場合、作者にコーヒーを一杯おごってサポートを示すことができます!
![donate](https://unpkg.com/@vbenjs/static-source@0.1.5/source/sponsor.png)
<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://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img 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)

View File

@ -1,11 +1,11 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="200" height="200" src="https://unpkg.com/@vbenjs/static-source@0.1.5/source/logo-v1.webp"> </a> <br> <br>
<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.5/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
<h1>Vue Vben Admin</h1>
</div>
**English** | [中文](./README.zh-CN.md)
**English** | [中文](./README.zh-CN.md) | [日本語](./README.ja-JP.md)
## Introduction

View File

@ -1,11 +1,11 @@
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="200" height="200" src="https://unpkg.com/@vbenjs/static-source@0.1.5/source/logo-v1.webp"> </a> <br> <br>
<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.5/source/logo-v1.webp"> </a> <br> <br>
[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
<h1>Vue Vben Admin</h1>
</div>
**中文** | [English](./README.md)
**中文** | [English](./README.md) | [日本語](./README.ja-JP.md)
## 简介

View File

@ -48,8 +48,8 @@
"jsencrypt": "^3.3.2",
"lodash-es": "^4.17.21",
"pinia": "2.2.0",
"vue": "^3.4.35",
"vue-router": "^4.4.2"
"vue": "^3.4.36",
"vue-router": "^4.4.3"
},
"devDependencies": {
"@types/crypto-js": "^4.2.2",

View File

@ -26,7 +26,7 @@ export namespace AuthApi {
/**
*
*/
export async function login(data: AuthApi.LoginParams) {
export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>(
'/auth/login',
{ ...data, clientId },
@ -70,3 +70,7 @@ export interface TenantResp {
export function tenantList() {
return requestClient.get<TenantResp>('/auth/tenant/list');
}
export async function getAccessCodesApi() {
return requestClient.get<string[]>('/auth/codes');
}

View File

@ -40,6 +40,6 @@ export interface Menu {
/**
*
*/
export async function getAllMenus() {
export async function getAllMenusApi() {
return requestClient.get<Menu[]>('/system/menu/getRouters');
}

View File

@ -40,6 +40,6 @@ export interface UserInfoResp {
/**
*
*/
export async function getUserInfo() {
export async function getUserInfoApi() {
return requestClient.get<UserInfoResp>('/system/user/getInfo');
}

View File

@ -3,8 +3,8 @@ import { requestClient } from '#/api/request';
/**
*
*/
async function getMockStatus(status: string) {
async function getMockStatusApi(status: string) {
return requestClient.get('/status', { params: { status } });
}
export { getMockStatus };
export { getMockStatusApi };

View File

@ -10,7 +10,7 @@ import { preferences } from '@vben/preferences';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es';
import { getAllMenus, type Menu } from '#/api';
import { getAllMenusApi, type Menu } from '#/api';
import { BasicLayout, IFrameView } from '#/layouts';
import { $t } from '#/locales';
@ -110,7 +110,8 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
// 根目录为菜单形式
// 固定有一个children children为当前菜单
if (menu.path === '/' && menu.children && menu.children.length === 1) {
menu.meta = menu.children[0].meta;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
menu.meta = menu.children[0]!.meta;
/**
* todo
*/
@ -241,7 +242,7 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
duration: 1,
});
// 后台返回路由/菜单
const backMenuList = await getAllMenus();
const backMenuList = await getAllMenusApi();
// 转换为vben能用的路由
const vbenMenuList = backMenuToVbenMenu(backMenuList);
// 特别注意 这里要深拷贝

View File

@ -10,7 +10,7 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { notification } from 'ant-design-vue';
import { defineStore } from 'pinia';
import { doLogout, getUserInfo, login } from '#/api';
import { doLogout, getUserInfoApi, loginApi } from '#/api';
import { $t } from '#/locales';
export const useAuthStore = defineStore('auth', () => {
@ -33,7 +33,7 @@ export const useAuthStore = defineStore('auth', () => {
let userInfo: null | UserInfo = null;
try {
loginLoading.value = true;
const { access_token } = await login(params);
const { access_token } = await loginApi(params);
// 将 accessToken 存储到 accessStore 中
accessStore.setAccessToken(access_token);
@ -92,7 +92,7 @@ export const useAuthStore = defineStore('auth', () => {
}
async function fetchUserInfo() {
const { permissions = [], roles = [], user } = await getUserInfo();
const { permissions = [], roles = [], user } = await getUserInfoApi();
/**
* user -> vben user转换

View File

@ -5,13 +5,13 @@ import { preferences, updatePreferences } from '@vben/preferences';
import { Button } from 'ant-design-vue';
import { getMockStatus } from '#/api';
import { getMockStatusApi } from '#/api';
async function handleClick(type: LoginExpiredModeType) {
const loginExpiredMode = preferences.app.loginExpiredMode;
updatePreferences({ app: { loginExpiredMode: type } });
await getMockStatus('401');
await getMockStatusApi('401');
updatePreferences({ app: { loginExpiredMode } });
}
</script>

View File

@ -44,8 +44,8 @@
"dayjs": "^1.11.12",
"element-plus": "^2.7.8",
"pinia": "2.2.0",
"vue": "^3.4.35",
"vue-router": "^4.4.2"
"vue": "^3.4.36",
"vue-router": "^4.4.3"
},
"devDependencies": {
"unplugin-element-plus": "^0.8.0"

View File

@ -21,13 +21,13 @@ export namespace AuthApi {
/**
*
*/
export async function login(data: AuthApi.LoginParams) {
export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
}
/**
*
*/
export async function getAccessCodes() {
export async function getAccessCodesApi() {
return requestClient.get<string[]>('/auth/codes');
}

View File

@ -5,6 +5,6 @@ import { requestClient } from '#/api/request';
/**
*
*/
export async function getAllMenus() {
export async function getAllMenusApi() {
return requestClient.get<RouteRecordStringComponent[]>('/menu/all');
}

View File

@ -5,6 +5,6 @@ import { requestClient } from '#/api/request';
/**
*
*/
export async function getUserInfo() {
export async function getUserInfoApi() {
return requestClient.get<UserInfo>('/user/info');
}

View File

@ -8,7 +8,7 @@ import { preferences } from '@vben/preferences';
import { ElMessage } from 'element-plus';
import { getAllMenus } from '#/api';
import { getAllMenusApi } from '#/api';
import { BasicLayout, IFrameView } from '#/layouts';
import { $t } from '#/locales';
@ -29,7 +29,7 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
duration: 1500,
message: `${$t('common.loadingMenu')}...`,
});
return await getAllMenus();
return await getAllMenusApi();
},
// 可以指定没有权限跳转403页面
forbiddenComponent,

View File

@ -10,7 +10,7 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { ElNotification } from 'element-plus';
import { defineStore } from 'pinia';
import { getAccessCodes, getUserInfo, login } from '#/api';
import { getAccessCodesApi, getUserInfoApi, loginApi } from '#/api';
import { $t } from '#/locales';
export const useAuthStore = defineStore('auth', () => {
@ -33,7 +33,7 @@ export const useAuthStore = defineStore('auth', () => {
let userInfo: null | UserInfo = null;
try {
loginLoading.value = true;
const { accessToken, refreshToken } = await login(params);
const { accessToken, refreshToken } = await loginApi(params);
// 如果成功获取到 accessToken
if (accessToken) {
@ -44,7 +44,7 @@ export const useAuthStore = defineStore('auth', () => {
// 获取用户信息并存储到 accessStore 中
const [fetchUserInfoResult, accessCodes] = await Promise.all([
fetchUserInfo(),
getAccessCodes(),
getAccessCodesApi(),
]);
userInfo = fetchUserInfoResult;
@ -92,7 +92,7 @@ export const useAuthStore = defineStore('auth', () => {
async function fetchUserInfo() {
let userInfo: null | UserInfo = null;
userInfo = await getUserInfo();
userInfo = await getUserInfoApi();
userStore.setUserInfo(userInfo);
return userInfo;
}

View File

@ -43,7 +43,7 @@
"@vueuse/core": "^10.11.0",
"naive-ui": "^2.39.0",
"pinia": "2.2.0",
"vue": "^3.4.35",
"vue-router": "^4.4.2"
"vue": "^3.4.36",
"vue-router": "^4.4.3"
}
}

View File

@ -21,13 +21,13 @@ export namespace AuthApi {
/**
*
*/
export async function login(data: AuthApi.LoginParams) {
export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
}
/**
*
*/
export async function getAccessCodes() {
export async function getAccessCodesApi() {
return requestClient.get<string[]>('/auth/codes');
}

View File

@ -5,6 +5,6 @@ import { requestClient } from '#/api/request';
/**
*
*/
export async function getAllMenus() {
export async function getAllMenusApi() {
return requestClient.get<RouteRecordStringComponent[]>('/menu/all');
}

View File

@ -5,6 +5,6 @@ import { requestClient } from '#/api/request';
/**
*
*/
export async function getUserInfo() {
export async function getUserInfoApi() {
return requestClient.get<UserInfo>('/user/info');
}

View File

@ -6,7 +6,7 @@ import type {
import { generateAccessible } from '@vben/access';
import { preferences } from '@vben/preferences';
import { getAllMenus } from '#/api';
import { getAllMenusApi } from '#/api';
import { BasicLayout, IFrameView } from '#/layouts';
import { $t } from '#/locales';
import { message } from '#/naive';
@ -27,7 +27,7 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
message.loading(`${$t('common.loadingMenu')}...`, {
duration: 1.5,
});
return await getAllMenus();
return await getAllMenusApi();
},
// 可以指定没有权限跳转403页面
forbiddenComponent,

View File

@ -9,7 +9,7 @@ import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
import { defineStore } from 'pinia';
import { getAccessCodes, getUserInfo, login } from '#/api';
import { getAccessCodesApi, getUserInfoApi, loginApi } from '#/api';
import { $t } from '#/locales';
import { notification } from '#/naive';
@ -33,7 +33,7 @@ export const useAuthStore = defineStore('auth', () => {
let userInfo: null | UserInfo = null;
try {
loginLoading.value = true;
const { accessToken, refreshToken } = await login(params);
const { accessToken, refreshToken } = await loginApi(params);
// 如果成功获取到 accessToken
if (accessToken) {
@ -44,7 +44,7 @@ export const useAuthStore = defineStore('auth', () => {
// 获取用户信息并存储到 accessStore 中
const [fetchUserInfoResult, accessCodes] = await Promise.all([
fetchUserInfo(),
getAccessCodes(),
getAccessCodesApi(),
]);
userInfo = fetchUserInfoResult;
@ -92,7 +92,7 @@ export const useAuthStore = defineStore('auth', () => {
async function fetchUserInfo() {
let userInfo: null | UserInfo = null;
userInfo = await getUserInfo();
userInfo = await getUserInfoApi();
userStore.setUserInfo(userInfo);
return userInfo;
}

View File

@ -13,6 +13,6 @@
"devDependencies": {
"@vite-pwa/vitepress": "^0.5.0",
"vitepress": "^1.3.2",
"vue": "^3.4.35"
"vue": "^3.4.36"
}
}

View File

@ -2,8 +2,8 @@
社区交流群主要是为了方便大家交流,提问,解答问题,分享经验等。偏自助方式,如果你有问题,可以通过以下方式加入社区交流群:
- [QQ频道](https://qun.qq.com/qqweb/qunpro/share?_wv=3&_wwv=128&appChannel=share&inviteCode=1Zp3KrdpaiB&jumpsource=shorturl#/pc)主要提供问题解答,分享经验等。
- [QQ群](https://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=mjZmlhgVzzUxvdxllB6C1vHpX8O8QRL0&authKey=DBdFbBwERmfaKY95JvRWqLCJIRGJAmKyZbrpzZ41EKDMZ5SR6MfbjOBaaNRN73fr&noverify=0&group_code=4286109)主要使用者的交流群。
- [QQ频道](https://pd.qq.com/s/16p8lvvob):推荐,主要提供问题解答,分享经验等。
- QQ群[1群(满)](https://qm.qq.com/q/YacMHPYAMu)、[2群(满)](https://qm.qq.com/q/ajVKZvFICk)、[3群](https://qm.qq.com/q/36zdwThP2E)主要使用者的交流群。
- [Discord](https://discord.com/invite/VU62jTecad): 主要提供问题解答,分享经验等。
## 微信群

View File

@ -10,7 +10,7 @@
项目开发完成之后,执行以下命令进行构建:
**注意:** 请在项目目录下执行以下命令
**注意:** 请在项目目录下执行以下命令
```bash
pnpm build
@ -24,7 +24,7 @@ pnpm build
- 使用项目自定的命令进行预览(推荐)
**注意:** 请在项目目录下执行以下命令
**注意:** 请在项目目录下执行以下命令
```bash
pnpm preview

View File

@ -117,7 +117,7 @@ VITE_GLOB_API_URL=https://mock-napi.vben.pro/api
```ts
import { requestClient } from '#/api/request';
export async function getUserInfo() {
export async function getUserInfoApi() {
return requestClient.get<UserInfo>('/user/info');
}
```
@ -127,15 +127,15 @@ export async function getUserInfo() {
```ts
import { requestClient } from '#/api/request';
export async function saveUser(user: UserInfo) {
export async function saveUserApi(user: UserInfo) {
return requestClient.post<UserInfo>('/user', user);
}
export async function saveUser(user: UserInfo) {
export async function saveUserApi(user: UserInfo) {
return requestClient.put<UserInfo>('/user', user);
}
export async function saveUser(user: UserInfo) {
export async function saveUserApi(user: UserInfo) {
const url = user.id ? `/user/${user.id}` : '/user/';
return requestClient.request<UserInfo>(url, {
data: user,
@ -150,7 +150,7 @@ export async function saveUser(user: UserInfo) {
```ts
import { requestClient } from '#/api/request';
export async function deleteUser(user: UserInfo) {
export async function deleteUserApi(user: UserInfo) {
return requestClient.delete<boolean>(`/user/${user.id}`, user);
}
```

View File

@ -23,7 +23,7 @@
}
},
"dependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/cli": "^19.4.0",
"@commitlint/config-conventional": "^19.2.2",
"@vben/node-utils": "workspace:*",
"commitlint-plugin-function-rules": "^4.0.0",

View File

@ -27,7 +27,7 @@
}
},
"dependencies": {
"eslint-config-turbo": "^2.0.11",
"eslint-config-turbo": "^2.0.12",
"eslint-plugin-command": "^0.2.3",
"eslint-plugin-import-x": "^3.1.0"
},
@ -39,7 +39,7 @@
"eslint": "^9.8.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-jsdoc": "^48.10.2",
"eslint-plugin-jsdoc": "^50.0.0",
"eslint-plugin-jsonc": "^2.16.0",
"eslint-plugin-n": "^17.10.2",
"eslint-plugin-no-only-tests": "^3.1.0",

View File

@ -28,7 +28,7 @@
"stylelint-scss": "^6.5.0"
},
"devDependencies": {
"postcss": "^8.4.40",
"postcss": "^8.4.41",
"postcss-html": "^1.7.0",
"postcss-scss": "^4.0.9",
"prettier": "^3.3.3",

View File

@ -52,7 +52,7 @@
"@tailwindcss/typography": "^0.5.13",
"autoprefixer": "^10.4.20",
"cssnano": "^7.0.4",
"postcss": "^8.4.40",
"postcss": "^8.4.41",
"postcss-antd-fixes": "^0.2.0",
"postcss-import": "^16.1.0",
"postcss-preset-env": "^10.0.0",

View File

@ -13,6 +13,7 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"allowImportingTsExtensions": true,
"strict": true,
"strictNullChecks": true,

View File

@ -28,7 +28,7 @@
},
"dependencies": {
"@intlify/unplugin-vue-i18n": "^4.0.0",
"@jspm/generator": "^2.1.2",
"@jspm/generator": "^2.1.3",
"cheerio": "1.0.0-rc.12",
"get-port": "^7.1.0",
"html-minifier-terser": "^7.2.0",

View File

@ -72,14 +72,14 @@
"@vue/test-utils": "^2.4.6",
"autoprefixer": "^10.4.20",
"cross-env": "^7.0.3",
"cspell": "^8.13.0",
"cspell": "^8.13.1",
"husky": "^9.1.4",
"is-ci": "^3.0.1",
"jsdom": "^24.1.1",
"lint-staged": "^15.2.8",
"rimraf": "^6.0.1",
"tailwindcss": "^3.4.7",
"turbo": "^2.0.11",
"turbo": "^2.0.12",
"typescript": "^5.5.4",
"unbuild": "^2.0.0",
"vite": "^5.3.5",
@ -100,7 +100,7 @@
"overrides": {
"@ctrl/tinycolor": "^4.1.0",
"clsx": "^2.1.1",
"vue": "^3.4.35"
"vue": "^3.4.36"
},
"neverBuiltDependencies": [
"canvas",

View File

@ -34,21 +34,6 @@
transform: translateX(30px) skewX(-30deg);
}
/*
.breadcrumb-transition-move,
.breadcrumb-transition-enter-active {
transition: all 0.5s cubic-bezier(0.76, 0, 0.24, 1);
}
.breadcrumb-transition-leave-active {
display: none;
}
.breadcrumb-transition-enter-from {
opacity: 0;
transform: translateX(-5px);
} */
@keyframes slide-down {
from {
opacity: 0;

View File

@ -1,6 +1,7 @@
import './css/global.css';
import './css/transition.css';
import './css/nprogress.css';
import './css/ui.css';
import './design-tokens';
export {};

View File

@ -36,6 +36,6 @@
"dependencies": {
"@iconify/vue": "^4.1.2",
"lucide-vue-next": "^0.424.0",
"vue": "^3.4.35"
"vue": "^3.4.36"
}
}

View File

@ -7,7 +7,7 @@ export default defineBuildConfig({
'src/index',
'src/constants/index',
'src/utils/index',
'src/colorful/index',
'src/color/index',
'src/cache/index',
],
});

View File

@ -35,10 +35,10 @@
"development": "./src/utils/index.ts",
"default": "./dist/utils/index.mjs"
},
"./colorful": {
"types": "./src/colorful/index.ts",
"development": "./src/colorful/index.ts",
"default": "./dist/colorful/index.mjs"
"./color": {
"types": "./src/color/index.ts",
"development": "./src/color/index.ts",
"default": "./dist/color/index.mjs"
},
"./cache": {
"types": "./src/cache/index.ts",
@ -56,7 +56,7 @@
},
"dependencies": {
"@ctrl/tinycolor": "^4.1.0",
"@vue/shared": "^3.4.35",
"@vue/shared": "^3.4.36",
"clsx": "^2.1.1",
"defu": "^6.1.4",
"lodash.clonedeep": "^4.5.0",

View File

@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest';
import { convertToHsl, convertToHslCssVar, isValidColor } from './convert';
import { convertToHsl, convertToHslCssVar, convertToRgb } from './convert';
describe('color conversion functions', () => {
it('should correctly convert color to HSL format', () => {
@ -26,16 +26,16 @@ describe('color conversion functions', () => {
const expectedHsl = '0 100% 50% / 0.5';
expect(convertToHslCssVar(color)).toEqual(expectedHsl);
});
});
describe('isValidColor', () => {
it('isValidColor function', () => {
// 测试有效颜色
expect(isValidColor('blue')).toBe(true);
expect(isValidColor('#000000')).toBe(true);
it('should correctly convert color to RGB CSS variable format', () => {
const color = 'hsl(284, 100%, 50%)';
const expectedRgb = 'rgb(187, 0, 255)';
expect(convertToRgb(color)).toEqual(expectedRgb);
});
// 测试无效颜色
expect(isValidColor('invalid color')).toBe(false);
expect(isValidColor()).toBe(false);
it('should correctly convert color with alpha to RGBA CSS variable format', () => {
const color = 'hsla(284, 100%, 50%, 0.92)';
const expectedRgba = 'rgba(187, 0, 255, 0.92)';
expect(convertToRgb(color)).toEqual(expectedRgba);
});
});

View File

@ -0,0 +1,44 @@
import { TinyColor } from '@ctrl/tinycolor';
/**
* HSL格式
*
* HSL是一种颜色模型(Hue)(Saturation)(Lightness)
*
* @param {string} color
* @returns {string} HSL格式的颜色字符串
*/
function convertToHsl(color: string): string {
const { a, h, l, s } = new TinyColor(color).toHsl();
const hsl = `hsl(${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%)`;
return a < 1 ? `${hsl} ${a}` : hsl;
}
/**
* HSL CSS变量
*
* convertToHsl函数类似
* 便CSS变量使用
*
* @param {string} color
* @returns {string} CSS变量使用的HSL格式的颜色字符串
*/
function convertToHslCssVar(color: string): string {
const { a, h, l, s } = new TinyColor(color).toHsl();
const hsl = `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
return a < 1 ? `${hsl} / ${a}` : hsl;
}
/**
* RGB颜色字符串
* TinyColor无法处理hsl内包含'deg''grad''rad''turn'
* hsl(231deg 98% 65%)rgb(0, 0, 0)
*
* @param str HLS颜色值的字符串
* @returns RGB颜色字符串rgb(0, 0, 0)
*/
function convertToRgb(str: string): string {
return new TinyColor(str.replaceAll(/deg|grad|rad|turn/g, '')).toRgbString();
}
export { convertToHsl, convertToHslCssVar, convertToRgb, TinyColor };

View File

@ -1,7 +1,6 @@
import { TinyColor } from '@ctrl/tinycolor';
import { getColors } from 'theme-colors';
import { convertToHslCssVar } from './convert';
import { convertToHslCssVar, TinyColor } from './convert';
interface ColorItem {
alias?: string;

View File

@ -1,73 +0,0 @@
import { TinyColor } from '@ctrl/tinycolor';
/**
* HSL格式
*
* HSL是一种颜色模型(Hue)(Saturation)(Lightness)
* 使TinyColor库将输入的颜色转换为HSL格式
*
* @param {string} color TinyColor支持的颜色格式
* @returns {string} HSL格式的颜色字符串
*/
function convertToHsl(color: string): string {
const { a, h, l, s } = new TinyColor(color).toHsl();
const hsl = `hsl(${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%)`;
return a < 1 ? `${hsl} ${a}` : hsl;
}
/**
* HSL CSS变量
*
* convertToHsl函数类似
* 便CSS变量使用
*
* @param {string} color TinyColor支持的颜色格式
* @returns {string} CSS变量使用的HSL格式的颜色字符串
*/
function convertToHslCssVar(color: string): string {
const { a, h, l, s } = new TinyColor(color).toHsl();
const hsl = `${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
return a < 1 ? `${hsl} / ${a}` : hsl;
}
/**
*
* @param {string} color -
* truefalse
*/
function isValidColor(color?: string) {
if (!color) {
return false;
}
return new TinyColor(color).isValid;
}
/**
* HLS字符串转换为RGB颜色字符串
*
* HLS值的字符串
* TinyColor对象便
*
* RGB颜色字符串
*
* @param str HLS颜色值的字符串'deg''grad''rad''turn'
* @returns RGB颜色字符串
*/
function hlsStringToRGBString(str: string): string {
// 移除HLS字符串中的度量单位以便正确解析
const color = new TinyColor(
`hsl(${str.replaceAll(/deg|grad|rad|turn/g, '')})`,
);
// 检查颜色是否有效,如果无效则直接返回原始字符串
if (!color.isValid) {
return str;
}
// 返回转换后的RGB颜色字符串
return color.toRgbString();
}
export {
convertToHsl,
convertToHslCssVar,
hlsStringToRGBString,
isValidColor,
TinyColor,
};

View File

@ -1,4 +1,4 @@
export * from './cache';
export * from './colorful';
export * from './color';
export * from './constants';
export * from './utils';

View File

@ -38,7 +38,7 @@
}
},
"dependencies": {
"vue": "^3.4.35",
"vue-router": "^4.4.2"
"vue": "^3.4.36",
"vue-router": "^4.4.3"
}
}

View File

@ -37,9 +37,9 @@
"dependencies": {
"@vben-core/shared": "workspace:*",
"@vueuse/core": "^10.11.0",
"radix-vue": "^1.9.2",
"radix-vue": "^1.9.3",
"sortablejs": "^1.15.2",
"vue": "^3.4.35"
"vue": "^3.4.36"
},
"devDependencies": {
"@types/sortablejs": "^1.15.8"

View File

@ -32,6 +32,6 @@
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^10.11.0",
"vue": "^3.4.35"
"vue": "^3.4.36"
}
}

View File

@ -42,6 +42,6 @@
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^10.11.0",
"vue": "^3.4.35"
"vue": "^3.4.36"
}
}

View File

@ -43,6 +43,6 @@
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^10.11.0",
"vue": "^3.4.35"
"vue": "^3.4.36"
}
}

View File

@ -49,7 +49,7 @@
"@vueuse/core": "^10.11.0",
"class-variance-authority": "^0.7.0",
"lucide-vue-next": "^0.424.0",
"radix-vue": "^1.9.2",
"vue": "^3.4.35"
"radix-vue": "^1.9.3",
"vue": "^3.4.36"
}
}

View File

@ -3,7 +3,7 @@ import type { MenuRecordBadgeRaw } from '@vben-core/typings';
import { computed } from 'vue';
import { isValidColor } from '@vben-core/shared';
import { convertToRgb } from '@vben-core/shared';
import BadgeDot from './menu-badge-dot.vue';
@ -34,9 +34,9 @@ const badgeClass = computed(() => {
});
const badgeStyle = computed(() => {
if (badgeClass.value && isValidColor(badgeClass.value)) {
if (badgeClass.value) {
return {
backgroundColor: badgeClass.value,
backgroundColor: convertToRgb(badgeClass.value),
};
}
return {};

View File

@ -1,4 +1,2 @@
import './styles/index.css';
export * from './components';
export { VisuallyHidden } from 'radix-vue';

View File

@ -41,6 +41,6 @@
"@vben-core/icons": "workspace:*",
"@vben-core/shadcn-ui": "workspace:*",
"@vben-core/typings": "workspace:*",
"vue": "^3.4.35"
"vue": "^3.4.36"
}
}

View File

@ -24,6 +24,6 @@
"@vben/stores": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"vue": "^3.4.35"
"vue": "^3.4.36"
}
}

View File

@ -23,6 +23,6 @@
"@vben/preferences": "workspace:*",
"@vueuse/core": "^10.11.0",
"echarts": "^5.5.1",
"vue": "^3.4.35"
"vue": "^3.4.36"
}
}

View File

@ -27,9 +27,9 @@
"@vben/locales": "workspace:*",
"@vben/types": "workspace:*",
"@vueuse/integrations": "^10.11.0",
"qrcode": "^1.5.3",
"vue": "^3.4.35",
"vue-router": "^4.4.2"
"qrcode": "^1.5.4",
"vue": "^3.4.36",
"vue-router": "^4.4.3"
},
"devDependencies": {
"@types/qrcode": "^1.5.5"

View File

@ -25,8 +25,8 @@
"@vben/stores": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"vue": "^3.4.35",
"vue-router": "^4.4.2",
"vue": "^3.4.36",
"vue-router": "^4.4.3",
"watermark-js-plus": "^1.5.2"
}
}

View File

@ -1,7 +1,7 @@
import { reactive, watch } from 'vue';
import { preferences } from '@vben/preferences';
import { hlsStringToRGBString, updateCSSVariables } from '@vben/utils';
import { convertToRgb, updateCSSVariables } from '@vben/utils';
/**
*
@ -102,7 +102,7 @@ export function useNaiveDesignTokens() {
const getCssVariableValue = (variable: string, isColor: boolean = true) => {
const value = rootStyles.getPropertyValue(variable);
return isColor ? hlsStringToRGBString(value) : value;
return isColor ? convertToRgb(`hsl(${value})`) : value;
};
watch(
@ -145,8 +145,6 @@ export function useNaiveDesignTokens() {
commonTokens.invertedColor = getCssVariableValue('--background-deep');
commonTokens.borderRadius = getCssVariableValue('--radius', false);
// antDesignTokens.colorBgMask = getCssVariableValue('--overlay');
},
{ immediate: true },
);
@ -160,7 +158,7 @@ export function useElementPlusDesignTokens() {
const getCssVariableValue = (variable: string, isColor: boolean = true) => {
const value = rootStyles.getPropertyValue(variable);
return isColor ? `hsl(${value})` : value;
return isColor ? convertToRgb(`hsl(${value})`) : value;
};
watch(
() => preferences.theme,

View File

@ -33,7 +33,7 @@
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"@vueuse/core": "^10.11.0",
"vue": "^3.4.35",
"vue-router": "^4.4.2"
"vue": "^3.4.36",
"vue-router": "^4.4.3"
}
}

View File

@ -22,17 +22,11 @@ const modelValue = defineModel<BuiltinThemeType>({ default: 'default' });
const themeColorPrimary = defineModel<string>('themeColorPrimary');
const inputValue = computed(() => {
return new TinyColor(themeColorPrimary.value).toHexString();
return new TinyColor(themeColorPrimary.value || '').toHexString();
});
const builtinThemePresets = computed(() => {
return [
// {
// color: 'hsl(231 98% 65%)',
// type: 'default',
// },
...BUILT_IN_THEME_PRESETS,
];
return [...BUILT_IN_THEME_PRESETS];
});
function typeView(name: BuiltinThemeType) {

View File

@ -277,12 +277,6 @@ async function handleReset() {
v-model:theme-semi-dark-menu="themeSemiDarkMenu"
/>
</Block>
<!-- <Block :title="$t('preferences.theme-color')">
<ThemeColor
v-model="themeColorPrimary"
:color-primary-presets="colorPrimaryPresets"
/>
</Block> -->
<Block :title="$t('preferences.theme.builtin.title')">
<BuiltinTheme
v-model="themeBuiltinType"

View File

@ -21,7 +21,7 @@
},
"dependencies": {
"@intlify/core-base": "^9.13.1",
"vue": "^3.4.35",
"vue": "^3.4.36",
"vue-i18n": "^9.13.1"
}
}

View File

@ -24,7 +24,7 @@
"@vben-core/typings": "workspace:*",
"pinia": "2.2.0",
"pinia-plugin-persistedstate": "^3.2.1",
"vue": "^3.4.35",
"vue-router": "^4.4.2"
"vue": "^3.4.36",
"vue-router": "^4.4.3"
}
}

View File

@ -21,7 +21,7 @@
},
"dependencies": {
"@vben-core/typings": "workspace:*",
"vue": "^3.4.35",
"vue-router": "^4.4.2"
"vue": "^3.4.36",
"vue-router": "^4.4.3"
}
}

View File

@ -24,6 +24,6 @@
"dependencies": {
"@vben-core/shared": "workspace:*",
"@vben-core/typings": "workspace:*",
"vue-router": "^4.4.2"
"vue-router": "^4.4.3"
}
}

View File

@ -1,3 +1,3 @@
export * from './helpers';
export * from '@vben-core/shared/colorful';
export * from '@vben-core/shared/color';
export * from '@vben-core/shared/utils';

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@ async function runDepcheck() {
// 删除file:前缀的依赖提示,该依赖是本地依赖
Reflect.deleteProperty(unused.missing, 'file:');
Object.keys(unused.missing).forEach((key) => {
unused.missing[key] = unused.missing[key].filter(
unused.missing[key] = (unused.missing[key] || []).filter(
(item: string) => !item.startsWith('/'),
);
if (unused.missing[key].length === 0) {