mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-31 09:30:05 +08:00
Merge remote-tracking branch 'origin/dev' into feature/springdoc
This commit is contained in:
commit
4f2c08f8db
50
README.md
50
README.md
@ -169,21 +169,21 @@ ps:核心功能已经实现,正在对接微信小程序中...
|
||||
|
||||
## 🐨 技术栈
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----------------------|--------------------|
|
||||
| `yudao-dependencies` | Maven 依赖版本管理 |
|
||||
| `yudao-framework` | Java 框架拓展 |
|
||||
| `yudao-server` | 管理后台 + 用户 APP 的服务端 |
|
||||
| `yudao-ui-admin` | 管理后台的 Vue2 前端项目 |
|
||||
| `yudao-ui-admin-vue3` | 管理后台的 Vue3 前端项目 |
|
||||
| `yudao-ui-admin-uniapp` | 管理后台的 uni-app 多端项目 |
|
||||
| `yudao-ui-app` | 用户 APP 的 UI 界面 |
|
||||
| `yudao-module-system` | 系统功能的 Module 模块 |
|
||||
| `yudao-module-member` | 会员中心的 Module 模块 |
|
||||
| `yudao-module-infra` | 基础设施的 Module 模块 |
|
||||
| `yudao-module-tool` | 研发工具的 Module 模块 |
|
||||
| `yudao-module-bpm` | 工作流程的 Module 模块 |
|
||||
| `yudao-module-pay` | 支付系统的 Module 模块 |
|
||||
| 项目 | 说明 |
|
||||
|-------------------------|-----------------------|
|
||||
| `yudao-dependencies` | Maven 依赖版本管理 |
|
||||
| `yudao-framework` | Java 框架拓展 |
|
||||
| `yudao-server` | 管理后台 + 用户 APP 的服务端 |
|
||||
| `yudao-ui-admin` | 管理后台的 Vue2 前端项目 |
|
||||
| `yudao-ui-admin-vue3` | 管理后台的 Vue3 前端项目 |
|
||||
| `yudao-ui-admin-uniapp` | 管理后台的 uni-app 多端项目 |
|
||||
| `yudao-ui-app` | 用户 APP 的 UI 界面 |
|
||||
| `yudao-module-system` | 系统功能的 Module 模块 |
|
||||
| `yudao-module-member` | 会员中心的 Module 模块 |
|
||||
| `yudao-module-infra` | 基础设施的 Module 模块 |
|
||||
| `yudao-module-tool` | 研发工具的 Module 模块 |
|
||||
| `yudao-module-bpm` | 工作流程的 Module 模块 |
|
||||
| `yudao-module-pay` | 支付系统的 Module 模块 |
|
||||
|
||||
### 后端
|
||||
|
||||
@ -193,7 +193,7 @@ ps:核心功能已经实现,正在对接微信小程序中...
|
||||
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
|
||||
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.15 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) |
|
||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||
| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |
|
||||
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.18.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
||||
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
||||
@ -204,12 +204,12 @@ ps:核心功能已经实现,正在对接微信小程序中...
|
||||
| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.3 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||
| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.1 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
|
||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.7 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.9 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
|
||||
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.5.3.Final | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
||||
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.24 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
||||
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
|
||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.2 | - |
|
||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
|
||||
|
||||
### [管理后台 Vue2 前端](./yudao-ui-admin)
|
||||
|
||||
@ -223,12 +223,12 @@ ps:核心功能已经实现,正在对接微信小程序中...
|
||||
| 框架 | 说明 | 版本 |
|
||||
|----------------------------------------------------------------------|:------------:|:------:|
|
||||
| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.2.45 |
|
||||
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.2.3 |
|
||||
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.25 |
|
||||
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.0.2 |
|
||||
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.27 |
|
||||
| [TypeScript](https://www.typescriptlang.org/docs/) | TypeScript | 4.9.4 |
|
||||
| [pinia](https://pinia.vuejs.org/) | vuex5 | 2.0.27 |
|
||||
| [pinia](https://pinia.vuejs.org/) | vuex5 | 2.0.28 |
|
||||
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 |
|
||||
| [vxe-table](https://vxetable.cn/) | vue最强表单 | 4.5.6 |
|
||||
| [vxe-table](https://vxetable.cn/) | vue最强表单 | 4.3.7 |
|
||||
|
||||
### [管理后台 uni-app 跨端](./yudao-ui-admin-uniapp)
|
||||
|
||||
@ -242,15 +242,15 @@ ps:核心功能已经实现,正在对接微信小程序中...
|
||||
### 系统功能
|
||||
|
||||
| 模块 | biu | biu | biu |
|
||||
|----------|--------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------|
|
||||
|------------|--------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------|
|
||||
| 登录 & 首页 | ![登录](https://static.iocoder.cn/images/ruoyi-vue-pro/登录.jpg?imageView2/2/format/webp/w/1280) | ![首页](https://static.iocoder.cn/images/ruoyi-vue-pro/首页.jpg?imageView2/2/format/webp/w/1280) | ![个人中心](https://static.iocoder.cn/images/ruoyi-vue-pro/个人中心.jpg?imageView2/2/format/webp/w/1280) |
|
||||
| 用户 & 应用 | ![用户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/用户管理.jpg?imageView2/2/format/webp/w/1280) | ![令牌管理](https://static.iocoder.cn/images/ruoyi-vue-pro/令牌管理.jpg?imageView2/2/format/webp/w/1280) | ![应用管理](https://static.iocoder.cn/images/ruoyi-vue-pro/应用管理.jpg?imageView2/2/format/webp/w/1280) |
|
||||
| 用户 & 应用 | ![用户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/用户管理.jpg?imageView2/2/format/webp/w/1280) | ![令牌管理](https://static.iocoder.cn/images/ruoyi-vue-pro/令牌管理.jpg?imageView2/2/format/webp/w/1280) | ![应用管理](https://static.iocoder.cn/images/ruoyi-vue-pro/应用管理.jpg?imageView2/2/format/webp/w/1280) |
|
||||
| 租户 & 套餐 | ![租户管理](https://static.iocoder.cn/images/ruoyi-vue-pro/租户管理.jpg?imageView2/2/format/webp/w/1280) | ![租户套餐](https://static.iocoder.cn/images/ruoyi-vue-pro/租户套餐.png) | - |
|
||||
| 部门 & 岗位 | ![部门管理](https://static.iocoder.cn/images/ruoyi-vue-pro/部门管理.jpg?imageView2/2/format/webp/w/1280) | ![岗位管理](https://static.iocoder.cn/images/ruoyi-vue-pro/岗位管理.jpg?imageView2/2/format/webp/w/1280) | - |
|
||||
| 菜单 & 角色 | ![菜单管理](https://static.iocoder.cn/images/ruoyi-vue-pro/菜单管理.jpg?imageView2/2/format/webp/w/1280) | ![角色管理](https://static.iocoder.cn/images/ruoyi-vue-pro/角色管理.jpg?imageView2/2/format/webp/w/1280) | - |
|
||||
| 审计日志 | ![操作日志](https://static.iocoder.cn/images/ruoyi-vue-pro/操作日志.jpg?imageView2/2/format/webp/w/1280) | ![登录日志](https://static.iocoder.cn/images/ruoyi-vue-pro/登录日志.jpg?imageView2/2/format/webp/w/1280) | - |
|
||||
| 短信 | ![短信渠道](https://static.iocoder.cn/images/ruoyi-vue-pro/短信渠道.jpg?imageView2/2/format/webp/w/1280) | ![短信模板](https://static.iocoder.cn/images/ruoyi-vue-pro/短信模板.jpg?imageView2/2/format/webp/w/1280) | ![短信日志](https://static.iocoder.cn/images/ruoyi-vue-pro/短信日志.jpg?imageView2/2/format/webp/w/1280) |
|
||||
| 字典 & 敏感词 | ![字典类型](https://static.iocoder.cn/images/ruoyi-vue-pro/字典类型.jpg?imageView2/2/format/webp/w/1280) | ![字典数据](https://static.iocoder.cn/images/ruoyi-vue-pro/字典数据.jpg?imageView2/2/format/webp/w/1280) | ![敏感词](https://static.iocoder.cn/images/ruoyi-vue-pro/敏感词.jpg?imageView2/2/format/webp/w/1280) |
|
||||
| 字典 & 敏感词 | ![字典类型](https://static.iocoder.cn/images/ruoyi-vue-pro/字典类型.jpg?imageView2/2/format/webp/w/1280) | ![字典数据](https://static.iocoder.cn/images/ruoyi-vue-pro/字典数据.jpg?imageView2/2/format/webp/w/1280) | ![敏感词](https://static.iocoder.cn/images/ruoyi-vue-pro/敏感词.jpg?imageView2/2/format/webp/w/1280) |
|
||||
| 错误码 & 通知 | ![错误码管理](https://static.iocoder.cn/images/ruoyi-vue-pro/错误码管理.jpg?imageView2/2/format/webp/w/1280) | ![通知公告](https://static.iocoder.cn/images/ruoyi-vue-pro/通知公告.jpg?imageView2/2/format/webp/w/1280) | - |
|
||||
|
||||
### 工作流程
|
||||
|
@ -11,7 +11,7 @@
|
||||
Target Server Version : 80026
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 29/07/2022 00:33:25
|
||||
Date: 20/12/2022 00:33:25
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
@ -300,7 +300,7 @@ CREATE TABLE `bpm_form` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的表单定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的表单定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_form
|
||||
@ -329,7 +329,7 @@ CREATE TABLE `bpm_oa_leave` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 33 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OA 请假申请表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_oa_leave
|
||||
@ -359,7 +359,7 @@ CREATE TABLE `bpm_process_definition_ext` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 135 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 流程定义的拓展表\n';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 流程定义的拓展表\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_process_definition_ext
|
||||
@ -389,7 +389,7 @@ CREATE TABLE `bpm_process_instance_ext` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 290 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程实例的拓展';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程实例的拓展';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_process_instance_ext
|
||||
@ -415,7 +415,7 @@ CREATE TABLE `bpm_task_assign_rule` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 265 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 任务规则表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'Bpm 任务规则表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_task_assign_rule
|
||||
@ -444,7 +444,7 @@ CREATE TABLE `bpm_task_ext` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 341 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程任务的拓展表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '工作流的流程任务的拓展表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_task_ext
|
||||
@ -469,7 +469,7 @@ CREATE TABLE `bpm_user_group` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 111 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of bpm_user_group
|
||||
@ -504,7 +504,7 @@ CREATE TABLE `infra_api_access_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 35822 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_api_access_log
|
||||
@ -546,7 +546,7 @@ CREATE TABLE `infra_api_error_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 647 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_api_error_log
|
||||
@ -584,7 +584,7 @@ CREATE TABLE `infra_codegen_column` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1126 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_codegen_column
|
||||
@ -616,7 +616,7 @@ CREATE TABLE `infra_codegen_table` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 99 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_codegen_table
|
||||
@ -673,7 +673,7 @@ CREATE TABLE `infra_data_source_config` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '数据源配置表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '数据源配置表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_data_source_config
|
||||
@ -699,7 +699,7 @@ CREATE TABLE `infra_file` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 93 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_file
|
||||
@ -753,7 +753,7 @@ CREATE TABLE `infra_file_content` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_file_content
|
||||
@ -781,13 +781,13 @@ CREATE TABLE `infra_job` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_job
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2022-04-03 20:35:25', b'0');
|
||||
INSERT INTO `infra_job` (`id`, `name`, `status`, `handler_name`, `handler_param`, `cron_expression`, `retry_count`, `retry_interval`, `monitor_timeout`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '支付通知 Job', 2, 'payNotifyJob', NULL, '* * * * * ?', 0, 0, 0, '1', '2021-10-27 08:34:42', '1', '2022-04-03 20:35:25', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -811,7 +811,7 @@ CREATE TABLE `infra_job_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 25295 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_job_log
|
||||
@ -836,7 +836,7 @@ CREATE TABLE `infra_test_demo` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 108 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of infra_test_demo
|
||||
@ -866,7 +866,7 @@ CREATE TABLE `member_user` (
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `uk_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 248 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of member_user
|
||||
@ -893,7 +893,7 @@ CREATE TABLE `pay_app` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付应用信息';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付应用信息';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_app
|
||||
@ -921,7 +921,7 @@ CREATE TABLE `pay_channel` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付渠道\n';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付渠道\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_channel
|
||||
@ -947,7 +947,7 @@ CREATE TABLE `pay_merchant` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付商户信息';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付商户信息';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_merchant
|
||||
@ -972,7 +972,7 @@ CREATE TABLE `pay_notify_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 363051 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付通知 App 的日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付通知 App 的日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_notify_log
|
||||
@ -1004,7 +1004,7 @@ CREATE TABLE `pay_notify_task` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 112 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商户支付、退款等的通知\n';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商户支付、退款等的通知\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_notify_task
|
||||
@ -1048,7 +1048,7 @@ CREATE TABLE `pay_order` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 125 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_order
|
||||
@ -1077,7 +1077,7 @@ CREATE TABLE `pay_order_extension` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 124 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '支付订单\n';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of pay_order_extension
|
||||
@ -1166,8 +1166,6 @@ INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`,
|
||||
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (107, '运维部门', 101, 5, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:33', b'0', 1);
|
||||
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (108, '市场部门', 102, 1, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2022-02-16 08:35:45', b'0', 1);
|
||||
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (109, '财务部门', 102, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:29', b'0', 1);
|
||||
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (110, '新部门', 0, 1, NULL, NULL, NULL, 0, '110', '2022-02-23 20:46:30', '110', '2022-02-23 20:46:30', b'0', 121);
|
||||
INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (111, '顶级部门', 0, 1, NULL, NULL, NULL, 0, '113', '2022-03-07 21:44:50', '113', '2022-03-07 21:44:50', b'0', 122);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -1335,19 +1333,20 @@ COMMIT;
|
||||
-- Table structure for system_dict_type
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `system_dict_type`;
|
||||
CREATE TABLE `system_dict_type` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键',
|
||||
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典名称',
|
||||
`type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典类型',
|
||||
`status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
|
||||
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE
|
||||
CREATE TABLE `system_dict_type`(
|
||||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '字典主键',
|
||||
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典名称',
|
||||
`type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '字典类型',
|
||||
`status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
|
||||
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `dict_type`(`type` ASC,`deleted_time` ASC) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 149 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表';
|
||||
|
||||
-- ----------------------------
|
||||
@ -1413,7 +1412,7 @@ CREATE TABLE `system_error_code` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 5832 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_error_code
|
||||
@ -1442,7 +1441,7 @@ CREATE TABLE `system_login_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1670 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_login_log
|
||||
@ -1761,7 +1760,7 @@ CREATE TABLE `system_oauth2_access_token` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 404 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_access_token
|
||||
@ -1788,7 +1787,7 @@ CREATE TABLE `system_oauth2_approve` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 79 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 批准表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 批准表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_approve
|
||||
@ -1854,7 +1853,7 @@ CREATE TABLE `system_oauth2_code` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 103 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 授权码表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 授权码表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_code
|
||||
@ -1881,7 +1880,7 @@ CREATE TABLE `system_oauth2_refresh_token` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 295 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '刷新令牌';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '刷新令牌';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_oauth2_refresh_token
|
||||
@ -1921,7 +1920,7 @@ CREATE TABLE `system_operate_log` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 2764 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_operate_log
|
||||
@ -1947,7 +1946,7 @@ CREATE TABLE `system_post` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '岗位信息表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_post
|
||||
@ -2303,7 +2302,7 @@ CREATE TABLE `system_sms_code` (
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号'
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 480 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_code
|
||||
@ -2346,7 +2345,7 @@ CREATE TABLE `system_sms_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 337 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_sms_log
|
||||
@ -2416,7 +2415,7 @@ CREATE TABLE `system_social_user` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_social_user
|
||||
@ -2441,7 +2440,7 @@ CREATE TABLE `system_social_user_bind` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_social_user_bind
|
||||
@ -2527,12 +2526,7 @@ CREATE TABLE `system_user_post` (
|
||||
-- Records of system_user_post
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (112, 1, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0', 1);
|
||||
INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (113, 100, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0', 1);
|
||||
INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (114, 114, 3, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0', 1);
|
||||
INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (115, 104, 1, '1', '2022-05-16 19:36:28', '1', '2022-05-16 19:36:28', b'0', 1);
|
||||
INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (116, 117, 2, '1', '2022-07-09 17:40:26', '1', '2022-07-09 17:40:26', b'0', 1);
|
||||
INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (117, 118, 1, '1', '2022-07-09 17:44:44', '1', '2022-07-09 17:44:44', b'0', 1);
|
||||
INSERT INTO `system_user_post` (`id`, `user_id`, `post_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 1, 1, 'admin', '2022-05-02 07:25:24', 'admin', '2022-05-02 07:25:24', b'0', 1);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -2550,7 +2544,7 @@ CREATE TABLE `system_user_role` (
|
||||
`deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户和角色关联表';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户和角色关联表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_user_role
|
||||
@ -2558,21 +2552,6 @@ CREATE TABLE `system_user_role` (
|
||||
BEGIN;
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 1, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:17', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 2, 2, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:13', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 100, 101, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:13', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, 100, 1, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:12', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 100, 2, '', '2022-01-11 13:19:45', '', '2022-05-12 12:35:11', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (10, 103, 1, '1', '2022-01-11 13:19:45', '1', '2022-01-11 13:19:45', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (11, 107, 106, '1', '2022-02-20 22:59:33', '1', '2022-02-20 22:59:33', b'0', 118);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (12, 108, 107, '1', '2022-02-20 23:00:50', '1', '2022-02-20 23:00:50', b'0', 119);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (13, 109, 108, '1', '2022-02-20 23:11:50', '1', '2022-02-20 23:11:50', b'0', 120);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (14, 110, 109, '1', '2022-02-22 00:56:14', '1', '2022-02-22 00:56:14', b'0', 121);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (15, 111, 110, '110', '2022-02-23 13:14:38', '110', '2022-02-23 13:14:38', b'0', 121);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (16, 113, 111, '1', '2022-03-07 21:37:58', '1', '2022-03-07 21:37:58', b'0', 122);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (17, 114, 101, '1', '2022-03-19 21:51:13', '1', '2022-03-19 21:51:13', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (18, 1, 2, '1', '2022-05-12 20:39:29', '1', '2022-05-12 20:39:29', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (19, 116, 113, '1', '2022-05-17 10:07:10', '1', '2022-05-17 10:07:10', b'0', 124);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (20, 104, 101, '1', '2022-05-28 15:43:57', '1', '2022-05-28 15:43:57', b'0', 1);
|
||||
INSERT INTO `system_user_role` (`id`, `user_id`, `role_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (22, 115, 2, '1', '2022-07-21 22:08:30', '1', '2022-07-21 22:08:30', b'0', 1);
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -2595,7 +2574,7 @@ CREATE TABLE `system_user_session` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户在线 Session';
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户在线 Session';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_user_session
|
||||
|
@ -418,17 +418,19 @@ CREATE TABLE `jimu_report_data_source` (
|
||||
`update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
|
||||
`update_time` datetime NULL DEFAULT NULL COMMENT '更新日期',
|
||||
`connect_times` int(1) UNSIGNED NULL DEFAULT 0 COMMENT '连接失败次数',
|
||||
`tenant_id` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '多租户标识',
|
||||
`type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型(report:报表;drag:仪表盘)',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_jmdatasource_report_id`(`report_id`) USING BTREE,
|
||||
INDEX `idx_jmdatasource_code`(`code`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of jimu_report_data_source
|
||||
-- ----------------------------
|
||||
INSERT INTO `jimu_report_data_source` VALUES ('1324261983692902402', 'jeewx', '1324261770294071296', '', NULL, 'MYSQL', 'com.mysql.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeewx-boot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8', 'root', 'root', 'jeecg', '2020-11-05 16:07:15', NULL, '2020-11-05 16:07:15', 0);
|
||||
INSERT INTO `jimu_report_data_source` VALUES ('26d21fe4f27920d2f56abc8d90a8e527', 'oracle', '1308645288868712448', '', NULL, 'ORACLE', 'oracle.jdbc.OracleDriver', 'jdbc:oracle:thin:@192.168.1.199:1521:helowin', 'jeecgbootbpm', 'jeecg196283', 'admin', '2021-01-05 19:26:24', NULL, '2021-01-05 19:26:24', 1);
|
||||
INSERT INTO `jimu_report_data_source` VALUES ('8f90daf47d15d35ca6cf420748b8b9ba', 'localhost', '1316944968992034816', '', NULL, 'MYSQL5.7', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeecg-boot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8', 'root', 'root', 'admin', '2021-01-13 14:34:00', NULL, '2021-01-13 14:34:00', 0);
|
||||
INSERT INTO `jimu_report_data_source` VALUES ('1324261983692902402', 'jeewx', '1324261770294071296', '', NULL, 'MYSQL', 'com.mysql.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeewx-boot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8', 'root', 'root', 'jeecg', '2020-11-05 16:07:15', NULL, '2020-11-05 16:07:15', 0, NULL, 'report');
|
||||
INSERT INTO `jimu_report_data_source` VALUES ('26d21fe4f27920d2f56abc8d90a8e527', 'oracle', '1308645288868712448', '', NULL, 'ORACLE', 'oracle.jdbc.OracleDriver', 'jdbc:oracle:thin:@192.168.1.199:1521:helowin', 'jeecgbootbpm', 'jeecg196283', 'admin', '2021-01-05 19:26:24', NULL, '2021-01-05 19:26:24', 1, NULL, 'report');
|
||||
INSERT INTO `jimu_report_data_source` VALUES ('8f90daf47d15d35ca6cf420748b8b9ba', 'localhost', '1316944968992034816', '', NULL, 'MYSQL5.7', 'com.mysql.cj.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeecg-boot?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8', 'root', 'root', 'admin', '2021-01-13 14:34:00', NULL, '2021-01-13 14:34:00', 0, NULL, 'report');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for jimu_report_db
|
||||
|
@ -2474,17 +2474,18 @@ COMMIT;
|
||||
-- Table structure for SYSTEM_DICT_TYPE
|
||||
-- ----------------------------
|
||||
DROP TABLE "SYSTEM_DICT_TYPE";
|
||||
CREATE TABLE "SYSTEM_DICT_TYPE" (
|
||||
"ID" NUMBER(20,0) NOT NULL,
|
||||
"NAME" NVARCHAR2(100),
|
||||
"TYPE" NVARCHAR2(100),
|
||||
"STATUS" NUMBER(4,0) NOT NULL,
|
||||
"REMARK" NVARCHAR2(500),
|
||||
"CREATOR" NVARCHAR2(64),
|
||||
"CREATE_TIME" DATE NOT NULL,
|
||||
"UPDATER" NVARCHAR2(64),
|
||||
"UPDATE_TIME" DATE NOT NULL,
|
||||
"DELETED" NUMBER(1,0) DEFAULT 0 NOT NULL
|
||||
CREATE TABLE "SYSTEM_DICT_TYPE"(
|
||||
"ID" NUMBER(20,0) NOT NULL,
|
||||
"NAME" NVARCHAR2(100),
|
||||
"TYPE" NVARCHAR2(100),
|
||||
"STATUS" NUMBER(4,0) NOT NULL,
|
||||
"REMARK" NVARCHAR2(500),
|
||||
"CREATOR" NVARCHAR2(64),
|
||||
"CREATE_TIME" DATE NOT NULL,
|
||||
"UPDATER" NVARCHAR2(64),
|
||||
"UPDATE_TIME" DATE NOT NULL,
|
||||
"DELETED_TIME" DATE,
|
||||
"DELETED" NUMBER(1,0) DEFAULT 0 NOT NULL
|
||||
)
|
||||
LOGGING
|
||||
NOCOMPRESS
|
||||
@ -2503,25 +2504,54 @@ PARALLEL 1
|
||||
NOCACHE
|
||||
DISABLE ROW MOVEMENT
|
||||
;
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."ID" IS '字典主键';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."NAME" IS '字典名称';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."TYPE" IS '字典类型';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."STATUS" IS '状态(0正常 1停用)';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."REMARK" IS '备注';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."CREATOR" IS '创建者';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."CREATE_TIME" IS '创建时间';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."UPDATER" IS '更新者';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."UPDATE_TIME" IS '更新时间';
|
||||
COMMENT ON COLUMN "SYSTEM_DICT_TYPE"."DELETED" IS '是否删除';
|
||||
COMMENT ON TABLE "SYSTEM_DICT_TYPE" IS '字典类型表';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."ID" IS '字典主键';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."NAME" IS '字典名称';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."TYPE" IS '字典类型';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."STATUS" IS '状态(0正常 1停用)';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."REMARK" IS '备注';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."CREATOR" IS '创建者';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."CREATE_TIME" IS '创建时间';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."UPDATER" IS '更新者';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."UPDATE_TIME" IS '更新时间';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."DELETED_TIME" IS '删除时间';
|
||||
COMMENT
|
||||
ON COLUMN "SYSTEM_DICT_TYPE"."DELETED" IS '是否删除';
|
||||
COMMENT
|
||||
ON TABLE "SYSTEM_DICT_TYPE" IS '字典类型表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of SYSTEM_DICT_TYPE
|
||||
-- ----------------------------
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('1', '用户性别', 'system_user_sex', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-05-01 12:55:56', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('6', '参数类型', 'infra_config_type', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:36:54', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('7', '通知类型', 'system_notice_type', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:35:26', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('9', '操作类型', 'system_operate_type', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-16 09:32:21', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER",
|
||||
"UPDATE_TIME", "DELETED")
|
||||
VALUES ('1', '用户性别', 'system_user_sex', '0', NULL, 'admin',
|
||||
TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), '1',
|
||||
TO_DATE('2022-05-01 12:55:56', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER",
|
||||
"UPDATE_TIME", "DELETED")
|
||||
VALUES ('6', '参数类型', 'infra_config_type', '0', NULL, 'admin',
|
||||
TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL,
|
||||
TO_DATE('2022-02-01 16:36:54', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER",
|
||||
"UPDATE_TIME", "DELETED")
|
||||
VALUES ('7', '通知类型', 'system_notice_type', '0', NULL, 'admin',
|
||||
TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL,
|
||||
TO_DATE('2022-02-01 16:35:26', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER",
|
||||
"UPDATE_TIME", "DELETED")
|
||||
VALUES ('9', '操作类型', 'system_operate_type', '0', NULL, 'admin',
|
||||
TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), '1',
|
||||
TO_DATE('2022-02-16 09:32:21', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('10', '系统状态', 'common_status', '0', NULL, 'admin', TO_DATE('2021-01-05 17:03:48', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:21:28', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('11', 'Boolean 是否类型', 'infra_boolean_string', '0', 'boolean 转是否', NULL, TO_DATE('2021-01-19 03:20:08', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:37:10', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
INSERT INTO "SYSTEM_DICT_TYPE" ("ID", "NAME", "TYPE", "STATUS", "REMARK", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('104', '登陆结果', 'system_login_result', '0', '登陆结果', NULL, TO_DATE('2021-01-18 06:17:11', 'SYYYY-MM-DD HH24:MI:SS'), NULL, TO_DATE('2022-02-01 16:36:00', 'SYYYY-MM-DD HH24:MI:SS'), '0');
|
||||
|
@ -2357,38 +2357,58 @@ COMMIT;
|
||||
-- Table structure for system_dict_type
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS "system_dict_type";
|
||||
CREATE TABLE "system_dict_type" (
|
||||
"id" int8 NOT NULL,
|
||||
"name" varchar(100) COLLATE "pg_catalog"."default" NOT NULL,
|
||||
"type" varchar(100) COLLATE "pg_catalog"."default" NOT NULL,
|
||||
"status" int2 NOT NULL,
|
||||
"remark" varchar(500) COLLATE "pg_catalog"."default",
|
||||
"creator" varchar(64) COLLATE "pg_catalog"."default",
|
||||
"create_time" timestamp(6) NOT NULL,
|
||||
"updater" varchar(64) COLLATE "pg_catalog"."default",
|
||||
"update_time" timestamp(6) NOT NULL,
|
||||
"deleted" int2 NOT NULL DEFAULT 0
|
||||
CREATE TABLE "system_dict_type"(
|
||||
"id" int8 NOT NULL,
|
||||
"name" varchar(100) COLLATE "pg_catalog"."default" NOT NULL,
|
||||
"type" varchar(100) COLLATE "pg_catalog"."default" NOT NULL,
|
||||
"status" int2 NOT NULL,
|
||||
"remark" varchar(500) COLLATE "pg_catalog"."default",
|
||||
"creator" varchar(64) COLLATE "pg_catalog"."default",
|
||||
"create_time" timestamp(6) NOT NULL,
|
||||
"updater" varchar(64) COLLATE "pg_catalog"."default",
|
||||
"update_time" timestamp(6) NOT NULL,
|
||||
"deleted_time" timestamp(6),
|
||||
"deleted" int2 NOT NULL DEFAULT 0
|
||||
)
|
||||
;
|
||||
COMMENT ON COLUMN "system_dict_type"."id" IS '字典主键';
|
||||
COMMENT ON COLUMN "system_dict_type"."name" IS '字典名称';
|
||||
COMMENT ON COLUMN "system_dict_type"."type" IS '字典类型';
|
||||
COMMENT ON COLUMN "system_dict_type"."status" IS '状态(0正常 1停用)';
|
||||
COMMENT ON COLUMN "system_dict_type"."remark" IS '备注';
|
||||
COMMENT ON COLUMN "system_dict_type"."creator" IS '创建者';
|
||||
COMMENT ON COLUMN "system_dict_type"."create_time" IS '创建时间';
|
||||
COMMENT ON COLUMN "system_dict_type"."updater" IS '更新者';
|
||||
COMMENT ON COLUMN "system_dict_type"."update_time" IS '更新时间';
|
||||
COMMENT ON COLUMN "system_dict_type"."deleted" IS '是否删除';
|
||||
COMMENT ON TABLE "system_dict_type" IS '字典类型表';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."id" IS '字典主键';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."name" IS '字典名称';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."type" IS '字典类型';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."status" IS '状态(0正常 1停用)';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."remark" IS '备注';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."creator" IS '创建者';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."create_time" IS '创建时间';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."updater" IS '更新者';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."update_time" IS '更新时间';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."deleted_time" IS '删除时间';
|
||||
COMMENT
|
||||
ON COLUMN "system_dict_type"."deleted" IS '是否删除';
|
||||
COMMENT
|
||||
ON TABLE "system_dict_type" IS '字典类型表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of system_dict_type
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (1, '用户性别', 'system_user_sex', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:30:31', 0);
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (6, '参数类型', 'infra_config_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:36:54', 0);
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (7, '通知类型', 'system_notice_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:35:26', 0);
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater",
|
||||
"update_time", "deleted")
|
||||
VALUES (1, '用户性别', 'system_user_sex', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:30:31', 0);
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater",
|
||||
"update_time", "deleted")
|
||||
VALUES (6, '参数类型', 'infra_config_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:36:54', 0);
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater",
|
||||
"update_time", "deleted")
|
||||
VALUES (7, '通知类型', 'system_notice_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:35:26', 0);
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (9, '操作类型', 'system_operate_type', 0, NULL, 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 09:32:21', 0);
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (10, '系统状态', 'common_status', 0, NULL, 'admin', '2021-01-05 17:03:48', '', '2022-02-01 16:21:28', 0);
|
||||
INSERT INTO "system_dict_type" ("id", "name", "type", "status", "remark", "creator", "create_time", "updater", "update_time", "deleted") VALUES (11, 'Boolean 是否类型', 'infra_boolean_string', 0, 'boolean 转是否', '', '2021-01-19 03:20:08', '', '2022-02-01 16:37:10', 0);
|
||||
|
@ -5813,18 +5813,51 @@ IF EXISTS (SELECT * FROM sys.all_objects WHERE object_id = OBJECT_ID(N'[dbo].[sy
|
||||
DROP TABLE [dbo].[system_dict_type]
|
||||
GO
|
||||
|
||||
CREATE TABLE [dbo].[system_dict_type] (
|
||||
[id] bigint IDENTITY(1,1) NOT NULL,
|
||||
[name] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||
[type] nvarchar(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||
[status] tinyint NOT NULL,
|
||||
[remark] nvarchar(500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||
[creator] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||
[create_time] datetime2(7) NOT NULL,
|
||||
[updater] nvarchar(64) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||
[update_time] datetime2(7) NOT NULL,
|
||||
[deleted] bit DEFAULT 0 NOT NULL
|
||||
)
|
||||
CREATE TABLE [dbo].[system_dict_type]
|
||||
(
|
||||
[
|
||||
id]
|
||||
bigint
|
||||
IDENTITY
|
||||
(
|
||||
1,
|
||||
1
|
||||
) NOT NULL,
|
||||
[name] nvarchar
|
||||
(
|
||||
100
|
||||
) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||
[type] nvarchar
|
||||
(
|
||||
100
|
||||
) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||
[status] tinyint NOT NULL,
|
||||
[remark] nvarchar
|
||||
(
|
||||
500
|
||||
) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||
[creator] nvarchar
|
||||
(
|
||||
64
|
||||
) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||
[create_time] datetime2
|
||||
(
|
||||
7
|
||||
) NOT NULL,
|
||||
[updater] nvarchar
|
||||
(
|
||||
64
|
||||
) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
|
||||
[update_time] datetime2
|
||||
(
|
||||
7
|
||||
) NOT NULL,
|
||||
[deleted_time] datetime2
|
||||
(
|
||||
7
|
||||
),
|
||||
[deleted] bit DEFAULT 0 NOT NULL
|
||||
)
|
||||
GO
|
||||
|
||||
ALTER TABLE [dbo].[system_dict_type] SET (LOCK_ESCALATION = TABLE)
|
||||
@ -5882,26 +5915,29 @@ GO
|
||||
EXEC sp_addextendedproperty
|
||||
'MS_Description', N'更新者',
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'system_dict_type',
|
||||
'COLUMN', N'updater'
|
||||
GO
|
||||
|
||||
EXEC sp_addextendedproperty
|
||||
'MS_Description', N'更新时间',
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'system_dict_type',
|
||||
'COLUMN', N'update_time'
|
||||
GO
|
||||
|
||||
EXEC sp_addextendedproperty
|
||||
'MS_Description', N'是否删除',
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'system_dict_type',
|
||||
'COLUMN', N'deleted'
|
||||
GO
|
||||
|
||||
EXEC sp_addextendedproperty
|
||||
'MS_Description', N'字典类型表',
|
||||
'TABLE', N'system_dict_type',
|
||||
'COLUMN', N'updater'
|
||||
GO
|
||||
EXEC sp_addextendedproperty
|
||||
'MS_Description', N'更新时间',
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'system_dict_type',
|
||||
'COLUMN', N'update_time'
|
||||
GO
|
||||
EXEC sp_addextendedproperty
|
||||
'MS_Description', N'删除时间',
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'system_dict_type',
|
||||
'COLUMN', N'deleted_time'
|
||||
GO
|
||||
EXEC sp_addextendedproperty
|
||||
'MS_Description', N'是否删除',
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'system_dict_type',
|
||||
'COLUMN', N'deleted'
|
||||
GO
|
||||
EXEC sp_addextendedproperty
|
||||
'MS_Description', N'字典类型表',
|
||||
'SCHEMA', N'dbo',
|
||||
'TABLE', N'system_dict_type'
|
||||
GO
|
||||
|
@ -24,15 +24,15 @@
|
||||
<!-- DB 相关 -->
|
||||
<druid.version>1.2.15</druid.version>
|
||||
<mybatis-plus.version>3.5.2</mybatis-plus.version>
|
||||
<mybatis-plus-generator.version>3.5.2</mybatis-plus-generator.version>
|
||||
<dynamic-datasource.version>3.5.2</dynamic-datasource.version>
|
||||
<mybatis-plus-generator.version>3.5.3</mybatis-plus-generator.version>
|
||||
<dynamic-datasource.version>3.6.0</dynamic-datasource.version>
|
||||
<redisson.version>3.18.0</redisson.version>
|
||||
<!-- 服务保障相关 -->
|
||||
<lock4j.version>2.2.3</lock4j.version>
|
||||
<resilience4j.version>1.7.1</resilience4j.version>
|
||||
<!-- 监控相关 -->
|
||||
<skywalking.version>8.12.0</skywalking.version>
|
||||
<spring-boot-admin.version>2.7.7</spring-boot-admin.version>
|
||||
<spring-boot-admin.version>2.7.9</spring-boot-admin.version>
|
||||
<opentracing.version>0.33.0</opentracing.version>
|
||||
<!-- Test 测试相关 -->
|
||||
<podam.version>7.2.11.RELEASE</podam.version>
|
||||
@ -53,7 +53,7 @@
|
||||
<transmittable-thread-local.version>2.14.2</transmittable-thread-local.version>
|
||||
<commons-net.version>3.8.0</commons-net.version>
|
||||
<jsch.version>0.1.55</jsch.version>
|
||||
<tika-core.version>2.5.0</tika-core.version>
|
||||
<tika-core.version>2.6.0</tika-core.version>
|
||||
<aj-captcha.version>1.3.0</aj-captcha.version>
|
||||
<netty-all.version>4.1.85.Final</netty-all.version>
|
||||
<!-- 三方云服务相关 -->
|
||||
@ -64,7 +64,7 @@
|
||||
<aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
|
||||
<tencentcloud-sdk-java.version>3.1.637</tencentcloud-sdk-java.version>
|
||||
<justauth.version>1.4.0</justauth.version>
|
||||
<jimureport.version>1.5.4</jimureport.version>
|
||||
<jimureport.version>1.5.6</jimureport.version>
|
||||
<xercesImpl.version>2.12.2</xercesImpl.version>
|
||||
</properties>
|
||||
|
||||
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule;
|
||||
import cn.iocoder.yudao.framework.expression.OrExpressionX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
@ -20,7 +21,6 @@ import net.sf.jsqlparser.expression.Alias;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.LongValue;
|
||||
import net.sf.jsqlparser.expression.NullValue;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
|
||||
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
|
||||
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
||||
import net.sf.jsqlparser.expression.operators.relational.InExpression;
|
||||
@ -143,8 +143,8 @@ public class DeptDataPermissionRule implements DataPermissionRule {
|
||||
if (userExpression == null) {
|
||||
return deptExpression;
|
||||
}
|
||||
// 目前,如果有指定部门 + 可查看自己,采用 OR 条件。即,WHERE dept_id IN ? OR user_id = ?
|
||||
return new OrExpression(deptExpression, userExpression);
|
||||
// 目前,如果有指定部门 + 可查看自己,采用 OR 条件。即,WHERE (dept_id IN ? OR user_id = ?)
|
||||
return new OrExpressionX(deptExpression, userExpression);
|
||||
}
|
||||
|
||||
private Expression buildDeptExpression(String tableName, Alias tableAlias, Set<Long> deptIds) {
|
||||
|
@ -52,7 +52,7 @@
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>4.34.71.ALL</version>
|
||||
<version>4.35.0.ALL</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
|
@ -46,7 +46,6 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.13.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
|
@ -30,8 +30,8 @@
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.framework.expression;
|
||||
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
||||
|
||||
/**
|
||||
* AndExpression 的扩展类(会在原有表达式两端加上括号)
|
||||
*/
|
||||
public class AndExpressionX extends AndExpression {
|
||||
|
||||
public AndExpressionX() {
|
||||
}
|
||||
|
||||
public AndExpressionX(Expression leftExpression, Expression rightExpression) {
|
||||
this.setLeftExpression(leftExpression);
|
||||
this.setRightExpression(rightExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + super.toString() + ")";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.yudao.framework.expression;
|
||||
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
|
||||
|
||||
/**
|
||||
* OrExpression 的扩展类(会在原有表达式两端加上括号)
|
||||
*/
|
||||
public class OrExpressionX extends OrExpression {
|
||||
|
||||
public OrExpressionX() {
|
||||
}
|
||||
|
||||
public OrExpressionX(Expression leftExpression, Expression rightExpression) {
|
||||
this.setLeftExpression(leftExpression);
|
||||
this.setRightExpression(rightExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + super.toString() + ")";
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ import lombok.*;
|
||||
#foreach ($column in $columns)
|
||||
#if (${column.javaType} == "LocalDateTime")
|
||||
import java.time.LocalDateTime;
|
||||
#break
|
||||
#end
|
||||
#end
|
||||
import io.swagger.annotations.*;
|
||||
|
@ -34,9 +34,9 @@ const crudSchemas = reactive<VxeCrudSchema>({
|
||||
#if ("" != $dictType)## 有数据字典
|
||||
dictType: DICT_TYPE.$dictType.toUpperCase(),
|
||||
#if (${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer")
|
||||
dictData: 'number',
|
||||
dictClass: 'number',
|
||||
#else
|
||||
dictData: 'string',
|
||||
dictClass: 'string',
|
||||
#end
|
||||
#end
|
||||
#if (!$column.createOperation && !$column.updateOperation)
|
||||
@ -78,10 +78,7 @@ const crudSchemas = reactive<VxeCrudSchema>({
|
||||
},
|
||||
#elseif($column.htmlType == "imageUpload")## 图片上传
|
||||
form: {
|
||||
component: 'UploadImg',
|
||||
componentProps: {
|
||||
limit: 1
|
||||
}
|
||||
component: 'UploadImg' // 单图上传,多图为UploadImgs
|
||||
},
|
||||
#elseif($column.htmlType == "fileUpload")## 图片上传
|
||||
form: {
|
||||
|
@ -103,7 +103,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
if (order != null) {
|
||||
log.warn("[createPayOrder][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]", order.getAppId(),
|
||||
order.getMerchantOrderId(), JsonUtils.toJsonString(order)); // 理论来说,不会出现这个情况
|
||||
return app.getId();
|
||||
return order.getId();
|
||||
}
|
||||
|
||||
// 创建支付交易单
|
||||
|
@ -130,7 +130,7 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
} else {
|
||||
// 成功,插入退款单 状态为生成.没有和渠道交互
|
||||
// TODO @jason:搞到 convert 里。一些额外的自动,手动 set 下;
|
||||
payRefundDO = PayRefundDO.builder().channelOrderNo(order.getChannelOrderNo())
|
||||
payRefundDO = PayRefundDO.builder()
|
||||
.appId(order.getAppId())
|
||||
.channelOrderNo(order.getChannelOrderNo())
|
||||
.channelCode(order.getChannelCode())
|
||||
|
@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 字典类型表
|
||||
*
|
||||
@ -47,4 +49,9 @@ public class DictTypeDO extends BaseDO {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 删除时间
|
||||
*/
|
||||
private LocalDateTime deletedTime;
|
||||
|
||||
}
|
||||
|
@ -7,8 +7,12 @@ import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExpo
|
||||
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
@ -39,4 +43,10 @@ public interface DictTypeMapper extends BaseMapperX<DictTypeDO> {
|
||||
return selectOne(DictTypeDO::getName, name);
|
||||
}
|
||||
|
||||
@Update("UPDATE system_dict_type SET DELETED = 1,DELETED_TIME=#{deletedTime} WHERE id = #{id}")
|
||||
int deleteById(@Param("id") Long id, @Param("deletedTime") LocalDateTime deletedTime);
|
||||
|
||||
default int deleteById(Long id) {
|
||||
return deleteById(id, LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
@ -12,3 +12,6 @@ VITE_APP_TENANT_ENABLE=true
|
||||
|
||||
# 验证码的开关
|
||||
VITE_APP_CAPTCHA_ENABLE=true
|
||||
|
||||
# 路由在只有一个子集的时候是否显示父级
|
||||
VITE_ROUTE_ALWAYSSHOW_ENABLE=true
|
||||
|
@ -1,21 +1,20 @@
|
||||
<h1>🌈 yudao-ui-admin-vue3</h1>
|
||||
# 🌈 yudao-ui-admin-vue3 #
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/-Vue3.2-34495e?logo=vue.j" />
|
||||
<img src="https://img.shields.io/badge/-Vite3-646cff?logo=vite&logoColor=white" />
|
||||
<img src="https://img.shields.io/badge/-TypeScript4.9-blue?logo=typescript&logoColor=white" />
|
||||
<img src="https://img.shields.io/badge/-Pinia2-yellow?logo=picpay&logoColor=white" />
|
||||
<img src="https://img.shields.io/badge/-ESLint-4b32c3?logo=eslint&logoColor=white" />
|
||||
<img src="https://img.shields.io/badge/-pnpm7-F69220?logo=pnpm&logoColor=white" />
|
||||
<img src="https://img.shields.io/badge/-Axios-008fc7?logo=axios.js&logoColor=white" />
|
||||
<p style="text-align: center">
|
||||
<img src="https://img.shields.io/badge/-Vue3.2-34495e?logo=vue.j" alt="vue" />
|
||||
<img src="https://img.shields.io/badge/-Vite4-646cff?logo=vite&logoColor=white" alt="vite" />
|
||||
<img src="https://img.shields.io/badge/-TypeScript4.9-blue?logo=typescript&logoColor=white" alt="typescript" />
|
||||
<img src="https://img.shields.io/badge/-Pinia2-yellow?logo=picpay&logoColor=white" alt="Pinia2" />
|
||||
<img src="https://img.shields.io/badge/-ESLint-4b32c3?logo=eslint&logoColor=white" alt="eslint" />
|
||||
<img src="https://img.shields.io/badge/-pnpm7-F69220?logo=pnpm&logoColor=white" alt="pnpm" />
|
||||
<img src="https://img.shields.io/badge/-Prettier-ef9421?logo=Prettier&logoColor=white" alt="Prettier">
|
||||
<img src="https://img.shields.io/badge/-Sass-1D365D?logo=Sass&logoColor=white" alt="Sass">
|
||||
<img src="https://img.shields.io/badge/-Wind%20CSS-06B6D4?logo=Tailwind%20CSS&logoColor=white" alt="Taiwind">
|
||||
<img src="https://img.shields.io/badge/-Wind%20CSS-06B6D4?logo=Tailwind%20CSS&logoColor=white" alt="WindCSS">
|
||||
</p>
|
||||
|
||||
## 介绍
|
||||
|
||||
- 基于 vue3.2+ ,TypeScript ,Element Plus 2.2.0+ ,Vite3 ,Pinia ,Vxe-table , Windicss 等开发的后台管理系统
|
||||
- 基于 vue3.2+ ,TypeScript ,Element Plus 2.2.0+ ,Vite4 ,Pinia ,Vxe-table , Windicss 等开发的后台管理系统
|
||||
|
||||
## 注意事项
|
||||
|
||||
@ -30,12 +29,12 @@
|
||||
| 框架 | 说明 | 版本 |
|
||||
| --- | --- | --- |
|
||||
| [Vue](https://staging-cn.vuejs.org/) | vue 框架 | 3.2.45 |
|
||||
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 3.2.3 |
|
||||
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.23 |
|
||||
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.0.2 |
|
||||
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.2.27 |
|
||||
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 4.9.4 |
|
||||
| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.26 |
|
||||
| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.0.28 |
|
||||
| [vueuse](https://vueuse.org/) | 常用工具集 | 9.6.0 |
|
||||
| [vxe-table](https://vxetable.cn/) | vue 最强表单 | 4.3.6 |
|
||||
| [vxe-table](https://vxetable.cn/) | vue 最强表单 | 4.3.7 |
|
||||
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.2.2 |
|
||||
| [vue-router](https://router.vuejs.org/) | vue 路由 | 4.1.6 |
|
||||
| [windicss](https://cn.windicss.org/) | 下一代工具优先的 CSS 框架 | 3.5.6 |
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { resolve } from 'path'
|
||||
import Vue from '@vitejs/plugin-vue'
|
||||
import VueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import VueI18n from '@intlify/vite-plugin-vue-i18n'
|
||||
import WindiCSS from 'vite-plugin-windicss'
|
||||
import progress from 'vite-plugin-progress'
|
||||
import EslintPlugin from 'vite-plugin-eslint'
|
||||
@ -9,6 +8,7 @@ import PurgeIcons from 'vite-plugin-purge-icons'
|
||||
import { ViteEjsPlugin } from 'vite-plugin-ejs'
|
||||
import viteCompression from 'vite-plugin-compression'
|
||||
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
|
||||
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
|
||||
import {
|
||||
createStyleImportPlugin,
|
||||
@ -51,7 +51,7 @@ export function createVitePlugins(VITE_APP_TITLE: string) {
|
||||
cache: false,
|
||||
include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件
|
||||
}),
|
||||
VueI18n({
|
||||
VueI18nPlugin({
|
||||
runtimeOnly: true,
|
||||
compositionOnly: true,
|
||||
include: [resolve(__dirname, 'src/locales/**')]
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "yudao-ui-admin-vue3",
|
||||
"version": "1.6.5.1874",
|
||||
"description": "基于vue3、vite3、element-plus、typesScript",
|
||||
"version": "1.6.5.1878",
|
||||
"description": "基于vue3、vite4、element-plus、typesScript",
|
||||
"author": "xingyu",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
@ -25,67 +25,67 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/iconify": "^3.0.1",
|
||||
"@vueuse/core": "^9.6.0",
|
||||
"@vueuse/core": "^9.8.2",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||
"@zxcvbn-ts/core": "^2.1.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.2.1",
|
||||
"cropperjs": "^1.5.13",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dayjs": "^1.11.7",
|
||||
"echarts": "^5.4.0",
|
||||
"echarts": "^5.4.1",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "2.2.26",
|
||||
"element-plus": "2.2.27",
|
||||
"intro.js": "^6.0.0",
|
||||
"jsencrypt": "^3.3.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.27",
|
||||
"pinia": "^2.0.28",
|
||||
"qrcode": "^1.5.1",
|
||||
"qs": "^6.11.0",
|
||||
"url": "^0.11.0",
|
||||
"vue": "3.2.45",
|
||||
"vue-cropper": "^1.0.3",
|
||||
"vue-i18n": "9.2.2",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue-types": "^5.0.1",
|
||||
"vxe-table": "^4.3.6",
|
||||
"vxe-table": "^4.3.7",
|
||||
"web-storage-cache": "^1.1.1",
|
||||
"xe-utils": "^3.5.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.3.0",
|
||||
"@commitlint/config-conventional": "^17.3.0",
|
||||
"@iconify/json": "^2.1.149",
|
||||
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
|
||||
"@iconify/json": "^2.1.155",
|
||||
"@intlify/unplugin-vue-i18n": "^0.8.1",
|
||||
"@purge-icons/generated": "^0.9.0",
|
||||
"@types/intro.js": "^5.1.0",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/node": "^18.11.11",
|
||||
"@types/node": "^18.11.17",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/qrcode": "^1.5.0",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@typescript-eslint/eslint-plugin": "^5.46.0",
|
||||
"@typescript-eslint/parser": "^5.46.0",
|
||||
"@vitejs/plugin-legacy": "^2.3.1",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vitejs/plugin-vue-jsx": "^2.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.47.0",
|
||||
"@typescript-eslint/parser": "^5.47.0",
|
||||
"@vitejs/plugin-legacy": "^3.0.1",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"consola": "^2.15.3",
|
||||
"eslint": "^8.29.0",
|
||||
"eslint": "^8.30.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-define-config": "^1.12.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.8.0",
|
||||
"lint-staged": "^13.1.0",
|
||||
"postcss": "^8.4.19",
|
||||
"postcss": "^8.4.20",
|
||||
"postcss-html": "^1.5.0",
|
||||
"postcss-scss": "^4.0.6",
|
||||
"prettier": "^2.8.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^3.7.0",
|
||||
"sass": "^1.56.1",
|
||||
"rollup": "^3.7.5",
|
||||
"sass": "^1.57.1",
|
||||
"stylelint": "^14.16.0",
|
||||
"stylelint-config-html": "^1.1.0",
|
||||
"stylelint-config-prettier": "^9.0.4",
|
||||
@ -94,17 +94,17 @@
|
||||
"stylelint-order": "^5.0.0",
|
||||
"terser": "^5.16.1",
|
||||
"typescript": "4.9.4",
|
||||
"vite": "3.2.5",
|
||||
"vite": "4.0.2",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-ejs": "^1.6.4",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-progress": "^0.0.6",
|
||||
"vite-plugin-purge-icons": "^0.9.1",
|
||||
"vite-plugin-purge-icons": "^0.9.2",
|
||||
"vite-plugin-style-import": "2.0.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vite-plugin-windicss": "^1.8.8",
|
||||
"vue-tsc": "^1.0.11",
|
||||
"vite-plugin-windicss": "^1.8.10",
|
||||
"vue-tsc": "^1.0.16",
|
||||
"windicss": "^3.5.6"
|
||||
},
|
||||
"engines": {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -73,5 +73,5 @@ export const updateUserPwdApi = (oldPassword: string, newPassword: string) => {
|
||||
|
||||
// 用户头像上传
|
||||
export const uploadAvatarApi = (data) => {
|
||||
return request.put({ url: '/system/user/profile/update-avatar', data })
|
||||
return request.upload({ url: '/system/user/profile/update-avatar', data: data })
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { ElCard } from 'element-plus'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { ref, onMounted, defineEmits } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { Sticky } from '@/components/Sticky'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
|
4
yudao-ui-admin-vue3/src/components/Cropper/index.ts
Normal file
4
yudao-ui-admin-vue3/src/components/Cropper/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import CropperImage from './src/Cropper.vue'
|
||||
import CropperAvatar from './src/CropperAvatar.vue'
|
||||
|
||||
export { CropperImage, CropperAvatar }
|
257
yudao-ui-admin-vue3/src/components/Cropper/src/CopperModal.vue
Normal file
257
yudao-ui-admin-vue3/src/components/Cropper/src/CopperModal.vue
Normal file
@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<div>
|
||||
<Dialog
|
||||
v-model="dialogVisible"
|
||||
:title="t('cropper.modalTitle')"
|
||||
width="800px"
|
||||
maxHeight="380px"
|
||||
:canFullscreen="false"
|
||||
>
|
||||
<div :class="prefixCls">
|
||||
<div :class="`${prefixCls}-left`">
|
||||
<div :class="`${prefixCls}-cropper`">
|
||||
<CropperImage
|
||||
v-if="src"
|
||||
:src="src"
|
||||
height="300px"
|
||||
:circled="circled"
|
||||
@cropend="handleCropend"
|
||||
@ready="handleReady"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div :class="`${prefixCls}-toolbar`">
|
||||
<el-upload :fileList="[]" accept="image/*" :beforeUpload="handleBeforeUpload">
|
||||
<el-tooltip :content="t('cropper.selectImage')" placement="bottom">
|
||||
<XButton preIcon="ant-design:upload-outlined" type="primary" />
|
||||
</el-tooltip>
|
||||
</el-upload>
|
||||
<el-space>
|
||||
<el-tooltip :content="t('cropper.btn_reset')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="ant-design:reload-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
@click="handlerToolbar('reset')"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_rotate_left')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="ant-design:rotate-left-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
@click="handlerToolbar('rotate', -45)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_rotate_right')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="ant-design:rotate-right-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
@click="handlerToolbar('rotate', 45)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_scale_x')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="vaadin:arrows-long-h"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
@click="handlerToolbar('scaleX')"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_scale_y')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="vaadin:arrows-long-v"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
@click="handlerToolbar('scaleY')"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_zoom_in')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="ant-design:zoom-in-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
@click="handlerToolbar('zoom', 0.1)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="t('cropper.btn_zoom_out')" placement="bottom">
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="ant-design:zoom-out-outlined"
|
||||
size="small"
|
||||
:disabled="!src"
|
||||
@click="handlerToolbar('zoom', -0.1)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</el-space>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`${prefixCls}-right`">
|
||||
<div :class="`${prefixCls}-preview`">
|
||||
<img :src="previewSource" v-if="previewSource" :alt="t('cropper.preview')" />
|
||||
</div>
|
||||
<template v-if="previewSource">
|
||||
<div :class="`${prefixCls}-group`">
|
||||
<el-avatar :src="previewSource" size="large" />
|
||||
<el-avatar :src="previewSource" :size="48" />
|
||||
<el-avatar :src="previewSource" :size="64" />
|
||||
<el-avatar :src="previewSource" :size="80" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="handleOk">{{ t('cropper.okText') }}</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { dataURLtoBlob } from '@/utils/filt'
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElUpload, ElAvatar, ElTooltip, ElSpace } from 'element-plus'
|
||||
import { Dialog } from '@/components/Dialog'
|
||||
import { CropperImage } from '@/components/Cropper'
|
||||
import type { CropendResult, Cropper } from './types'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
const props = defineProps({
|
||||
srcValue: propTypes.string.def(''),
|
||||
circled: propTypes.bool.def(true)
|
||||
})
|
||||
const emit = defineEmits(['uploadSuccess'])
|
||||
const { t } = useI18n()
|
||||
const { getPrefixCls } = useDesign()
|
||||
const prefixCls = getPrefixCls('cropper-am')
|
||||
|
||||
const src = ref(props.srcValue)
|
||||
const previewSource = ref('')
|
||||
const cropper = ref<Cropper>()
|
||||
const dialogVisible = ref(false)
|
||||
let filename = ''
|
||||
let scaleX = 1
|
||||
let scaleY = 1
|
||||
|
||||
// Block upload
|
||||
function handleBeforeUpload(file: File) {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
src.value = ''
|
||||
previewSource.value = ''
|
||||
reader.onload = function (e) {
|
||||
src.value = (e.target?.result as string) ?? ''
|
||||
filename = file.name
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function handleCropend({ imgBase64 }: CropendResult) {
|
||||
previewSource.value = imgBase64
|
||||
}
|
||||
|
||||
function handleReady(cropperInstance: Cropper) {
|
||||
cropper.value = cropperInstance
|
||||
}
|
||||
|
||||
function handlerToolbar(event: string, arg?: number) {
|
||||
if (event === 'scaleX') {
|
||||
scaleX = arg = scaleX === -1 ? 1 : -1
|
||||
}
|
||||
if (event === 'scaleY') {
|
||||
scaleY = arg = scaleY === -1 ? 1 : -1
|
||||
}
|
||||
cropper?.value?.[event]?.(arg)
|
||||
}
|
||||
|
||||
async function handleOk() {
|
||||
const blob = dataURLtoBlob(previewSource.value)
|
||||
emit('uploadSuccess', { source: previewSource.value, data: blob, filename: filename })
|
||||
}
|
||||
function openModal() {
|
||||
dialogVisible.value = true
|
||||
}
|
||||
function closeModal() {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
defineExpose({ openModal, closeModal })
|
||||
</script>
|
||||
<style lang="scss">
|
||||
$prefix-cls: #{$namespace}-cropper-am;
|
||||
|
||||
.#{$prefix-cls} {
|
||||
display: flex;
|
||||
|
||||
&-left,
|
||||
&-right {
|
||||
height: 340px;
|
||||
}
|
||||
|
||||
&-left {
|
||||
width: 55%;
|
||||
}
|
||||
|
||||
&-right {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
&-cropper {
|
||||
height: 300px;
|
||||
background: #eee;
|
||||
background-image: linear-gradient(
|
||||
45deg,
|
||||
rgb(0 0 0 / 25%) 25%,
|
||||
transparent 0,
|
||||
transparent 75%,
|
||||
rgb(0 0 0 / 25%) 0
|
||||
),
|
||||
linear-gradient(
|
||||
45deg,
|
||||
rgb(0 0 0 / 25%) 25%,
|
||||
transparent 0,
|
||||
transparent 75%,
|
||||
rgb(0 0 0 / 25%) 0
|
||||
);
|
||||
background-position: 0 0, 12px 12px;
|
||||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
&-toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
&-preview {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
border: 1px solid;
|
||||
border-radius: 50%;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&-group {
|
||||
display: flex;
|
||||
padding-top: 8px;
|
||||
margin-top: 8px;
|
||||
border-top: 1px solid;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
190
yudao-ui-admin-vue3/src/components/Cropper/src/Cropper.vue
Normal file
190
yudao-ui-admin-vue3/src/components/Cropper/src/Cropper.vue
Normal file
@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<div :class="getClass" :style="getWrapperStyle">
|
||||
<img
|
||||
v-show="isReady"
|
||||
ref="imgElRef"
|
||||
:src="src"
|
||||
:alt="alt"
|
||||
:crossorigin="crossorigin"
|
||||
:style="getImageStyle"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
computed,
|
||||
CSSProperties,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
PropType,
|
||||
ref,
|
||||
unref,
|
||||
useAttrs
|
||||
} from 'vue'
|
||||
import Cropper from 'cropperjs'
|
||||
import 'cropperjs/dist/cropper.css'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
type Options = Cropper.Options
|
||||
|
||||
const defaultOptions: Options = {
|
||||
aspectRatio: 1,
|
||||
zoomable: true,
|
||||
zoomOnTouch: true,
|
||||
zoomOnWheel: true,
|
||||
cropBoxMovable: true,
|
||||
cropBoxResizable: true,
|
||||
toggleDragModeOnDblclick: true,
|
||||
autoCrop: true,
|
||||
background: true,
|
||||
highlight: true,
|
||||
center: true,
|
||||
responsive: true,
|
||||
restore: true,
|
||||
checkCrossOrigin: true,
|
||||
checkOrientation: true,
|
||||
scalable: true,
|
||||
modal: true,
|
||||
guides: true,
|
||||
movable: true,
|
||||
rotatable: true
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
src: propTypes.string.def(''),
|
||||
alt: propTypes.string.def(''),
|
||||
circled: propTypes.bool.def(false),
|
||||
realTimePreview: propTypes.bool.def(true),
|
||||
height: propTypes.string.def('360px'),
|
||||
crossorigin: {
|
||||
type: String as PropType<'' | 'anonymous' | 'use-credentials' | undefined>,
|
||||
default: undefined
|
||||
},
|
||||
imageStyle: { type: Object as PropType<CSSProperties>, default: () => ({}) },
|
||||
options: { type: Object as PropType<Options>, default: () => ({}) }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['cropend', 'ready', 'cropendError'])
|
||||
const attrs = useAttrs()
|
||||
const imgElRef = ref<ElRef<HTMLImageElement>>()
|
||||
const cropper = ref<Nullable<Cropper>>()
|
||||
const isReady = ref(false)
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
const prefixCls = getPrefixCls('cropper-image')
|
||||
const debounceRealTimeCroppered = useDebounceFn(realTimeCroppered, 80)
|
||||
|
||||
const getImageStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
height: props.height,
|
||||
maxWidth: '100%',
|
||||
...props.imageStyle
|
||||
}
|
||||
})
|
||||
|
||||
const getClass = computed(() => {
|
||||
return [
|
||||
prefixCls,
|
||||
attrs.class,
|
||||
{
|
||||
[`${prefixCls}--circled`]: props.circled
|
||||
}
|
||||
]
|
||||
})
|
||||
const getWrapperStyle = computed((): CSSProperties => {
|
||||
return { height: `${props.height}`.replace(/px/, '') + 'px' }
|
||||
})
|
||||
|
||||
onMounted(init)
|
||||
|
||||
onUnmounted(() => {
|
||||
cropper.value?.destroy()
|
||||
})
|
||||
|
||||
async function init() {
|
||||
const imgEl = unref(imgElRef)
|
||||
if (!imgEl) {
|
||||
return
|
||||
}
|
||||
cropper.value = new Cropper(imgEl, {
|
||||
...defaultOptions,
|
||||
ready: () => {
|
||||
isReady.value = true
|
||||
realTimeCroppered()
|
||||
emit('ready', cropper.value)
|
||||
},
|
||||
crop() {
|
||||
debounceRealTimeCroppered()
|
||||
},
|
||||
zoom() {
|
||||
debounceRealTimeCroppered()
|
||||
},
|
||||
cropmove() {
|
||||
debounceRealTimeCroppered()
|
||||
},
|
||||
...props.options
|
||||
})
|
||||
}
|
||||
|
||||
// Real-time display preview
|
||||
function realTimeCroppered() {
|
||||
props.realTimePreview && croppered()
|
||||
}
|
||||
|
||||
// event: return base64 and width and height information after cropping
|
||||
function croppered() {
|
||||
if (!cropper.value) {
|
||||
return
|
||||
}
|
||||
let imgInfo = cropper.value.getData()
|
||||
const canvas = props.circled ? getRoundedCanvas() : cropper.value.getCroppedCanvas()
|
||||
canvas.toBlob((blob) => {
|
||||
if (!blob) {
|
||||
return
|
||||
}
|
||||
let fileReader: FileReader = new FileReader()
|
||||
fileReader.readAsDataURL(blob)
|
||||
fileReader.onloadend = (e) => {
|
||||
emit('cropend', {
|
||||
imgBase64: e.target?.result ?? '',
|
||||
imgInfo
|
||||
})
|
||||
}
|
||||
fileReader.onerror = () => {
|
||||
emit('cropendError')
|
||||
}
|
||||
}, 'image/png')
|
||||
}
|
||||
|
||||
// Get a circular picture canvas
|
||||
function getRoundedCanvas() {
|
||||
const sourceCanvas = cropper.value!.getCroppedCanvas()
|
||||
const canvas = document.createElement('canvas')
|
||||
const context = canvas.getContext('2d')!
|
||||
const width = sourceCanvas.width
|
||||
const height = sourceCanvas.height
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
context.imageSmoothingEnabled = true
|
||||
context.drawImage(sourceCanvas, 0, 0, width, height)
|
||||
context.globalCompositeOperation = 'destination-in'
|
||||
context.beginPath()
|
||||
context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true)
|
||||
context.fill()
|
||||
return canvas
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
$prefix-cls: #{$namespace}-cropper-image;
|
||||
|
||||
.#{$prefix-cls} {
|
||||
&--circled {
|
||||
.cropper-view-box,
|
||||
.cropper-face {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
136
yudao-ui-admin-vue3/src/components/Cropper/src/CropperAvatar.vue
Normal file
136
yudao-ui-admin-vue3/src/components/Cropper/src/CropperAvatar.vue
Normal file
@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div class="user-info-head" @click="open()">
|
||||
<img :src="sourceValue" v-if="sourceValue" class="img-circle img-lg" alt="avatar" />
|
||||
<el-button :class="`${prefixCls}-upload-btn`" @click="open()" v-if="showBtn">
|
||||
{{ btnText ? btnText : t('cropper.selectImage') }}
|
||||
</el-button>
|
||||
<CopperModal
|
||||
ref="cropperModelRef"
|
||||
@upload-success="handleUploadSuccess"
|
||||
:srcValue="sourceValue"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { ref, watch, watchEffect } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import CopperModal from './CopperModal.vue'
|
||||
|
||||
const props = defineProps({
|
||||
width: propTypes.string.def('200px'),
|
||||
value: propTypes.string.def(''),
|
||||
showBtn: propTypes.bool.def(true),
|
||||
btnText: propTypes.string.def('')
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:value', 'change'])
|
||||
const sourceValue = ref(props.value)
|
||||
const { getPrefixCls } = useDesign()
|
||||
const prefixCls = getPrefixCls('cropper-avatar')
|
||||
const message = useMessage()
|
||||
const { t } = useI18n()
|
||||
|
||||
const cropperModelRef = ref()
|
||||
|
||||
watchEffect(() => {
|
||||
sourceValue.value = props.value
|
||||
})
|
||||
|
||||
watch(
|
||||
() => sourceValue.value,
|
||||
(v: string) => {
|
||||
emit('update:value', v)
|
||||
}
|
||||
)
|
||||
|
||||
function handleUploadSuccess({ source, data, filename }) {
|
||||
sourceValue.value = source
|
||||
emit('change', { source, data, filename })
|
||||
message.success(t('cropper.uploadSuccess'))
|
||||
}
|
||||
|
||||
function open() {
|
||||
cropperModelRef.value.openModal()
|
||||
}
|
||||
function close() {
|
||||
cropperModelRef.value.closeModal()
|
||||
}
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
$prefix-cls: #{$namespace}--cropper-avatar;
|
||||
|
||||
.#{$prefix-cls} {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
|
||||
&-image-wrapper {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 1px solid;
|
||||
border-radius: 50%;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&-image-mask {
|
||||
opacity: 0%;
|
||||
position: absolute;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
border-radius: inherit;
|
||||
border: inherit;
|
||||
background: rgb(0 0 0 / 40%);
|
||||
cursor: pointer;
|
||||
transition: opacity 0.4s;
|
||||
|
||||
::v-deep(svg) {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&-image-mask:hover {
|
||||
opacity: 4000%;
|
||||
}
|
||||
|
||||
&-upload-btn {
|
||||
margin: 10px auto;
|
||||
}
|
||||
}
|
||||
.user-info-head {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.img-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
.user-info-head:hover:after {
|
||||
content: '+';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
color: #eee;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
font-size: 24px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
cursor: pointer;
|
||||
line-height: 110px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
8
yudao-ui-admin-vue3/src/components/Cropper/src/types.ts
Normal file
8
yudao-ui-admin-vue3/src/components/Cropper/src/types.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import type Cropper from 'cropperjs'
|
||||
|
||||
export interface CropendResult {
|
||||
imgBase64: string
|
||||
imgInfo: Cropper.Data
|
||||
}
|
||||
|
||||
export type { Cropper }
|
@ -23,6 +23,7 @@ const props = defineProps({
|
||||
type: Object as PropType<IEditorConfig>,
|
||||
default: () => undefined
|
||||
},
|
||||
readonly: propTypes.bool.def(false),
|
||||
modelValue: propTypes.string.def('')
|
||||
})
|
||||
|
||||
@ -61,7 +62,7 @@ const editorConfig = computed((): IEditorConfig => {
|
||||
return Object.assign(
|
||||
{
|
||||
placeholder: '请输入内容...',
|
||||
readOnly: false,
|
||||
readOnly: props.readonly,
|
||||
customAlert: (s: string, t: string) => {
|
||||
switch (t) {
|
||||
case 'success':
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
} from 'element-plus'
|
||||
import { InputPassword } from '@/components/InputPassword'
|
||||
import { Editor } from '@/components/Editor'
|
||||
import { UploadImg, UploadFile } from '@/components/UploadFile'
|
||||
import { UploadImg, UploadImgs, UploadFile } from '@/components/UploadFile'
|
||||
import { ComponentName } from '@/types/components'
|
||||
|
||||
const componentMap: Recordable<Component, ComponentName> = {
|
||||
@ -48,6 +48,7 @@ const componentMap: Recordable<Component, ComponentName> = {
|
||||
InputPassword: InputPassword,
|
||||
Editor: Editor,
|
||||
UploadImg: UploadImg,
|
||||
UploadImgs: UploadImgs,
|
||||
UploadFile: UploadFile
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,9 @@ const props = defineProps({
|
||||
// icon color
|
||||
color: propTypes.string,
|
||||
// icon size
|
||||
size: propTypes.number.def(16)
|
||||
size: propTypes.number.def(16),
|
||||
// icon svg class
|
||||
svgClass: propTypes.string.def('')
|
||||
})
|
||||
|
||||
const elRef = ref<ElRef>(null)
|
||||
@ -34,6 +36,11 @@ const getIconifyStyle = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const getSvgClass = computed(() => {
|
||||
const { svgClass } = props
|
||||
return `iconify ${svgClass}`
|
||||
})
|
||||
|
||||
const updateIcon = async (icon: string) => {
|
||||
if (unref(isLocal)) return
|
||||
|
||||
@ -66,13 +73,13 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElIcon :class="prefixCls" :size="size" :color="color">
|
||||
<svg v-if="isLocal" aria-hidden="true">
|
||||
<ElIcon :class="prefixCls" :color="color" :size="size">
|
||||
<svg v-if="isLocal" aria-hidden="true" :class="getSvgClass">
|
||||
<use :xlink:href="symbolId" />
|
||||
</svg>
|
||||
|
||||
<span v-else ref="elRef" :class="$attrs.class" :style="getIconifyStyle">
|
||||
<span class="iconify" :data-icon="symbolId"></span>
|
||||
<span :class="getSvgClass" :data-icon="symbolId"></span>
|
||||
</span>
|
||||
</ElIcon>
|
||||
</template>
|
||||
|
@ -64,7 +64,7 @@ const initQrcode = async () => {
|
||||
options.errorCorrectionLevel || getErrorCorrectionLevel(unref(renderText))
|
||||
const _width: number = await getOriginWidth(unref(renderText), options)
|
||||
options.scale = props.width === 0 ? undefined : (props.width / _width) * 4
|
||||
const canvasRef: HTMLCanvasElement = await toCanvas(
|
||||
const canvasRef: HTMLCanvasElement | any = await toCanvas(
|
||||
unref(wrapRef) as HTMLCanvasElement,
|
||||
unref(renderText),
|
||||
options
|
||||
|
@ -1,4 +1,5 @@
|
||||
import UploadImg from './src/UploadImg.vue'
|
||||
import UploadImgs from './src/UploadImgs.vue'
|
||||
import UploadFile from './src/UploadFile.vue'
|
||||
|
||||
export { UploadImg, UploadFile }
|
||||
export { UploadImg, UploadImgs, UploadFile }
|
||||
|
@ -32,8 +32,8 @@
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
<script setup lang="ts" name="UploadFile">
|
||||
import { PropType, ref } from 'vue'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
@ -43,7 +43,10 @@ const message = useMessage() // 消息弹窗
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: propTypes.oneOfType([String, Object, Array]),
|
||||
modelValue: {
|
||||
type: Array as PropType<UploadUserFile[]>,
|
||||
required: true
|
||||
},
|
||||
title: propTypes.string.def('文件上传'),
|
||||
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
|
||||
fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), // 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
@ -57,40 +60,12 @@ const props = defineProps({
|
||||
const valueRef = ref(props.modelValue)
|
||||
const uploadRef = ref<UploadInstance>()
|
||||
const uploadList = ref<UploadUserFile[]>([])
|
||||
const fileList = ref<UploadUserFile[]>([])
|
||||
const fileList = ref<UploadUserFile[]>(props.modelValue)
|
||||
const uploadNumber = ref<number>(0)
|
||||
const uploadHeaders = ref({
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
})
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (val) {
|
||||
// 首先将值转为数组, 当只穿了一个图片时,会报map方法错误
|
||||
const list = Array.isArray(props.modelValue)
|
||||
? props.modelValue
|
||||
: Array.isArray(props.modelValue?.split(','))
|
||||
? props.modelValue?.split(',')
|
||||
: Array.of(props.modelValue)
|
||||
// 然后将数组转为对象数组
|
||||
fileList.value = list.map((item) => {
|
||||
if (typeof item === 'string') {
|
||||
// edit by 芋道源码
|
||||
item = { name: item, url: item }
|
||||
}
|
||||
return item
|
||||
})
|
||||
} else {
|
||||
fileList.value = []
|
||||
return []
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
// 文件上传之前判断
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {
|
||||
if (fileList.value.length >= props.limit) {
|
||||
|
@ -1,176 +1,267 @@
|
||||
<template>
|
||||
<div class="component-upload-image">
|
||||
<div class="upload-box">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:multiple="props.limit > 1"
|
||||
name="file"
|
||||
v-model="valueRef"
|
||||
list-type="picture-card"
|
||||
v-model:file-list="fileList"
|
||||
:show-file-list="true"
|
||||
:action="updateUrl"
|
||||
:id="uuid"
|
||||
:class="['upload', drag ? 'no-border' : '']"
|
||||
:multiple="false"
|
||||
:show-file-list="false"
|
||||
:headers="uploadHeaders"
|
||||
:limit="props.limit"
|
||||
:before-upload="beforeUpload"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="handleFileSuccess"
|
||||
:on-error="excelUploadError"
|
||||
:on-remove="handleRemove"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:class="{ hide: fileList.length >= props.limit }"
|
||||
:on-success="uploadSuccess"
|
||||
:on-error="uploadError"
|
||||
:drag="drag"
|
||||
:accept="fileType.join(',')"
|
||||
>
|
||||
<Icon icon="ep:upload-filled" />
|
||||
<template v-if="modelValue">
|
||||
<img :src="modelValue" class="upload-image" />
|
||||
<div class="upload-handle" @click.stop>
|
||||
<div class="handle-icon" @click="editImg">
|
||||
<Icon icon="ep:edit" />
|
||||
<span>{{ t('action.edit') }}</span>
|
||||
</div>
|
||||
<div class="handle-icon" @click="imgViewVisible = true">
|
||||
<Icon icon="ep:zoom-in" />
|
||||
<span>{{ t('action.detail') }}</span>
|
||||
</div>
|
||||
<div class="handle-icon" @click="deleteImg">
|
||||
<Icon icon="ep:delete" />
|
||||
<span>{{ t('action.del') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="upload-empty">
|
||||
<slot name="empty">
|
||||
<Icon icon="ep:plus" />
|
||||
<!-- <span>请上传图片</span> -->
|
||||
</slot>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<div class="el-upload__tip">
|
||||
<slot name="tip"></slot>
|
||||
</div>
|
||||
<el-image-viewer
|
||||
v-if="imgViewVisible"
|
||||
@close="imgViewVisible = false"
|
||||
:url-list="[modelValue]"
|
||||
/>
|
||||
</div>
|
||||
<!-- 文件列表 -->
|
||||
<Dialog v-model="dialogVisible" title="预览" width="800" append-to-body>
|
||||
<img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" />
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { Dialog } from '@/components/Dialog'
|
||||
|
||||
<script setup lang="ts" name="UploadImg">
|
||||
import { ref } from 'vue'
|
||||
import type { UploadProps } from 'element-plus'
|
||||
import { ElUpload, ElNotification, ElImageViewer } from 'element-plus'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { generateUUID } from '@/utils'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
import { ElUpload, UploadInstance, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus'
|
||||
|
||||
type FileTypes =
|
||||
| 'image/apng'
|
||||
| 'image/bmp'
|
||||
| 'image/gif'
|
||||
| 'image/jpeg'
|
||||
| 'image/pjpeg'
|
||||
| 'image/png'
|
||||
| 'image/svg+xml'
|
||||
| 'image/tiff'
|
||||
| 'image/webp'
|
||||
| 'image/x-icon'
|
||||
|
||||
// 接受父组件参数
|
||||
const props = defineProps({
|
||||
modelValue: propTypes.string.def(''),
|
||||
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
|
||||
drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传(默认为 true)
|
||||
disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传(默认为 false)
|
||||
fileSize: propTypes.number.def(5), // 图片大小限制 ==> 非必传(默认为 5M)
|
||||
fileType: propTypes.array.def(['image/jpeg', 'image/png', 'image/gif']), // 图片类型限制 ==> 非必传(默认为 ["image/jpeg", "image/png", "image/gif"])
|
||||
height: propTypes.string.def('150px'), // 组件高度 ==> 非必传(默认为 150px)
|
||||
width: propTypes.string.def('150px'), // 组件宽度 ==> 非必传(默认为 150px)
|
||||
borderRadius: propTypes.string.def('8px') // 组件边框圆角 ==> 非必传(默认为 8px)
|
||||
})
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
// 生成组件唯一id
|
||||
const uuid = ref('id-' + generateUUID())
|
||||
// 查看图片
|
||||
const imgViewVisible = ref(false)
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: propTypes.oneOfType([String, Object, Array]),
|
||||
title: propTypes.string.def('图片上传'),
|
||||
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
|
||||
fileType: propTypes.array.def(['jpg', 'png', 'gif', 'jpeg']), // 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
fileSize: propTypes.number.def(5), // 大小限制(MB)
|
||||
limit: propTypes.number.def(1), // 数量限制
|
||||
isShowTip: propTypes.bool.def(false) // 是否显示提示
|
||||
})
|
||||
// ========== 上传相关 ==========
|
||||
const valueRef = ref(props.modelValue)
|
||||
const uploadRef = ref<UploadInstance>()
|
||||
const uploadList = ref<UploadUserFile[]>([])
|
||||
const fileList = ref<UploadUserFile[]>([])
|
||||
const uploadNumber = ref<number>(0)
|
||||
const dialogImageUrl = ref()
|
||||
const dialogVisible = ref(false)
|
||||
const deleteImg = () => {
|
||||
emit('update:modelValue', '')
|
||||
}
|
||||
|
||||
const uploadHeaders = ref({
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
})
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (val) {
|
||||
// 首先将值转为数组, 当只穿了一个图片时,会报map方法错误
|
||||
const list = Array.isArray(props.modelValue)
|
||||
? props.modelValue
|
||||
: Array.isArray(props.modelValue?.split(','))
|
||||
? props.modelValue?.split(',')
|
||||
: Array.of(props.modelValue)
|
||||
// 然后将数组转为对象数组
|
||||
fileList.value = list.map((item) => {
|
||||
if (typeof item === 'string') {
|
||||
// edit by 芋道源码
|
||||
item = { name: item, url: item }
|
||||
}
|
||||
return item
|
||||
})
|
||||
} else {
|
||||
fileList.value = []
|
||||
return []
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
// 文件上传之前判断
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {
|
||||
if (fileList.value.length >= props.limit) {
|
||||
message.error(`上传文件数量不能超过${props.limit}个!`)
|
||||
return false
|
||||
}
|
||||
let fileExtension = ''
|
||||
if (file.name.lastIndexOf('.') > -1) {
|
||||
fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
|
||||
}
|
||||
const isImg = props.fileType.some((type: string) => {
|
||||
if (file.type.indexOf(type) > -1) return true
|
||||
return !!(fileExtension && fileExtension.indexOf(type) > -1)
|
||||
})
|
||||
const isLimit = file.size < props.fileSize * 1024 * 1024
|
||||
if (!isImg) {
|
||||
message.error(`文件格式不正确, 请上传${props.fileType.join('/')}格式!`)
|
||||
return false
|
||||
}
|
||||
if (!isLimit) {
|
||||
message.error(`上传文件大小不能超过${props.fileSize}MB!`)
|
||||
return false
|
||||
}
|
||||
message.success('正在上传文件,请稍候...')
|
||||
uploadNumber.value++
|
||||
|
||||
const editImg = () => {
|
||||
const dom = document.querySelector(`#${uuid.value} .el-upload__input`)
|
||||
dom && dom.dispatchEvent(new MouseEvent('click'))
|
||||
}
|
||||
// 处理上传的文件发生变化
|
||||
// const handleFileChange = (uploadFile: UploadFile): void => {
|
||||
// uploadRef.value.data.path = uploadFile.name
|
||||
// }
|
||||
// 文件上传成功
|
||||
const handleFileSuccess: UploadProps['onSuccess'] = (res: any): void => {
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
||||
const imgSize = rawFile.size / 1024 / 1024 < props.fileSize
|
||||
const imgType = props.fileType
|
||||
if (!imgType.includes(rawFile.type as FileTypes))
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: '上传图片不符合所需的格式!',
|
||||
type: 'warning'
|
||||
})
|
||||
if (!imgSize)
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: `上传图片大小不能超过 ${props.fileSize}M!`,
|
||||
type: 'warning'
|
||||
})
|
||||
return imgType.includes(rawFile.type as FileTypes) && imgSize
|
||||
}
|
||||
|
||||
// 图片上传成功提示
|
||||
const uploadSuccess: UploadProps['onSuccess'] = (res: any): void => {
|
||||
message.success('上传成功')
|
||||
uploadList.value.push({ name: res.data, url: res.data })
|
||||
if (uploadList.value.length == uploadNumber.value) {
|
||||
fileList.value = fileList.value.concat(uploadList.value)
|
||||
uploadList.value = []
|
||||
uploadNumber.value = 0
|
||||
emit('update:modelValue', listToString(fileList.value))
|
||||
}
|
||||
emit('update:modelValue', res.data)
|
||||
}
|
||||
// 文件数超出提示
|
||||
const handleExceed: UploadProps['onExceed'] = (): void => {
|
||||
message.error(`上传文件数量不能超过${props.limit}个!`)
|
||||
}
|
||||
// 上传错误提示
|
||||
const excelUploadError: UploadProps['onError'] = (): void => {
|
||||
message.error('导入数据失败,请您重新上传!')
|
||||
}
|
||||
// 删除上传文件
|
||||
const handleRemove = (file) => {
|
||||
const findex = fileList.value.map((f) => f.name).indexOf(file.name)
|
||||
if (findex > -1) {
|
||||
fileList.value.splice(findex, 1)
|
||||
emit('update:modelValue', listToString(fileList.value))
|
||||
}
|
||||
}
|
||||
// 对象转成指定字符串分隔
|
||||
const listToString = (list: UploadUserFile[], separator?: string) => {
|
||||
let strs = ''
|
||||
separator = separator || ','
|
||||
for (let i in list) {
|
||||
strs += list[i].url + separator
|
||||
}
|
||||
return strs != '' ? strs.substr(0, strs.length - 1) : ''
|
||||
}
|
||||
// 预览
|
||||
const handlePictureCardPreview: UploadProps['onPreview'] = (file) => {
|
||||
dialogImageUrl.value = file.url
|
||||
dialogVisible.value = true
|
||||
|
||||
// 图片上传错误提示
|
||||
const uploadError = () => {
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: '图片上传失败,请您重新上传!',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
// .el-upload--picture-card 控制加号部分
|
||||
:deep(.hide .el-upload--picture-card) {
|
||||
display: none;
|
||||
.is-error {
|
||||
.upload {
|
||||
:deep(.el-upload),
|
||||
:deep(.el-upload-dragger) {
|
||||
border: 1px dashed var(--el-color-danger) !important;
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 去掉动画效果
|
||||
:deep(.el-list-enter-active, .el-list-leave-active) {
|
||||
transition: all 0s;
|
||||
:deep(.disabled) {
|
||||
.el-upload,
|
||||
.el-upload-dragger {
|
||||
cursor: not-allowed !important;
|
||||
background: var(--el-disabled-bg-color);
|
||||
border: 1px dashed var(--el-border-color-darker) !important;
|
||||
&:hover {
|
||||
border: 1px dashed var(--el-border-color-darker) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-list-enter, .el-list-leave-active) {
|
||||
opacity: 0;
|
||||
transform: translateY(0);
|
||||
.upload-box {
|
||||
.no-border {
|
||||
:deep(.el-upload) {
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
:deep(.upload) {
|
||||
.el-upload {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: v-bind(width);
|
||||
height: v-bind(height);
|
||||
overflow: hidden;
|
||||
border: 1px dashed var(--el-border-color-darker);
|
||||
border-radius: v-bind(borderRadius);
|
||||
transition: var(--el-transition-duration-fast);
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
.upload-handle {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.el-upload-dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: transparent;
|
||||
border: 1px dashed var(--el-border-color-darker);
|
||||
border-radius: v-bind(borderRadius);
|
||||
&:hover {
|
||||
border: 1px dashed var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
.el-upload-dragger.is-dragover {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border: 2px dashed var(--el-color-primary) !important;
|
||||
}
|
||||
.upload-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.upload-empty {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
color: var(--el-color-info);
|
||||
.el-icon {
|
||||
font-size: 28px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
}
|
||||
.upload-handle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
background: rgb(0 0 0 / 60%);
|
||||
opacity: 0;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
.handle-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 6%;
|
||||
color: aliceblue;
|
||||
.el-icon {
|
||||
margin-bottom: 40%;
|
||||
font-size: 130%;
|
||||
line-height: 130%;
|
||||
}
|
||||
span {
|
||||
font-size: 85%;
|
||||
line-height: 85%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-upload__tip {
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
277
yudao-ui-admin-vue3/src/components/UploadFile/src/UploadImgs.vue
Normal file
277
yudao-ui-admin-vue3/src/components/UploadFile/src/UploadImgs.vue
Normal file
@ -0,0 +1,277 @@
|
||||
<template>
|
||||
<div class="upload-box">
|
||||
<el-upload
|
||||
:action="updateUrl"
|
||||
list-type="picture-card"
|
||||
:class="['upload', drag ? 'no-border' : '']"
|
||||
v-model:file-list="fileList"
|
||||
:multiple="true"
|
||||
:limit="limit"
|
||||
:headers="uploadHeaders"
|
||||
:before-upload="beforeUpload"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="uploadSuccess"
|
||||
:on-error="uploadError"
|
||||
:drag="drag"
|
||||
:accept="fileType.join(',')"
|
||||
>
|
||||
<div class="upload-empty">
|
||||
<slot name="empty">
|
||||
<Icon icon="ep:plus" />
|
||||
<!-- <span>请上传图片</span> -->
|
||||
</slot>
|
||||
</div>
|
||||
<template #file="{ file }">
|
||||
<img :src="file.url" class="upload-image" />
|
||||
<div class="upload-handle" @click.stop>
|
||||
<div class="handle-icon" @click="handlePictureCardPreview(file)">
|
||||
<Icon icon="ep:zoom-in" />
|
||||
<span>查看</span>
|
||||
</div>
|
||||
<div class="handle-icon" @click="handleRemove(file)">
|
||||
<Icon icon="ep:delete" />
|
||||
<span>删除</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
<div class="el-upload__tip">
|
||||
<slot name="tip"></slot>
|
||||
</div>
|
||||
<el-image-viewer
|
||||
v-if="imgViewVisible"
|
||||
@close="imgViewVisible = false"
|
||||
:url-list="[viewImageUrl]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="UploadImgs">
|
||||
import { PropType, ref } from 'vue'
|
||||
import { ElUpload, ElNotification, ElImageViewer } from 'element-plus'
|
||||
import type { UploadProps, UploadFile, UploadUserFile } from 'element-plus'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { getAccessToken, getTenantId } from '@/utils/auth'
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
type FileTypes =
|
||||
| 'image/apng'
|
||||
| 'image/bmp'
|
||||
| 'image/gif'
|
||||
| 'image/jpeg'
|
||||
| 'image/pjpeg'
|
||||
| 'image/png'
|
||||
| 'image/svg+xml'
|
||||
| 'image/tiff'
|
||||
| 'image/webp'
|
||||
| 'image/x-icon'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array as PropType<UploadUserFile[]>,
|
||||
required: true
|
||||
},
|
||||
updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL),
|
||||
drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传(默认为 true)
|
||||
disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传(默认为 false)
|
||||
limit: propTypes.number.def(5), // 最大图片上传数 ==> 非必传(默认为 5张)
|
||||
fileSize: propTypes.number.def(5), // 图片大小限制 ==> 非必传(默认为 5M)
|
||||
fileType: propTypes.array.def(['image/jpeg', 'image/png', 'image/gif']), // 图片类型限制 ==> 非必传(默认为 ["image/jpeg", "image/png", "image/gif"])
|
||||
height: propTypes.string.def('150px'), // 组件高度 ==> 非必传(默认为 150px)
|
||||
width: propTypes.string.def('150px'), // 组件宽度 ==> 非必传(默认为 150px)
|
||||
borderRadius: propTypes.string.def('8px') // 组件边框圆角 ==> 非必传(默认为 8px)
|
||||
})
|
||||
|
||||
const uploadHeaders = ref({
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
})
|
||||
|
||||
const fileList = ref<UploadUserFile[]>(props.modelValue)
|
||||
|
||||
/**
|
||||
* @description 文件上传之前判断
|
||||
* @param rawFile 上传的文件
|
||||
* */
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
||||
const imgSize = rawFile.size / 1024 / 1024 < props.fileSize
|
||||
const imgType = props.fileType
|
||||
if (!imgType.includes(rawFile.type as FileTypes))
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: '上传图片不符合所需的格式!',
|
||||
type: 'warning'
|
||||
})
|
||||
if (!imgSize)
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: `上传图片大小不能超过 ${props.fileSize}M!`,
|
||||
type: 'warning'
|
||||
})
|
||||
return imgType.includes(rawFile.type as FileTypes) && imgSize
|
||||
}
|
||||
|
||||
// 图片上传成功
|
||||
interface UploadEmits {
|
||||
(e: 'update:modelValue', value: UploadUserFile[]): void
|
||||
}
|
||||
const emit = defineEmits<UploadEmits>()
|
||||
const uploadSuccess = (response, uploadFile: UploadFile) => {
|
||||
if (!response) return
|
||||
uploadFile.url = response.data
|
||||
emit('update:modelValue', fileList.value)
|
||||
message.success('上传成功')
|
||||
}
|
||||
|
||||
// 删除图片
|
||||
const handleRemove = (uploadFile: UploadFile) => {
|
||||
fileList.value = fileList.value.filter(
|
||||
(item) => item.url !== uploadFile.url || item.name !== uploadFile.name
|
||||
)
|
||||
emit('update:modelValue', fileList.value)
|
||||
}
|
||||
|
||||
// 图片上传错误提示
|
||||
const uploadError = () => {
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: '图片上传失败,请您重新上传!',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
|
||||
// 文件数超出提示
|
||||
const handleExceed = () => {
|
||||
ElNotification({
|
||||
title: '温馨提示',
|
||||
message: `当前最多只能上传 ${props.limit} 张图片,请移除后上传!`,
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
|
||||
// 图片预览
|
||||
const viewImageUrl = ref('')
|
||||
const imgViewVisible = ref(false)
|
||||
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
|
||||
viewImageUrl.value = uploadFile.url!
|
||||
imgViewVisible.value = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.is-error {
|
||||
.upload {
|
||||
:deep(.el-upload--picture-card),
|
||||
:deep(.el-upload-dragger) {
|
||||
border: 1px dashed var(--el-color-danger) !important;
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.disabled) {
|
||||
.el-upload--picture-card,
|
||||
.el-upload-dragger {
|
||||
cursor: not-allowed;
|
||||
background: var(--el-disabled-bg-color) !important;
|
||||
border: 1px dashed var(--el-border-color-darker);
|
||||
&:hover {
|
||||
border-color: var(--el-border-color-darker) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.upload-box {
|
||||
.no-border {
|
||||
:deep(.el-upload--picture-card) {
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
:deep(.upload) {
|
||||
.el-upload-dragger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border: 1px dashed var(--el-border-color-darker);
|
||||
border-radius: v-bind(borderRadius);
|
||||
&:hover {
|
||||
border: 1px dashed var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
.el-upload-dragger.is-dragover {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border: 2px dashed var(--el-color-primary) !important;
|
||||
}
|
||||
.el-upload-list__item,
|
||||
.el-upload--picture-card {
|
||||
width: v-bind(width);
|
||||
height: v-bind(height);
|
||||
background-color: transparent;
|
||||
border-radius: v-bind(borderRadius);
|
||||
}
|
||||
.upload-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
.upload-handle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
background: rgb(0 0 0 / 60%);
|
||||
opacity: 0;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
.handle-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 6%;
|
||||
color: aliceblue;
|
||||
.el-icon {
|
||||
margin-bottom: 15%;
|
||||
font-size: 140%;
|
||||
}
|
||||
span {
|
||||
font-size: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-upload-list__item {
|
||||
&:hover {
|
||||
.upload-handle {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.upload-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
color: var(--el-color-info);
|
||||
.el-icon {
|
||||
font-size: 28px;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-upload__tip {
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -44,7 +44,7 @@ export default {
|
||||
},
|
||||
upload: async <T = any>(option: any) => {
|
||||
option.headersType = 'multipart/form-data'
|
||||
const res = await request({ method: 'PUT', ...option })
|
||||
const res = await request({ method: 'POST', ...option })
|
||||
return res as unknown as Promise<T>
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { reactive } from 'vue'
|
||||
import { AxiosPromise } from 'axios'
|
||||
import { findIndex } from '@/utils'
|
||||
import { eachTree, treeMap, filter } from '@/utils/tree'
|
||||
import { getBoolDictOptions, getDictOptions, getIntDictOptions } from '@/utils/dict'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { FormSchema } from '@/types/form'
|
||||
import { TableColumn } from '@/types/table'
|
||||
import { DescriptionsSchema } from '@/types/descriptions'
|
||||
@ -23,6 +26,8 @@ export type CrudSchema = Omit<TableColumn, 'children'> & {
|
||||
type CrudSearchParams = {
|
||||
// 是否显示在查询项
|
||||
show?: boolean
|
||||
// 接口
|
||||
api?: () => Promise<any>
|
||||
} & Omit<FormSchema, 'field'>
|
||||
|
||||
type CrudTableParams = {
|
||||
@ -33,6 +38,8 @@ type CrudTableParams = {
|
||||
type CrudFormParams = {
|
||||
// 是否显示表单项
|
||||
show?: boolean
|
||||
// 接口
|
||||
api?: () => Promise<any>
|
||||
} & Omit<FormSchema, 'field'>
|
||||
|
||||
type CrudDescriptionsParams = {
|
||||
@ -47,6 +54,8 @@ interface AllSchemas {
|
||||
detailSchema: DescriptionsSchema[]
|
||||
}
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// 过滤所有结构
|
||||
export const useCrudSchemas = (
|
||||
crudSchema: CrudSchema[]
|
||||
@ -61,13 +70,13 @@ export const useCrudSchemas = (
|
||||
detailSchema: []
|
||||
})
|
||||
|
||||
const searchSchema = filterSearchSchema(crudSchema)
|
||||
const searchSchema = filterSearchSchema(crudSchema, allSchemas)
|
||||
allSchemas.searchSchema = searchSchema || []
|
||||
|
||||
const tableColumns = filterTableSchema(crudSchema)
|
||||
allSchemas.tableColumns = tableColumns || []
|
||||
|
||||
const formSchema = filterFormSchema(crudSchema)
|
||||
const formSchema = filterFormSchema(crudSchema, allSchemas)
|
||||
allSchemas.formSchema = formSchema
|
||||
|
||||
const detailSchema = filterDescriptionsSchema(crudSchema)
|
||||
@ -79,9 +88,11 @@ export const useCrudSchemas = (
|
||||
}
|
||||
|
||||
// 过滤 Search 结构
|
||||
const filterSearchSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
|
||||
const filterSearchSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => {
|
||||
const searchSchema: FormSchema[] = []
|
||||
|
||||
// 获取字典列表队列
|
||||
const searchRequestTask: Array<() => Promise<void>> = []
|
||||
eachTree(crudSchema, (schemaItem: CrudSchema) => {
|
||||
// 判断是否显示
|
||||
if (schemaItem?.isSearch || schemaItem.search?.show) {
|
||||
@ -107,12 +118,31 @@ const filterSearchSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
|
||||
field: schemaItem.field,
|
||||
label: schemaItem.search?.label || schemaItem.label
|
||||
}
|
||||
if (searchSchemaItem.api) {
|
||||
searchRequestTask.push(async () => {
|
||||
const res = await (searchSchemaItem.api as () => AxiosPromise)()
|
||||
if (res) {
|
||||
const index = findIndex(allSchemas.searchSchema, (v: FormSchema) => {
|
||||
return v.field === searchSchemaItem.field
|
||||
})
|
||||
if (index !== -1) {
|
||||
allSchemas.searchSchema[index]!.componentProps!.options = filterOptions(
|
||||
res,
|
||||
searchSchemaItem.componentProps.optionsAlias?.labelField
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 删除不必要的字段
|
||||
delete searchSchemaItem.show
|
||||
|
||||
searchSchema.push(searchSchemaItem)
|
||||
}
|
||||
})
|
||||
for (const task of searchRequestTask) {
|
||||
task()
|
||||
}
|
||||
return searchSchema
|
||||
}
|
||||
|
||||
@ -139,9 +169,12 @@ const filterTableSchema = (crudSchema: CrudSchema[]): TableColumn[] => {
|
||||
}
|
||||
|
||||
// 过滤 form 结构
|
||||
const filterFormSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
|
||||
const filterFormSchema = (crudSchema: CrudSchema[], allSchemas: AllSchemas): FormSchema[] => {
|
||||
const formSchema: FormSchema[] = []
|
||||
|
||||
// 获取字典列表队列
|
||||
const formRequestTask: Array<() => Promise<void>> = []
|
||||
|
||||
eachTree(crudSchema, (schemaItem: CrudSchema) => {
|
||||
// 判断是否显示
|
||||
if (schemaItem?.isForm !== false && schemaItem?.form?.show !== false) {
|
||||
@ -185,6 +218,23 @@ const filterFormSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
|
||||
label: schemaItem.form?.label || schemaItem.label
|
||||
}
|
||||
|
||||
if (formSchemaItem.api) {
|
||||
formRequestTask.push(async () => {
|
||||
const res = await (formSchemaItem.api as () => AxiosPromise)()
|
||||
if (res) {
|
||||
const index = findIndex(allSchemas.formSchema, (v: FormSchema) => {
|
||||
return v.field === formSchemaItem.field
|
||||
})
|
||||
if (index !== -1) {
|
||||
allSchemas.formSchema[index]!.componentProps!.options = filterOptions(
|
||||
res,
|
||||
formSchemaItem.componentProps.optionsAlias?.labelField
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 删除不必要的字段
|
||||
delete formSchemaItem.show
|
||||
|
||||
@ -192,6 +242,9 @@ const filterFormSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
|
||||
}
|
||||
})
|
||||
|
||||
for (const task of formRequestTask) {
|
||||
task()
|
||||
}
|
||||
return formSchema
|
||||
}
|
||||
|
||||
@ -225,3 +278,15 @@ const filterDescriptionsSchema = (crudSchema: CrudSchema[]): DescriptionsSchema[
|
||||
|
||||
return descriptionsSchema
|
||||
}
|
||||
|
||||
// 给options添加国际化
|
||||
const filterOptions = (options: Recordable, labelField?: string) => {
|
||||
return options.map((v: Recordable) => {
|
||||
if (labelField) {
|
||||
v['labelField'] = t(v.labelField)
|
||||
} else {
|
||||
v['label'] = t(v.label)
|
||||
}
|
||||
return v
|
||||
})
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ type CrudDescriptionsParams = {
|
||||
} & Omit<DescriptionsSchema, 'field'>
|
||||
|
||||
type CrudPrintParams = {
|
||||
// 是否显示表单项
|
||||
// 是否显示打印项
|
||||
show?: boolean
|
||||
} & Omit<VxeTableDefines.ColumnInfo[], 'field'>
|
||||
|
||||
|
@ -53,7 +53,8 @@ export default defineComponent({
|
||||
<ElBreadcrumbItem to={{ path: disabled ? '' : v.path }} key={v.name}>
|
||||
{meta?.icon && breadcrumbIcon.value ? (
|
||||
<>
|
||||
<Icon icon={meta.icon} class="mr-[5px]"></Icon> {t(v?.meta?.title)}
|
||||
<Icon icon={meta.icon} class="mr-[2px]" svgClass="inline-block"></Icon>
|
||||
{t(v?.meta?.title)}
|
||||
</>
|
||||
) : (
|
||||
t(v?.meta?.title)
|
||||
|
@ -55,31 +55,33 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-link
|
||||
:class="[
|
||||
prefixCls,
|
||||
layout !== 'classic' ? `${prefixCls}__Top` : '',
|
||||
'flex !h-[var(--logo-height)] items-center cursor-pointer justify-center relative',
|
||||
'dark:bg-[var(--el-bg-color)]'
|
||||
]"
|
||||
to="/"
|
||||
>
|
||||
<img
|
||||
src="@/assets/imgs/logo.png"
|
||||
class="w-[calc(var(--logo-height)-10px)] h-[calc(var(--logo-height)-10px)]"
|
||||
/>
|
||||
<div
|
||||
v-if="show"
|
||||
<div>
|
||||
<router-link
|
||||
:class="[
|
||||
'ml-10px text-16px font-700',
|
||||
{
|
||||
'text-[var(--logo-title-text-color)]': layout === 'classic',
|
||||
'text-[var(--top-header-text-color)]':
|
||||
layout === 'topLeft' || layout === 'top' || layout === 'cutMenu'
|
||||
}
|
||||
prefixCls,
|
||||
layout !== 'classic' ? `${prefixCls}__Top` : '',
|
||||
'flex !h-[var(--logo-height)] items-center cursor-pointer justify-center relative',
|
||||
'dark:bg-[var(--el-bg-color)]'
|
||||
]"
|
||||
to="/"
|
||||
>
|
||||
{{ title }}
|
||||
</div>
|
||||
</router-link>
|
||||
<img
|
||||
src="@/assets/imgs/logo.png"
|
||||
class="w-[calc(var(--logo-height)-10px)] h-[calc(var(--logo-height)-10px)]"
|
||||
/>
|
||||
<div
|
||||
v-if="show"
|
||||
:class="[
|
||||
'ml-10px text-16px font-700',
|
||||
{
|
||||
'text-[var(--logo-title-text-color)]': layout === 'classic',
|
||||
'text-[var(--top-header-text-color)]':
|
||||
layout === 'topLeft' || layout === 'top' || layout === 'cutMenu'
|
||||
}
|
||||
]"
|
||||
>
|
||||
{{ title }}
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -161,6 +161,7 @@ $prefix-cls: #{$namespace}-menu;
|
||||
// 设置子菜单悬停的高亮和背景色
|
||||
.#{$elNamespace}-sub-menu__title,
|
||||
.#{$elNamespace}-menu-item {
|
||||
height: 59px;
|
||||
&:hover {
|
||||
color: var(--left-menu-text-active-color) !important;
|
||||
background-color: var(--left-menu-bg-color) !important;
|
||||
@ -170,6 +171,7 @@ $prefix-cls: #{$namespace}-menu;
|
||||
// 设置选中时的高亮背景和高亮颜色
|
||||
.#{$elNamespace}-sub-menu.is-active,
|
||||
.#{$elNamespace}-menu-item.is-active {
|
||||
height: 59px;
|
||||
color: var(--left-menu-text-active-color) !important;
|
||||
background-color: var(--left-menu-bg-active-color) !important;
|
||||
|
||||
|
@ -426,5 +426,19 @@ export default {
|
||||
cfPwdMsg: 'Please Enter Confirm Password',
|
||||
diffPwd: 'The Passwords Entered Twice No Match'
|
||||
}
|
||||
},
|
||||
cropper: {
|
||||
selectImage: 'Select Image',
|
||||
uploadSuccess: 'Uploaded success!',
|
||||
modalTitle: 'Avatar upload',
|
||||
okText: 'Confirm and upload',
|
||||
btn_reset: 'Reset',
|
||||
btn_rotate_left: 'Counterclockwise rotation',
|
||||
btn_rotate_right: 'Clockwise rotation',
|
||||
btn_scale_x: 'Flip horizontal',
|
||||
btn_scale_y: 'Flip vertical',
|
||||
btn_zoom_in: 'Zoom in',
|
||||
btn_zoom_out: 'Zoom out',
|
||||
preview: 'Preivew'
|
||||
}
|
||||
}
|
||||
|
@ -419,5 +419,19 @@ export default {
|
||||
pwdRules: '长度在 6 到 20 个字符',
|
||||
diffPwd: '两次输入密码不一致'
|
||||
}
|
||||
},
|
||||
cropper: {
|
||||
selectImage: '选择图片',
|
||||
uploadSuccess: '上传成功',
|
||||
modalTitle: '头像上传',
|
||||
okText: '确认并上传',
|
||||
btn_reset: '重置',
|
||||
btn_rotate_left: '逆时针旋转',
|
||||
btn_rotate_right: '顺时针旋转',
|
||||
btn_scale_x: '水平翻转',
|
||||
btn_scale_y: '垂直翻转',
|
||||
btn_zoom_in: '放大',
|
||||
btn_zoom_out: '缩小',
|
||||
preview: '预览'
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ watch(
|
||||
import('./theme/light.scss')
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
{ deep: true }
|
||||
)
|
||||
// 全局默认参数
|
||||
VXETable.setup({
|
||||
|
@ -14,7 +14,7 @@ import { usePermissionStoreWithOut } from '@/store/modules/permission'
|
||||
import { getInfoApi } from '@/api/login'
|
||||
import { listSimpleDictDataApi } from '@/api/system/dict/dict.data'
|
||||
|
||||
const { wsCache } = useCache('sessionStorage')
|
||||
const { wsCache } = useCache()
|
||||
|
||||
const { start, done } = useNProgress()
|
||||
|
||||
|
@ -64,7 +64,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
meta: {
|
||||
title: t('router.home'),
|
||||
icon: 'ep:home-filled',
|
||||
noCache: true,
|
||||
noCache: false,
|
||||
affix: true
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
meta: {
|
||||
canTo: true,
|
||||
hidden: true,
|
||||
noTagsView: true,
|
||||
noTagsView: false,
|
||||
icon: 'ep:user',
|
||||
title: t('common.profile')
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ export type ComponentName =
|
||||
| 'InputPassword'
|
||||
| 'Editor'
|
||||
| 'UploadImg'
|
||||
| 'UploadImgs'
|
||||
| 'UploadFile'
|
||||
|
||||
export type ColProps = {
|
||||
|
@ -69,7 +69,7 @@ export const trim = (str: string) => {
|
||||
* @param {Date | number | string} time 需要转换的时间
|
||||
* @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
export function formatTime(time: Date | number | string, fmt: string) {
|
||||
export const formatTime = (time: Date | number | string, fmt: string) => {
|
||||
if (!time) return ''
|
||||
else {
|
||||
const date = new Date(time)
|
||||
@ -100,7 +100,7 @@ export function formatTime(time: Date | number | string, fmt: string) {
|
||||
/**
|
||||
* 生成随机字符串
|
||||
*/
|
||||
export function toAnyString() {
|
||||
export const toAnyString = () => {
|
||||
const str: string = 'xxxxx-xxxxx-4xxxx-yxxxx-xxxxx'.replace(/[xy]/g, (c: string) => {
|
||||
const r: number = (Math.random() * 16) | 0
|
||||
const v: number = c === 'x' ? r : (r & 0x3) | 0x8
|
||||
@ -108,3 +108,34 @@ export function toAnyString() {
|
||||
})
|
||||
return str
|
||||
}
|
||||
|
||||
export const generateUUID = () => {
|
||||
if (typeof crypto === 'object') {
|
||||
if (typeof crypto.randomUUID === 'function') {
|
||||
return crypto.randomUUID()
|
||||
}
|
||||
if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
|
||||
const callback = (c: any) => {
|
||||
const num = Number(c)
|
||||
return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(
|
||||
16
|
||||
)
|
||||
}
|
||||
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback)
|
||||
}
|
||||
}
|
||||
let timestamp = new Date().getTime()
|
||||
let performanceNow =
|
||||
(typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||
let random = Math.random() * 16
|
||||
if (timestamp > 0) {
|
||||
random = (timestamp + random) % 16 | 0
|
||||
timestamp = Math.floor(timestamp / 16)
|
||||
} else {
|
||||
random = (performanceNow + random) % 16 | 0
|
||||
performanceNow = Math.floor(performanceNow / 16)
|
||||
}
|
||||
return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16)
|
||||
})
|
||||
}
|
||||
|
@ -56,7 +56,13 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord
|
||||
title: route.name,
|
||||
icon: route.icon,
|
||||
hidden: !route.visible,
|
||||
noCache: !route.keepAlive
|
||||
noCache: !route.keepAlive,
|
||||
alwaysShow:
|
||||
route.children &&
|
||||
route.children.length === 1 &&
|
||||
import.meta.env.VITE_ROUTE_ALWAYSSHOW_ENABLE === 'true'
|
||||
? true
|
||||
: false
|
||||
}
|
||||
// 路由地址转首字母大写驼峰,作为路由名称,适配keepAlive
|
||||
let data: AppRouteRecordRaw = {
|
||||
@ -71,6 +77,7 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord
|
||||
data.meta = {}
|
||||
data.name = toCamelCase(route.path, true) + 'Parent'
|
||||
data.redirect = ''
|
||||
meta.alwaysShow = true
|
||||
const childrenData: AppRouteRecordRaw = {
|
||||
path: '',
|
||||
name: toCamelCase(route.path, true),
|
||||
|
@ -1,245 +1,40 @@
|
||||
<template>
|
||||
<div class="user-info-head" @click="editCropper()">
|
||||
<img :src="props.img" title="点击上传头像" class="img-circle img-lg" alt="" />
|
||||
<div class="change-avatar">
|
||||
<CropperAvatar
|
||||
ref="cropperRef"
|
||||
:value="avatar"
|
||||
:showBtn="false"
|
||||
@change="handelUpload"
|
||||
:btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }"
|
||||
width="120px"
|
||||
/>
|
||||
</div>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
title="编辑头像"
|
||||
:mask-closable="false"
|
||||
width="800px"
|
||||
append-to-body
|
||||
@opened="cropperVisible = true"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
|
||||
<VueCropper
|
||||
ref="cropper"
|
||||
v-if="cropperVisible"
|
||||
:img="options.img"
|
||||
:info="true"
|
||||
:infoTrue="options.infoTrue"
|
||||
:autoCrop="options.autoCrop"
|
||||
:autoCropWidth="options.autoCropWidth"
|
||||
:autoCropHeight="options.autoCropHeight"
|
||||
:fixedNumber="options.fixedNumber"
|
||||
:fixedBox="options.fixedBox"
|
||||
:centerBox="options.centerBox"
|
||||
@real-time="realTime"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
|
||||
<div
|
||||
class="avatar-upload-preview"
|
||||
:style="{
|
||||
width: previews.w + 'px',
|
||||
height: previews.h + 'px',
|
||||
overflow: 'hidden',
|
||||
margin: '5px'
|
||||
}"
|
||||
>
|
||||
<div :style="previews.div">
|
||||
<img :src="previews.url" :style="previews.img" style="!max-width: 100%" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<template #footer>
|
||||
<el-row>
|
||||
<el-col :lg="2" :md="2">
|
||||
<el-upload
|
||||
action="#"
|
||||
:http-request="requestUpload"
|
||||
:show-file-list="false"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<el-button size="small">
|
||||
<Icon icon="ep:upload-filled" class="mr-5px" />
|
||||
选择
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</el-col>
|
||||
<el-col :lg="{ span: 1, offset: 2 }" :md="2">
|
||||
<el-button size="small" @click="changeScale(1)">
|
||||
<Icon icon="ep:zoom-in" class="mr-5px" />
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
|
||||
<el-button size="small" @click="changeScale(-1)">
|
||||
<Icon icon="ep:zoom-out" class="mr-5px" />
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
|
||||
<el-button size="small" @click="rotateLeft()">
|
||||
<Icon icon="ep:arrow-left-bold" class="mr-5px" />
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
|
||||
<el-button size="small" @click="rotateRight()">
|
||||
<Icon icon="ep:arrow-right-bold" class="mr-5px" />
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :lg="{ span: 2, offset: 6 }" :md="2">
|
||||
<el-button size="small" type="primary" @click="uploadImg()">提 交</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch, Ref, UnwrapNestedRefs } from 'vue'
|
||||
import VueCropper from 'vue-cropper/lib/vue-cropper.vue'
|
||||
import 'vue-cropper/dist/index.css'
|
||||
import { ElRow, ElCol, ElUpload, ElMessage, ElDialog } from 'element-plus'
|
||||
import { computed, ref } from 'vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { CropperAvatar } from '@/components/Cropper'
|
||||
import { uploadAvatarApi } from '@/api/system/user/profile'
|
||||
|
||||
const cropper = ref()
|
||||
const dialogVisible = ref(false)
|
||||
const cropperVisible = ref(false)
|
||||
const props = defineProps({
|
||||
img: propTypes.string.def('')
|
||||
})
|
||||
interface Options {
|
||||
img: string | ArrayBuffer | null // 裁剪图片的地址
|
||||
info: true // 裁剪框的大小信息
|
||||
outputSize: number // 裁剪生成图片的质量 [1至0.1]
|
||||
outputType: 'jpeg' // 裁剪生成图片的格式
|
||||
canScale: boolean // 图片是否允许滚轮缩放
|
||||
autoCrop: boolean // 是否默认生成截图框
|
||||
autoCropWidth: number // 默认生成截图框宽度
|
||||
autoCropHeight: number // 默认生成截图框高度
|
||||
fixedBox: boolean // 固定截图框大小 不允许改变
|
||||
fixed: boolean // 是否开启截图框宽高固定比例
|
||||
fixedNumber: Array<number> // 截图框的宽高比例 需要配合centerBox一起使用才能生效
|
||||
full: boolean // 是否输出原图比例的截图
|
||||
canMoveBox: boolean // 截图框能否拖动
|
||||
original: boolean // 上传图片按照原始比例渲染
|
||||
centerBox: boolean // 截图框是否被限制在图片里面
|
||||
infoTrue: boolean // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
|
||||
}
|
||||
const options: UnwrapNestedRefs<Options> = reactive({
|
||||
img: '', // 需要剪裁的图片
|
||||
autoCrop: true, // 是否默认生成截图框
|
||||
autoCropWidth: 200, // 默认生成截图框的宽度
|
||||
autoCropHeight: 200, // 默认生成截图框的长度
|
||||
fixedBox: false, // 是否固定截图框的大小 不允许改变
|
||||
info: true, // 裁剪框的大小信息
|
||||
outputSize: 1, // 裁剪生成图片的质量 [1至0.1]
|
||||
outputType: 'jpeg', // 裁剪生成图片的格式
|
||||
canScale: false, // 图片是否允许滚轮缩放
|
||||
fixed: true, // 是否开启截图框宽高固定比例
|
||||
fixedNumber: [1, 1], // 截图框的宽高比例 需要配合centerBox一起使用才能生效
|
||||
full: true, // 是否输出原图比例的截图
|
||||
canMoveBox: false, // 截图框能否拖动
|
||||
original: false, // 上传图片按照原始比例渲染
|
||||
centerBox: true, // 截图框是否被限制在图片里面
|
||||
infoTrue: true // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
|
||||
const avatar = computed(() => {
|
||||
return props.img
|
||||
})
|
||||
const previews: Ref<any> = ref({})
|
||||
/** 编辑头像 */
|
||||
const editCropper = () => {
|
||||
dialogVisible.value = true
|
||||
|
||||
const cropperRef = ref()
|
||||
const handelUpload = async ({ data }) => {
|
||||
await uploadAvatarApi({ avatarFile: data })
|
||||
cropperRef.value.close()
|
||||
}
|
||||
/** 向左旋转 */
|
||||
const rotateLeft = () => {
|
||||
cropper.value.rotateLeft()
|
||||
}
|
||||
/** 向右旋转 */
|
||||
const rotateRight = () => {
|
||||
cropper.value.rotateRight()
|
||||
}
|
||||
/** 图片缩放 */
|
||||
const changeScale = (num: number) => {
|
||||
num = num || 1
|
||||
cropper.value.changeScale(num)
|
||||
}
|
||||
// 覆盖默认的上传行为
|
||||
const requestUpload: any = () => {}
|
||||
/** 上传预处理 */
|
||||
const beforeUpload = (file: Blob) => {
|
||||
if (file.type.indexOf('image/') == -1) {
|
||||
ElMessage('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。')
|
||||
} else {
|
||||
const reader = new FileReader()
|
||||
// 转化为base64
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => {
|
||||
if (reader.result) {
|
||||
// 获取到需要剪裁的图片 展示到剪裁框中
|
||||
options.img = reader.result as string
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 上传图片 */
|
||||
const uploadImg = () => {
|
||||
cropper.value.getCropBlob((data: any) => {
|
||||
let formData = new FormData()
|
||||
formData.append('avatarFile', data)
|
||||
uploadAvatarApi(formData).then((res) => {
|
||||
options.img = res
|
||||
window.location.reload()
|
||||
})
|
||||
dialogVisible.value = false
|
||||
cropperVisible.value = false
|
||||
})
|
||||
}
|
||||
/** 实时预览 */
|
||||
const realTime = (data: any) => {
|
||||
previews.value = data
|
||||
}
|
||||
watch(
|
||||
() => props.img,
|
||||
() => {
|
||||
if (props.img) {
|
||||
options.img = props.img
|
||||
previews.value.img = props.img
|
||||
previews.value.url = props.img
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.user-info-head {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
.img-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
.avatar-upload-preview {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
-webkit-transform: translate(50%, -50%);
|
||||
transform: translate(50%, -50%);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
-webkit-box-shadow: 0 0 4px #ccc;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
overflow: hidden;
|
||||
}
|
||||
.user-info-head:hover:after {
|
||||
content: '+';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
color: #eee;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
font-size: 24px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
cursor: pointer;
|
||||
line-height: 110px;
|
||||
border-radius: 50%;
|
||||
<style scoped lang="scss">
|
||||
.change-avatar {
|
||||
img {
|
||||
display: block;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -95,9 +95,8 @@ const handleProcessClick = (
|
||||
message
|
||||
.confirm('确认标记为' + type + '?', t('common.reminder'))
|
||||
.then(async () => {
|
||||
ApiErrorLogApi.updateApiErrorLogPageApi(row.id, processSttatus).then(() => {
|
||||
message.success(t('common.updateSuccess'))
|
||||
})
|
||||
await ApiErrorLogApi.updateApiErrorLogPageApi(row.id, processSttatus)
|
||||
message.success(t('common.updateSuccess'))
|
||||
})
|
||||
.finally(async () => {
|
||||
// 刷新列表
|
||||
|
@ -64,8 +64,8 @@
|
||||
<el-form-item label="存储器" prop="storage">
|
||||
<el-select v-model="form.storage" placeholder="请选择存储器" :disabled="form.id !== 0">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_FILE_STORAGE)"
|
||||
:key="dict.value"
|
||||
v-for="(dict, index) in getIntDictOptions(DICT_TYPE.INFRA_FILE_STORAGE)"
|
||||
:key="index"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
@ -197,7 +197,7 @@ const dialogVisible = ref(false) // 是否显示弹出层
|
||||
const dialogTitle = ref('edit') // 弹出层标题
|
||||
const formRef = ref<FormInstance>() // 表单 Ref
|
||||
const detailData = ref() // 详情 Ref
|
||||
let form = ref<FileConfigApi.FileConfigVO>({
|
||||
const form = ref<FileConfigApi.FileConfigVO>({
|
||||
id: 0,
|
||||
name: '',
|
||||
storage: 0,
|
||||
@ -230,6 +230,28 @@ const setDialogTile = (type: string) => {
|
||||
const handleCreate = (formEl: FormInstance | undefined) => {
|
||||
setDialogTile('create')
|
||||
formEl?.resetFields()
|
||||
form.value = {
|
||||
id: 0,
|
||||
name: '',
|
||||
storage: 0,
|
||||
master: false,
|
||||
visible: false,
|
||||
config: {
|
||||
basePath: '',
|
||||
host: '',
|
||||
port: 0,
|
||||
username: '',
|
||||
password: '',
|
||||
mode: '',
|
||||
endpoint: '',
|
||||
bucket: '',
|
||||
accessKey: '',
|
||||
accessSecret: '',
|
||||
domain: ''
|
||||
},
|
||||
remark: '',
|
||||
createTime: new Date()
|
||||
}
|
||||
}
|
||||
|
||||
// 修改操作
|
||||
|
@ -12,8 +12,7 @@ export const rules = reactive({
|
||||
email: [required],
|
||||
phone: [
|
||||
{
|
||||
min: 11,
|
||||
max: 11,
|
||||
len: 11,
|
||||
trigger: 'blur',
|
||||
message: '请输入正确的手机号码'
|
||||
}
|
||||
|
@ -75,16 +75,15 @@
|
||||
</XModal>
|
||||
</template>
|
||||
<script setup lang="ts" name="Dept">
|
||||
import { nextTick, onMounted, reactive, ref, unref } from 'vue'
|
||||
import { nextTick, onMounted, ref, unref } from 'vue'
|
||||
import { ElSelect, ElTreeSelect, ElOption } from 'element-plus'
|
||||
import { VxeGridInstance } from 'vxe-table'
|
||||
import { handleTree, defaultProps } from '@/utils/tree'
|
||||
import { required } from '@/utils/formRules.js'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
import { useVxeGrid } from '@/hooks/web/useVxeGrid'
|
||||
import { FormExpose } from '@/components/Form'
|
||||
import { allSchemas } from './dept.data'
|
||||
import { allSchemas, rules } from './dept.data'
|
||||
import * as DeptApi from '@/api/system/dept'
|
||||
import { getListSimpleUsersApi, UserVO } from '@/api/system/user'
|
||||
|
||||
@ -107,13 +106,6 @@ const actionLoading = ref(false) // 遮罩层
|
||||
const formRef = ref<FormExpose>() // 表单 Ref
|
||||
const deptOptions = ref() // 树形结构
|
||||
const userOption = ref<UserVO[]>([])
|
||||
// 新增和修改的表单校验
|
||||
const rules = reactive({
|
||||
name: [required],
|
||||
sort: [required],
|
||||
path: [required],
|
||||
status: [required]
|
||||
})
|
||||
|
||||
const getUserList = async () => {
|
||||
const res = await getListSimpleUsersApi()
|
||||
|
@ -1,34 +1,8 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true">
|
||||
<el-form-item label="菜单名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入菜单名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择菜单状态">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<!-- 操作:搜索 -->
|
||||
<XButton
|
||||
type="primary"
|
||||
preIcon="ep:search"
|
||||
:title="t('common.query')"
|
||||
@click="handleQuery()"
|
||||
/>
|
||||
<!-- 操作:重置 -->
|
||||
<XButton preIcon="ep:refresh-right" :title="t('common.reset')" @click="resetQuery()" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<vxe-toolbar>
|
||||
<template #buttons>
|
||||
<!-- 列表 -->
|
||||
<vxe-grid ref="xGrid" v-bind="gridOptions" show-overflow class="xtable-scrollbar">
|
||||
<template #toolbar_buttons>
|
||||
<!-- 操作:新增 -->
|
||||
<XButton
|
||||
type="primary"
|
||||
@ -37,63 +11,30 @@
|
||||
v-hasPermi="['system:menu:create']"
|
||||
@click="handleCreate()"
|
||||
/>
|
||||
<XButton title="展开所有" @click="xTable?.setAllTreeExpand(true)" />
|
||||
<XButton title="关闭所有" @click="xTable?.clearTreeExpand()" />
|
||||
<XButton title="展开所有" @click="xGrid?.setAllTreeExpand(true)" />
|
||||
<XButton title="关闭所有" @click="xGrid?.clearTreeExpand()" />
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
<!-- 列表 -->
|
||||
<vxe-table
|
||||
show-overflow
|
||||
keep-source
|
||||
ref="xTable"
|
||||
:loading="tableLoading"
|
||||
:row-config="{ keyField: 'id' }"
|
||||
:column-config="{ resizable: true }"
|
||||
:tree-config="{ transform: true, rowField: 'id', parentField: 'parentId' }"
|
||||
:print-config="{}"
|
||||
:export-config="{}"
|
||||
:data="tableData"
|
||||
>
|
||||
<vxe-column title="菜单名称" field="name" width="200" tree-node>
|
||||
<template #default="{ row }">
|
||||
<Icon :icon="row.icon" />
|
||||
<span class="ml-3">{{ row.name }}</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="菜单类型" field="type">
|
||||
<template #default="{ row }">
|
||||
<DictTag :type="DICT_TYPE.SYSTEM_MENU_TYPE" :value="row.type" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="路由地址" field="path" />
|
||||
<vxe-column title="组件路径" field="component" />
|
||||
<vxe-column title="权限标识" field="permission" />
|
||||
<vxe-column title="排序" field="sort" />
|
||||
<vxe-column title="状态" field="status">
|
||||
<template #default="{ row }">
|
||||
<DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="创建时间" field="createTime" formatter="formatDate" />
|
||||
<vxe-column title="操作" width="200">
|
||||
<template #default="{ row }">
|
||||
<!-- 操作:修改 -->
|
||||
<XTextButton
|
||||
preIcon="ep:edit"
|
||||
:title="t('action.edit')"
|
||||
v-hasPermi="['system:menu:update']"
|
||||
@click="handleUpdate(row.id)"
|
||||
/>
|
||||
<!-- 操作:删除 -->
|
||||
<XTextButton
|
||||
preIcon="ep:delete"
|
||||
:title="t('action.del')"
|
||||
v-hasPermi="['system:menu:delete']"
|
||||
@click="handleDelete(row.id)"
|
||||
/>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<template #name_default="{ row }">
|
||||
<Icon :icon="row.icon" />
|
||||
<span class="ml-3">{{ row.name }}</span>
|
||||
</template>
|
||||
<template #actionbtns_default="{ row }">
|
||||
<!-- 操作:修改 -->
|
||||
<XTextButton
|
||||
preIcon="ep:edit"
|
||||
:title="t('action.edit')"
|
||||
v-hasPermi="['system:menu:update']"
|
||||
@click="handleUpdate(row.id)"
|
||||
/>
|
||||
<!-- 操作:删除 -->
|
||||
<XTextButton
|
||||
preIcon="ep:delete"
|
||||
:title="t('action.del')"
|
||||
v-hasPermi="['system:menu:delete']"
|
||||
@click="handleDelete(row.id)"
|
||||
/>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</ContentWrap>
|
||||
<!-- 添加或修改菜单对话框 -->
|
||||
<XModal id="menuModel" v-model="dialogVisible" :title="dialogTitle">
|
||||
@ -124,7 +65,7 @@
|
||||
<el-radio-group v-model="menuForm.type">
|
||||
<el-radio-button
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_MENU_TYPE)"
|
||||
:key="dict.value"
|
||||
:key="dict.label"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
@ -178,7 +119,7 @@
|
||||
<el-radio
|
||||
border
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value"
|
||||
:key="dict.label"
|
||||
:label="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
@ -235,7 +176,7 @@
|
||||
</template>
|
||||
<script setup lang="ts" name="Menu">
|
||||
// 全局相关的 import
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
||||
import { useMessage } from '@/hooks/web/useMessage'
|
||||
@ -245,9 +186,7 @@ import {
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
ElInputNumber,
|
||||
ElSelect,
|
||||
ElTreeSelect,
|
||||
ElOption,
|
||||
ElRadio,
|
||||
ElRadioGroup,
|
||||
ElRadioButton,
|
||||
@ -255,21 +194,33 @@ import {
|
||||
} from 'element-plus'
|
||||
import { Tooltip } from '@/components/Tooltip'
|
||||
import { IconSelect } from '@/components/Icon'
|
||||
import { VxeTableInstance } from 'vxe-table'
|
||||
import { VxeGridInstance } from 'vxe-table'
|
||||
// 业务相关的 import
|
||||
import * as MenuApi from '@/api/system/menu'
|
||||
import { required } from '@/utils/formRules.js'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { SystemMenuTypeEnum, CommonStatusEnum } from '@/utils/constants'
|
||||
import { handleTree, defaultProps } from '@/utils/tree'
|
||||
import * as MenuApi from '@/api/system/menu'
|
||||
import { allSchemas, rules } from './menu.data'
|
||||
import { useVxeGrid } from '@/hooks/web/useVxeGrid'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { wsCache } = useCache()
|
||||
// 列表相关的变量
|
||||
const xTable = ref<VxeTableInstance>()
|
||||
const tableLoading = ref(false)
|
||||
const tableData = ref()
|
||||
// 列表相关的变量
|
||||
const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
|
||||
const treeConfig = {
|
||||
transform: true,
|
||||
rowField: 'id',
|
||||
parentField: 'parentId',
|
||||
expandAll: false
|
||||
}
|
||||
const { gridOptions, getList, deleteData } = useVxeGrid<MenuApi.MenuVO>({
|
||||
allSchemas: allSchemas,
|
||||
treeConfig: treeConfig,
|
||||
getListApi: MenuApi.getMenuListApi,
|
||||
deleteApi: MenuApi.deleteMenuApi
|
||||
})
|
||||
// 弹窗相关的变量
|
||||
const dialogVisible = ref(false) // 是否显示弹出层
|
||||
const dialogTitle = ref('edit') // 弹出层标题
|
||||
@ -292,13 +243,6 @@ const menuForm = ref<MenuApi.MenuVO>({
|
||||
keepAlive: true,
|
||||
createTime: new Date()
|
||||
})
|
||||
// 新增和修改的表单校验
|
||||
const rules = reactive({
|
||||
name: [required],
|
||||
sort: [required],
|
||||
path: [required],
|
||||
status: [required]
|
||||
})
|
||||
|
||||
// ========== 下拉框[上级菜单] ==========
|
||||
const menuOptions = ref<any[]>([]) // 树形结构
|
||||
@ -311,31 +255,6 @@ const getTree = async () => {
|
||||
menuOptions.value.push(menu)
|
||||
}
|
||||
|
||||
// ========== 查询 ==========
|
||||
const queryParams = reactive<MenuApi.MenuPageReqVO>({
|
||||
name: undefined,
|
||||
status: undefined
|
||||
})
|
||||
// 执行查询
|
||||
const getList = async () => {
|
||||
tableLoading.value = true
|
||||
const res = await MenuApi.getMenuListApi(queryParams)
|
||||
tableData.value = res
|
||||
tableLoading.value = false
|
||||
}
|
||||
|
||||
// 查询操作
|
||||
const handleQuery = async () => {
|
||||
await getList()
|
||||
}
|
||||
|
||||
// 重置操作
|
||||
const resetQuery = async () => {
|
||||
queryParams.name = undefined
|
||||
queryParams.status = undefined
|
||||
await getList()
|
||||
}
|
||||
|
||||
// ========== 新增/修改 ==========
|
||||
|
||||
// 设置标题
|
||||
@ -407,7 +326,7 @@ const submitForm = async () => {
|
||||
actionLoading.value = false
|
||||
wsCache.delete(CACHE_KEY.ROLE_ROUTERS)
|
||||
// 操作成功,重新加载列表
|
||||
await getList()
|
||||
await getList(xGrid)
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,15 +338,6 @@ const isExternal = (path: string) => {
|
||||
// ========== 删除 ==========
|
||||
// 删除操作
|
||||
const handleDelete = async (rowId: number) => {
|
||||
message.delConfirm().then(async () => {
|
||||
await MenuApi.deleteMenuApi(rowId)
|
||||
message.success(t('common.delSuccess'))
|
||||
await getList()
|
||||
})
|
||||
await deleteData(xGrid, rowId)
|
||||
}
|
||||
|
||||
// ========== 初始化 ==========
|
||||
onMounted(async () => {
|
||||
await getList()
|
||||
})
|
||||
</script>
|
||||
|
75
yudao-ui-admin-vue3/src/views/system/menu/menu.data.ts
Normal file
75
yudao-ui-admin-vue3/src/views/system/menu/menu.data.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { reactive } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { required } from '@/utils/formRules'
|
||||
import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
// 新增和修改的表单校验
|
||||
export const rules = reactive({
|
||||
name: [required],
|
||||
sort: [required],
|
||||
path: [required],
|
||||
status: [required]
|
||||
})
|
||||
|
||||
// CrudSchema
|
||||
const crudSchemas = reactive<VxeCrudSchema>({
|
||||
primaryKey: 'id',
|
||||
primaryType: null,
|
||||
action: true,
|
||||
columns: [
|
||||
{
|
||||
title: '上级菜单',
|
||||
field: 'parentId',
|
||||
isTable: false
|
||||
},
|
||||
{
|
||||
title: '菜单名称',
|
||||
field: 'name',
|
||||
isSearch: true,
|
||||
table: {
|
||||
treeNode: true,
|
||||
align: 'left',
|
||||
width: '200px',
|
||||
slots: {
|
||||
default: 'name_default'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '菜单类型',
|
||||
field: 'type',
|
||||
dictType: DICT_TYPE.SYSTEM_MENU_TYPE
|
||||
},
|
||||
{
|
||||
title: '路由地址',
|
||||
field: 'path'
|
||||
},
|
||||
{
|
||||
title: '组件路径',
|
||||
field: 'component'
|
||||
},
|
||||
{
|
||||
title: '权限标识',
|
||||
field: 'permission'
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
field: 'sort'
|
||||
},
|
||||
{
|
||||
title: t('common.status'),
|
||||
field: 'status',
|
||||
dictType: DICT_TYPE.COMMON_STATUS,
|
||||
dictClass: 'number',
|
||||
isSearch: true
|
||||
},
|
||||
{
|
||||
title: t('common.createTime'),
|
||||
field: 'createTime',
|
||||
formatter: 'formatDate'
|
||||
}
|
||||
]
|
||||
})
|
||||
export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
|
@ -53,7 +53,7 @@
|
||||
:data="detailData"
|
||||
>
|
||||
<template #content="{ row }">
|
||||
<Editor :model-value="row.content" read-only="true" />
|
||||
<Editor :model-value="row.content" :readonly="true" />
|
||||
</template>
|
||||
</Descriptions>
|
||||
<template #footer>
|
||||
|
@ -43,10 +43,7 @@ const crudSchemas = reactive<VxeCrudSchema>({
|
||||
}
|
||||
},
|
||||
form: {
|
||||
component: 'UploadImg',
|
||||
componentProps: {
|
||||
limit: 1
|
||||
}
|
||||
component: 'UploadImg'
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -145,7 +145,7 @@
|
||||
v-for="item in postOptions"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
:value="(item.id as unknown as number)"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
|
@ -10,12 +10,10 @@ export const rules = reactive({
|
||||
username: [required],
|
||||
nickname: [required],
|
||||
email: [required],
|
||||
postIds: [required],
|
||||
status: [required],
|
||||
mobile: [
|
||||
{
|
||||
min: 11,
|
||||
max: 11,
|
||||
len: 11,
|
||||
trigger: 'blur',
|
||||
message: '请输入正确的手机号码'
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"types": [
|
||||
"@intlify/vite-plugin-vue-i18n/client",
|
||||
"@intlify/unplugin-vue-i18n/types",
|
||||
"vite/client",
|
||||
"element-plus/global",
|
||||
"@types/intro.js",
|
||||
|
3
yudao-ui-admin-vue3/types/env.d.ts
vendored
3
yudao-ui-admin-vue3/types/env.d.ts
vendored
@ -10,7 +10,8 @@ declare module '*.vue' {
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_APP_TITLE: string
|
||||
readonly VITE_PORT: number
|
||||
readonly VITE_OPEN: boolean
|
||||
readonly VITE_OPEN: string
|
||||
readonly VITE_ROUTE_ALWAYSSHOW_ENABLE: string
|
||||
readonly VITE_APP_CAPTCHA_ENABLE: string
|
||||
readonly VITE_APP_TENANT_ENABLE: string
|
||||
readonly VITE_BASE_URL: string
|
||||
|
@ -30,7 +30,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||
// 端口号
|
||||
port: env.VITE_PORT,
|
||||
host: "0.0.0.0",
|
||||
open: env.VITE_OPEN,
|
||||
open: env.VITE_OPEN === 'true',
|
||||
// 本地跨域代理
|
||||
proxy: {
|
||||
['/admin-api']: {
|
||||
|
Loading…
Reference in New Issue
Block a user