
UI
前端框架设计原则和说明
⚠️前端完整模版尚未正式发布,还在内侧中⚠️。
项目整体采用 Monorepo 设计:
├─packages (1)
│ ├─antd
│ ├─util
│ └─hook
├─src (2)
│ ├─assets
│ └─components
│
src 为主应用入口:
├─assets (1)
│ ├─styles
│ │ └─transition
│ └─svg-icon
├─components (2)
│ ├─dashboard
│ └─ui
│ ├─accordion
│ ├─alert
├─composables (3)
├─config (4)
├─directive (5)
├─layouts (6)
│ └─admin
├─lib (7)
├─locales (8)
│ └─langs
│ ├─en-US
│ └─zh-CN
├─pages (9)
│ ├─dashboard
│ └─example
├─router (10)
│ └─auto
├─service (11)
│ ├─api
│ ├─form
│ ├─model
│ └─table
├─stores (12)
├─types (13)
└─utils (14)
| Directory | Content |
|---|---|
| (1) | CSS 风格 |
| (2) | 组件库 |
| (3) | Hook |
| (4) | 配置 |
| (5) | 指令扩展 |
| (6) | 布局 |
| (7) | 三方类 |
| (8) | 国际化 |
| (9) | 页面 |
| (10) | 路由 |
| (11) | 服务 |
| (12) | 状态 |
| (13) | d.ts定义 |
| (14) | 帮助类 |
ui
来自 shadcn-vue , 独立共享组件。
This is NOT a component library. It’s a collection of re-usable components that you can copy and paste or use the CLI to add to your apps.
源头来自: react 社区:shadcn
TBD: 移动到独立 packages
other
本目录下, 非 ui 为自定义组件, 注意所有 src/components 将被 unplugin-vue-components/vite 自动导入:
Components({
dts: 'src/types/components.d.ts',
dirs: ['src/components']
})
路由自动发现注册,可由 hope 工具链,完整自动发现和生成, 配置在 {module}-app 的 ui.json 配置 ui。
打开 autoRouter 标志, 自动扫描, pagesDir 默认配置自 {module}-ui模块下的src/pages路径。
页面 meta 信息需要额外配置元信息(defineOptions),如src/pages/dashboard/index.vue:
<script setup lang="ts">
defineOptions({
name: 'Dashboard',
meta: {
title: 'Dashboard页面',
//i18key: 'pages.dashboard.title',
icon: 'lucide:table',
hidden: false,
layout: 'admin',
sort: 1,
},
})
</script>
工具执行后,输出到 src/router/auto/index.ts (routerOutDir 默认配置 src/router/auto):
export const pages: RouteRecordRaw[] = [{
name: 'Dashboard',
path: '/dashboard',
component: () => import('@/pages/dashboard/index.vue'),
meta: {
title: 'Dashboard页面',
i18key: 'pages.dashboard.title',
icon: 'dash',
layout: 'admin',
hidden: false,
type: 'LEAF',
level: 0,
displayOrder: 0,
},
}]
| Property | Comment |
|---|---|
| title | 标题描述 |
| i18key | 国际化key |
| icon | icon |
| layout | 样式布局 |
| hidden | 是否隐藏 |
| type | 类型 |
| level | level |
| displayOrder | 显示顺序 |
ROOT|BRANCH|LEAF 路径在整个路由中位置,根、中间、叶节点其他输出:
由路由树状结构生成菜单树结构可以作为默认菜单结构,也可做为定配菜单输入元信息。
export const menus: MenuItem[] = [{
name: 'Dashboard',
path: '/dashboard',
title: 'Dashboard页面',
i18key: 'pages.dashboard.title',
icon: 'dash',
hidden: false,
type: 'LEAF',
level: 0,
displayOrder: 0,
}, {
path: '/example',
i18key: 'pages.example.title',
type: 'ROOT',
level: 0,
children: [{
name: 'ExampleForm',
path: '/example/form',
title: '示例表单',
i18key: 'pages.example.form.title',
icon: 'lucide:search',
type: 'LEAF',
level: 1,
parentPath: '/example',
displayOrder: 0,
}]
}]
工具自动生成 i18n 配置 sr/locals/{lang}/pages.json:
{
"dashboard": {
"title": "Dashboard页面"
},
"example": {
"title": "纯例子",
"form": {
"title": "示例表单-大帅"
},
"search-table": {
"title": "搜索表格-小萌"
},
"table": {
"title": "$示例表格"
},
"trivial": {
"title": "示例页面"
}
}
}
这里会根据, ui 配置的 firstLanguage & secondLanguage, 进行处理:
title Meta 信息会输出到默认语言值配置中i18key 如未配置,默认使用路径名: x/y/z → pages.x.y.z.titlei18key 如配置,会自动格式化: pages. 开头, .title 结尾;如 x.y.z → pages.x.y.z.title, 以和框架 i18n 机制一致; 参考 ui 里配置 pagePrefix & pageSuffix$前缀, 手动修正完后去掉 $—避免merger被覆盖。如例子中:
example.form.title 值为 示例表单-大帅, 未以$开头,后续 merger 不再复制页面中 meta.title定义任何信息⚠️;example.table.title 值为 $示例表格,以 $开头,后续 merger 将根据页面 meta.title 自动更新(但依然强制添加 $ 前缀);此工作机制主要帮助第一次构建页面 i18n 配置, 同时提醒开发人员改变默认配置($将展示在前台)。
根据目录名称,自动设置转换参数型路由:
[param][[param]]参数命名应具有描述性,避免使用过于简单或模糊的名称;复杂的参数组合可以使用多参数语法 detail_[id]_[userId] 来提高可读性。
例子:
/list/detail/[id]/[userId] -> /list/detail/:id/:userId/list/detail/[[id]]/[[userId]] -> /list/detail/:id?/:userId?参考Hope 框架极简 Authentication & Authorization设计。
为便捷前端使用Hope框架 Authentication & Authorization,工具栈对 Authority 处理如下:
Authority 定义 Enum 将被处理,生成到如下信息:
src/service/model/{authority}.ts authority enum 对象定义src/types/auth.d.ts 全局 enum authority type 定义enum WorkAuthorityEnum {
option (hope.swagger.enm) = { description: "Example Authority Enum for the project, MODIFY IT" };
ROLE_ADD = 200 [(hope.constant.field) = {code: 200,message: "system:role:add", message2: "Authority to add role"}];
//.... other
}
enum 定义
export const WorkAuthorityEnum = {
USER_ADD: { title: 'USER_ADD', code: 1, permission: 'user:add', deprecated: false, remark: 'Authority to add user'},
//......
}
// eslint-disable-next-line ts/no-redeclare
export type WorkAuthorityEnum = keyof typeof WorkAuthorityEnum
export type WorkAuthorityEnumValue = typeof WorkAuthorityEnum[keyof typeof WorkAuthorityEnum]
Enum 包含属性:
| Property | Comment |
|---|---|
| title | 标题: USER_ADD |
| code | 代码: 1 |
| permission | 权限: user:add 一般: 代表层级关系 |
| deprecated | 失效否? |
| remark | 描述:Authority to add user |
auth.d.ts 定义
Api.Authority.Map Authority 定义 (map)Api.Authority.Type Authority 类型Api.Authority.TypeList Authority 类型列表Api.Authority.Item Authority 体Api.Authority.AuthorityItem Authority Tree 结构定义Api.Authority.AuthorityTree Authority Treedeclare namespace Api {
namespace Authority {
export const Map: {
USER_ADD: { title: 'USER_ADD', code: 1, permission: 'user:add', deprecated: false, remark: 'Authority to remove user(Remove or modify this template sample)'}
//...
}
export type Type = keyof typeof Map
export type TypeList = Type[]
/**
* Authority item type, contains the following properties:
* - title: Authority title, USER_ADD
* - code: Authority code, 1024
* - permission: Permission, user:add
* - deprecated: Whether it's deprecated, false
* - remark: Additional notes, permission to add user account
*/
export type Item = typeof Map[Type]
interface AuthorityItem {
code: number
name: string
expression: string
deprecated: boolean
type?: 'LEAF' | 'ROOT' | 'BRANCH'
description?: string
level?: number
children?: AuthorityItem[]
}
export const AuthorityTree: AuthorityItem[] = [{
"code" : 0,
"name" : "system",
"expression" : "system",
"deprecated" : false,
"type" : "ROOT",
"children" : [ {
"code" : 0,
"name" : "system:role",
"expression" : "system:role",
"deprecated" : false,
"type" : "BRANCH",
"children" : [ {
"code" : 10240200,
"name" : "ROLE_ADD",
"expression" : "system:role:add",
"description" : "Authority to add role",
"deprecated" : false,
"type" : "LEAF",
"level" : 2
}],
"level" : 1
} ],
"level" : 0
}]
}
}
TBD
统一三方依赖版本配置和管理,采用 catalog 方式统一配置, pnpm-workspace.yaml:
packages:
- 'packages/*'
catalog:
# UI 框架相关
'vue': '^3.5.13'
'vue-router': '^4.5.0'
'vue-i18n': '^11.1.2'
项目中包依赖:
{
"dependencies": {
"vee-validate": "catalog:",
"axios": "catalog:"
}
}
unplugin-auto-import/viteunplugin-vue-components/viteunplugin-icons/vite// hope-no-merger 禁止生成覆盖,⚠️无法升级更新TBD