diff --git a/.vitepress/src/zh/sidebars.ts b/.vitepress/src/zh/sidebars.ts index 3795866..1f971c4 100644 --- a/.vitepress/src/zh/sidebars.ts +++ b/.vitepress/src/zh/sidebars.ts @@ -132,10 +132,6 @@ const sidebar:DefaultTheme.Sidebar = { text: '服务提供器', link: '/zh/front/high/provider' }, - { - text: '插件', - link: '/zh/front/high/plugin' - }, { text: 'Hooks', link: '/zh/front/high/hooks' @@ -144,6 +140,10 @@ const sidebar:DefaultTheme.Sidebar = { text: '常用Store', link: '/zh/front/high/store' }, + { + text: '插件系统', + link: '/zh/front/high/plugins' + }, { text: 'JSX和TSX开发', link: '/zh/front/high/tsx' diff --git a/docs/zh/front/advanced/permission.md b/docs/zh/front/advanced/permission.md index 6f51202..6453d41 100644 --- a/docs/zh/front/advanced/permission.md +++ b/docs/zh/front/advanced/permission.md @@ -1 +1,127 @@ -# 权限 \ No newline at end of file +# 权限 + + +## 概括 +:::tip 权限概括 +路由页面可否访问是基于后端返回的菜单确定的,而静态路由暂无权限控制(后面会增加**前端**对静态路由的控制)。而前端目前主要控制了 +`内容` 是否可显示`(v-show)`以及渲染`(v-if)`,内容包括了: +- 页面的元素 +- 页面的组件 +- 按钮...等等 +::: + +## 细粒度介绍及使用 + +目前权限分为三种细粒度: +- 基于权限码(菜单的 `name` 字段) +- 基于角色码(角色的 `code` 字段) +- 基于用户名(用户的 `username` 字段) + +::: info +三种细粒度各有 `助手函数` 和 `指令` 来控制内容的渲染,其中基于权限码的还有 **组件** 使用的方式来控制是否渲染内容。 +::: + +### 业务逻辑使用 +```vue + +``` + +### API使用方式 +```vue + + + +``` + +### 指令使用方式 + +其实同样支持传入字符串,为了简单演示,就省略字符串传入模式了. + +```vue + +``` +::: tip 提示 +`hasAuth`、`hasRole`、`hasUser` 函数还有第二个参数,用于是否连带**路由里的权限**是否检查。 +::: + +### 权限组件使用 + +相比其他方式,组件对大范围的内容控制更友好和方便,因为用组件包裹着需要显示的内容,再传入需要检查的权限即可。 +而且组件还有针对没有权限的提供了插槽,可以自定义提示无权限的可看到的内容。 + +:::info 组件位置 +**`src/components/ma-auth/index.vue`** + +组件已全局引入,不需要再手动引入。 +::: + +```vue + +``` \ No newline at end of file diff --git a/docs/zh/front/high/hooks.md b/docs/zh/front/high/hooks.md index 744f34e..ee82c3a 100644 --- a/docs/zh/front/high/hooks.md +++ b/docs/zh/front/high/hooks.md @@ -1 +1,25 @@ # Hooks + +## useCache() + +## useDialog() + +## useEcharts() + +## useForm() + +## useTable() + +## useLocalTrans() + +## useMessage() + +## useTabCollection() + +## useImageViewer() + +## useResourcePicker() + +## useWatermark() + +## useThemeColor() \ No newline at end of file diff --git a/docs/zh/front/high/i18n.md b/docs/zh/front/high/i18n.md index c483959..f634702 100644 --- a/docs/zh/front/high/i18n.md +++ b/docs/zh/front/high/i18n.md @@ -1 +1,103 @@ # 国际化配置 + +前端的项目内已经集成了 `Vue i18n`,在请求时会自动根据当前语言向后端请求对应语言的文案,后端部分不在这里讲解有兴趣可查看源码。 + +前端目前支持 `中文、繁体中文、英文`,三种语言包。 + +## 插件推荐 + +- 如果你使用 `vscode` ,建议安装 [i18n Ally](https://marketplace.visualstudio.com/items?itemName=Lokalise.i18n-ally) +- 如果你使用 `webStorm` ,建议安装 [Easy i18n](https://plugins.jetbrains.com/plugin/16316-easy-i18n) + +以上插件能很好帮助你完善语言包。 + +## 语言包定义 + +::: tip 必看 +`Vue i18n` 支持两种语言包类型,**全局语言包** 和 **局部语言包**。其中局部语言包也叫本文件内的语言包,只用于 `vue` 扩展名的文件内, +全局的语言包支持 `vue`,`tsx`,`jsx` 类型文件。 + +语言包定义使用的 `yaml` 格式语法,比 `json` 写起来要舒服很多 + +如果需要扩展其他语言,需要注意格式,不然会找不到定义的语言包。格式为:`语言标识符[本语言名称]` +- en[English].yaml +- zh_CN[简体中文].yaml +- zh_TW[繁體中文].yaml +::: + +### 全局语言包 +全局语言包存放分为三种形式,它们都会被系统自动扫描引入 +- `src/locales` 目录下 +- `src/modules/<模块名>/locales` 目录下 +- `src/plugins/<插件名>/locales` 目录下 + +::: danger 注意事项 +**模块** 和 **插件** 下的全局语言包要和 `src/locales` 下的文件名一致,不然控制台会出现找不到 `key` 的警告信息(很烦这个)。 +::: + +### 局部语言包 +项目内的所有 `vue` 文件都支持局部语言包,只需要在 `vue` 文件内定义 `i18n` 标签即可,如下: +```vue + +zh_CN: + hello: 你好 +zh_TW: + hello: 你好 +en: + hello: hello + + + + + + + +``` + +## 使用 + +首先,完全可以自己手动引入 `Vue i18n` ,拿到 `i18n` 对象后,就可以使用 `i18n` 对象的 `t` 方法来获取文案了,如下: +```ts +import { i18n } from 'vue-i18n' + +// 全局模式 +const { t } = i18n() + +// 局部模式 +const { t } = i18n({ + inheritLocale: true, + useScope: 'local', +}) + +``` + +但是,前端项目内已经封装好了获取 `i18n` 对象的方法,只需要在 `setup` 函数内使用 `useTrans()` 方法即可,如下: + +```ts +// 已自动引入 useTrans() +const trans = useTrans() + +// useTrans() 会返回一个对象,里面包含了全局和局部两个对象: +// trans.globalTrans 和 trans.localTrans + +trans.globalTrans('global.title') +trans.localTrans('title') + +// 也可直接使用,默认先找全局的 key,如果找不到的话,会找局部的 key +useTrans('title') +``` + +除此之外,还有一个 `useLocalTrans()` 这个方法,它只会返回局部的 `i18n` 对象,并且需要手动引入,如下: +```ts +import useLocalTrans from '@/hooks/useLocalTrans' + +// 只会寻找本文件内的 key +const t = useLocalTrans() + +// 两种使用方式 +t('title') +useLocalTrans('title') +``` \ No newline at end of file diff --git a/docs/zh/front/high/plugin.md b/docs/zh/front/high/plugin.md deleted file mode 100644 index f007e86..0000000 --- a/docs/zh/front/high/plugin.md +++ /dev/null @@ -1 +0,0 @@ -# 插件 diff --git a/docs/zh/front/high/plugins.md b/docs/zh/front/high/plugins.md new file mode 100644 index 0000000..937c354 --- /dev/null +++ b/docs/zh/front/high/plugins.md @@ -0,0 +1,215 @@ +# 插件系统 + +::: tip 插件系统说明 +`3.0` 前端从核心层面支持了插件系统,相比 `2.0` 在设计之初没有考虑插件功能, +在改变系统界面或者行为、功能的时候都需要去修改源代码,而后导致后续无法升级,跟官方代码差别越来越大, +后面增加了应用商店功能,虽然可以强行支持插件,插件也必须修改源代码,而且在需要初始化的地方,插件无法去扩展实现,只能去修改 `main.js`。 + +**现在以上问题全部都不存在了,前端插件系统提供了强有力的支持,从替换界面、增加功能、引入第三方组件或者自研组件都可以无缝融入到系统里去, +而且还提供了多种 `hooks(钩子)` ,甚至可以去影响和改变前端的运行** +::: + +## 插件数据类型介绍 + +::: info 类型定义文件 +类型定义在 `types/global.d.ts` 内 +::: + +:::details 点击查看类型定义 +```ts +declare namespace Plugin { + + /** + * 插件基础信息 + */ + interface Info { + name: string + version: string + author: string + description: string + order?: number + } + + interface Config { + /** + * 插件信息 + */ + info: Info + /** + * 是否开启插件 + */ + enable: boolean + } + + interface Views extends Route.RouteRecordRaw {} + + interface PluginConfig { + install: (app: App) => void + config: Config + views?: Views[] + /** + * 插件hooks + * 插件禁用时,定义的hook不会被触发 + */ + hooks?: { + // 插件启动时触发,比如可以设置 enable = false,阻止插件启动 + start?: (config: Config) => any | void + // 插件在系统初始化完毕后触发,可调用Vue的上下文、inject等服务 + setup?: () => any | void + // 注册路由时触发,可以对路由进行所有操作 + registerRoute?: (router: Router, routesRaw: Route.RouteRecordRaw[] | Plugin.Views[] | MineRoute.routeRecord[]) => any | void + // 登录时触发 + login?: (formInfo: any) => any | void + // 退出登录时触发 + logout?: () => any | void + // 获取用户信息时触发 + getUserInfo?: (userInfo: any) => any | void + // 路由跳转时钩子,外链形式路由不生效 + routerRedirect?: (route: RouteRecordRaw, router: Router) => any | void + // 网络请求时钩子 + networkRequest?: (request: T) => any | void + // 网络返回后钩子 + networkResponse?: (response: T) => any | void + } + [key: string]: T + } +} +``` +::: + +## 创建插件 + +### 目录说明 +所有插件都放在 `src/plugins` 目录下,且插件有别名 `$` 指向了此目录,插件跟后端结构相同, +由 `开发作者名称空间/插件名称` 组成插件目录。斜杠左边是**作者名称空间**,可在 [MineAdmin官网设置](https://www.mineadmin.com), +斜杠右边则为**插件名称**,在这个作者名称空间下唯一。 + +插件目录示例: +- `mine-admin/app-store` 内置的应用商店插件 +- `zhang-san/oss-uploader` 示例插件 + +::: tip 提示 +本地直接在插件目录创建插件也可以被识别和使用。**只是无法上传到MineAdmin应用市场去!** +::: + +### 文件说明 +```bash +# 示例插件,目录地址:src/plugins +- zhang-san/ # 作者名称空间 +- demo/ # 插件目录 +- config.ts # 此为插件可发布的配置文件,以供开发者修改,而非修改插件源码。 +- index.ts # 此为每个插件必须有的文件,存放了插件基础信息,启用、hooks定义内容。 + +``` + +### `index.ts` 配置 +此文件是插件暴露给系统控制的文件,插件基础信息、是否启用、插件的初始化、引入第三方组件等等功能都在这里面定义。 + +以下是定义示例内容: +```ts +// 引入相关所需数据类型 +import type { Router, RouteRecordRaw } from 'vue-router' +import type { MineToolbarExpose, Plugin } from '#/global' + +// 定义插件 +const pluginConfig: Plugin.PluginConfig = { + // 插件安装方法,必须实现 + install(app) { + // app 是当前 vue 的示例 + // 可通过 app 调用 vue 的 `use`、`component` 等函数去注册组件。 + // 此方法只会在插件状态为启用时执行一次,禁用后下次再启用也不会执行该方法。 + }, + // 插件基础信息,必须配置 + config: { + // 是否启用,也可以根据 import.meta.env 环境变量来确定是否启用,必须打包后不可使用。 + enable: true, + // 基础信息 + info: { + // 插件名称,和目录层级一致 + name: 'zhang-san/demo', + // 插件版本 + version: '1.0.0', + // 插件作者 + author: '张三', + // 插件介绍 + description: '张三的演示插件', + // 插件启动顺序,越大越先被启动执行,包括hooks + order: 1 + }, + }, + // 插件 hooks 定义,非必须实现 + hooks: { + // 插件在启动时被调用,会传入插件的 config 对象 + start: (config) => {}, + // 插件在系统执行到 `vue` 的 `setup` 生命周期时被调用。 + setup: () => {}, + // 在用户登录时被调用,传入(用户名、token等参数) + login: (formInfo) => {}, + // 在用户退出时被调用 + logout: () => {}, + // 在请求用户信息后被调用,传入用户权限、角色等数据。 + getUserInfo: (userInfo) => {}, + // 在系统注册路由时被调用,传入了 `vue-router` 实例和路由原始数据。 + registerRoute: (router: Router, routesRaw) => {}, + // 在页面跳转时被调用,传入了当前路由的数据。 + routerRedirect: (route: RouteRecordRaw) => {}, + // 在网络请求时被调用,传入了原始的请求数据,可对数据加密之类的 + networkRequest: (request) => {}, + // 在服务器返回数据后被调用,传入了原始的响应数据。 + networkResponse: (response) => {}, + }, + // 插件页面,这里的静态路由数据会被系统自动注册。(非必须实现) + views: [ + { + name: 'zhangsan:demo:index', + path: '/zhangsan/demo', + component: () => import('./views/index.vue'), + meta: { + title: '张三的演示插件', + i18n: '国际化的key', + } + } + ] +} +``` + +::: info 大功告成 +做完以上的事,插件就创建完成了,可以开始使用插件了。 +::: + +### 发布插件配置文件 +如果插件有可默认使用的配置,又担心使用者改变了源配置文件,导致插件升级有麻烦,则可以使用插件配置发布命令。 +```bash +# 在 ./web/ 的命令行界面,执行 + +pnpm plugin:publish zhang-san/demo +``` + +插件的配置文件会被发布到 `src/provider/plugins/config` 目录下, +依上述例子,文件名为:`zhang-san.demo.config.ts` + +使用发布的配置文件 +```ts +// 获取默认参数配置 +const config = useGlobal().$pluginsConfig['zhang-san/demo'] +``` + +## 动态启停插件 +可通过 `usePluginStore()` 来动态控制某个插件的启用和停用 + +```ts +const { disabled, enabled } = usePluginStore() + +// 启用插件 +enbaled('zhang-san/demo') + +// 停用插件 +disabled('li-si/demo') +``` + +## 默认自带插件 +在 `src/plugins/mine-admin` 下是官方插件,目前内置了: + +- `basic-ui` 系统基础UI库 +- `app-store` 应用市场 +- `demo` 演示插件 diff --git a/docs/zh/front/high/provider.md b/docs/zh/front/high/provider.md index ac452cb..9a322c1 100644 --- a/docs/zh/front/high/provider.md +++ b/docs/zh/front/high/provider.md @@ -1 +1,105 @@ # 服务提供器 + + +## 说明 +::: tip 前言 +服务提供器在后端很常见,`3.0`的前端也增加了类似功能,但属于简略版,它的作用也是提供一系列服务,比如: +- 注册全局数据到 `Vue` 的 `globalProperties` 或 `provide` 里去 +- 实现注册组件,对组件初始化 +- 提供插件默认配置文件 +- 等等由自己去发掘 + +服务提供器在前端初始化时已被自动扫描注册,无需关心引入的,你只需要关心如何向 `Vue` 的对象绑定、注册数据即可。 +::: + +::: danger 注意 +服务提供器初始化的环节早于 `pinia`、`vue-router`、`vue-i18n` 以上在服务提供器无法使用,需要注意。 +::: + +## 默认服务提供器 + +::: info 存放位置 + +所有服务提供都在 **`src/provider`** 目录下存放着,以归类为原则,自主考虑是否建立目录来区分不同服务提供器。 + +::: + +### dictionary (字典) +这个服务提供了**字典数据**存放功能,`3.0` 后端不自带字典功能,后续通过插件来支持,但前端需要提供一个完整的解决方案来解决现在及后续的支持。 + +在 `src/provider/dictionary/data` 下,存放着一个个数据字典文件,一个文件对应一个集合。文件名就是**字典名**,文件内容就是**字典数据** + +比如 `system-status.ts` 文件,定义了名为 `系统状态` 的数据集合,包含两个数据,**启用和禁用** +定义好之后,我们不需要关心如何引入、如何运作,只关心如何使用即可,使用的话参考后面的组件教程章节。 + +```ts +import type { Dictionary } from '#/global' + +export default [ + { label: '启用', value: 1, i18n: 'dictionary.system.statusEnabled', color: 'primary' }, + { label: '禁用', value: 2, i18n: 'dictionary.system.statusDisabled', color: 'danger' }, +] as Dictionary[] +``` + +### echarts +这个提供了 `echarts` 组件的初始化,包括引入需要使用的 `echarts` 组件(默认并没有全量引入,后续可自己修改添加), +以及将 `echarts` 绑定到 `Vue` 的 `globalProperties` 对象上: **$echarts**,还有黑暗模式下主题的注册等等。 + +在 `vue` 页面里通过 `useGlobal().$echarts` 获取实例,具体如何使用可参考 [MaEcharts](/zh/front/component/echarts) 章节 + + +### plugins +这个对 `MineAdmin插件系统` 提供了默认参数的注册,方便插件后续使用默认参数,也方便后续开发者在这里修改插件的参数,而非插件源码。 +这里不详细讲解如何发布插件配置文件,可以参考 [插件系统](/zh/front/high/plugins) 章节。 + +### mine-core +这个是对 `MineAdmin` 下的 **ma-table、ma-search、ma-form、ma-pro-table** 核心组件初始化, +并挂载全局参数和全局配置,可引入与局部配置一起使用。 + +在 `vue` 页面里通过 `useGlobal().$mineCore` 调取配置 + +### settings +这个里面提供了整个前端的配置参数,不要在默认的 `index.ts` 里修改参数,请复制里面的参数到 `settings.config.ts` 里修改, + +## 创建服务提供器 + +### 服务提供器类型 +```ts +declare namespace ProviderService { + interface Provider { + name: string + init?: () => any | void + setProvider: (app: App) => any | void + getProvider: () => T + } +} +``` +每个服务提供器,需要创建一个目录,目录下必须存在 `index.ts` 文件,切必须要实现 `ProviderService` 下的 `Provider` 接口,并导出。 + +```ts +// src/provider/demo/index.ts +import type { ProviderService } from '#/global' + +const provider: ProviderService.Provider = { + // 实例名称,必须配置,且唯一。 + name: 'demoProvider', + // init 方法可有可无, + init: () => {}, + // 必须实现的方法,设置服务。 + setProvider(app: App): void { + app.config.globalProperties.$demo = 'demo 服务提供器' + }, + // 获取服务,必须实现的方法。但这个获取服务目前基本用不到 + // 因为可在外部直接使用 useGlobal() 获取,但为了规范还是定义一下比较好。 + getProvider() { + return useGlobal().$demo + }, +} + +// 导出配置 +export default provider as ProviderService.Provider +``` + +## 移除服务提供器 + +如果需要移除的话,把某个提供器的目录删除即可。 \ No newline at end of file diff --git a/docs/zh/front/high/store.md b/docs/zh/front/high/store.md index 98c7f60..00ff42b 100644 --- a/docs/zh/front/high/store.md +++ b/docs/zh/front/high/store.md @@ -1 +1,15 @@ -# 常用 Store \ No newline at end of file +# 常用 Store + +::: tip 说明 +因为篇幅问题,只列出以下常用的 `store`,其他可自行查看源码了解。 + +提示:前端下的 `src/store/modules` 已配置自动引入,无需显性引入。 +::: + +## useUserStore() + +## useTabStore() + +## usePluginStore() + +## useDictStore() \ No newline at end of file diff --git a/docs/zh/front/high/tsx.md b/docs/zh/front/high/tsx.md index cf4861f..853bf1b 100644 --- a/docs/zh/front/high/tsx.md +++ b/docs/zh/front/high/tsx.md @@ -1 +1,36 @@ -# JSX 和 TSX 开发 \ No newline at end of file +# JSX 和 TSX 开发 + +在 `3.0` 的前端中,路由视图不仅支持 `vue`,也支持 **`jsx、tsx`** 作为视图文件,给开发者提供不同的选择, +当然在 `vue` 文件内也可以写 `tsx` 或 `jsx`,同时还可以保持传统写法。 + +我们强烈建议把 `vue` 的 `script` 的 `lang` 属性设置为 `tsx` + +```vue + + + +``` + +:::info +会发现,与普通写法没有什么大的差别,但在 `script` 标签里直接写 `
` 之类的标签时候,就会发现特别方便。 +::: + +以上仅仅是简单示例,下面分享几个学习的地方: +- [vue3.0 的官方插件 babel-plugin-jsx 语法教学](https://github.com/vuejs/babel-plugin-jsx#syntax) +- [拥抱 Vue3 系列之 JSX 语法](https://juejin.cn/post/6846687592138670094) \ No newline at end of file