前端完整模版尚未正式发布,还在内侧中。

Structure

项目整体采用 Monorepo 设计:

├─packages (1)
│  ├─antd
│  ├─util
│  └─hook
├─src (2)
│  ├─assets
│  └─components
│
  1. (1) 独立包模块:组件、util、hook etc
  2. (2) 主应用

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)
DirectoryContent
(1)CSS 风格
(2)组件库
(3)Hook
(4)配置
(5)指令扩展
(6)布局
(7)三方类
(8)国际化
(9)页面
(10)路由
(11)服务
(12)状态
(13)d.ts定义
(14)帮助类

功能

Component

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']
    })

Router

路由自动发现注册,可由 hope 工具链,完整自动发现和生成, 配置在 {module}-appui.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,
  },
}]
PropertyComment
title标题描述
i18key国际化key
iconicon
layout样式布局
hidden是否隐藏
type类型
levellevel
displayOrder显示顺序
  1. type: ROOT|BRANCH|LEAF 路径在整个路由中位置,根、中间、叶节点
  2. level: 深度,0 为根
  3. displayOrder: 显示顺序,同级别展示先后顺序, 在路由菜单中显示顺序

其他输出:

由路由树状结构生成菜单树结构可以作为默认菜单结构,也可做为定配菜单输入元信息。

Menu

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

工具自动生成 i18n 配置 sr/locals/{lang}/pages.json:

{
  "dashboard": {
    "title": "Dashboard页面"
  },
  "example": {
    "title": "纯例子",
    "form": {
      "title": "示例表单-大帅"
    },
    "search-table": {
      "title": "搜索表格-小萌"
    },
    "table": {
      "title": "$示例表格"
    },
    "trivial": {
      "title": "示例页面"
    }
  }
}

这里会根据, ui 配置 firstLanguage & secondLanguage, 符合规则:

  1. 页面自带 title Meta 信息会输出到默认语言配置中
  2. 未配置,默认采用路径为值
  3. i18key 如果未配置默认使用路径名
  4. i18key 会自动格式化: pages. 开头, .title 结尾; 这个和框架 i18n 机制一致; 参考 ui 里配置 pagePrefix & pageSuffix
  5. i18n 配置符合整体框架原则:默认未改动一 $前缀, 修改完后去掉 $,后续不会再覆盖。

如例子中: example.form.title 后续页面中 meta.title 跟新,不再同步到这个 pages.json 配置内,应该没有 $ 前缀; 而 example.table.title 将根据 这个页面内 meta.title 自动更新。

这种工作机制主要帮助第一次构建页面 i18n 配置, 同时提醒开发人员改变默认配置($将展示在前台)。

Authority

参考Hope 框架极简 Authentication & Authorization设计。

配合前端便捷利用现在Hope框架 Authentication & Authorization,工具栈对 Authority 处理如下:

Authority 定义 Enum 将被处理,生成到如下几个目录:

  1. src/service/model/{authority}.ts authority enum 对象定义
  2. 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 包含属性:

PropertyComment
title标题: USER_ADD
code代码: 1
permission权限: user:add 一般: 代表层级关系
deprecated失效否?
remark描述:Authority to add user

d.ts 定义

  1. Api.Authority.Map Authority 定义 (map)
  2. Api.Authority.Type Authority 类型
  3. Api.Authority.TypeList Authority 类型列表
  4. Api.Authority.Item Authority 体
  5. Api.Authority.AuthorityItem Authority Tree 结构定义
  6. Api.Authority.AuthorityTree Authority Tree
declare 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
      }]

  }
}

Layout

TBD

Style

  1. Theme
  2. Color
  3. Tailwindcss

Catalog

统一三方依赖版本配置和管理,采用 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:"
   }
 }

packages

antd

util

hook

Plugin

  1. Auto-import unplugin-auto-import/vite
  2. Auto-component unplugin-vue-components/vite
  3. Icon unplugin-icons/vite

Trivial

  1. lint
  2. prettier
  3. vscode
  4. format/antfu

Tip

  1. 生成文件可以在文件备注 // hope-no-merger 禁止生成覆盖,⚠️无法升级更新

TBD