chore: docs 迁移至 apps

This commit is contained in:
wangxuefeng
2025-03-12 14:32:58 +08:00
parent c86bf9e62e
commit bcdb4e8c95
91 changed files with 111 additions and 193 deletions

View File

@@ -0,0 +1,243 @@
# 构建与部署
::: tip 前言
由于是展示项目,所以打包后相对较大,如果项目中没有用到的插件,可以删除对应的文件或者路由,不引用即可,没有引用就不会打包。
:::
## 构建
项目开发完成之后,执行以下命令进行构建:
**注意:** 请在项目根目录下执行以下命令
```bash
pnpm build
```
构建打包成功之后,会在根目录生成对应的应用下的 `dist` 文件夹,里面就是构建打包好的文件,例如: `apps/web-antd/dist/`
## 预览
发布之前可以在本地进行预览,有多种方式,这里介绍两种:
- 使用项目自定的命令进行预览(推荐)
**注意:** 请在项目根目录下执行以下命令
```bash
pnpm preview
```
等待构建成功后,访问 `http://localhost:4173` 即可查看效果。
- 本地服务器预览
可以在电脑全局安装 `serve` 服务,如 `live-server`,
```bash
npm i -g live-server
```
然后在 `dist` 目录下执行 `live-server` 命令,即可在本地查看效果。
```bash
cd apps/web-antd/dist
# 本地预览默认端口8080
live-server
# 指定端口
live-server --port=9000
```
## 压缩
### 开启 `gzip` 压缩
需要在打包的时候更改`.env.production`配置:
```bash
VITE_COMPRESS=gzip
```
### 开启 `brotli` 压缩
需要在打包的时候更改`.env.production`配置:
```bash
VITE_COMPRESS=brotli
```
### 同时开启 `gzip` 和 `brotli` 压缩
需要在打包的时候更改`.env.production`配置:
```bash
VITE_COMPRESS=gzip,brotli
```
::: tip 提示
`gzip``brotli` 都需要安装特定模块才能使用。
:::
::: details gzip 与 brotli 在 nginx 内的配置
```bash
http {
# 开启gzip
gzip on;
# 开启gzip_static
# gzip_static 开启后可能会报错,需要安装相应的模块, 具体安装方式可以自行查询
# 只有这个开启vue文件打包的.gz文件才会有效果否则不需要开启gzip进行打包
gzip_static on;
gzip_proxied any;
gzip_min_length 1k;
gzip_buffers 4 16k;
#如果nginx中使用了多层代理 必须设置这个才可以开启gzip。
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary off;
gzip_disable "MSIE [1-6]\.";
# 开启 brotli压缩
# 需要安装对应的nginx模块,具体安装方式可以自行查询
# 可以与gzip共存不会冲突
brotli on;
brotli_comp_level 6;
brotli_buffers 16 8k;
brotli_min_length 20;
brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
}
```
:::
## 构建分析
如果你的构建文件很大,可以通过项目内置 [rollup-plugin-analyzer](https://github.com/doesdev/rollup-plugin-analyzer) 插件进行代码体积分析,从而优化你的代码。只需要在`根目录`下执行以下命令:
```bash
pnpm run build:analyze
```
运行之后,在自动打开的页面可以看到具体的体积分布,以分析哪些依赖有问题。
![Build analysis report](/guide/report.png)
## 部署
简单的部署只需要将最终生成的静态文件dist 文件夹的静态文件发布到你的 cdn 或者静态服务器即可,需要注意的是其中的 index.html 通常会是你后台服务的入口页面,在确定了 js 和 css 的静态之后可能需要改变页面的引入路径。
例如上传到 nginx 服务器,可以将 dist 文件夹下的文件上传到服务器的 `/srv/www/project/index.html` 目录下,然后访问配置好的域名即可。
```bash
# nginx配置
location / {
# 不缓存html防止程序更新后缓存继续生效
if ($request_filename ~* .*\.(?:htm|html)$) {
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
access_log on;
}
# 这里是vue打包文件dist内的文件的存放路径
root /srv/www/project/;
index index.html index.htm;
}
```
部署时可能会发现资源路径不对,只需要修改`.env.production`文件即可。
```bash
# 根据自己路径来配置更改
# 注意需要以 / 开头和结尾
VITE_BASE=/
VITE_BASE=/xxx/
```
### 前端路由与服务端的结合
项目前端路由使用的是 vue-router所以你可以选择两种方式history 和 hash。
- `hash` 默认会在 url 后面拼接`#`
- `history` 则不会,不过 `history` 需要服务器配合
可在 `.env.production` 内进行 mode 修改
```bash
VITE_ROUTER_HISTORY=hash
```
### history 路由模式下服务端配置
开启 `history` 模式需要服务器配置,更多的服务器配置详情可以看 [history-mode](https://router.vuejs.org/guide/essentials/history-mode.html#html5-mode)
这里以 `nginx` 配置为例:
#### 部署到根目录
```bash {5}
server {
listen 80;
location / {
# 用于配合 History 使用
try_files $uri $uri/ /index.html;
}
}
```
#### 部署到非根目录
- 首先需要在打包的时候更改`.env.production`配置:
```bash
VITE_BASE = /sub/
```
- 然后在 nginx 配置文件中配置
```bash {8}
server {
listen 80;
server_name localhost;
location /sub/ {
# 这里是vue打包文件dist内的文件的存放路径
alias /srv/www/project/;
index index.html index.htm;
try_files $uri $uri/ /sub/index.html;
}
}
```
## 跨域处理
使用 nginx 处理项目部署后的跨域问题
1. 配置前端项目接口地址,在项目目录下的``.env.production`文件中配置:
```bash
VITE_GLOB_API_URL=/api
```
2. 在 nginx 配置请求转发到后台
```bash {10-11}
server {
listen 8080;
server_name localhost;
# 接口代理,用于解决跨域问题
location /api {
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_pass http://110.110.1.1:8080/api;
rewrite "^/api/(.*)$" /$1 break;
proxy_redirect default;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
}
}
```

View File

@@ -0,0 +1,24 @@
# 基础概念
## 低代码引擎
新版本中,悦码整体进行了重构,现在我们将会介绍一些基础概念,以便于你更好的理解悦码是如何工作的。请务必仔细阅读这一部分。
## 悦码中的 DSL (领域特定语言)
> DSL (Domain-Specific Language领域特定语言) 在低代码平台中是一种专门设计用来描述和定义应用程序特定方面的语言或表达方式。
核心特点:
- 专注于特定领域DSL 专门针对特定问题域设计,如 UI 布局、工作流定义、数据模型等。
- 声明式而非命令式:通常使用声明式语法描述"做什么"而非"怎么做"。
- 抽象层次高:隐藏底层实现细节,让用户专注于业务逻辑。
- 结构化数据格式:通常使用 JSON、YAML 或 XML 等格式表示。
主要作用:
- 抽象复杂性:将复杂的编程概念转化为领域专家能理解的表达方式。
- 提高效率:通过声明式语法快速构建应用,减少编码工作。
- 标准化:为应用开发提供统一的描述方式,便于团队协作。
- 可视化编辑DSL 通常可以通过可视化编辑器生成和修改,无需直接编写。
- 跨平台兼容:同一套 DSL 可以被转译为不同平台的代码。

View File

@@ -0,0 +1 @@
# 本地开发 {#development}

View File

@@ -0,0 +1 @@
# 外部模块

View File

@@ -0,0 +1 @@
# icons

View File

@@ -0,0 +1 @@
# route

View File

@@ -0,0 +1 @@
server

View File

@@ -0,0 +1 @@
# settings

View File

@@ -0,0 +1 @@
# styles

View File

@@ -0,0 +1,311 @@
---
outline: deep
---
# 权限
框架内置了两种权限控制方式:
- 通过用户角色来判断菜单或者按钮是否可以访问
- 通过接口来判断菜单或者按钮是否可以访问
## 前端访问控制
**实现原理**: 在前端固定写死路由的权限,指定路由有哪些权限可以查看。只初始化通用的路由,需要权限才能访问的路由没有被加入路由表内。在登录后或者其他方式获取用户角色后,通过角色去遍历路由表,获取该角色可以访问的路由表,生成路由表,再通过 `router.addRoute` 添加到路由实例,实现权限的过滤。
**缺点**: 权限相对不自由,如果后台改动角色,前台也需要跟着改动。适合角色较固定的系统
### 步骤
- 确保当前模式为前端访问控制模式
调整对应应用目录下的`preferences.ts`,确保`accessMode='frontend'`
```ts
import { defineOverridesPreferences } from '@vben/preferences';
export const overridesPreferences = defineOverridesPreferences({
// overrides
app: {
// 默认值,可不填
accessMode: 'frontend',
},
});
```
- 配置路由权限
**如果不配置,默认可见**
```ts {3}
{
meta: {
authority: ['super'],
},
},
```
- 确保接口返回的角色和路由表的权限匹配
可查看应用下的 `src/store/auth`,找到下面代码,
```ts
// 设置登录用户信息,需要确保 userInfo.roles 是一个数组,且包含路由表中的权限
// 例如userInfo.roles=['super', 'admin']
authStore.setUserInfo(userInfo);
```
到这里,就已经配置完成,你需要确保登录后,接口返回的角色和路由表的权限匹配,否则无法访问。
### 菜单可见,但禁止访问
有时候,我们需要菜单可见,但是禁止访问,可以通过下面的方式实现,设置 `menuVisibleWithForbidden` 为 `true`此时菜单可见但是禁止访问会跳转403页面。
```ts
{
meta: {
menuVisibleWithForbidden: true,
},
},
```
## 后端访问控制
**实现原理**: 是通过接口动态生成路由表,且遵循一定的数据结构返回。前端根据需要处理该数据为可识别的结构,再通过 `router.addRoute` 添加到路由实例,实现权限的动态生成。
**缺点**: 后端需要提供符合规范的数据结构,前端需要处理数据结构,适合权限较为复杂的系统。
### 步骤
- 确保当前模式为后端访问控制模式
调整对应应用目录下的`preferences.ts`,确保`accessMode='backend'`。
```ts
import { defineOverridesPreferences } from '@vben/preferences';
export const overridesPreferences = defineOverridesPreferences({
// overrides
app: {
accessMode: 'backend',
},
});
```
- 确保接口返回的菜单数据结构正确
可查看应用下的 `src/router/access.ts`,找到下面代码,
```ts {5}
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
return await generateAccessible(preferences.app.accessMode, {
fetchMenuListAsync: async () => {
// 这个接口为后端返回的菜单数据
return await getAllMenus();
},
});
}
```
- 接口返回菜单数据,可看注释说明
::: details 接口返回菜单数据示例
```ts
const dashboardMenus = [
{
// 这里固定写死 BasicLayout不可更改
component: 'BasicLayout',
meta: {
order: -1,
title: 'page.dashboard.title',
},
name: 'Dashboard',
path: '/',
redirect: '/analytics',
children: [
{
name: 'Analytics',
path: '/analytics',
// 这里为页面的路径,需要去掉 views/ 和 .vue
component: '/dashboard/analytics/index',
meta: {
affixTab: true,
title: 'page.dashboard.analytics',
},
},
{
name: 'Workspace',
path: '/workspace',
component: '/dashboard/workspace/index',
meta: {
title: 'page.dashboard.workspace',
},
},
],
},
];
```
:::
到这里,就已经配置完成,你需要确保登录后,接口返回的菜单格式正确,否则无法访问。
## 按钮细粒度控制
在某些情况下,我们需要对按钮进行细粒度的控制,我们可以借助接口或者角色来控制按钮的显示。
### 权限码
权限码为接口返回的权限码,通过权限码来判断按钮是否显示,逻辑在`src/store/auth`下:
```ts
const [fetchUserInfoResult, accessCodes] = await Promise.all([
fetchUserInfo(),
getAccessCodes(),
]);
userInfo = fetchUserInfoResult;
authStore.setUserInfo(userInfo);
accessStore.setAccessCodes(accessCodes);
```
找到 `getAccessCodes` 对应的接口,可根据业务逻辑进行调整。
权限码返回的数据结构为字符串数组,例如:`['AC_100100', 'AC_100110', 'AC_100120', 'AC_100010']`
有了权限码,就可以使用 `@vben/access` 提供的`AccessControl`组件及API来进行按钮的显示与隐藏。
#### 组件方式
```vue
<script lang="ts" setup>
import { AccessControl, useAccess } from '@vben/access';
const { accessMode, hasAccessByCodes } = useAccess();
</script>
<template>
<!-- 需要指明 type="code" -->
<AccessControl :codes="['AC_100100']" type="code">
<Button> Super 账号可见 ["AC_1000001"] </Button>
</AccessControl>
<AccessControl :codes="['AC_100030']" type="code">
<Button> Admin 账号可见 ["AC_100010"] </Button>
</AccessControl>
<AccessControl :codes="['AC_1000001']" type="code">
<Button> User 账号可见 ["AC_1000001"] </Button>
</AccessControl>
<AccessControl :codes="['AC_100100', 'AC_100010']" type="code">
<Button> Super & Admin 账号可见 ["AC_100100","AC_1000001"] </Button>
</AccessControl>
</template>
```
#### API方式
```vue
<script lang="ts" setup>
import { AccessControl, useAccess } from '@vben/access';
const { hasAccessByCodes } = useAccess();
</script>
<template>
<Button v-if="hasAccessByCodes(['AC_100100'])">
Super 账号可见 ["AC_1000001"]
</Button>
<Button v-if="hasAccessByCodes(['AC_100030'])">
Admin 账号可见 ["AC_100010"]
</Button>
<Button v-if="hasAccessByCodes(['AC_1000001'])">
User 账号可见 ["AC_1000001"]
</Button>
<Button v-if="hasAccessByCodes(['AC_100100', 'AC_1000001'])">
Super & Admin 账号可见 ["AC_100100","AC_1000001"]
</Button>
</template>
```
#### 指令方式
> 指令支持绑定单个或多个权限码。单个时可以直接传入字符串或数组中包含一个权限码,多个权限码则传入数组。
```vue
<template>
<Button class="mr-4" v-access:code="'AC_100100'">
Super 账号可见 'AC_100100'
</Button>
<Button class="mr-4" v-access:code="['AC_100030']">
Admin 账号可见 ["AC_100010"]
</Button>
<Button class="mr-4" v-access:code="['AC_1000001']">
User 账号可见 ["AC_1000001"]
</Button>
<Button class="mr-4" v-access:code="['AC_100100', 'AC_1000001']">
Super & Admin 账号可见 ["AC_100100","AC_1000001"]
</Button>
</template>
```
### 角色
角色判断方式不需要接口返回的权限码,直接通过角色来判断按钮是否显示。
#### 组件方式
```vue
<script lang="ts" setup>
import { AccessControl } from '@vben/access';
</script>
<template>
<AccessControl :codes="['super']">
<Button> Super 角色可见 </Button>
</AccessControl>
<AccessControl :codes="['admin']">
<Button> Admin 角色可见 </Button>
</AccessControl>
<AccessControl :codes="['user']">
<Button> User 角色可见 </Button>
</AccessControl>
<AccessControl :codes="['super', 'admin']">
<Button> Super & Admin 角色可见 </Button>
</AccessControl>
</template>
```
#### API方式
```vue
<script lang="ts" setup>
import { useAccess } from '@vben/access';
const { hasAccessByRoles } = useAccess();
</script>
<template>
<Button v-if="hasAccessByRoles(['super'])"> Super 账号可见 </Button>
<Button v-if="hasAccessByRoles(['admin'])"> Admin 账号可见 </Button>
<Button v-if="hasAccessByRoles(['user'])"> User 账号可见 </Button>
<Button v-if="hasAccessByRoles(['super', 'admin'])">
Super & Admin 账号可见
</Button>
</template>
```
#### 指令方式
> 指令支持绑定单个或多个角色。单个时可以直接传入字符串或数组中包含一个角色,多个角色均可访问则传入数组。
```vue
<template>
<Button class="mr-4" v-access:role="'super'"> Super 角色可见 </Button>
<Button class="mr-4" v-access:role="['super']"> Super 角色可见 </Button>
<Button class="mr-4" v-access:role="['admin']"> Admin 角色可见 </Button>
<Button class="mr-4" v-access:role="['user']"> User 角色可见 </Button>
<Button class="mr-4" v-access:role="['super', 'admin']">
Super & Admin 角色可见
</Button>
</template>
```

View File

@@ -0,0 +1,48 @@
# 检查更新
## 介绍
当网站有更新时,您可能需要检查更新。框架提供了这一功能,通过定时检查更新,您可以在应用的 preferences.ts 文件中配置 `checkUpdatesInterval``enableCheckUpdates` 字段,以开启和设置检查更新的时间间隔(单位:分钟)。
```ts
import { defineOverridesPreferences } from '@vben/preferences';
export const overridesPreferences = defineOverridesPreferences({
// overrides
app: {
// 是否开启检查更新
enableCheckUpdates: true,
// 检查更新的时间间隔,单位为分钟
checkUpdatesInterval: 1,
},
});
```
## 效果
检测到更新时,会弹出提示框,询问用户是否刷新页面:
![check-updates](/guide/update-notice.png)
## 替换为其他检查更新方式
如果需要通过其他方式检查更新,例如通过接口来更灵活地控制更新逻辑(如强制刷新、显示更新内容等),你可以通过修改 `@vben/layouts` 下面的 `src/widgets/check-updates/check-updates.vue`文件来实现。
```ts
// 这里可以替换为你的检查更新逻辑
async function getVersionTag() {
try {
const response = await fetch('/', {
cache: 'no-cache',
method: 'HEAD',
});
return (
response.headers.get('etag') || response.headers.get('last-modified')
);
} catch {
console.error('Failed to fetch version tag');
return null;
}
}
```

View File

@@ -0,0 +1,84 @@
# 常用功能
一些常用的功能合集。
## 登录认证过期
当接口返回`401`状态码时,框架会认为登录认证过期,登录超时会跳转到登录页或者打开登录弹窗。在应用目录下的`preferences.ts`可以配置:
### 跳转登录页面
登录超时会跳转到登录页
```ts
import { defineOverridesPreferences } from '@vben/preferences';
export const overridesPreferences = defineOverridesPreferences({
// overrides
app: {
loginExpiredMode: 'page',
},
});
```
### 打开登录弹窗
登录超时会打开登录弹窗
![](/guide/login-expired.png)
配置:
```ts
import { defineOverridesPreferences } from '@vben/preferences';
export const overridesPreferences = defineOverridesPreferences({
// overrides
app: {
loginExpiredMode: 'modal',
},
});
```
## 动态标题
- 默认值:`true`
开启后网页标题随着路由的`title`而变化。在应用目录下的`preferences.ts`,开启或者关闭即可。
```ts
export const overridesPreferences = defineOverridesPreferences({
// overrides
app: {
dynamicTitle: true,
},
});
```
## 页面水印
- 默认值:`false`
开启后网页会显示水印,在应用目录下的`preferences.ts`,开启或者关闭即可。
```ts
export const overridesPreferences = defineOverridesPreferences({
// overrides
app: {
watermark: true,
},
});
```
如果你想更新水印的内容,可以这么做,参数可以参考 [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/)
```ts
import { useWatermark } from '@vben/hooks';
const { destroyWatermark, updateWatermark } = useWatermark();
await updateWatermark({
// 水印内容
content: 'hello my watermark',
});
```

View File

@@ -0,0 +1 @@
# 布局

View File

@@ -0,0 +1,46 @@
# 全局loading
全局 loading 指的是页面刷新时出现的加载效果,通常是一个旋转的图标:
![Global loading spinner](/guide/loading.png)
## 原理
`vite-plugin-inject-app-loading` 插件实现,插件会在每个应用都注入一个全局的 `loading html`
## 关闭
如果你不需要全局 loading可以在 `.env` 文件中关闭:
```bash
VITE_INJECT_APP_LOADING=false
```
## 自定义
如果你想要自定义全局 loading可以在应用目录下`index.html`同级,创建一个`loading.html`文件插件会自动读取并注入。这个html可以自行定义样式和动画。
::: tip
- 你可以使用跟`index.html`一样的语法,比如`VITE_APP_TITLE`变量,来获取应用的标题。
- 必须保证有一个`id="__app-loading__"`的元素。
-`id="__app-loading__"`的元素,加一个 `hidden` class。
- 必须保证有一个`style[data-app-loading="inject-css"]`的元素。
```html{1,4}
<style data-app-loading="inject-css">
#__app-loading__.hidden {
pointer-events: none;
visibility: hidden;
opacity: 0;
transition: all 1s ease-out;
}
/* ... */
</style>
<div id="__app-loading__">
<!-- ... -->
<div class="title"><%= VITE_APP_TITLE %></div>
</div>
```
:::

View File

@@ -0,0 +1,227 @@
# 国际化
项目已经集成了 [Vue i18n](https://kazupon.github.io/vue-i18n/),并且已经配置好了中文和英文的语言包。
## IDE 插件
如果你使用的 vscode 开发工具,则推荐安装 [i18n Ally](https://marketplace.visualstudio.com/items?itemName=Lokalise.i18n-ally) 这个插件。它可以帮助你更方便的管理国际化的文案,安装了该插件后,你的代码内可以实时看到对应的语言内容:
![](/public/guide/locale.png)
## 配置默认语言
只需要覆盖默认的偏好设置即可,在对应的应用内,找到 `src/preferences.ts` 文件,修改 `locale` 的值即可:
```ts {3}
export const overridesPreferences = defineOverridesPreferences({
app: {
locale: 'en-US',
},
});
```
## 动态切换语言
切换语言有两部分组成:
- 更新偏好设置
- 加载对应的语言包
```ts
import type { SupportedLanguagesType } from '@vben/locales';
import { loadLocaleMessages } from '@vben/locales';
import { updatePreferences } from '@vben/preferences';
async function updateLocale(value: string) {
// 1. 更新偏好设置
const locale = value as SupportedLanguagesType;
updatePreferences({
app: {
locale,
},
});
// 2. 加载对应的语言包
await loadLocaleMessages(locale);
}
updateLocale('en-US');
```
## 新增翻译文本
::: warning 注意
- 请不要将业务翻译文本放到 `@vben/locales` 内,这样可以更好的管理业务和通用的翻译文本。
- 有多个语言包的情况下,新增翻译文本时,需要在所有语言包内新增对应的文本。
:::
新增翻译文本,只需要在对应的应用内,找到 `src/locales/langs/`,新增对应的文本即可,例:
**src/locales/langs/zh-CN/\*.json**
````ts
```json
{
"about": {
"desc": "y-code-platform 是一个现代的管理模版。"
}
}
````
**src/locales/langs/en-US.ts**
````ts
```json
{
"about": {
"desc": "y-code-platform is a modern management template."
}
}
````
## 使用翻译文本
通过 `@vben/locales`,你可以很方便的使用翻译文本:
### 在代码中使用
```vue
<script setup lang="ts">
import { computed } from 'vue';
import { $t } from '@vben/locales';
const items = computed(() => [{ title: $t('about.desc') }]);
</script>
<template>
<div>{{ $t('about.desc') }}</div>
<template v-for="item in items.value">
<div>{{ item.title }}</div>
</template>
</template>
```
## 新增语言包
如果你需要新增语言包,需要按照以下步骤进行:
- 在 `packages/locales/langs` 目录下新增对应的语言包文件,例:`zh-TW.json`,并翻译对应的文本。
- 在对应的应用内,找到 `src/locales/langs` 文件,新增对应的语言包 `zh-TW.json`
- 在 `packages/constants/src/core.ts`内,新增对应的语言:
```ts
export interface LanguageOption {
label: string;
value: 'en-US' | 'zh-CN'; // [!code --]
value: 'en-US' | 'zh-CN' | 'zh-TW'; // [!code ++]
}
export const SUPPORT_LANGUAGES: LanguageOption[] = [
{
label: '简体中文',
value: 'zh-CN',
},
{
label: 'English',
value: 'en-US',
},
{
label: '繁体中文', // [!code ++]
value: 'zh-TW', // [!code ++]
},
];
```
- 在 `packages/locales/typing.ts`内,新增 Typescript 类型:
```ts
export type SupportedLanguagesType = 'en-US' | 'zh-CN'; // [!code --]
export type SupportedLanguagesType = 'en-US' | 'zh-CN' | 'zh-TW'; // [!code ++]
```
到这里,你就可以在项目内使用新增的语言包了。
## 界面切换语言功能
如果你想关闭界面上的语言切换显示按钮,在对应的应用内,找到 `src/preferences.ts` 文件,修改 `locale` 的值即可:
```ts {3}
export const overridesPreferences = defineOverridesPreferences({
widget: {
languageToggle: false,
},
});
```
## 远程加载语言包
::: tip 提示
通过项目自带的`request`工具进行接口请求时,默认请求头里会带上 [Accept-Language](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Language) ,服务端可根据请求头进行动态数据国际化处理。
:::
每个应用都有一个独立的语言包,它可以覆盖通用的语言配置,你可以通过远程加载的方式来获取对应的语言包,只需要在对应的应用内,找到 `src/locales/index.ts` 文件,修改 `loadMessages` 方法即可:
```ts {3-4}
async function loadMessages(lang: SupportedLanguagesType) {
const [appLocaleMessages] = await Promise.all([
// 这里修改为远程接口加载数据即可
localesMap[lang](),
loadThirdPartyMessage(lang),
]);
return appLocaleMessages.default;
}
```
## 第三方语言包
不同应用内使用的第三方组件库或者插件国际化方式可能不一致,所以需要差别处理。 如果你需要引入第三方的语言包,你可以在对应的应用内,找到 `src/locales/index.ts` 文件,修改 `loadThirdPartyMessage` 方法即可:
```ts
/**
* 加载dayjs的语言包
* @param lang
*/
async function loadDayjsLocale(lang: SupportedLanguagesType) {
let locale;
switch (lang) {
case 'zh-CN': {
locale = await import('dayjs/locale/zh-cn');
break;
}
case 'en-US': {
locale = await import('dayjs/locale/en');
break;
}
// 默认使用英语
default: {
locale = await import('dayjs/locale/en');
}
}
if (locale) {
dayjs.locale(locale);
} else {
console.error(`Failed to load dayjs locale for ${lang}`);
}
}
```
## 移除国际化
首先,不是很建议移除国际化,因为国际化是一个很好的开发习惯,但是如果你真的需要移除国际化,你可以直接使用中文文案,然后保留项目自带的语言包即可,整体开发体验不会影响。移除国际化的步骤如下:
- 隐藏界面上的语言切换按钮,见:[界面切换语言功能](#界面切换语言功能)
- 修改默认语言,见:[配置默认语言](#配置默认语言)
- 关闭 `vue-i18n`的警告提示,在`src/locales/index.ts`文件内,修改`missingWarn`为`false`即可:
```ts
async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
await coreSetup(app, {
defaultLocale: preferences.app.locale,
loadMessages,
missingWarn: !import.meta.env.PROD, // [!code --]
missingWarn: false, // [!code ++]
...options,
});
}
```

View File

@@ -0,0 +1,220 @@
---
outline: deep
---
# 登录
本文介绍如何去改造自己的应用程序登录页以及如何快速的对接登录页面接口。
## 登录页面调整
如果你想调整登录页面的标题、描述和图标以及工具栏,你可以通过配置 `AuthPageLayout` 组件的参数来实现。
![login](/guide/login.png)
只需要在应用下的 `src/layouts/auth.vue` 内,配置`AuthPageLayout``props`参数即可:
```vue {2-7}
<AuthPageLayout
:copyright="true"
:toolbar="true"
:toolbarList="['color', 'language', 'layout', 'theme']"
:app-name="appName"
:logo="logo"
:page-description="$t('authentication.pageDesc')"
:page-title="$t('authentication.pageTitle')"
>
</AuthPageLayout>
```
## 登录表单调整
如果你想调整登录表单的相关内容,你可以在应用下的 `src/views/_core/authentication/login.vue` 内,配置`AuthenticationLogin` 组件参数即可:
```vue
<AuthenticationLogin
:loading="authStore.loginLoading"
@submit="authStore.authLogin"
/>
```
::: details AuthenticationLogin 组件参数
```ts
{
/**
* @zh_CN 验证码登录路径
*/
codeLoginPath?: string;
/**
* @zh_CN 忘记密码路径
*/
forgetPasswordPath?: string;
/**
* @zh_CN 是否处于加载处理状态
*/
loading?: boolean;
/**
* @zh_CN 二维码登录路径
*/
qrCodeLoginPath?: string;
/**
* @zh_CN 注册路径
*/
registerPath?: string;
/**
* @zh_CN 是否显示验证码登录
*/
showCodeLogin?: boolean;
/**
* @zh_CN 是否显示忘记密码
*/
showForgetPassword?: boolean;
/**
* @zh_CN 是否显示二维码登录
*/
showQrcodeLogin?: boolean;
/**
* @zh_CN 是否显示注册按钮
*/
showRegister?: boolean;
/**
* @zh_CN 是否显示记住账号
*/
showRememberMe?: boolean;
/**
* @zh_CN 是否显示第三方登录
*/
showThirdPartyLogin?: boolean;
/**
* @zh_CN 登录框子标题
*/
subTitle?: string;
/**
* @zh_CN 登录框标题
*/
title?: string;
}
```
:::
::: tip Note
如果这些配置不能满足你的需求,你可以自行实现登录表单及相关登录逻辑或者给我们提交 `PR`。
:::
## 接口对接流程
这里将会快速的介绍如何快速对接自己的后端。
### 前置条件
- 首先文档用的后端服务,接口返回的格式统一如下:
```ts
interface HttpResponse<T = any> {
/**
* 0 表示成功 其他表示失败
* 0 means success, others means fail
*/
code: number;
data: T;
message: string;
}
```
如果你不符合这个格式,你需要先阅读 [服务端交互](../essentials/server.md) 文档,改造你的`request.ts`配置。
- 其次你需要在先将本地代理地址改为你的真实后端地址,你可以在应用下的 `vite.config.mts` 内配置:
```ts
import { defineConfig } from '@vben/vite-config';
export default defineConfig(async () => {
return {
vite: {
server: {
proxy: {
'/api': {
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
// 这里改为你的真实接口地址
target: 'http://localhost:5320/api',
ws: true,
},
},
},
},
};
});
```
### 登录接口
为了能正常登录,你的后端最少需要提供 `2-3` 个接口:
- 登录接口
接口地址可在应用下的 `src/api/core/auth` 内修改,以下为默认接口地址:
```ts
/**
* 登录
*/
export async function loginApi(data: AuthApi.LoginParams) {
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
}
/** 只需要保证登录接口返回值有 `accessToken` 字段即可 */
export interface LoginResult {
accessToken: string;
}
```
- 获取用户信息接口
接口地址可在应用下的 `src/api/core/user` 内修改,以下为默认接口地址:
```ts
export async function getUserInfoApi() {
return requestClient.get<UserInfo>('/user/info');
}
/** 只需要保证登录接口返回值有以下字段即可,多的字段可以自行使用 */
export interface UserInfo {
roles: string[];
realName: string;
}
```
- 获取权限码 (可选)
这个接口用于获取用户的权限码,权限码是用于控制用户的权限的,接口地址可在应用下的 `src/api/core/auth` 内修改,以下为默认接口地址:
```ts
export async function getAccessCodesApi() {
return requestClient.get<string[]>('/auth/codes');
}
```
如果你不需要这个权限,你只需要把代码改为返回一个空数组即可。
```ts {2}
export async function getAccessCodesApi() {
// 这里返回一个空数组即可
return [];
}
```

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
# 组件库切换
`Vue Admin` 支持你自由选择组件库,目前演示站点的默认组件库是 `Ant Design Vue`,与旧版本保持一致。同时框架还内置了 `Element Plus` 版本和 `Naive UI` 版本,你可以根据自己的喜好选择。
## 新增组件库应用
如果你想用其他别的组件库,你只需要按以下步骤进行操作:
1.`apps`内创建一个新的文件夹,例如`apps/web-xxx`
2. 更改`apps/web-xxx/package.json``name`字段为`web-xxx`
3. 移除其他组件库依赖及代码,并用你的组件库进行替换相应逻辑,需要改动的地方不多。
4. 调整`locales`内的语言文件。
5. 调整 `app.vue` 内的组件。
6. 自行适配组件库的主题,与 `y-code-platform` 契合。
7. 调整 `.env` 内的应用名
8. 在大仓根目录增加 `dev:xxx` 脚本
9. 执行 `pnpm install` 安装依赖

View File

@@ -0,0 +1,3 @@
# 更新日志
TODO

View File

@@ -0,0 +1,17 @@
# 关于低代码管理平台
## 特点
- **最新技术栈**:使用 `Vue3``Vite``TypeScript` 等前端前沿技术开发。
- **组件丰富**:提供了丰富的组件,可以满足大部分的业务需求。
- **多UI库支持**:支持 `Ant Design Vue``Element Plus` 等主流 UI 库,不再限制于特定框架。
## 浏览器支持
- **本地开发**推荐使用`Chrome 最新版`浏览器,**不支持**`Chrome 80`以下版本。
- **生产环境**支持现代浏览器,不支持 IE。
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="IE" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)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/)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/)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/)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/)Safari |
| :-: | :-: | :-: | :-: | :-: |
| 不支持 | last 2 versions | last 2 versions | last 2 versions | last 2 versions |

View File

@@ -0,0 +1,112 @@
---
outline: deep
---
# 快速开始 {#quick-start}
## 前置准备
::: info 环境要求
在启动项目前,你需要确保你的环境满足以下要求:
- [Node.js](https://nodejs.org/en) 20.15.0 及以上版本,推荐使用 [fnm](https://github.com/Schniz/fnm) 、 [nvm](https://github.com/nvm-sh/nvm) 或者直接使用[pnpm](https://pnpm.io/cli/env) 进行版本管理。
- [Git](https://git-scm.com/) 任意版本。
验证你的环境是否满足以上要求,你可以通过以下命令查看版本:
```bash
# 出现相应 node LTS版本即可
node -v
# 出现相应 git 版本即可
git -v
```
:::
<!--
## 启动项目
### 获取源码
::: code-group
```sh [GitHub]
# clone 代码
git clone https://github.com/vbenjs/vue-vben-admin.git
```
```sh [Gitee]
# clone 代码
# Gitee 的代码可能不是最新的
git clone https://gitee.com/annsion/vue-vben-admin.git
```
:::
::: danger 注意
注意存放代码的目录及所有父级目录不能存在中文、韩文、日文以及空格,否则安装依赖后启动会出错。
:::
### 安装依赖
在你的代码目录内打开终端,并执行以下命令:
```bash
# 进入项目目录
cd vue-vben-admin
# 使用项目指定的pnpm版本进行依赖安装
corepack enable
# 安装依赖
pnpm install
```
::: tip 注意
- 项目只支持使用 `pnpm` 进行依赖安装,默认会使用 `corepack` 来安装指定版本的 `pnpm`。:
- 如果你的网络环境无法访问npm源你可以设置系统的环境变量`COREPACK_NPM_REGISTRY=https://registry.npmmirror.com`,然后再执行`pnpm install`。
- 如果你不想使用`corepack`,你需要禁用`corepack`,然后使用你自己的`pnpm`进行安装。
:::
### 运行项目
#### 选择项目
执行以下命令运行项目:
```bash
# 启动项目
pnpm dev
```
此时,你会看到类似如下的输出,选择你需要运行的项目:
```bash
◆ Select the app you need to run [dev]:
│ ○ @vben/web-antd
│ ○ @vben/web-ele
│ ○ @vben/web-naive
│ ○ @vben/docs
│ ● @vben/playground
```
现在,你可以在浏览器访问 `http://localhost:5555` 查看项目。
#### 运行指定项目
如果你不想选择项目,可以直接运行以下命令运行你需要的应用:
```bash
pnpm run dev:antd
pnpm run dev:ele
pnpm run dev:naive
pnpm run dev:docs
pnpm run dev:play
``` -->

