|
|
@@ -1,1420 +0,0 @@
|
|
|
-# PIGX 前端技术文档汇总
|
|
|
-
|
|
|
-> **更新日期**: 2025-10-23
|
|
|
-> **适配版本**: 5.0 以上单体和微服务版本
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 目录
|
|
|
-
|
|
|
-- [一、环境配置](#一环境配置)
|
|
|
- - [1.1 ENV 环境配置](#11-env环境配置)
|
|
|
- - [1.2 前端配置项说明](#12-前端配置项说明)
|
|
|
-- [二、项目结构](#二项目结构)
|
|
|
- - [2.1 目录结构](#21-目录结构)
|
|
|
-- [三、核心功能](#三核心功能)
|
|
|
- - [3.1 国际化配置](#31-国际化配置)
|
|
|
- - [3.2 字体图标配置](#32-字体图标配置)
|
|
|
- - [3.3 权限管理](#33-权限管理)
|
|
|
- - [3.4 路由管理](#34-路由管理)
|
|
|
- - [3.5 标签页管理](#35-标签页管理)
|
|
|
- - [3.6 数据状态管理](#36-数据状态管理)
|
|
|
-- [四、工具函数](#四工具函数)
|
|
|
- - [4.1 字典工具使用](#41-字典工具使用)
|
|
|
- - [4.2 参数工具使用](#42-参数工具使用)
|
|
|
- - [4.3 通用工具函数](#43-通用工具函数)
|
|
|
-- [五、组件使用](#五组件使用)
|
|
|
- - [5.1 表格组件](#51-表格组件)
|
|
|
- - [5.2 表格分页组件](#52-表格分页组件)
|
|
|
- - [5.3 表格工具栏组件](#53-表格工具栏组件)
|
|
|
- - [5.4 上传组件](#54-上传组件)
|
|
|
- - [5.5 富文本组件](#55-富文本组件)
|
|
|
- - [5.6 代码编辑组件](#56-代码编辑组件)
|
|
|
- - [5.7 图表功能](#57-图表功能)
|
|
|
- - [5.8 左侧查询树](#58-左侧查询树)
|
|
|
- - [5.9 组织架构组件](#59-组织架构组件)
|
|
|
- - [5.10 标签列表组件](#510-标签列表组件)
|
|
|
- - [5.11 悬浮输入组件](#511-悬浮输入组件)
|
|
|
- - [5.12 文字提示组件](#512-文字提示组件)
|
|
|
- - [5.13 省市区街四级联动组件](#513-省市区街四级联动组件)
|
|
|
- - [5.14 表单校验](#514-表单校验)
|
|
|
-- [六、首页开发](#六首页开发)
|
|
|
- - [6.1 首页组件开发](#61-首页组件开发)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 一、环境配置
|
|
|
-
|
|
|
-### 1.1 ENV 环境配置
|
|
|
-
|
|
|
-| 配置项 | 值 | 描述 |
|
|
|
-| ------------------------------- | ----------------------- | ---------------------------------------------------------- |
|
|
|
-| **VITE_IS_MICRO** | `true` | 是否是微服务架构(重要),因为单体和微服务版本共用一套前端 |
|
|
|
-| **VITE_GLOBAL_TITLE** | `'PIGX ADMIN'` | 网站主标题(修改需要清空 localstore) |
|
|
|
-| **VITE_FOOTER_TITLE** | `'©2024 pig4cloud.com'` | 网站页脚信息(修改需要清空 localstore) |
|
|
|
-| **VITE_PUBLIC_PATH** | `/` | 前端访问前缀 |
|
|
|
-| **VITE_API_URL** | `/api` | 后端请求前缀 |
|
|
|
-| **VITE_ADMIN_PROXY_PATH** | `http://localhost:9999` | ADMIN 服务地址 |
|
|
|
-| **VITE_PWD_ENC_KEY** | `'pigxpigxpigxpigx'` | 前端加密密钥(16 位) |
|
|
|
-| **VITE_OAUTH2_PASSWORD_CLIENT** | `'pig:pig'` | OAUTH2 密码模式客户端信息 |
|
|
|
-| **VITE_OAUTH2_MOBILE_CLIENT** | `'app:app'` | OAUTH2 短信客户端信息 |
|
|
|
-| **VITE_OAUTH2_SOCIAL_CLIENT** | `'social:social'` | OAUTH2 社交登录客户端信息 |
|
|
|
-| **VITE_VERIFY_ENABLE** | `true` | 是否开启前端滑块验证码 |
|
|
|
-| **VITE_VERIFY_IMAGE_ENABLE** | `false` | 是否开启前端图形验证码 |
|
|
|
-| **VITE_WEBSOCKET_ENABLE** | `false` | 是否开启 WebSocket 消息接收 |
|
|
|
-| **VITE_REGISTER_ENABLE** | `true` | 是否开启注册 |
|
|
|
-| **VITE_AUTO_TENANT** | `false` | 是否开启租户自动选择(根据租户域名) |
|
|
|
-| **VITE_I18N_ENABLE** | `true` | 登录页是否开启多语言切换 |
|
|
|
-| **VITE_DARK_MODE_ENABLE** | `true` | 登录页是否开启暗黑模式切换 |
|
|
|
-| **VITE_ENABLE_ANTI_DEBUG** | `false` | 是否启用禁用浏览器调试功能(反爬) |
|
|
|
-| **VITE_ANTI_DEBUG_KEY** | `pig` | 绕过反爬参数值(URL 中 `?ddtk=参数值`) |
|
|
|
-| **VITE_GRAY_VERSION** | 无 | 对应灰度路由的 header Version |
|
|
|
-| **VITE_API_ENC_ENABLED** | `false` | 是否开启请求加解密 |
|
|
|
-| **VITE_TENANT_ENABLE** | `true` | 是否开启租户功能(v5.9) |
|
|
|
-
|
|
|
-### 1.2 前端配置项说明
|
|
|
-
|
|
|
-**配置文件**: `src/stores/themeConfig.ts`
|
|
|
-
|
|
|
-> ⚠️ **注意**:
|
|
|
->
|
|
|
-> 1. 需要每次都清理 `window.localStorage` 浏览器永久缓存
|
|
|
-> 2. 或者点击布局配置最底部 `一键恢复默认` 按钮即可看到效果
|
|
|
-
|
|
|
-#### 主题配置
|
|
|
-
|
|
|
-| 配置项 | 默认值 | 描述 |
|
|
|
-| ---------- | --------- | ----------------------------- |
|
|
|
-| `isDrawer` | `false` | 是否开启布局配置抽屉 |
|
|
|
-| `primary` | `#2E5CF6` | 全局主题默认 primary 主题颜色 |
|
|
|
-| `isDark` | `false` | 是否开启深色模式 |
|
|
|
-
|
|
|
-#### 顶栏设置
|
|
|
-
|
|
|
-| 配置项 | 默认值 | 描述 |
|
|
|
-| ---------------------- | --------- | ------------------------ |
|
|
|
-| `topBar` | `#ffffff` | 默认顶栏导航背景颜色 |
|
|
|
-| `topBarColor` | `#606266` | 默认顶栏导航字体颜色 |
|
|
|
-| `isTopBarColorGradual` | `false` | 是否开启顶栏背景颜色渐变 |
|
|
|
-
|
|
|
-#### 菜单设置
|
|
|
-
|
|
|
-| 配置项 | 默认值 | 描述 |
|
|
|
-| ----------------------- | -------------- | ------------------------ |
|
|
|
-| `menuBar` | `#FFFFFF` | 默认菜单导航背景颜色 |
|
|
|
-| `menuBarColor` | `#505968` | 默认菜单导航字体颜色 |
|
|
|
-| `menuBarActiveColor` | `rgba(242...)` | 默认菜单高亮背景色 |
|
|
|
-| `isMenuBarColorGradual` | `false` | 是否开启菜单背景颜色渐变 |
|
|
|
-
|
|
|
-#### 界面设置
|
|
|
-
|
|
|
-| 配置项 | 默认值 | 描述 |
|
|
|
-| -------------------- | ------- | ------------------------ |
|
|
|
-| `isCollapse` | `false` | 是否开启菜单水平折叠效果 |
|
|
|
-| `isUniqueOpened` | `true` | 是否开启菜单手风琴效果 |
|
|
|
-| `isFixedHeader` | `false` | 是否开启固定 Header |
|
|
|
-| `isClassicSplitMenu` | `false` | 是否开启经典布局分割菜单 |
|
|
|
-| `isLockScreen` | `false` | 是否开启自动锁屏 |
|
|
|
-| `lockScreenTime` | `30` | 开启自动锁屏倒计时(s/秒) |
|
|
|
-
|
|
|
-#### 界面显示
|
|
|
-
|
|
|
-| 配置项 | 默认值 | 描述 |
|
|
|
-| -------------------- | ------- | ---------------------------- |
|
|
|
-| `isShowLogo` | `true` | 是否开启侧边栏 Logo |
|
|
|
-| `isBreadcrumb` | `true` | 是否开启 Breadcrumb |
|
|
|
-| `isTagsview` | `true` | 是否开启 Tagsview |
|
|
|
-| `isBreadcrumbIcon` | `false` | 是否开启 Breadcrumb 图标 |
|
|
|
-| `isTagsviewIcon` | `false` | 是否开启 Tagsview 图标 |
|
|
|
-| `isCacheTagsView` | `true` | 是否开启 TagsView 缓存 |
|
|
|
-| `isSortableTagsView` | `true` | 是否开启 TagsView 拖拽 |
|
|
|
-| `isShareTagsView` | `false` | 是否开启 TagsView 共用 |
|
|
|
-| `isFooter` | `true` | 是否开启 Footer 底部版权信息 |
|
|
|
-| `isGrayscale` | `false` | 是否开启灰色模式 |
|
|
|
-| `isInvert` | `false` | 是否开启色弱模式 |
|
|
|
-| `isWartermark` | `true` | 是否开启水印 |
|
|
|
-| `wartermarkText` | `PigX` | 水印文案 |
|
|
|
-
|
|
|
-#### 其它设置
|
|
|
-
|
|
|
-| 配置项 | 默认值 | 描述 |
|
|
|
-| -------------------- | ------------------ | -------------------- |
|
|
|
-| `tagsStyle` | `tags-style-five` | Tagsview 风格 |
|
|
|
-| `animation` | `slide-right` | 主页面切换动画 |
|
|
|
-| `columnsAsideStyle` | `columns-round` | 分栏高亮风格 |
|
|
|
-| `columnsAsideLayout` | `columns-vertical` | 分栏布局风格 |
|
|
|
-| `layout` | `defaults` | 布局设置 |
|
|
|
-| `isRequestRoutes` | `true` | 后端控制路由是否开启 |
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 二、项目结构
|
|
|
-
|
|
|
-### 2.1 目录结构
|
|
|
-
|
|
|
-```
|
|
|
-├── src/ # 源代码目录
|
|
|
-│ ├── api/ # API 接口定义
|
|
|
-│ ├── assets/ # 静态资源
|
|
|
-│ ├── components/ # 公共组件
|
|
|
-│ ├── directive/ # Vue 自定义指令
|
|
|
-│ ├── hooks/ # Vue Composition API hooks
|
|
|
-│ ├── i18n/ # 国际化相关
|
|
|
-│ ├── layout/ # 布局组件
|
|
|
-│ ├── locales/ # 语言包
|
|
|
-│ ├── router/ # Vue Router 配置
|
|
|
-│ ├── stores/ # Pinia 状态管理
|
|
|
-│ ├── theme/ # 主题相关
|
|
|
-│ ├── types/ # TypeScript 类型定义
|
|
|
-│ ├── utils/ # 工具函数
|
|
|
-│ ├── views/ # 页面组件
|
|
|
-│ ├── App.vue # 根组件
|
|
|
-│ └── main.ts # 应用入口文件
|
|
|
-├── public/ # 公共静态资源
|
|
|
-├── docker/ # Docker 相关配置
|
|
|
-├── index.html # HTML 入口文件
|
|
|
-├── vite.config.ts # Vite 配置
|
|
|
-├── tsconfig.json # TypeScript 配置
|
|
|
-├── tailwind.config.js # Tailwind CSS 配置
|
|
|
-├── postcss.config.js # PostCSS 配置
|
|
|
-├── package.json # 项目依赖配置
|
|
|
-├── .env # 环境变量
|
|
|
-├── .env.development # 开发环境变量
|
|
|
-├── .env.development.local # 本地开发环境变量
|
|
|
-├── .env.local # 本地环境变量
|
|
|
-├── .eslintrc.js # ESLint 配置
|
|
|
-└── .prettierrc.js # Prettier 配置
|
|
|
-```
|
|
|
-
|
|
|
-> ⚠️ **注意**:清空浏览器永久缓存或者点击 `布局配置 -> 一键恢复默认`,前提是修改了 `/src/stores/themeConfig.ts` 配置文件内容。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 三、核心功能
|
|
|
-
|
|
|
-### 3.1 国际化配置
|
|
|
-
|
|
|
-框架内置 `中文简体`、`英文`
|
|
|
-
|
|
|
-#### 多国语言配置
|
|
|
-
|
|
|
-**前端配置国际化**
|
|
|
-
|
|
|
-> 注意:页面国际化数据最好放 `同级的目录中 i18n` 里。`/@/i18n` 为框架内置,为了更好的升级,最好别添加到里面
|
|
|
-
|
|
|
-**后端配置国际化**
|
|
|
-
|
|
|
-与前端 i18n 配置 ts 文件格式相同,i18n 可以通过后台进行国际化管理的配置和使用。
|
|
|
-
|
|
|
-#### 国际化使用
|
|
|
-
|
|
|
-**页面上使用 `.vue`,`$t('xxx.xxx')`**
|
|
|
-
|
|
|
-```vue
|
|
|
-<el-button>
|
|
|
- <span>{{ $t('message.account.accountBtnText') }}</span>
|
|
|
-</el-button>
|
|
|
-
|
|
|
-<el-divider content-position="left">
|
|
|
- {{ $t('message.layout.oneTitle') }}
|
|
|
-</el-divider>
|
|
|
-```
|
|
|
-
|
|
|
-**ts 上使用 `.ts`,`i18n.global.t(xxx)`**
|
|
|
-
|
|
|
-```typescript
|
|
|
-import { i18n } from '/@/i18n/index';
|
|
|
-
|
|
|
-const webTitle = i18n.global.t(router.currentRoute.value.meta.title as any);
|
|
|
-```
|
|
|
-
|
|
|
-**setup 里使用 ,`t(xxx)`**
|
|
|
-
|
|
|
-```typescript
|
|
|
-<script lang="ts">
|
|
|
-import { defineComponent } from 'vue';
|
|
|
-import { useI18n } from 'vue-i18n';
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'xxx',
|
|
|
- setup() {
|
|
|
- const { t } = useI18n();
|
|
|
-
|
|
|
- // 使用,xxx 为变量
|
|
|
- t(xxx)
|
|
|
- }
|
|
|
-})
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-### 3.2 字体图标配置
|
|
|
-
|
|
|
-#### ElementPlus 图标
|
|
|
-
|
|
|
-使用 element plus 的图标,可去 [https://element-plus.org/zh-CN/component/icon.html](https://element-plus.org/zh-CN/component/icon.html) 复制粘贴
|
|
|
-
|
|
|
-`<el-icon></el-icon>` 包裹着
|
|
|
-
|
|
|
-```vue
|
|
|
-<el-input type="text" :placeholder="$t('message.account.accountPlaceholder1')" v-model="ruleForm.userName" clearable autocomplete="off">
|
|
|
- <template #prefix>
|
|
|
- <el-icon class="el-input__icon"><ele-User /></el-icon>
|
|
|
- </template>
|
|
|
-</el-input>
|
|
|
-```
|
|
|
-
|
|
|
-#### 阿里巴巴在线图标
|
|
|
-
|
|
|
-**1. 创建图标项目**
|
|
|
-
|
|
|
-1. 访问 [iconfont 官网](https://www.iconfont.cn/) 并登录
|
|
|
-2. 创建新项目 -> 设置`FontClass/Symbol 前缀`为 `icon`,`Font Family` 为 `iconfont`
|
|
|
-3. 添加所需图标到项目 -> 生成在线链接
|
|
|
-
|
|
|
-**2. 设置在线链接**
|
|
|
-
|
|
|
-代码位置:`/@/utils/setIconfont.ts`
|
|
|
-
|
|
|
-```typescript
|
|
|
-// `/@/utils/setIconfont.ts` cssCdnUrlList 方法中添加在线链接
|
|
|
-// 字体图标 url (新增)
|
|
|
-const cssCdnUrlList: Array<string> = [
|
|
|
- '//at.alicdn.com/t/font_2298093_y6u00apwst.css',
|
|
|
- '//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css',
|
|
|
-];
|
|
|
-```
|
|
|
-
|
|
|
-**3. 界面中使用**
|
|
|
-
|
|
|
-> ⚠️ **警告**:
|
|
|
->
|
|
|
-> - iconfont(阿里巴巴素材库):需要添加 `iconfont` 前缀,如:`iconfont xitongshezhi`
|
|
|
-> - font-awesome:需要添加 `fa` 前缀,如:`fa xitongshezhi`
|
|
|
-
|
|
|
-```vue
|
|
|
-<!-- 项目使用 -->
|
|
|
-<i class="iconfont xitongshezhi"></i>
|
|
|
-<!-- <i class="fa xitongshezhi"></i> -->
|
|
|
-
|
|
|
-<!-- 或者 -->
|
|
|
-<SvgIcon name="iconfont xitongshezhi"></SvgIcon>
|
|
|
-<!-- <SvgIcon name="fa xitongshezhi"></SvgIcon> -->
|
|
|
-```
|
|
|
-
|
|
|
-#### 本地图标
|
|
|
-
|
|
|
-支持下载 svg ,放在前端的 icons 目录
|
|
|
-
|
|
|
-前端可通过 local-文件名的形式加载
|
|
|
-
|
|
|
-```vue
|
|
|
-<SvgIcon name="local-gitee" :size="30" />
|
|
|
-```
|
|
|
-
|
|
|
-#### 阿里巴巴图标库离线
|
|
|
-
|
|
|
-为了提高系统的稳定性和加载速度,我们可以将原本使用的阿里巴巴在线图标库转换为本地离线使用。
|
|
|
-
|
|
|
-**1. 下载图标资源包**
|
|
|
-
|
|
|
-[点击下载 PIGX-UI 都有依赖的阿里巴巴图标](https://minio.pigx.vip/oss/202501/1737972483.zip)
|
|
|
-
|
|
|
-**2. 创建本地图标目录**
|
|
|
-
|
|
|
-```bash
|
|
|
-mkdir -p pigx-ui/public/assets/iconfont
|
|
|
-```
|
|
|
-
|
|
|
-**3. 复制资源文件**
|
|
|
-
|
|
|
-将下载的资源包中的以下文件复制到 `public/assets/iconfont/` 目录:
|
|
|
-
|
|
|
-- iconfont.css
|
|
|
-- iconfont.ttf
|
|
|
-- iconfont.woff
|
|
|
-- iconfont.woff2
|
|
|
-
|
|
|
-**4. 修改配置文件**
|
|
|
-
|
|
|
-修改 `src/utils/setIconfont.ts` 文件中的图标引用路径:
|
|
|
-
|
|
|
-```typescript
|
|
|
-const cssCdnUrlList: Array<string> = [
|
|
|
- '/assets/iconfont/iconfont.css', // 本地图标文件
|
|
|
- '/assets/styles/font-awesome.min.css',
|
|
|
-];
|
|
|
-```
|
|
|
-
|
|
|
-### 3.3 权限管理
|
|
|
-
|
|
|
-#### 1. 组件方式
|
|
|
-
|
|
|
-组件位置:`/@/components/auth`
|
|
|
-
|
|
|
-**单个权限验证(:value="xxx")**
|
|
|
-
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <!-- 使用 -->
|
|
|
- <Auth :value="'btn.add'" />
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup lang="ts" name="xxx">
|
|
|
-// 局部引入
|
|
|
-import Auth from '/@/components/auth/auth.vue';
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-**多个权限验证,满足一个则显示(:value="[xxx,xxx]")**
|
|
|
-
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <!-- 使用 -->
|
|
|
- <Auths :value="['btn.addsss', 'btn.edit', 'btn.delsss', 'btn.linksss']" />
|
|
|
-</template>
|
|
|
-
|
|
|
-<script lang="ts">
|
|
|
-import { defineComponent } from 'vue';
|
|
|
-// 局部引入
|
|
|
-import Auths from '/@/components/auth/auths.vue';
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'xxxx',
|
|
|
- // 局部注册
|
|
|
- components: { Auths },
|
|
|
-});
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-**多个权限验证,全部满足则显示(:value="[xxx,xxx]")**
|
|
|
-
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <!-- 使用 -->
|
|
|
- <AuthAll :value="['btn.add', 'btn.edit', 'btn.del', 'btn.link']" />
|
|
|
-</template>
|
|
|
-
|
|
|
-<script lang="ts">
|
|
|
-import { defineComponent } from 'vue';
|
|
|
-// 局部引入
|
|
|
-import AuthAll from '/@/components/auth/authAll.vue';
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'xxxx',
|
|
|
- // 局部注册
|
|
|
- components: { AuthAll },
|
|
|
-});
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-#### 2. 指令方式
|
|
|
-
|
|
|
-指令位置:`/@/directive/authDirective.ts`
|
|
|
-
|
|
|
-**单个权限验证(v-auth="xxx")**
|
|
|
-
|
|
|
-```vue
|
|
|
-<div v-auth="'btn.add'">
|
|
|
- <el-button>新增</el-button>
|
|
|
-</div>
|
|
|
-
|
|
|
-<div v-auth="'btn.edit'">
|
|
|
- <el-button>编辑</el-button>
|
|
|
-</div>
|
|
|
-
|
|
|
-<div v-auth="'btn.del'">
|
|
|
- <el-button>删除</el-button>
|
|
|
-</div>
|
|
|
-
|
|
|
-<div v-auth="'btn.link'">
|
|
|
- <el-button>跳转</el-button>
|
|
|
-</div>
|
|
|
-```
|
|
|
-
|
|
|
-**多个权限验证,满足一个则显示(v-auths="[xxx,xxx]")**
|
|
|
-
|
|
|
-```vue
|
|
|
-<div v-auths="['btn.addsss', 'btn.edit', 'btn.delsss', 'btn.linksss']">
|
|
|
- <el-button>新增</el-button>
|
|
|
-</div>
|
|
|
-
|
|
|
-<div v-auths="['btn.add', 'btn.edit', 'btn.del', 'btn.link']">
|
|
|
- <el-button>编辑</el-button>
|
|
|
-</div>
|
|
|
-```
|
|
|
-
|
|
|
-**多个权限验证,全部满足则显示(v-auth-all="[xxx,xxx]")**
|
|
|
-
|
|
|
-```vue
|
|
|
-<div v-auth-all="['btn.add', 'btn.edit', 'btn.del', 'btn.link']">
|
|
|
- <el-button>新增</el-button>
|
|
|
-</div>
|
|
|
-
|
|
|
-<div v-auth-all="['btn.add', 'btn.edit', 'btn.del', 'btn.link']">
|
|
|
- <el-button>编辑</el-button>
|
|
|
-</div>
|
|
|
-```
|
|
|
-
|
|
|
-#### 3. 函数方式
|
|
|
-
|
|
|
-方法位置:`/@/utils/authFunction.ts`,用于方法中的判断
|
|
|
-
|
|
|
-```typescript
|
|
|
-<script lang="ts" setup>
|
|
|
-import { ElMessage } from 'element-plus';
|
|
|
-import { auth, auths, authAll } from '/@/utils/authFunction';
|
|
|
-
|
|
|
-// 单个权限验证
|
|
|
-const onAuthClick = () => {
|
|
|
- if (!auth('btn.add')) ElMessage.error('抱歉,您没有权限!');
|
|
|
- else ElMessage.success('恭喜,您有权限!');
|
|
|
-};
|
|
|
-
|
|
|
-// 多个权限验证,满足一个则为 true
|
|
|
-const onAuthsClick = () => {
|
|
|
- if (!auths(['btn.add', 'btn.edit'])) ElMessage.error('抱歉,您没有权限!');
|
|
|
- else ElMessage.success('恭喜,您有权限!');
|
|
|
-};
|
|
|
-
|
|
|
-// 多个权限验证,全部满足则为 true
|
|
|
-const onAuthAllClick = () => {
|
|
|
- if (!authAll(['btn.add', 'btn.edit'])) ElMessage.error('抱歉,您没有权限!');
|
|
|
- else ElMessage.success('恭喜,您有权限!');
|
|
|
-};
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-或者在模板中使用:
|
|
|
-
|
|
|
-```vue
|
|
|
-<div v-if="auth('sys_file_del')">...</div>
|
|
|
-```
|
|
|
-
|
|
|
-### 3.4 路由管理
|
|
|
-
|
|
|
-#### 静态路由
|
|
|
-
|
|
|
-静态路由是指直接在前端代码中配置的路由,不需要通过后端接口动态获取。这些路由在项目编译时就已确定,适用于固定不变的页面导航结构。
|
|
|
-
|
|
|
-在 PIGX-UI 中使用静态路由的主要原因:适合配置系统级别的页面(如登录、404 等),可以独立于后端菜单权限系统(不需要鉴权等配置)
|
|
|
-
|
|
|
-**路由配置位置**
|
|
|
-
|
|
|
-```
|
|
|
-src/
|
|
|
- └── router/
|
|
|
- └── route.ts # 路由配置文件
|
|
|
-```
|
|
|
-
|
|
|
-**属性配置说明**
|
|
|
-
|
|
|
-| 配置项 | 说明 |
|
|
|
-| ------------- | -------------------------------------------------------------------------- |
|
|
|
-| `title` | 菜单栏及 tagsView 栏、菜单搜索名称(国际化) |
|
|
|
-| `isLink` | 是否超链接菜单,开启外链条件:1. isLink: 链接地址不为空 2. isIframe: false |
|
|
|
-| `isHide` | 是否隐藏此路由 |
|
|
|
-| `isKeepAlive` | 是否缓存组件状态 |
|
|
|
-| `isAuth` | 是否需要认证才能进入的页面 |
|
|
|
-| `isAffix` | 是否固定在 tagsView 栏上 |
|
|
|
-| `isIframe` | 是否内嵌窗口,开启条件:1. isIframe: true 2. isLink:链接地址不为空 |
|
|
|
-| `icon` | 菜单、tagsView 图标,阿里:加 `iconfont xxx`,fontawesome:加 `fa xxx` |
|
|
|
-
|
|
|
-#### 动态路由
|
|
|
-
|
|
|
-点击页面上的按钮可以打开新的 Tagsview 标签页,同时也可以传递参数。
|
|
|
-
|
|
|
-**代码实现方式**
|
|
|
-
|
|
|
-**① 菜单管理中定义隐藏菜单**
|
|
|
-
|
|
|
-> ⚠️ 注意为角色分配该菜单的权限。
|
|
|
-
|
|
|
-**② 点击目标按钮触发路由跳转**
|
|
|
-
|
|
|
-```typescript
|
|
|
-const click = () => {
|
|
|
- router.push({
|
|
|
- path: '/app/appArticle/form',
|
|
|
- query: { tagsViewName: '动态路由测试', param1: '123' },
|
|
|
- });
|
|
|
-};
|
|
|
-```
|
|
|
-
|
|
|
-**③ 在跳转的页面获取请求参数**
|
|
|
-
|
|
|
-```typescript
|
|
|
-const route = useRoute();
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- console.log(route.query.tagsViewName);
|
|
|
- console.log(route.query.param1);
|
|
|
-});
|
|
|
-```
|
|
|
-
|
|
|
-#### 菜单参数方式
|
|
|
-
|
|
|
-在多个菜单中引用同一个路由下的组件,通过路由进行区分。
|
|
|
-
|
|
|
-**① 配置菜单(带参)**
|
|
|
-
|
|
|
-指向 /admin/test/index 组件
|
|
|
-
|
|
|
-```
|
|
|
-AAA /admin/test/1
|
|
|
-BBB /admin/test/2
|
|
|
-```
|
|
|
-
|
|
|
-**② 页面获取参数**
|
|
|
-
|
|
|
-admin/test/index.vue
|
|
|
-
|
|
|
-```typescript
|
|
|
-const route = useRoute();
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- // test/index/参数
|
|
|
- const parts = route.path.split('/');
|
|
|
- const lastParam = parts[parts.length - 1];
|
|
|
- console.log(lastParam);
|
|
|
-});
|
|
|
-```
|
|
|
-
|
|
|
-### 3.5 标签页管理
|
|
|
-
|
|
|
-#### 1. 指定标签页名称
|
|
|
-
|
|
|
-跳转函数中指定路由参数 `tagsViewName`。
|
|
|
-
|
|
|
-```typescript
|
|
|
-const router = useRouter();
|
|
|
-router.push({ path: '/xxx', query: { tagsViewName: '标签名称' } });
|
|
|
-```
|
|
|
-
|
|
|
-#### 2. 刷新当前页面
|
|
|
-
|
|
|
-```typescript
|
|
|
-import { useRoute } from 'vue-router';
|
|
|
-import mittBus from '/@/utils/mitt';
|
|
|
-
|
|
|
-const route = useRoute();
|
|
|
-
|
|
|
-// 刷新当前页面
|
|
|
-const refreshPage = () => {
|
|
|
- mittBus.emit('onCurrentContextmenuClick', {
|
|
|
- contextMenuClickId: 0,
|
|
|
- ...route,
|
|
|
- });
|
|
|
-};
|
|
|
-```
|
|
|
-
|
|
|
-#### 3. 关闭当前页面
|
|
|
-
|
|
|
-```typescript
|
|
|
-// 关闭当前页面
|
|
|
-const closePage = () => {
|
|
|
- mittBus.emit('onCurrentContextmenuClick', {
|
|
|
- contextMenuClickId: 1,
|
|
|
- ...route,
|
|
|
- });
|
|
|
-};
|
|
|
-```
|
|
|
-
|
|
|
-#### 4. 关闭其它页面
|
|
|
-
|
|
|
-```typescript
|
|
|
-// 关闭除当前页外的其它页面
|
|
|
-const closeOthers = () => {
|
|
|
- mittBus.emit('onCurrentContextmenuClick', {
|
|
|
- contextMenuClickId: 2,
|
|
|
- ...route,
|
|
|
- });
|
|
|
-};
|
|
|
-```
|
|
|
-
|
|
|
-#### 5. 关闭全部页面
|
|
|
-
|
|
|
-```typescript
|
|
|
-// 关闭所有页面
|
|
|
-const closeAll = () => {
|
|
|
- mittBus.emit('onCurrentContextmenuClick', {
|
|
|
- contextMenuClickId: 3,
|
|
|
- ...route,
|
|
|
- });
|
|
|
-};
|
|
|
-```
|
|
|
-
|
|
|
-#### 6. 全屏显示
|
|
|
-
|
|
|
-```typescript
|
|
|
-// 当前页面全屏显示
|
|
|
-const fullscreen = () => {
|
|
|
- mittBus.emit('onCurrentContextmenuClick', {
|
|
|
- contextMenuClickId: 4,
|
|
|
- ...route,
|
|
|
- });
|
|
|
-};
|
|
|
-```
|
|
|
-
|
|
|
-**操作 ID 说明**
|
|
|
-
|
|
|
-| 操作 ID | 功能说明 |
|
|
|
-| ------- | -------------- |
|
|
|
-| 0 | 刷新当前页面 |
|
|
|
-| 1 | 关闭当前页面 |
|
|
|
-| 2 | 关闭其它页面 |
|
|
|
-| 3 | 关闭全部页面 |
|
|
|
-| 4 | 当前页全屏显示 |
|
|
|
-
|
|
|
-### 3.6 数据状态管理
|
|
|
-
|
|
|
-框架中数据状态使用 vuex Module 模块化进行管理,您可能需要了解 [vuex 核心概念 Module](https://next.vuex.vuejs.org/zh/guide/modules.html)
|
|
|
-
|
|
|
-#### pinia
|
|
|
-
|
|
|
-代码位置:`/src/stores`
|
|
|
-
|
|
|
-相关文档:[pinia 官网](https://pinia.vuejs.org/)
|
|
|
-
|
|
|
-相关文档:[vuex 3.x 官网](https://v3.vuex.vuejs.org/zh/)
|
|
|
-
|
|
|
-#### 全局引入
|
|
|
-
|
|
|
-页面模块已做全局自动引入,代码位置:`/@/store/index.ts`。
|
|
|
-
|
|
|
-```typescript
|
|
|
-const modulesFiles = import.meta.globEager("./modules/*.ts");
|
|
|
-const pathList: string[] = [];
|
|
|
-
|
|
|
-for (const path in modulesFiles) {
|
|
|
- pathList.push(path);
|
|
|
-}
|
|
|
-
|
|
|
-const modules = pathList.reduce(
|
|
|
- (modules: { [x: string]: any }, modulePath: string) => {
|
|
|
- const moduleName = modulePath.replace(/^./modules/(.*).w+$/, "$1");
|
|
|
- const value = modulesFiles[modulePath];
|
|
|
- modules[moduleName] = value.default;
|
|
|
- return modules;
|
|
|
- },
|
|
|
- {}
|
|
|
-);
|
|
|
-```
|
|
|
-
|
|
|
-#### 定义接口
|
|
|
-
|
|
|
-**1. interface 定义**
|
|
|
-
|
|
|
-`/@/store/interface/index.ts`,如:路由缓存列表 `KeepAliveNamesState`
|
|
|
-
|
|
|
-```typescript
|
|
|
-// 路由缓存列表
|
|
|
-export interface KeepAliveNamesState {
|
|
|
- keepAliveNames: Array<string>;
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-**2. interface 使用**
|
|
|
-
|
|
|
-在 `/@/store/modules/` 新增 `keepAliveNames.ts`,界面写入如下代码:
|
|
|
-
|
|
|
-```typescript
|
|
|
-import { Module } from 'vuex';
|
|
|
-import { KeepAliveNamesState, RootStateTypes } from '/@/store/interface/index';
|
|
|
-
|
|
|
-const keepAliveNamesModule: Module<KeepAliveNamesState, RootStateTypes> = {
|
|
|
- namespaced: true,
|
|
|
- state: {
|
|
|
- keepAliveNames: [],
|
|
|
- },
|
|
|
- mutations: {
|
|
|
- // 设置路由缓存(name字段)
|
|
|
- getCacheKeepAlive(state: any, data: Array<string>) {
|
|
|
- state.keepAliveNames = data;
|
|
|
- },
|
|
|
- },
|
|
|
- actions: {
|
|
|
- // 设置路由缓存(name字段)
|
|
|
- async setCacheKeepAlive({ commit }, data: Array<string>) {
|
|
|
- commit('getCacheKeepAlive', data);
|
|
|
- },
|
|
|
- },
|
|
|
-};
|
|
|
-
|
|
|
-export default keepAliveNamesModule;
|
|
|
-```
|
|
|
-
|
|
|
-#### 使用模块
|
|
|
-
|
|
|
-**1. 在 .ts 中使用**
|
|
|
-
|
|
|
-```typescript
|
|
|
-import { store } from '/@/store/index.ts';
|
|
|
-
|
|
|
-// dispatch
|
|
|
-store.dispatch('keepAliveNames/setCacheKeepAlive', cacheList);
|
|
|
-
|
|
|
-// 或者 commit
|
|
|
-// store.commit("keepAliveNames/getCacheKeepAlive", cacheList);
|
|
|
-```
|
|
|
-
|
|
|
-**2. 在 .vue 中使用**
|
|
|
-
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <div v-if="getThemeConfig.isLockScreen">在 .vue 中使用</div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script lang="ts">
|
|
|
-import { computed, defineComponent } from 'vue';
|
|
|
-import { useStore } from '/@/store/index';
|
|
|
-
|
|
|
-export default defineComponent({
|
|
|
- name: 'app',
|
|
|
- setup() {
|
|
|
- const store = useStore();
|
|
|
- // 获取布局配置信息
|
|
|
- const getThemeConfig = computed(() => {
|
|
|
- return store.state.themeConfig.themeConfig;
|
|
|
- });
|
|
|
- },
|
|
|
-});
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 四、工具函数
|
|
|
-
|
|
|
-### 4.1 字典工具使用
|
|
|
-
|
|
|
-#### 1. useDict 函数
|
|
|
-
|
|
|
-字典类型对应 sys_dict 表中字典数据
|
|
|
-
|
|
|
-```typescript
|
|
|
-import {useDict} from '/@/hooks/dict';
|
|
|
-
|
|
|
-const {字典类型A, 字典类型B} = useDict('字典类型A','字典类型B');
|
|
|
-```
|
|
|
-
|
|
|
-> ⚠️ **注意**:element-plus 的 radio 和 select 等类型组件对 value 字段有强制的数据类型要求。实体字段应该使用字符串而不是数字类型来对应字典功能使用。
|
|
|
-
|
|
|
-#### 2. 页面使用 dict-tag
|
|
|
-
|
|
|
-```vue
|
|
|
-<el-table-column>
|
|
|
- <template #default="scope">
|
|
|
- <dict-tag :options="字典类型" :value="scope.row.xx"></dict-tag>
|
|
|
- </template>
|
|
|
-</el-table-column>
|
|
|
-```
|
|
|
-
|
|
|
-### 4.2 参数工具使用
|
|
|
-
|
|
|
-#### 1. useParam 函数
|
|
|
-
|
|
|
-| 入参 | 出参 |
|
|
|
-| ------------------------------------ | -------------------------------------- |
|
|
|
-| sys_public_param 表中 publicKey 字段 | sys_public_param 表中 publicValue 字段 |
|
|
|
-
|
|
|
-```typescript
|
|
|
-import { useParam } from '/@/hooks/param';
|
|
|
-const param = useParam('GEN_TABLE_PREFIX');
|
|
|
-```
|
|
|
-
|
|
|
-#### 2. 页面使用
|
|
|
-
|
|
|
-```vue
|
|
|
-{{ useParam('GEN_TABLE_PREFIX') }}
|
|
|
-```
|
|
|
-
|
|
|
-### 4.3 通用工具函数
|
|
|
-
|
|
|
-#### 点击复制文本
|
|
|
-
|
|
|
-```vue
|
|
|
-<button @click="copyText('文案内容')">复制</button>
|
|
|
-```
|
|
|
-
|
|
|
-```typescript
|
|
|
-const { copyText } = commonFunction();
|
|
|
-```
|
|
|
-
|
|
|
-#### 格式化时间
|
|
|
-
|
|
|
-**html 代码中直接使用 parseDate parseTime 进行格式化**
|
|
|
-
|
|
|
-```vue
|
|
|
-<el-table-column :label="t('tenant.startTime')" prop="startTime" show-overflow-tooltip>
|
|
|
- <template #default="scope">
|
|
|
- <span>{{ parseDate(scope.row.startTime) }}</span>
|
|
|
- </template>
|
|
|
-</el-table-column>
|
|
|
-
|
|
|
-<el-table-column :label="t('tenant.endTime')" prop="endTime" show-overflow-tooltip>
|
|
|
- <template #default="scope">
|
|
|
- <span>{{ parseTime(scope.row.endTime) }}</span>
|
|
|
- </template>
|
|
|
-</el-table-column>
|
|
|
-```
|
|
|
-
|
|
|
-**ts 中需要手动导入**
|
|
|
-
|
|
|
-```typescript
|
|
|
-import { formatDate, parseDate } from '/@/utils/formatTime';
|
|
|
-```
|
|
|
-
|
|
|
-#### 获取后端参数
|
|
|
-
|
|
|
-```typescript
|
|
|
-import params from '/@/utils/params';
|
|
|
-
|
|
|
-let result = await params.get('参数管理中的KEY');
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 五、组件使用
|
|
|
-
|
|
|
-### 5.1 表格组件
|
|
|
-
|
|
|
-#### 1. useTable 函数是什么
|
|
|
-
|
|
|
-官方对自定义 hook 定义:在 Vue 应用的概念中,"组合式函数" (Composables) 是一个利用 Vue 组合式 API 来封装和复用有状态逻辑的函数。
|
|
|
-
|
|
|
-**useTable 函数的名称就能清晰地表达其作用,它是集成了前端 element-plus 表格的一些通用函数。**
|
|
|
-
|
|
|
-| 方法名 | 描述 |
|
|
|
-| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
|
-| `tableStyle` | 返回包含表格样式的对象,其中包含 `cellStyle` 和 `headerCellStyle` 两个属性,分别用于设置表格单元格和表头单元格的样式 |
|
|
|
-| `getDataList(refresh?: any)` | 获取数据列表,并可选择是否刷新当前页码。如果需要刷新,则将 `state.pagination.current` 重置为 1 |
|
|
|
-| `sizeChangeHandle(val: number)` | 分页大小改变时触发的事件处理函数。会修改 `state.pagination` 中的 `size` 属性,并再次调用 `query()` 方法进行查询 |
|
|
|
-| `currentChangeHandle(val: number)` | 当前页码改变时触发的事件处理函数。会修改 `state.pagination` 中的 `current` 属性,并再次调用 `query()` 方法进行查询 |
|
|
|
-| `sortChangeHandle(column: any)` | 排序方式改变时触发的事件处理函数。根据 `column` 的内容,修改 `state.descs` 和 `state.ascs` 中的排序字段,并再次调用 `query()` 方法进行查询 |
|
|
|
-| `downBlobFile(url: string, query: any, fileName: string)` | 用于下载文件的方法。接收三个参数:文件下载地址 `url`、请求参数 `query` 和文件名 `fileName`。返回一个 Promise 对象,用于异步处理结果 |
|
|
|
-
|
|
|
-#### 2. 页面中如何使用
|
|
|
-
|
|
|
-```typescript
|
|
|
-// 使用 useTable 自动生成表格一些通用方法
|
|
|
-const { getDataList, currentChangeHandle, sizeChangeHandle, downBlobFile, tableStyle } = useTable(state);
|
|
|
-```
|
|
|
-
|
|
|
-#### 3. useTable 初始化 state 如何构建
|
|
|
-
|
|
|
-如果你想通过 useTable 生成一些通用的表格方法,那么就需要向它提供一些初始值,比如查询的 URL 和分页大小等参数。
|
|
|
-
|
|
|
-```typescript
|
|
|
-const state: BasicTableProps = reactive<BasicTableProps>({
|
|
|
- queryForm: {},
|
|
|
- pageList: pageList,
|
|
|
-});
|
|
|
-```
|
|
|
-
|
|
|
-**完整的 BasicTable 定义属性如下**
|
|
|
-
|
|
|
-```typescript
|
|
|
-export interface BasicTableProps {
|
|
|
- // 是否在创建页面时即调用数据列表接口,默认为true
|
|
|
- createdIsNeed?: boolean;
|
|
|
- // 是否需要分页,默认为true
|
|
|
- isPage?: boolean;
|
|
|
- // 查询条件表单对象,类型为any
|
|
|
- queryForm?: any;
|
|
|
- // 数据列表数组
|
|
|
- dataList?: any[];
|
|
|
- // 分页属性对象
|
|
|
- pagination?: Pagination;
|
|
|
- // 数据列表,loading状态标志,默认为false
|
|
|
- dataListLoading?: boolean;
|
|
|
- // 数据列表多选项数组
|
|
|
- dataListSelections?: any[];
|
|
|
- // 数据列表查询接口api方法,接收任意数量参数,返回Promise
|
|
|
- pageList?: (...arg: any) => Promise<any>;
|
|
|
- // loading标志,默认为false
|
|
|
- loading?: Boolean;
|
|
|
- // 多选结果数组
|
|
|
- selectObjs?: any[];
|
|
|
- // 排序字段数组
|
|
|
- descs?: string[];
|
|
|
- // 排序方式数组
|
|
|
- ascs?: string[];
|
|
|
- // props属性对象,类型为any
|
|
|
- props?: any;
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-### 5.2 表格分页组件
|
|
|
-
|
|
|
-#### 分页组件使用
|
|
|
-
|
|
|
-分页组件一般和表格组件一起使用,只需要回调 useTable hook 中的函数即可
|
|
|
-
|
|
|
-```vue
|
|
|
-<pagination v-bind="state.pagination" @current-change="currentChangeHandle" @size-change="sizeChangeHandle"></pagination>
|
|
|
-```
|
|
|
-
|
|
|
-```typescript
|
|
|
-const { currentChangeHandle, sizeChangeHandle } = useTable(state);
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性 | 类型 | 默认值 | 说明 |
|
|
|
-| ----------- | -------- | ------------------------------------------- | -------------------- |
|
|
|
-| `current` | `Number` | `1` | 当前页码 |
|
|
|
-| `size` | `Number` | `10` | 每页展示的条数 |
|
|
|
-| `total` | `Number` | `0` | 数据总数 |
|
|
|
-| `pageSizes` | `Array` | `[1, 10, 20, 50, 100, 200]` | 每页展示的条数可选项 |
|
|
|
-| `layout` | `String` | `'total, sizes, prev, pager, next, jumper'` | 分页组件的布局 |
|
|
|
-
|
|
|
-### 5.3 表格工具栏组件
|
|
|
-
|
|
|
-#### 工具栏组件使用
|
|
|
-
|
|
|
-工具栏组件一般和表格组件一起使用,只需要回调 useTable hook 中的函数即可
|
|
|
-
|
|
|
-```vue
|
|
|
-<right-toolbar v-model:showSearch="showSearch" :export="'sys_user_export'" @exportExcel="exportExcel" @queryTable="getDataList" />
|
|
|
-```
|
|
|
-
|
|
|
-```typescript
|
|
|
-const { getDataList } = useTable(state);
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性 | 类型 | 默认值 | 说明 |
|
|
|
-| ------------ | ------------------- | ------------------------------------------------------------------ | ---------------- |
|
|
|
-| `showSearch` | `Boolean` | `true` | 是否显示搜索框 |
|
|
|
-| `export` | `String or Boolean` | `当设置为true的显示,如设置为权限字符串则根据当前用户权限动态控制` | 是否导出下载按钮 |
|
|
|
-| `search` | `Boolean` | `true` | 是否显示搜索框 |
|
|
|
-| `gutter` | `Number` | `10` | 列表项之间的间距 |
|
|
|
-
|
|
|
-### 5.4 上传组件
|
|
|
-
|
|
|
-#### 普通文件上传
|
|
|
-
|
|
|
-```vue
|
|
|
-<upload-file @change="success" />
|
|
|
-```
|
|
|
-
|
|
|
-**属性说明**
|
|
|
-
|
|
|
-| 属性名称 | 描述 | 类型 | 默认值 |
|
|
|
-| --------------- | ------------------------- | --------- | ----------------------------------------------------------------------------------- |
|
|
|
-| `modelValue` | 组件的值 | `string` | `Array` |
|
|
|
-| `limit` | 数量限制 | `number` | `5` |
|
|
|
-| `fileSize` | 文件大小限制 | `number` | `5MB` |
|
|
|
-| `fileType` | 文件类型限制 | `Array` | `['png', 'jpg', 'jpeg', 'doc', 'xls', 'ppt', 'txt', 'pdf', 'docx', 'xlsx', 'pptx']` |
|
|
|
-| `isShowTip` | 是否显示提示 | `boolean` | `true` |
|
|
|
-| `uploadFileUrl` | 上传文件的 API 方法 | `string` | `'/admin/sys-file/upload'` |
|
|
|
-| `type` | 组件类型 | `string` | `'default'` |
|
|
|
-| `data` | 需要额外传递给 API 的数据 | `Object` | - |
|
|
|
-| `dir` | 子目录名称 | `String` | `a/b 格式, v5.3+` |
|
|
|
-| `autoUpload` | 是否自动上传文件 | `boolean` | `true` |
|
|
|
-
|
|
|
-#### 图片上传
|
|
|
-
|
|
|
-```vue
|
|
|
-<upload-img v-model:imageUrl="formData.avatar" borderRadius="50%">
|
|
|
- <template #empty>
|
|
|
- <el-icon><Avatar /></el-icon>
|
|
|
- <span>请上传头像</span>
|
|
|
- </template>
|
|
|
-</upload-img>
|
|
|
-```
|
|
|
-
|
|
|
-**属性说明**
|
|
|
-
|
|
|
-| 属性名称 | 描述 | 类型 |
|
|
|
-| --------------- | ------------------------------------------ | -------------------------------------------------------------------------------- |
|
|
|
-| `imageUrl` | 图片地址(双向绑定,上传会更新返回此字段) | `string (必传)` |
|
|
|
-| `uploadFileUrl` | 上传图片的 API 方法 | `string (非必传)` |
|
|
|
-| `dir` | 子目录名称 | `String (非必传)` |
|
|
|
-| `drag` | 是否支持拖拽上传 | `boolean (非必传,默认为 true)` |
|
|
|
-| `disabled` | 是否禁用上传组件 | `boolean (非必传,默认为 false)` |
|
|
|
-| `fileSize` | 图片大小限制 | `number (非必传,默认为 5M)` |
|
|
|
-| `fileType` | 图片类型限制 | `File.ImageMimeType[] (非必传,默认为 ["image/jpeg", "image/png", "image/gif"])` |
|
|
|
-| `height` | 组件高度 | `string (非必传,默认为 150px)` |
|
|
|
-| `width` | 组件宽度 | `string (非必传,默认为 150px)` |
|
|
|
-| `borderRadius` | 组件边框圆角 | `string (非必传,默认为 8px)` |
|
|
|
-
|
|
|
-#### Excel 文件上传
|
|
|
-
|
|
|
-```vue
|
|
|
-<upload-excel
|
|
|
- ref="excelUploadRef"
|
|
|
- :title="$t('sysuser.importUserTip')"
|
|
|
- temp-url="/admin/sys-file/local/file/user.xlsx"
|
|
|
- url="/admin/user/import"
|
|
|
- @refreshDataList="getDataList"
|
|
|
-/>
|
|
|
-```
|
|
|
-
|
|
|
-**属性说明**
|
|
|
-
|
|
|
-| 属性名称 | 描述 | 类型 |
|
|
|
-| --------- | --------------------------- | -------- |
|
|
|
-| `url` | 导入文件后台接口 | `String` |
|
|
|
-| `title` | 弹出框标题 | `String` |
|
|
|
-| `tempUrl` | 获取当前导如 excel 模板地址 | `String` |
|
|
|
-
|
|
|
-### 5.5 富文本组件
|
|
|
-
|
|
|
-Wangeditor 是一款基于 Web 的所见即所得富文本编辑器,它提供了丰富的富文本编辑功能,支持插入图片、音视频等多媒体内容,并且可以通过自定义插件扩展其功能。
|
|
|
-
|
|
|
-#### 页面使用
|
|
|
-
|
|
|
-```vue
|
|
|
-<editor v-model:get-html="form.content" />
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性名称 | 描述 | 类型 | 默认值 |
|
|
|
-| --------------- | ------------------------------------------ | --------- | -------------------------- |
|
|
|
-| `disable` | 是否禁用编辑器 | `Boolean` | `false` |
|
|
|
-| `placeholder` | 编辑器默认占位符 | `String` | `"请输入内容..."` |
|
|
|
-| `mode` | 编辑器模式,可选值为 default 或 simple | `String` | `default` |
|
|
|
-| `height` | 编辑器高度 | `String` | `"310px"` |
|
|
|
-| `getHtml` | 双向绑定的属性,用于获取编辑器中 HTML 内容 | `String` | - |
|
|
|
-| `getText` | 双向绑定的属性,用于获取编辑器中纯文本内容 | `String` | - |
|
|
|
-| `uploadFileUrl` | 上传文件的接口地址 | `String` | `"/admin/sys-file/upload"` |
|
|
|
-
|
|
|
-### 5.6 代码编辑组件
|
|
|
-
|
|
|
-#### 引入组件
|
|
|
-
|
|
|
-```typescript
|
|
|
-const CodeEditor = defineAsyncComponent(() => import('/@/components/CodeEditor/index.vue'));
|
|
|
-```
|
|
|
-
|
|
|
-#### 使用方法
|
|
|
-
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <div>
|
|
|
- <CodeEditor v-model="code" mode="go" theme="idea" :readOnly="false" :height="300" />
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-```
|
|
|
-
|
|
|
-#### Props
|
|
|
-
|
|
|
-| 属性 | 类型 | 默认值 | 说明 |
|
|
|
-| ------------ | ------------------ | -------- | --------------------- |
|
|
|
-| `modelValue` | `String` | `''` | 绑定的代码内容 |
|
|
|
-| `mode` | `String` | `'go'` | 代码语言 |
|
|
|
-| `theme` | `String` | `'idea'` | 代码编辑器的主题 |
|
|
|
-| `height` | `[String, Number]` | `300` | 代码编辑器的高度 |
|
|
|
-| `options` | `Object` | `{}` | CodeMirror 的配置选项 |
|
|
|
-| `readOnly` | `Boolean` | `false` | 是否只读 |
|
|
|
-
|
|
|
-### 5.7 图表功能
|
|
|
-
|
|
|
-Vue Echarts 是一个 Vue.js 的 ECharts 图表组件,对 EChart 进行了封装,简化了 Echart 图表的使用。
|
|
|
-
|
|
|
-pigx-ui 默认引入了 vue-echarts ,业务代码中可以非常方便地使用相关的 EChart 图表组件【例如:日志管理】。
|
|
|
-
|
|
|
-#### 快速使用
|
|
|
-
|
|
|
-1. 访问 [ECharts 官网](https://echarts.apache.org/examples/zh/index.html#chart-type-bar),选择目标类型的图表组件,获取图表的 option 配置 JSON。
|
|
|
-
|
|
|
-2. 访问 [vue-echarts 代码生成器](https://vue-echarts.dev/#codegen)。
|
|
|
-
|
|
|
-#### 业务页面使用 vue-echarts
|
|
|
-
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <v-chart class="h-80 w-full" :option="option" />
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup lang="ts" name="demo-chart">
|
|
|
-// 直接复制 vue-echart codegen 生成的 vue 代码部分
|
|
|
-import { use, reactive } from 'echarts/core'
|
|
|
-import {
|
|
|
- BarChart
|
|
|
-} from 'echarts/charts'
|
|
|
-import {
|
|
|
- GridComponent
|
|
|
-} from 'echarts/components'
|
|
|
-import {
|
|
|
- CanvasRenderer
|
|
|
-} from 'echarts/renderers'
|
|
|
-
|
|
|
-use([
|
|
|
- GridComponent,
|
|
|
- BarChart,
|
|
|
- CanvasRenderer
|
|
|
-])
|
|
|
-
|
|
|
-// 定义 JSON
|
|
|
-const option = reactive(复制 EChart option JSON)
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-### 5.8 左侧查询树
|
|
|
-
|
|
|
-```vue
|
|
|
-<query-tree :query="state.queryList" @node-click="handleNodeClick">
|
|
|
-</query-tree>
|
|
|
-```
|
|
|
-
|
|
|
-```typescript
|
|
|
-const QueryTree = defineAsyncComponent(() => import('/@/components/QueryTree/index.vue'));
|
|
|
-
|
|
|
-const state = reactive({
|
|
|
- queryList: (name: String) => {
|
|
|
- return api({ name: name });
|
|
|
- },
|
|
|
-});
|
|
|
-
|
|
|
-const handleNodeClick = (e: any) => {};
|
|
|
-```
|
|
|
-
|
|
|
-#### 卡槽扩展
|
|
|
-
|
|
|
-```vue
|
|
|
-<query-tree>
|
|
|
- <template #default="{ node, data }">
|
|
|
- </template>
|
|
|
-</query-tree>
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性 | 类型 | 默认值 | 说明 |
|
|
|
-| ------------- | ---------- | ------------------------------------------------------ | ----------------------------------------------------------------- |
|
|
|
-| `props` | `Object` | `{ label: 'name', children: 'children', value: 'id' }` | 树形结构的属性配置 |
|
|
|
-| `placeholder` | `String` | `''` | 输入框的占位符 |
|
|
|
-| `loading` | `Boolean` | `false` | 是否显示加载状态 |
|
|
|
-| `query` | `Function` | - | 包含查询方法的函数,必须返回 Promise 类型的数据,并在组件中被调用 |
|
|
|
-
|
|
|
-### 5.9 组织架构组件
|
|
|
-
|
|
|
-#### 页面使用
|
|
|
-
|
|
|
-```vue
|
|
|
-<template>
|
|
|
- <org-selector v-model:orgList="userList" type="user" :multiple="false" />
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup>
|
|
|
-import orgSelector from '/@/components/OrgSelector/index.vue';
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-#### 数据格式
|
|
|
-
|
|
|
-```json
|
|
|
-[
|
|
|
- {
|
|
|
- "type": "user",
|
|
|
- "id": "1",
|
|
|
- "name": "admin",
|
|
|
- "avatar": "xx.png"
|
|
|
- }
|
|
|
-]
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性名 | 类型 | 默认值 | 描述 |
|
|
|
-| ------------ | --------- | ------- | -------------------------------------------------------------------------------------------------------------- |
|
|
|
-| `orgList` | `Array` | `[]` | 组织列表,用于显示可选的组织 |
|
|
|
-| `type` | `String` | `user` | 类型,可选值为 user、dept、org (部门、用户 同时可选)、role、post |
|
|
|
-| `multiple` | `Boolean` | `true` | 是否允许多选。如果为 `true`,则可以选择多个组织或用户;如果为 `false`,则只能选择一个组织或用户。默认为 `true` |
|
|
|
-| `disabled` | `Boolean` | `false` | 是否禁用组件。如果为 `true`,则组件将不可用,用户无法进行选择。默认为 `false` |
|
|
|
-| `selectSelf` | `Boolean` | `true` | 是否包含自身。如果为 `true`,则在可选项中包含当前用户自身;如果为 `false`,则不包含当前用户自身。默认为 `true` |
|
|
|
-
|
|
|
-### 5.10 标签列表组件
|
|
|
-
|
|
|
-#### 使用方法
|
|
|
-
|
|
|
-```vue
|
|
|
-<tag-list buttonText="+手机号" v-model="phoneList" />
|
|
|
-;
|
|
|
-
|
|
|
-<script setup>
|
|
|
-const phoneList = ref([]);
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性 | 类型 | 默认值 | 说明 |
|
|
|
-| ------------ | ---------------------------------------- | ----------- | ---------------------- |
|
|
|
-| `modelValue` | `Array[String]` | `[]` | 双向绑定绑定的标签数组 |
|
|
|
-| `buttonText` | `String` | `+ New Tag` | 按钮显示的文本 |
|
|
|
-| `tagType` | `'success', 'info', 'warning', 'danger'` | - | 按钮显示类型 |
|
|
|
-
|
|
|
-### 5.11 悬浮输入组件
|
|
|
-
|
|
|
-```typescript
|
|
|
-const PopoverInput = defineAsyncComponent(() => import('/@/components/PopoverInput/index.vue'));
|
|
|
-```
|
|
|
-
|
|
|
-```vue
|
|
|
-<popover-input @confirm="onConfirm">
|
|
|
- <template #default>
|
|
|
- <el-button> 点击输入 </el-button>
|
|
|
- </template>
|
|
|
-</popover-input>
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性名称 | 描述 | 类型 | 默认值 |
|
|
|
-| ------------- | ---------------------------------- | -------------- | --------- |
|
|
|
-| `value` | 值 | `String` | - |
|
|
|
-| `type` | 类型 | `String` | `'text'` |
|
|
|
-| `width` | 宽度 | `Number` | `String` |
|
|
|
-| `placeholder` | 提示文字 | `String` | - |
|
|
|
-| `disabled` | 是否禁用 | `Boolean` | `false` |
|
|
|
-| `options` | 选项列表 | `Array<any[]>` | `[]` |
|
|
|
-| `size` | 大小 | `'default'` | `'small'` |
|
|
|
-| `limit` | 字符限制 | `Number` | `200` |
|
|
|
-| `showLimit` | 是否显示字符限制 | `Boolean` | `false` |
|
|
|
-| `teleported` | 是否使用传送门(teleport)进行渲染 | `Boolean` | `true` |
|
|
|
-
|
|
|
-### 5.12 文字提示组件
|
|
|
-
|
|
|
-```vue
|
|
|
-<el-form-item label="初始浏览量" prop="visit">
|
|
|
- <template #label>
|
|
|
- 浏览量<tip content="初始值" />
|
|
|
- </template>
|
|
|
-</el-form-item>
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性名称 | 描述 | 类型 | 默认值 |
|
|
|
-| ----------- | -------- | -------- | ------------- |
|
|
|
-| `content` | 内容 | `String` | - |
|
|
|
-| `placement` | 放置位置 | `String` | `'top-start'` |
|
|
|
-
|
|
|
-### 5.13 省市区街四级联动组件
|
|
|
-
|
|
|
-#### 省市区三级联动
|
|
|
-
|
|
|
-```typescript
|
|
|
-const ChinaArea = defineAsyncComponent(() => import('/@/components/ChinaArea/index.vue'));
|
|
|
-```
|
|
|
-
|
|
|
-```vue
|
|
|
-<china-area v-model="data" @change="handleChange" />
|
|
|
-;
|
|
|
-
|
|
|
-<script setup>
|
|
|
-// 双向绑定数据 自动回显: 北京市/市辖区/东城区
|
|
|
-const data = ref('11,1101,110101');
|
|
|
-
|
|
|
-// 可选 输出: 11,1101,110101
|
|
|
-const handleChange = (val: String) => {};
|
|
|
-</script>
|
|
|
-```
|
|
|
-
|
|
|
-#### 属性说明
|
|
|
-
|
|
|
-| 属性名称 | 描述 | 类型 |
|
|
|
-| --------- | ------------------------- | ---------- |
|
|
|
-| `v-model` | 双向绑定 | `String` |
|
|
|
-| `type` | 省级 1 市 2 区 3 街道 4 | `Number` |
|
|
|
-| `plus` | 默认 false, 不用选择某级 | `Boolean` |
|
|
|
-| `@change` | 选中回调事件 | `Function` |
|
|
|
-
|
|
|
-#### 完整区划数据
|
|
|
-
|
|
|
-下载 [👉🏻 省市街区详细 SQL](https://minio.pigx.top/oss/202402/1708152046.sql),导入至 sys_area 表即可。
|
|
|
-
|
|
|
-如果此数据(来自民政部 2023 年的数据)中不存在对应地区,您可以根据规则自行新增。请注意,编码需保持唯一。
|
|
|
-
|
|
|
-### 5.14 表单校验
|
|
|
-
|
|
|
-#### 表单校验使用
|
|
|
-
|
|
|
-Form 组件允许你验证用户的输入是否符合规范,来帮助你找到和纠正错误。
|
|
|
-
|
|
|
-Form 组件提供了表单验证的功能,只需为 rules 属性传入约定的验证规则,并将 form-Item 的 prop 属性设置为需要验证的特殊键值即可。
|
|
|
-
|
|
|
-```typescript
|
|
|
-const rule = ref({
|
|
|
- 字段名称: [
|
|
|
- // 校验用户输入的长度避免超长 0-255个字符 超长
|
|
|
- { validator: rule.overLength, trigger: 'blur' },
|
|
|
- // 根据字段自动查询后台是否重复
|
|
|
- {
|
|
|
- validator: (rule: any, value: any, callback: any) => {
|
|
|
- validateExist(rule, value, callback, form.id !== '');
|
|
|
- },
|
|
|
- trigger: 'blur',
|
|
|
- },
|
|
|
- ],
|
|
|
-});
|
|
|
-```
|
|
|
-
|
|
|
-> ⚠️ **注意**:element-plus 的 radio 和 select 等类型组件对 value 字段有强制的数据类型要求。实体字段应该使用字符串而不是数字类型来对应字典功能使用。
|
|
|
-
|
|
|
-#### 内置规则
|
|
|
-
|
|
|
-| 函数名称 | 函数作用 |
|
|
|
-| --------------------------- | ----------------------------------------------- |
|
|
|
-| `validateExist` | 根据字段自动查询后台是否重复 |
|
|
|
-| `overLength` | 校验用户输入的长度避免超长,范围为 0-255 个字符 |
|
|
|
-| `validatorNameCn` | 校验用户输入是否为中文、英文、数字包括下划线 |
|
|
|
-| `validatorCapital` | 校验用户输入是否为大写英文、下划线 |
|
|
|
-| `validatorLowercase` | 校验用户输入是否为小写英文、下划线 |
|
|
|
-| `validatorLower` | 校验用户输入是否为小写英文 |
|
|
|
-| `checkSpace` | 校验输入是否包含首尾空白字符 |
|
|
|
-| `validatePhone` | 校验手机号的合法性 |
|
|
|
-| `number` | 校验输入是否为数字 |
|
|
|
-| `letter` | 校验输入是否为字母 |
|
|
|
-| `letterAndNumber` | 校验输入是否为字母和数字 |
|
|
|
-| `mobilePhone` | 校验输入是否为正确格式的手机号码 |
|
|
|
-| `letterStartNumberIncluded` | 校验输入是否以字母开头,可包含数字 |
|
|
|
-| `noChinese` | 校验输入是否包含中文字符 |
|
|
|
-| `chinese` | 校验输入是否为中文字符 |
|
|
|
-| `email` | 校验输入是否为正确格式的电子邮箱 |
|
|
|
-| `url` | 校验输入是否为正确格式的 URL |
|
|
|
-| `regExp` | 校验输入是否符合给定的正则表达式 |
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 六、首页开发
|
|
|
-
|
|
|
-### 6.1 首页组件开发
|
|
|
-
|
|
|
-#### 开发组件
|
|
|
-
|
|
|
-在 `src/views/home/widgets/components` 目录下创建组件
|
|
|
-
|
|
|
-#### 挂载组件
|
|
|
-
|
|
|
-在 `src/views/home/widgets/index.vue` 中挂载组件,将 myGrid 数组增加上一步创建的组件文件名称
|
|
|
-
|
|
|
-```typescript
|
|
|
-const myGrid = ['test-demo'];
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 总结
|
|
|
-
|
|
|
-本文档汇总了 PIGX 前端技术框架的核心内容,包括:
|
|
|
-
|
|
|
-- ✅ **环境配置**:ENV 配置、前端配置项说明
|
|
|
-- ✅ **项目结构**:完整的目录结构说明
|
|
|
-- ✅ **核心功能**:国际化、图标、权限、路由、标签页、状态管理
|
|
|
-- ✅ **工具函数**:字典、参数、通用工具函数
|
|
|
-- ✅ **组件使用**:表格、分页、上传、富文本、代码编辑、图表等 14 个常用组件
|
|
|
-- ✅ **首页开发**:首页组件开发指南
|
|
|
-
|
|
|
-更多详细信息请参考官方文档:[https://pig4cloud.com](https://pig4cloud.com)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-**文档版本**: v1.0
|
|
|
-**最后更新**: 2025-10-23
|
|
|
-**维护团队**: PIGX 开发团队
|