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
+
+
+
+
+
+
{{ example }}
+
+
+
+
+
+```
+
+:::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