View File

@@ -0,0 +1,3 @@
# 路线图
TODO:

View File

@@ -0,0 +1,159 @@
# 常见问题 #{faq}
::: tip 列举了一些常见的问题
有问题可以先来这里寻找,如果没有可以在 [GitHub Issue](https://github.com/vbenjs/vue-vben-admin/issues) 搜索或者提交你的问题, 如果是讨论性的问题可以在 [GitHub Discussions](https://github.com/vbenjs/vue-vben-admin/discussions)
:::
## 说明
遇到问题,可以先从以下几个方面查找
1. 对应模块的 GitHub 仓库 [issue](https://github.com/vbenjs/vue-vben-admin/issues) 搜索
2. 从[google](https://www.google.com)搜索问题
3. 从[百度](https://www.baidu.com)搜索问题
4. 在下面列表找不到问题可以到 issue 提问 [issues](https://github.com/vbenjs/vue-vben-admin/issues)
5. 如果不是问题类型的,需要讨论的,请到 [discussions](https://github.com/vbenjs/vue-vben-admin/discussions) 讨论
## 依赖问题
`Monorepo` 项目下,需要养成每次 `git pull`代码都要执行`pnpm install`的习惯,因为经常会有新的依赖包加入,项目在`.husky/git-merge`已经配置了自动执行`pnpm install`,但是有时候会出现问题,如果没有自动执行,建议手动执行一次。
## 关于缓存更新问题
项目配置默认是缓存在 `localStorage` 内,所以版本更新后可能有些配置没改变。
解决方式是每次更新代码的时候修改 `package.json` 内的 `version` 版本号. 因为 localStorage 的 key 是根据版本号来的。所以更新后版本不同前面的配置会失效。重新登录即可
## 关于修改配置文件的问题
当修改 `.env` 等环境文件以及 `vite.config.ts` 文件时vite 会自动重启服务。
自动重启有几率出现问题,请重新运行项目即可解决.
## 本地运行报错
由于 vite 在本地没有转换代码,且代码中用到了可选链等比较新的语法。所以本地开发需要使用版本较高的浏览器(`Chrome 90+`)进行开发
## 页面切换后页面空白
这是由于开启了路由切换动画,且对应的页面组件存在多个根节点导致的,在页面最外层添加`<div></div>`即可
**错误示例**
```vue
<template>
<!-- 注释也算一个节点 -->
<h1>text h1</h1>
<h2>text h2</h2>
</template>
```
**正确示例**
```vue
<template>
<div>
<h1>text h1</h1>
<h2>text h2</h2>
</div>
</template>
```
::: tip 提示
- 如果想使用多个根标签,可以禁用路由切换动画
- template 下面的根注释节点也算一个节点
:::
## 我的代码本地开发可以,打包就不行了
目前发现这个原因可能有以下,可以从以下原因来排查,如果还有别的可能,欢迎补充
- 使用了 ctx 这个变量ctx 本身未暴露出在实例类型内Vue官方也是说了不要用这个属性。这个属性只是用于内部使用。
```ts
import { getCurrentInstance } from 'vue';
getCurrentInstance().ctx.xxxx;
```
## 依赖安装问题
- 如果依赖安装不了或者启动报错可以尝试执行`pnpm run reinstall`
- 如果依赖安装不了或者报错,可以尝试切换手机热点来进行依赖安装。
- 如果还是不行,可以自行配置国内镜像安装。
- 也可以在项目根目录创建 `.npmrc` 文件,内容如下
```bash
# .npmrc
registry = https://registry.npmmirror.com/
```
## 打包文件过大
- 首先,完整版由于引用了比较多的库文件,所以打包会比较大。可以使用精简版来进行开发
- 其次建议开启 gzip使用之后体积会只有原先 1/3 左右。gzip 可以由服务器直接开启。如果是这样,前端不需要构建 `.gz` 格式的文件,如果前端构建了 `.gz` 文件,以 nginx 为例nginx 需要开启 `gzip_static: on` 这个选项。
- 开启 gzip 的同时还可以同时开启 `brotli`,比 gzip 更好的压缩。两者可以共存
**注意**
- gzip_static: 这个模块需要 nginx 另外安装,默认的 nginx 没有安装这个模块。
- 开启 `brotli` 也需要 nginx 另外安装模块
## 运行错误
如果出现类似以下错误,请检查项目全路径(包含所有父级路径)不能出现中文、日文、韩文。否则将会出现路径访问 404 导致以下问题
```ts
[vite] Failed to resolve module import "ant-design-vue/dist/antd.css-vben-adminode_modulesant-design-vuedistantd.css". (imported by /@/setup/ant-design-vue/index.ts)
```
## 控制台路由警告问题
如果看到控制台有如下警告,且页面**能正常打开** 可以忽略该警告。
后续 `vue-router` 可能会提供配置项来关闭警告
```ts
[Vue Router warn]: No match found for location with path "xxxx"
```
## 启动报错
当出现以下错误信息时,请检查你的 nodejs 版本号是否符合要求
```bash
TypeError: str.matchAll is not a function
at Object.extractor (vue-vben-admin-main\node_modules@purge-icons\core\dist\index.js:146:27)
at Extract (vue-vben-admin-main\node_modules@purge-icons\core\dist\index.js:173:54)
```
## nginx 部署
部署到 `nginx`后,可能会出现以下错误:
```bash
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/octet-stream". Strict MIME type checking is enforced for module scripts per HTML spec.
```
解决方式一:
```bash
http {
#如果有此项配置需要注释掉
#include mime.types;
types {
application/javascript js mjs;
}
}
```
解决方式二:
进入 `nginx` 下的`mime.types`文件, 将`application/javascript js;` 修改为 `application/javascript js mjs;`

View File

@@ -0,0 +1,55 @@
# 项目更新
## 为什么无法像 npm 插件一样更新
因为项目是一个完整的项目模版,不是一个插件或者安装包,无法像插件一样更新,你使用代码后,会根据业务需求,进行二次开发,需要自行手动合并升级。
## 我需要怎么做
项目采用了 `Monorepo` 的方式进行管理,并将一些比较核心的代码进行了抽离,比如 `packages/@core``packages/effects`,只要业务代码没有修改这部分代码,那么你可以直接拉取最新代码,然后合并到你的分支上,只需要简单的处理部分冲突即可。其余文件夹只会进行一些小的调整,不会对业务代码产生影响。
::: tip 推荐
建议关注仓库动态,积极去合并,不要长时间积累,否则将会导致合并冲突过多,增加合并难度。
:::
## 使用 Git 更新代码
1. 克隆代码
```bash
git clone https://github.com/vbenjs/vue-vben-admin.git
```
2. 添加自己的公司 git 源地址
```bash
# up 为源名称,可以随意设置
# gitUrl为开源最新代码
git remote add up gitUrl;
```
3. 提交代码到自己公司 git
```bash
# 提交代码到自己公司
# main为分支名 需要自行根据情况修改
git push up main
# 同步公司的代码
# main为分支名 需要自行根据情况修改
git pull up main
```
4. 如何同步开源最新代码
```bash
git pull origin main
```
::: tip 提示
同步代码的时候会出现冲突。只需要把冲突解决即可
:::

View File

@@ -0,0 +1,18 @@
# 移除代码
## 移除百度统计代码
在对应应用的 `index.html` 文件中,找到如下代码,删除即可:
```html
<!-- apps/web-antd -->
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement('script');
hm.src = 'https://hm.baidu.com/hm.js?d20a01273820422b6aa2ee41b6c9414d';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
```

View File

@@ -0,0 +1,21 @@
# Changeset
项目内置了 [changeset](https://github.com/changesets/changesets) 作为版本管理工具。Changeset 是一个版本管理工具,它可以帮助我们更好的管理版本,生成 changelog以及自动发布。
详细使用方式可查看官方文档,这里不再阐述。如果你不需要它,可以直接忽略。
## 命令行
changeset 命令在项目中已经内置:
### 交互式填写变更集
```bash
pnpm run changeset
```
### 统一提升版本号
```bash
pnpm run version
```

View File

@@ -0,0 +1,113 @@
---
outline: deep
---
# CLI
项目中,提供了一些命令行工具,用于一些常用的操作,代码位于 `scrips` 内。
## vsh
用于一些项目操作,如清理项目、检查项目等。
### 用法
```bash
pnpm vsh [command] [options]
```
### vsh check-circular
检查整个项目循环引用,如果有循环引用,会在控制台输出循环引用的模块。
#### 用法
```bash
pnpm vsh check-circular
```
#### 选项
| 选项 | 说明 |
| ---------- | ----------------------------------- |
| `--staged` | 只检查git暂存区内的文件,默认`false` |
### vsh check-dep
检查整个项目依赖情况,并在控制台输出`未使用的依赖``未安装的依赖`信息
#### 用法
```bash
pnpm vsh check-dep
```
#### 选项
| 选项 | 说明 |
| ---------------- | --------------------------------------- |
| `-r,--recursive` | 递归删除整个项目,默认`true` |
| `--del-lock` | 是否删除`pnpm-lock.yaml`文件,默认`true` |
### vsh lint
对项目进行lint检查检查项目中的代码是否符合规范。
#### 用法
```bash
pnpm vsh lint
```
#### 选项
| 选项 | 说明 |
| ---------- | ------------------------------ |
| `--format` | 检查并尝试修复错误,默认`false` |
### vsh publint
`Monorepo` 项目进行包规范检查,检查项目中的包是否符合规范。
#### 用法
```bash
pnpm vsh publint
```
#### 选项
| 选项 | 说明 |
| --------- | ---------------------- |
| `--check` | 仅执行检查,默认`false` |
### vsh code-workspace
生成 `vben-admin.code-workspace` 文件,目前不需要手动执行,会在代码提交时自动执行。
#### 用法
```bash
pnpm vsh code-workspace
```
#### 选项
| 选项 | 说明 |
| --------------- | -------------------------------------- |
| `--auto-commit` | `git commit`时候,自动提交,默认`false` |
| `--spaces` | 缩进格式,默认 `2`个缩进 |
## turbo-run
用于快速执行大仓中脚本,并提供选项式交互选择。
### 用法
```bash
pnpm turbo-run [command]
```
### turbo-run dev
快速执行`dev`命令,并提供选项式交互选择。

View File

@@ -0,0 +1,68 @@
# 目录说明
目录使用 Monorepo 管理,项目结构如下:
```bash
.
├── Dockerfile # Docker 镜像构建文件
├── README.md # 项目说明文档
├── apps # 项目应用目录
│   ├── backend-mock # 后端模拟服务应用
│   ├── web-antd # 基于 Ant Design Vue 的前端应用
│   ├── web-ele # 基于 Element Plus 的前端应用
│   └── web-naive # 基于 Naive UI 的前端应用
├── build-local-docker-image.sh # 本地构建 Docker 镜像脚本
├── cspell.json # CSpell 配置文件
├── docs # 项目文档目录
├── eslint.config.mjs # ESLint 配置文件
├── internal # 内部工具目录
│   ├── lint-configs # 代码检查配置
│   │   ├── commitlint-config # Commitlint 配置
│   │   ├── eslint-config # ESLint 配置
│   │   ├── prettier-config # Prettier 配置
│   │   └── stylelint-config # Stylelint 配置
│   ├── node-utils # Node.js 工具
│   ├── tailwind-config # Tailwind 配置
│   ├── tsconfig # 通用 tsconfig 配置
│   └── vite-config # 通用Vite 配置
├── package.json # 项目依赖配置
├── packages # 项目包目录
│   ├── @core # 核心包
│   │   ├── base # 基础包
│   │   │   ├── design # 设计相关
│   │   │   ├── icons # 图标
│   │   │   ├── shared # 共享
│   │   │   └── typings # 类型定义
│   │   ├── composables # 组合式 API
│   │   ├── preferences # 偏好设置
│   │   └── ui-kit # UI 组件集合
│   │   ├── layout-ui # 布局 UI
│   │   ├── menu-ui # 菜单 UI
│   │   ├── shadcn-ui # shadcn UI
│   │   └── tabs-ui # 标签页 UI
│   ├── constants # 常量
│   ├── effects # 副作用相关包
│   │   ├── access # 访问控制
│   │   ├── plugins # 第三方大型依赖插件
│   │   ├── common-ui # 通用 UI
│   │   ├── hooks # 组合式 API
│   │   ├── layouts # 布局
│   │   └── request # 请求
│   ├── icons # 图标
│   ├── locales # 国际化
│   ├── preferences # 偏好设置
│   ├── stores # 状态管理
│   ├── styles # 样式
│   ├── types # 类型定义
│   └── utils # 工具
├── playground # 演示目录
├── pnpm-lock.yaml # pnpm 锁定文件
├── pnpm-workspace.yaml # pnpm 工作区配置文件
├── scripts # 脚本目录
│   ├── turbo-run # Turbo 运行脚本
│   └── vsh # VSH 脚本
├── stylelint.config.mjs # Stylelint 配置文件
├── turbo.json # Turbo 配置文件
├── vben-admin.code-workspace # VS Code 工作区配置文件
└── vitest.config.ts # Vite 配置文件
```

View File

@@ -0,0 +1,165 @@
# 规范
::: tip 贡献代码
- 如果你想向项目贡献代码,请确保你的代码符合项目的代码规范。
- 如果你使用的是 `vscode`,需要安装以下插件:
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - 脚本代码检查
- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - 代码格式化
- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) - 单词语法检查
- [Stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) - css 格式化
:::
## 作用
具备基本工程素养的同学都会注重编码规范而代码风格检查Code Linting简称 Lint是保障代码规范一致性的重要手段。
遵循相应的代码规范有以下好处:
- 较少 bug 错误率
- 高效的开发效率
- 更高的可读性
## 工具
项目的配置文件位于 `internal/lint-configs`你可以在这里修改各种lint的配置。
项目内集成了以下几种代码校验工具:
- [ESLint](https://eslint.org/) 用于 JavaScript 代码检查
- [Stylelint](https://stylelint.io/) 用于 CSS 样式检查
- [Prettier](https://prettier.io/) 用于代码格式化
- [Commitlint](https://commitlint.js.org/) 用于检查 git 提交信息的规范
- [Publint](https://publint.dev/) 用于检查 npm 包的规范
- [Lint Staged](https://github.com/lint-staged/lint-staged) 用于在 git 提交前运行代码校验
- [Cspell](https://cspell.org/) 用于检查拼写错误
## ESLint
ESLint 是一个代码规范和错误检查工具,用于识别和报告 TypeScript 代码中的语法错误。
### 命令
```bash
pnpm eslint .
```
### 配置
eslint 配置文件为 `eslint.config.mjs`,其核心配置放在`internal/lint-configs/eslint-config`目录下,可以根据项目需求进行修改。
## Stylelint
Stylelint 用于校验项目内部 css 的风格,加上编辑器的自动修复,可以很好的统一项目内部 css 风格
### 命令
```bash
pnpm stylelint "**/*.{vue,css,less.scss}"
```
### 配置
Stylelint 配置文件为 `stylelint.config.mjs`,其核心配置放在`internal/lint-configs/stylelint-config`目录下,可以根据项目需求进行修改。
## Prettier
Prettier 可以用于统一项目代码风格,统一的缩进,单双引号,尾逗号等等风格
### 命令
```bash
pnpm prettier .
```
### 配置
Prettier 配置文件为 `.prettier.mjs`,其核心配置放在`internal/lint-configs/prettier-config`目录下,可以根据项目需求进行修改。
## CommitLint
在一个团队中,每个人的 git 的 commit 信息都不一样,五花八门,没有一个机制很难保证规范化,如何才能规范化呢?可能你想到的是 git 的 hook 机制,去写 shell 脚本去实现。这当然可以,其实 JavaScript 有一个很好的工具可以实现这个模板,它就是 commitlint用于校验 git 提交信息规范)。
### 配置
CommitLint 配置文件为 `.commitlintrc.mjs`,其核心配置放在`internal/lint-configs/commitlint-config`目录下,可以根据项目需求进行修改。
### Git 提交规范
参考 [Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)
- `feat` 增加新功能
- `fix` 修复问题/BUG
- `style` 代码风格相关无影响运行结果的
- `perf` 优化/性能提升
- `refactor` 重构
- `revert` 撤销修改
- `test` 测试相关
- `docs` 文档/注释
- `chore` 依赖更新/脚手架配置修改等
- `workflow` 工作流改进
- `ci` 持续集成
- `types` 类型修改
### 关闭Git提交规范检查
如果你想关闭 Git 提交规范检查,有两种方式:
::: code-group
```bash [临时关闭]
git commit -m 'feat: add home page' --no-verify
```
```bash [永久关闭]
# 在 .husky/commit-msg 内注释以下代码即可
pnpm exec commitlint --edit "$1" # [!code --]
```
:::
## Publint
Publint 是一个用于检查 npm 包的规范的工具,可以检查包的版本号是否符合规范,是否符合标准的 ESM 规范包等等。
### 命令
```bash
pnpm vsh publint
```
## Cspell
Cspell 是一个用于检查拼写错误的工具,可以检查代码中的拼写错误,避免因为拼写错误导致的 bug。
### 命令
```bash
pnpm cspell lint \"**/*.ts\" \"**/README.md\" \".changeset/*.md\" --no-progress
```
### 配置
cspell 配置文件为 `cspell.json`,可以根据项目需求进行修改。
## Git Hook
git hook 一般结合各种 lint在 git 提交代码的时候进行代码风格校验,如果校验没通过,则不会进行提交。需要开发者自行修改后再次进行提交
### husky
有一个问题就是校验会校验全部代码,但是我们只想校验我们自己提交的代码,这个时候就可以使用 husky。
最有效的解决方案就是将 Lint 校验放到本地,常见做法是使用 husky 或者 pre-commit 在本地提交之前先做一次 Lint 校验。
项目在 `.husky` 内部定义了相应的 hooks
#### 如何关闭 Husky
如果你想关闭 Husky直接删除 `.husky` 目录即可。
### lint-staged
用于自动修复提交文件风格问题,其配置文件为 `.lintstagedrc.mjs`,可以根据项目需求进行修改。

View File

@@ -0,0 +1,13 @@
# Tailwind CSS
[Tailwind CSS](https://tailwindcss.com/) 是一个实用性优先的CSS框架用于快速构建自定义设计。
## 配置
项目的配置文件位于 `internal/tailwind-config` 下,你可以在这里修改 Tailwind CSS 的配置。
::: tip 包使用 tailwindcss 的限制
当前只有对应的包下面存在 `tailwind.config.mjs` 文件才会启用 tailwindcss 的编译,否则不会启用 tailwindcss。如果你是纯粹的 SDK 包,不需要使用 tailwindcss可以不用创建 `tailwind.config.mjs` 文件。
:::

View File

@@ -0,0 +1,33 @@
# 单元测试
项目内置了 [Vitest](https://vitest.dev/) 作为单元测试工具。Vitest 是一个基于 Vite 的测试运行器,它提供了一套简单的 API 来编写测试用例。
## 编写测试用例
在项目中,我们约定将测试文件名以 `.test.ts` 结尾,或者存放到`__tests__`目录内。例如,创建一个 `utils.ts` 文件,然后同级目录`utils.test.ts` 文件,
```ts
// utils.test.ts
import { expect, test } from 'vitest';
import { sum } from './sum';
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
```
## 运行测试
在大仓根目录下运行以下命令即可:
```bash
pnpm test:unit
```
## 现有单元测试
项目中已经有一些单元测试用例,可以搜索以`.test.ts`结尾的文件查看,在你更改到相关代码时,可以运行单元测试来保证代码的正确性,建议在开发过程中,保持单元测试的覆盖率,且同时在 CI/CD 流程中运行单元测试,保证测试通过在进行项目部署。
现有单元测试情况:
![](/guide/test.png)

View File

@@ -0,0 +1,33 @@
# Vite Config
项目封装了一层vite配置并集成了一些插件方便在多个包以及应用内复用使用方式如下
## 应用
```ts
// vite.config.mts
import { defineConfig } from '@vben/vite-config';
export default defineConfig(async () => {
return {
application: {},
// vite配置参考vite官方文档进行覆盖
vite: {},
};
});
```
## 包
```ts
// vite.config.mts
import { defineConfig } from '@vben/vite-config';
export default defineConfig(async () => {
return {
library: {},
// vite配置参考vite官方文档进行覆盖
vite: {},
};
});
```