116 Commits

Author SHA1 Message Date
zhangdaiscott
95ca88b47c 1 2023-02-09 10:03:31 +08:00
zhangdaiscott
30855ad4a0 更新介绍 2023-01-04 15:16:56 +08:00
zhangdaiscott
19931fb273 useForm的getFieldsValue将数组转成字符导致无法读取上传文件 #4330 2022-12-07 16:19:50 +08:00
zhangdaiscott
787e763b9d [issues/248]原生表单内使用图片组件,关闭弹窗图片组件值不会被清空 2022-11-26 10:18:47 +08:00
zhangdaiscott
104e975a13 单选模式取值要改成字符串 2022-11-26 10:18:37 +08:00
zhangdaiscott
136e30360c [issues/215]列表页查询框(日期选择框)设置初始时间,一进入页面时,后台报日期转换类型错误的 2022-11-26 10:16:39 +08:00
zhangdaiscott
c402eec726 【重要升级】3.4.4 online低代码功能,依赖升级 & 升级封装组件库
具体升级内容:
支持高级查询控件
online表单附表支持省市区组件
online表单开发是否支持多租户
online表单,支持快速配置菜单
online报表,支持快速配置菜单
online表单扩展配置优化使用体验
online表单 js增强输入多个hook报错处理
online表单,值规则的JS增强写法执行报错 #251
online表单,用户选择 控件的单选控制没有效果 #242
2022-11-24 10:27:53 +08:00
zhangdaiscott
1b5f6caa41 【代码生成】Tab风格 一对多子表校验不通过时,点击提交表单空白了 2022-11-23 10:08:28 +08:00
zhangdaiscott
7b7bcba3b4 版本要求Node说明 2022-11-22 10:51:18 +08:00
zhangdaiscott
e4c952c81c jeecgboot 3.4.4版本发布 2022-11-18 12:03:27 +08:00
zhangdaiscott
ad08851397 修复写法JSwitch组件直接使用了 props 中定义的value issues/243 2022-11-17 13:49:48 +08:00
zhangdaiscott
2f94ba9ddb 点击外部打开菜单冲掉了当前页面,应该打开新页面 2022-11-16 15:28:36 +08:00
JEECG
f0fd265554 Merge pull request #237 from lm356536/master
feat: 单选按钮组,支持图标icon的扩展,label改为可选
2022-11-14 22:29:00 +08:00
Lm2021
836070b165 feat: 单选按钮组,添加图片的扩展 2022-11-14 21:15:35 +08:00
zhangdaiscott
565957033e JFormContainer组件禁用时无法下载文件 #224 2022-11-14 20:28:04 +08:00
zhangdaiscott
74bf90014d 修复升级vite3导致主题设置无效问题【issues/236】【插件@rys-fe/vite-plugin-theme非官方版,但可以用,后期跟踪vben官方是否更新】
package.json
src\logics\theme\index.ts
src\logics\theme\dark.ts
build\vite\plugin\theme.ts
2022-11-14 20:18:40 +08:00
zhangdaiscott
bc4fbad872 更新yarn lock 2022-11-14 12:14:50 +08:00
zhangdaiscott
04a7630564 build混淆器换成Esbuild & 关闭pnpm严格的对等依赖模式 2022-11-11 11:35:11 +08:00
zhangdaiscott
822b20fb15 更新readme 2022-11-10 15:13:19 +08:00
zhangdaiscott
6f0b9421d9 修改readme 2022-11-10 14:57:32 +08:00
zhangdaiscott
147fb3450c 修改readme 2022-11-10 14:54:08 +08:00
zhangdaiscott
2e199de1aa 修改readme 2022-11-10 14:49:09 +08:00
zhangdaiscott
5a0980e6b0 重复activeKey删除 2022-11-10 14:45:39 +08:00
zhangdaiscott
8890e52e47 切换pnpm安装依赖 2022-11-10 14:45:15 +08:00
zhangdaiscott
7abd3e5204 修复聚合路由问题 2022-11-10 14:31:34 +08:00
zhangdaiscott
32ffd19dc4 同步vben代码,删除作废插件 2022-11-10 14:20:27 +08:00
zhangdaiscott
3c3353da4f 升级到vite3,据说能提升首屏性能,但感觉不明显 2022-11-10 12:06:45 +08:00
zhangdaiscott
78fa18f5aa deep修改 2022-11-09 19:16:09 +08:00
zhangdaiscott
0674a32fe9 下拉多选控件JSelectMultiple,搜索不好使 2022-11-09 16:29:46 +08:00
zhangdaiscott
e59303f3bb 删除两个用不到的依赖 2022-11-09 15:10:21 +08:00
zhangdaiscott
8ffe88ea8b JDictSelectTag 目前选择显示有问题,option选择选项选择后不会正确显示到结果上 #226 2022-11-09 15:08:02 +08:00
zhangdaiscott
d619e7a123 下拉多选时候,搜索不好使 2022-11-09 14:04:41 +08:00
zhangdaiscott
1072347d40 JDictSelectTag 目前选择显示有问题,option选择选项选择后不会正确显示到结果上 #226 2022-11-09 11:50:21 +08:00
JEECG
d8d23560f3 Merge pull request #216 from xiaolinhaha/master
FIX 修复在消息中心,信息模板中编码为空提示重复问题
2022-11-08 23:49:02 +08:00
zhangdaiscott
a9aadae545 antd3升级导致,issues/218 所有功能表单的下拉搜索框搜索无效 2022-11-08 22:08:37 +08:00
zhangdaiscott
503475c7ae Antdv3升级问题,导致表格分页选择失效 issues/4185 2022-11-08 22:03:25 +08:00
zhangdaiscott
79571477cf 表单校验有问题修复,必填的form的validate校验反过来了 #issues/4189 2022-11-08 22:00:25 +08:00
zhangdaiscott
d9eaf06d7d minify警告处理 2022-11-07 19:19:42 +08:00
zhangdaiscott
abdc9da743 系统UI美化 2022-11-07 19:11:34 +08:00
zhangdaiscott
0168d71154 支持多字段排序&表格列字段拖拽 2022-11-07 19:06:04 +08:00
zhangdaiscott
155b817346 修复小问题 2022-11-07 19:05:54 +08:00
zhangdaiscott
6a28a0fa58 deep警告 2022-11-07 19:04:51 +08:00
zhangdaiscott
8309e171d4 【issues/136】同步Vben:BasicTable 调用插入函数异常插入两条记录] 2022-11-07 19:04:24 +08:00
zhangdaiscott
4da6c77856 修复一些小bug 2022-11-07 19:01:49 +08:00
zhangdaiscott
e76080d176 getContainer问题将下拉框、日期等组件挂载到modal上,解决弹窗遮盖问题 2022-11-07 17:52:03 +08:00
zhangdaiscott
1563ae28ad cron表达式控件 # 工作日暂不支持,会报错,先隐藏了 2022-11-07 17:51:37 +08:00
zhangdaiscott
7b0c76d1b1 表单默认宽度修改 2022-11-07 17:33:46 +08:00
zhangdaiscott
ef3cb6a2ad deep警告修改 2022-11-07 17:32:59 +08:00
zhangdaiscott
9889c1ccca 还原 2022-11-07 14:39:14 +08:00
zhangdaiscott
73f1a28df3 表格默认按照id降序排列 2022-11-07 13:35:56 +08:00
zhangdaiscott
602aac5bf0 配置聚合路由的地址时,报系统已存在该值的错误 2022-11-06 22:27:14 +08:00
zhangdaiscott
4a78bef74b 图标本地化,内网也不影响图片渲染 2022-11-06 18:11:00 +08:00
xiaolinhaha
924d26910d FIX 修复在消息中心,信息模板中编码为空提示重复问题 2022-11-04 14:28:05 +08:00
zhangdaiscott
67d937f74f 提醒不支持过低的谷歌浏览器,刷新页面会报错props.ts:15 Uncaught (in promise) SyntaxError: Unexpected token '=' 2022-11-04 10:36:07 +08:00
zhangdaiscott
c9362f142e [issues/183]下拉搜索,使用动态字典,在线页面不报错,生成的代码报错 2022-11-03 16:04:31 +08:00
zhangdaiscott
088f72db62 优化自定义控件,避免报警告(不影响功能) 2022-11-01 19:33:22 +08:00
zhangdaiscott
737312e959 jeecgboot-vue3/issues/181 修复第一次进入时列表配置不能拖拽 2022-11-01 16:40:53 +08:00
zhangdaiscott
5b4a37cf95 online开发,使用部门选择组件时,多个默认参数时,仍然有问题。点击“确认”按钮,没反应。 #4166 2022-11-01 16:34:28 +08:00
zhangdaiscott
b19ddbd449 打包到服务器上,定时任务点“立即执行“报错 #204 2022-10-31 19:12:15 +08:00
zhangdaiscott
f9365883c0 文档调整 2022-10-31 14:20:25 +08:00
zhangdaiscott
5dacdeb939 3.4.3-GA阶段性版本!又升级了,重要的事情说三遍,升级 Online 前端依赖,解决了几个很棒的功能! 2022-10-31 09:37:08 +08:00
zhangdaiscott
b7da59c0b7 判断子菜单是否全部隐藏路由,如果是全部隐藏则隐藏当前菜单图标 2022-10-30 17:56:18 +08:00
zhangdaiscott
c21f4e7f82 前端启动报类型找不到 #200 2022-10-30 11:29:07 +08:00
zhangdaiscott
90e2c6cd68 最新版可以自动切换路由,删除不需要的文档 2022-10-29 00:32:44 +08:00
zhangdaiscott
e581f7f7eb 在线表单》数据库属性模块,对字段跨多字段进行拖拽排序时,无法成功。 #191 2022-10-28 21:08:24 +08:00
zhangdaiscott
166f7e1888 解决: token过期退出重新登录,online菜单还是提示token过期 2022-10-27 23:24:39 +08:00
zhangdaiscott
22e656daf3 解决: token过期退出重新登录,online菜单还是提示token过期 2022-10-27 16:02:23 +08:00
zhangdaiscott
cbe7ea4bb5 关闭Gitee的issue通道,使用中遇到问题或者BUG可以在 Github上提Issues,https://github.com/jeecgboot/jeecgboot-vue3/issues/new 2022-10-27 10:20:58 +08:00
zhangdaiscott
ae55451395 同步lock的依赖版本 2022-10-26 13:53:41 +08:00
zhangdaiscott
ecfe531b3d 非常重要——修复严重bug(访问online菜单报401 token失效)
https://gitee.com/jeecg/jeecgboot-vue3/issues/I5XQ33
https://github.com/jeecgboot/jeecg-boot/issues/4132
2022-10-26 12:39:30 +08:00
zhangdaiscott
6dfcfbcf2a 严重问题,临时方案:暂时还原到上个online lib版本,解决低代码开发下的菜单报401 token失效问题 2022-10-26 11:45:30 +08:00
zhangdaiscott
61d2ff490d 解决 标签页样式更多下拉显示样式错乱问题 2022-10-25 22:15:31 +08:00
zhangdaiscott
300387d380 修改注释 2022-10-25 22:04:11 +08:00
zhangdaiscott
bc9bb7304e 同步vben代码,在本地开发中引入的,以提高浏览器响应速度【目测没啥效果】 2022-10-25 22:04:01 +08:00
zhangdaiscott
6882eef000 1 固定vxe-table-plugin-antd版本,暂时不支持升级
2 更新lock版本号
2022-10-25 12:22:57 +08:00
zhangdaiscott
147055fba2 升级online-lib依赖版本,解决几个重大问题
1、支持关联记录和他表字段控件
2、支持三级联动控件
3、online报表查询支持字典下拉搜索控件
4、online报表查询,字符串类型默认支持模糊查询,不需要输入*
5、online代码生成,支持选择那种前端代码生成(vue3\vue2\vue3原生)
2022-10-25 11:57:31 +08:00
zhangdaiscott
8472f42126 补充注释 2022-10-25 11:12:36 +08:00
zhangdaiscott
335c82e08a 【重要性能问题】解决点击online功能测试,重新加载首页问题 issues/I5XBZF
src\settings\registerThirdComp.ts
src\components\jeecg\comment\useComment.ts
src\components\jeecg\comment\MyComment.vue
src\components\jeecg\comment\DataLogList.vue
src\components\jeecg\comment\CommentList.vue
2022-10-24 18:39:36 +08:00
zhangdaiscott
6bf259427c 解决RangePicker日期选择器异常 issues/I5X0J0 2022-10-21 18:12:23 +08:00
zhangdaiscott
f19a3025e1 解决 issues/I5VXTW 带参数的路由菜单点击右上角刷新报错 2022-10-20 20:49:50 +08:00
zhangdaiscott
fea9146b1a 用户添加按钮不做v-auth控制 2022-10-20 17:49:46 +08:00
zhangdaiscott
1dff1f0d93 博客地址更新 2022-10-19 15:01:13 +08:00
zhangdaiscott
1ae94cf036 技术支持 2022-10-19 14:13:55 +08:00
zhangdaiscott
c112e703b6 高级查询未实现,去掉按钮 2022-10-18 16:57:37 +08:00
zhangdaiscott
455b6672d2 更新文档 2022-10-18 14:38:03 +08:00
zhangdaiscott
616b4c01fb 【新版严重bug】修复Online表单开发自己录入的属性保存不了 issues/I5W9BW 2022-10-18 14:25:37 +08:00
zhangdaiscott
48499d1af7 【新版严重bug】修复Online表单开发自己录入的属性保存不了 issues/I5W9BW 2022-10-18 14:18:42 +08:00
zhangdaiscott
78230e1d0e 【新版严重bug】修复Online表单开发自己录入的属性保存不了 issues/I5W9BW 2022-10-18 14:14:30 +08:00
zhangdaiscott
1213e7e2c8 更新文档 2022-10-17 17:09:02 +08:00
zhangdaiscott
a91c7d39f7 3.4.3 版本发布,低代码功能专项升级 2022-10-17 14:07:16 +08:00
zhangdaiscott
30bfbfc308 gateway情况下,必须有斜杠结尾 2022-10-17 13:53:24 +08:00
zhangdaiscott
c669bee385 文档调整 2022-10-17 13:10:59 +08:00
zhangdaiscott
e7371ddb43 升级vxe-table和lock 2022-10-17 13:04:27 +08:00
zhangdaiscott
2e84090b7d 文档调整 2022-10-16 11:20:03 +08:00
zhangdaiscott
83791978ed 3.4.3 版本发布,低代码功能专项升级 2022-10-14 17:47:32 +08:00
zhangdaiscott
6adeb05d07 3.4.3 版本发布,低代码功能专项升级 2022-10-14 17:20:18 +08:00
zhangdaiscott
908cae7235 3.4.3 版本发布,低代码功能专项升级 2022-10-14 17:12:01 +08:00
zhangdaiscott
c6e48c1c43 表单评论区域功能问题修复 2022-10-14 13:47:24 +08:00
zhangdaiscott
052e63d875 pnpm install 问题解决 2022-10-13 14:34:34 +08:00
zhangdaiscott
6686287991 pnpm install 时出现 ERR_PNPM_INVALID_OVERRIDE_SELECTOR  Cannot parse the "//" selector in the overrides 2022-10-13 14:30:56 +08:00
zhangdaiscott
433a4bfab9 引入依赖错误 2022-10-13 14:28:26 +08:00
zhangdaiscott
23c3ec8294 引入依赖错误 2022-10-13 14:25:56 +08:00
zhangdaiscott
ae5787d1df 项目说明 2022-10-13 10:45:57 +08:00
zhangdaiscott
75029d0a2c 打包提示内存不足 2022-10-13 10:45:42 +08:00
zhangdaiscott
af1fd634f3 项目介绍调整 2022-10-13 09:29:02 +08:00
zhangdaiscott
2db96af605 解决 头部“密码修改”菜单,因代码中接口url少了一个斜杠导致请求错误 2022-10-12 17:54:13 +08:00
zhangdaiscott
d92041fa37 解决routerHelper.ts报错packageViews is not defined #165 2022-10-12 15:36:56 +08:00
zhangdaiscott
91bb10a861 单表示例,加入字段排序和默认排序例子 2022-10-10 11:23:54 +08:00
zhangdaiscott
5b806bc70d 修复【jeecg-boot/issues/I5N2PN】左侧动态菜单怎么做国际化 2022-10-09 17:16:24 +08:00
zhangdaiscott
e036565709 修复[jeecgboot-vue3/issues/I5UMML] chatRef无此引用 2022-10-09 15:17:08 +08:00
zhangdaiscott
d6130b685d online报表动态参数,不生效, 2022-09-29 17:11:27 +08:00
zhangdaiscott
013f6c2e81 Merge branch 'master' of https://github.com/jeecgboot/jeecgboot-vue3 2022-09-29 15:19:37 +08:00
JEECG
3ac00df8e5 Merge pull request #155 from WalkingMoonWell/master
修复上传附件(JUpload)在returnUrl为false多文件上传时附件数错误的问题
2022-09-29 15:19:01 +08:00
zhangdaiscott
c968aac7ed JVxeTypes.selectDictSearch sync问题 2022-09-29 15:11:45 +08:00
zhangdaiscott
8e33da231e vertical 布局时页面布局显示错乱问题解决 2022-09-29 15:06:50 +08:00
heqin
43db6d8b2e 修复上传附件(JUpload)在returnUrl为false多文件上传时附件数错误的问题 2022-09-21 19:38:52 +08:00
142 changed files with 27100 additions and 51467 deletions

2
.npmrc Normal file
View File

@@ -0,0 +1,2 @@
shamefully-hoist=true
strict-peer-dependencies=false

View File

@@ -4,8 +4,8 @@ VOLUME /tmp
ENV LANG en_US.UTF-8
RUN echo "server { \
listen 80; \
location /jeecgboot { \
proxy_pass http://jeecg-boot-system:8080/jeecg-boot; \
location /jeecgboot/ { \
proxy_pass http://jeecg-boot-system:8080/jeecg-boot/; \
proxy_redirect off; \
proxy_set_header Host jeecg-boot-system; \
proxy_set_header X-Real-IP \$remote_addr; \
@@ -27,4 +27,4 @@ RUN echo "server { \
ADD dist/ /var/www/html/
EXPOSE 80
EXPOSE 443
EXPOSE 443

161
README.md
View File

@@ -1,57 +1,55 @@
JEECG BOOT 低代码开发平台Vue3前端
===============
当前最新版本: 3.4.2发布时间20220922
> 变更大版本号与后台同步 3.3.X后续单独发布版本会更新小版本号。
当前最新版本: 3.4.4发布时间2022-11-21
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://my.oschina.net/jeecg)
[![](https://img.shields.io/badge/version-3.4.2-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/Author-北京敲敲云科技-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.4.4-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
## 简介
JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue、TypeScript 等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。
Vben-Admin 基础上研发的适合于JeecgBoot低代码平台的VUE3版前端解决方案目前已是稳定版本可用于生产项目
JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue3、TypeScript 等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。
采用Vben实现的 JeecgBoot低代码平台的全新vue3版本
> 强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性
## 项目源码
## 技术支持
| 仓库 |前端源码Vue3版 | 前端源码Vue2版 | 后端源码 |
|-|-|-|-|
| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3) | [ant-design-vue-jeecg](https://github.com/jeecgboot/ant-design-vue-jeecg) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) |
| 码云 | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3) | [ant-design-vue-jeecg](https://gitee.com/jeecg/ant-design-vue-jeecg) | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) |
关闭Gitee的issue通道使用中遇到问题或者BUG可以在 [Github上提Issues](https://github.com/jeecgboot/jeecgboot-vue3/issues/new)
官方支持: http://jeecg.com/doc/help
## 源码下载
- 后台源码 https://github.com/jeecgboot/jeecg-boot
- 前端源码 https://github.com/jeecgboot/jeecgboot-vue3
##### 项目说明
| 项目名 | 说明 |
|--------------------|------------------------|
| `jeecgboot-vue3` | Vue3版前端代码 |
| `jeecg-boot` | JAVA后台(支持微服务) |
| `ant-design-vue-jeecg` |Vue2版前端代码 |
> 入门必看>>[切换Vue3路由](http://vue3.jeecg.com/2671576)
| `jeecg-boot` | SpringBoot后台项目(支持微服务) |
## 技术文档
- 开发文档:[http://vue3.jeecg.com](http://vue3.jeecg.com)
- 官方文档:[http://vue3.jeecg.com](http://vue3.jeecg.com)
- 官方网站: [http://www.jeecg.com](http://www.jeecg.com)
- 在线演示:[http://boot3.jeecg.com](http://boot3.jeecg.com)
- 快速入门:[入门视频](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://vue3.jeecg.com/2677352)
- 在线演示:[低代码演示](http://boot3.jeecg.com) | [敲敲云零代码](https://www.qiaoqiaoyun.com)
- 快速入门:[常见问题](http://vue3.jeecg.com/2426559) | [入门视频](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://vue3.jeecg.com/2677352)
- QQ交流群683903138
## 安装与使用
> 环境要求: Node.js版本要求12.x以上且不能为13.x版本这里推荐14.x及以上
> 环境要求: 版本要求Node 14.18+ / 16+ 版本以上,不再支持 Node 12 / 13 / 15
> 建议使用pnpm如果使用yarn,请用Yarn1.x版本否则依赖可能安装不上。
- Get the project code
@@ -65,26 +63,30 @@ git clone https://github.com/jeecgboot/jeecgboot-vue3.git
```bash
cd jeecgboot-vue3
yarn install
pnpm install
```
- 配置后台接口地址
- 配置接口地址 `.env.development`
```bash
.env.development
VITE_PROXY = [["/jeecgboot","http://localhost:8080/jeecg-boot"],["/upload","http://localhost:3300/upload"]]
VITE_GLOB_DOMAIN_URL=http://localhost:8080/jeecg-boot
```
> 说明:把`http://localhost:8080/jeecg-boot` 换成自己地址,其他不用改。
- run
```bash
yarn serve
pnpm serve
```
- build
```bash
yarn build
pnpm build
```
@@ -92,11 +94,13 @@ yarn build
- host设置
>注意: 需要把`127.0.0.1`替换成真实IP 比如`192.`开头,不然后端不通。
```bash
127.0.0.1 jeecg-boot-system
127.0.0.1 jeecg-boot-gateway
```
>注意: 需要把`127.0.0.1`替换成真实IP 比如`192.`开头,不然后端不通。
- 下载项目
@@ -104,10 +108,9 @@ yarn build
git clone https://github.com/jeecgboot/jeecgboot-vue3.git
cd jeecgboot-vue3
```
- 修改后台域名
.env.production
- 配置接口域名 `.env.production`
```bash
VITE_GLOB_API_URL=/jeecgboot
@@ -118,9 +121,9 @@ VITE_GLOB_DOMAIN_URL=http://jeecg-boot-system:8080/jeecg-boot
- 编译项目
```bash
yarn install
pnpm install
yarn build
pnpm build
```
- 启动容器
@@ -160,6 +163,42 @@ VITE_GLOB_DOMAIN_URL=http://jeecg-boot-gateway:9999
```
## 入门必备
本项目需要一定前端基础知识,请确保掌握 Vue 的基础知识,以便能处理一些常见的问题。 建议在开发前先学一下以下内容,提前了解和学习这些知识,会对项目理解非常有帮助:
* [JeecgBoot-Vue3文档](http://vue3.jeecg.com)
* [Vue3 文档](https://cn.vuejs.org/)
* [Vben文档](https://doc.vvbin.cn)
* [Ant-Design-Vue](https://www.antdv.com/docs/vue/introduce-cn/)
* [TypeScript](https://www.typescriptlang.org/)
* [Vue-router](https://router.vuejs.org/zh)
* [Es6](https://es6.ruanyifeng.com/)
* [Vitejs](https://cn.vitejs.dev/guide/)
* [Pinia(vuex替代方案)](https://pinia.esm.dev/introduction.html)
* [Vue-RFCS](https://github.com/vuejs/rfcs)
* [Vue2 迁移到 3](https://v3.vuejs.org/guide/migration/introduction.html)
* [vxetable文档](https://vxetable.cn)
* [~~WindiCss~~](https://windicss.netlify.app/)
## 浏览器支持
**本地开发**推荐使用`Chrome 最新版`浏览器,**不支持**`Chrome 90`以下版本。
**生产环境**支持现代浏览器,不支持 IE。
| [![IE](https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png)](http://godban.github.io/browsers-support-badges/)IE | [![ Edge](https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png)](http://godban.github.io/browsers-support-badges/)Edge | [![Firefox](https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png)](http://godban.github.io/browsers-support-badges/)Firefox | [![Chrome](https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png)](http://godban.github.io/browsers-support-badges/)Chrome | [![Safari](https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png)](http://godban.github.io/browsers-support-badges/)Safari |
| --- | --- | --- | --- | --- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
## 功能模块
> vue3版本已经实现了系统管理、系统监控、报表、各种组件、前端权限、GUI代码生成、Online表单、Online报表等平台功能完全可以用于生产环境。
@@ -269,11 +308,9 @@ VITE_GLOB_DOMAIN_URL=http://jeecg-boot-gateway:9999
│ ├─Online在线表单 - 功能已开放
│ ├─Online代码生成器 - 功能已开放
│ ├─Online在线报表 - 功能已开放
│ ├─Online在线图表(未开源)
│ ├─Online图表模板配置(未开源)
├─Online布局设计(未开源)
│ ├─多数据源管理 - 功能已开放
│─流程模块功能 (未开源)
│ ├─Online在线图表(未开源)
│ ├─多数据源管理
─流程模块功能 (暂未开源)
│ ├─流程设计器
│ ├─表单设计器
│ ├─大屏设计器
@@ -287,18 +324,13 @@ VITE_GLOB_DOMAIN_URL=http://jeecg-boot-gateway:9999
│ └─我发起的流程
│ └─我的抄送
│ └─流程委派、抄送、跳转
│ └─。。。
│─OA办公组件 (未开源)
│ ├─更多功能
│ └─。。。
└─其他模块 (暂不开源)
│ └─OA办公组件
└─其他模块
└─更多功能开发中。。
```
## 系统效果
系统后台
@@ -335,12 +367,6 @@ Online表单&Online报表&代码生成
![](https://static.oschina.net/uploads/img/201904/14160633_u59G.png "")
![](https://static.oschina.net/uploads/img/201907/05165142_yyQ7.png "")
报表设计
![](https://oscimg.oschina.net/oscnet/up-da89eb034b8583d57b3f61493fec313ed28.png)
![](https://oscimg.oschina.net/oscnet/up-35deca9d020d61ad464accfdeb3bb90ba5c.png)
![](https://oscimg.oschina.net/oscnet/up-d1695b4a53ebbc9e9651e309e5af1c8bd30.png)
![](https://oscimg.oschina.net/oscnet/up-4cc634b612e97f08ab702ef34f2ede53f2a.png)
大屏模板
@@ -353,32 +379,3 @@ Online表单&Online报表&代码生成
## 入门必备
本项目需要一定前端基础知识,请确保掌握 Vue 的基础知识,以便能处理一些常见的问题。 建议在开发前先学一下以下内容,提前了解和学习这些知识,会对项目理解非常有帮助:
* [Vue3 文档](https://v3.vuejs.org/)
* [TypeScript](https://www.typescriptlang.org/)
* [Vue-router](https://next.router.vuejs.org/)
* [Ant-Design-Vue](https://2x.antdv.com/docs/vue/introduce-cn/)
* [Vben文档](https://vvbin.cn/doc-next)
* [Es6](https://es6.ruanyifeng.com/)
* [Vitejs](https://vitejs.dev/)
* [Pinia(vuex替代方案)](https://pinia.esm.dev/introduction.html)
* [Vue-RFCS](https://github.com/vuejs/rfcs)
* [Vue2 迁移到 3](https://v3.vuejs.org/guide/migration/introduction.html)
* [~~WindiCss~~](https://windicss.netlify.app/)
## 浏览器支持
**本地开发**推荐使用`Chrome 最新版`浏览器,**不支持**`Chrome 80`以下版本。
**生产环境**支持现代浏览器,不支持 IE。
| [![IE](https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png)](http://godban.github.io/browsers-support-badges/)IE | [![ Edge](https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png)](http://godban.github.io/browsers-support-badges/)Edge | [![Firefox](https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png)](http://godban.github.io/browsers-support-badges/)Firefox | [![Chrome](https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png)](http://godban.github.io/browsers-support-badges/)Chrome | [![Safari](https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png)](http://godban.github.io/browsers-support-badges/)Safari |
| --- | --- | --- | --- | --- |
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |

View File

@@ -1,21 +0,0 @@
// TODO
import type { GetManualChunk } from 'rollup';
//
const vendorLibs: { match: string[]; output: string }[] = [
// {
// match: ['xlsx'],
// output: 'xlsx',
// },
];
// @ts-ignore
export const configManualChunk: GetManualChunk = (id: string) => {
if (/[\\/]node_modules[\\/]/.test(id)) {
const matchItem = vendorLibs.find((item) => {
const reg = new RegExp(`[\\/]node_modules[\\/]_?(${item.match.join('|')})(.*)`, 'ig');
return reg.test(id);
});
return matchItem ? matchItem.output : null;
}
};

View File

@@ -1,25 +0,0 @@
import type { Plugin } from 'vite';
/**
* TODO
* Temporarily solve the Vite circular dependency problem, and wait for a better solution to fix it later. I don't know what problems this writing will bring.
* @returns
*/
export function configHmrPlugin(): Plugin {
return {
name: 'singleHMR',
handleHotUpdate({ modules, file }) {
if (file.match(/xml$/)) return [];
modules.forEach((m) => {
if (!m.url.match(/\.(css|less)/)) {
m.importedModules = new Set();
m.importers = new Set();
}
});
return modules;
},
};
}

View File

@@ -15,6 +15,8 @@ import { configVisualizerConfig } from './visualizer';
import { configThemePlugin } from './theme';
import { configImageminPlugin } from './imagemin';
import { configSvgIconsPlugin } from './svgSprite';
import OptimizationPersist from 'vite-plugin-optimize-persist'
import PkgConfig from 'vite-plugin-package-config'
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const { VITE_USE_IMAGEMIN, VITE_USE_MOCK, VITE_LEGACY, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv;
@@ -71,5 +73,8 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
vitePlugins.push(configPwaConfig(viteEnv));
}
//vite-plugin-theme【解决vite首次打开界面加载慢问题】
vitePlugins.push(PkgConfig());
vitePlugins.push(OptimizationPersist());
return vitePlugins;
}

View File

@@ -5,9 +5,9 @@
import { createStyleImportPlugin } from 'vite-plugin-style-import';
export function configStyleImportPlugin(_isBuild: boolean) {
// if (!isBuild) {
// return [];
// }
if (!_isBuild) {
return [];
}
const styleImportPlugin = createStyleImportPlugin({
libs: [
{

View File

@@ -4,7 +4,7 @@
*/
import type { PluginOption } from 'vite';
import path from 'path';
import { viteThemePlugin, antdDarkThemePlugin, mixLighten, mixDarken, tinycolor } from 'vite-plugin-theme';
import { viteThemePlugin, antdDarkThemePlugin, mixLighten, mixDarken, tinycolor } from '@rys-fe/vite-plugin-theme';
import { getThemeColors, generateColors } from '../../config/themeConfig';
import { generateModifyVars } from '../../generate/generateModifyVars';

View File

@@ -1,16 +0,0 @@
## 切换到 Vue3菜单路由
- 第一步执行SQL脚本
```
alter table sys_permission rename as sys_permission_v2;
alter table sys_permission_v3 rename as sys_permission;
```
> 这个 sql 脚本做了什么?
> - 1、把表名 sys_permission 备份改为 sys_permission_v2
> - 2、把 sys_permission_v3 改为 sys_permission
> 说明:因为 vue3 和 vue2 的菜单配置不一样,所以通过切换表来实现 vue3 和 vue2 的切换。
- 第二步:登录进系统
> 从 jeecgboot3.3.0 版本默认 vue3 和 vue2 的权限都已经分配好, 不需要再手工授权。

View File

@@ -1,13 +1,13 @@
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
const modules = import.meta.globEager('./**/*.ts');
const modules = import.meta.glob('./**/*.ts', { eager: true });
const mockModules: any[] = [];
Object.keys(modules).forEach((key) => {
if (key.includes('/_')) {
return;
}
mockModules.push(...modules[key].default);
mockModules.push(...(modules as Recordable)[key].default);
});
/**

41497
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,25 @@
{
"name": "jeecgboot-vue3",
"version": "3.4.2",
"version": "3.4.4",
"author": {
"name": "jeecg",
"email": "jeecgos@163.com",
"url": "https://github.com/jeecgboot/jeecgboot-vue3"
},
"scripts": {
"bootstrap": "yarn install",
"bootstrap": "pnpm install",
"serve": "npm run dev",
"dev": "vite",
"clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
"clean:lib": "rimraf node_modules",
"build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 vite build && esno ./build/script/postBuild.ts",
"build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts",
"build:no-cache": "yarn clean:cache && npm run build",
"build:test": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build --mode test && esno ./build/script/postBuild.ts",
"build:no-cache": "pnpm clean:cache && npm run build",
"report": "cross-env REPORT=true npm run build",
"type:check": "vue-tsc --noEmit --skipLibCheck",
"preview": "npm run build && vite preview",
"preview:dist": "vite preview",
"log": "conventional-changelog -p angular -i CHANGELOG.md -s",
"clean:lib": "rimraf node_modules",
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
@@ -29,12 +29,12 @@
"test:unit-coverage": "jest --coverage",
"test:gzip": "http-server dist --cors --gzip -c-1",
"test:br": "http-server dist --cors --brotli -c-1",
"reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
"reinstall": "rimraf pnpm-lock.yaml && yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
"prepare": "husky install",
"gen:icon": "esno ./build/generate/icon/index.ts"
},
"dependencies": {
"@jeecg/online": "1.0.1",
"@jeecg/online": "3.4.4-RC",
"@iconify/iconify": "^2.2.1",
"@ant-design/colors": "^6.0.0",
"@ant-design/icons-vue": "^6.1.0",
@@ -45,7 +45,7 @@
"@vueuse/shared": "^8.3.0",
"@vueuse/core": "^8.3.0",
"@zxcvbn-ts/core": "^2.0.1",
"ant-design-vue": "3.2.12",
"ant-design-vue": "^3.2.12",
"axios": "^0.26.1",
"china-area-data": "^5.0.1",
"clipboard": "^2.0.8",
@@ -59,10 +59,8 @@
"emoji-mart-vue-fast": "^11.1.1",
"enquire.js": "^2.1.6",
"intro.js": "^5.1.0",
"js-cookie": "^2.2.1",
"lodash-es": "^4.17.21",
"lodash.get": "^4.4.2",
"lodash.pick": "^4.4.0",
"md5": "^2.3.0",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
@@ -87,7 +85,7 @@
"vue-types": "^4.1.1",
"vuedraggable": "^4.1.0",
"vxe-table": "4.1.0",
"vxe-table-plugin-antd": "^3.0.5",
"vxe-table-plugin-antd": "3.0.5",
"xe-utils": "^3.3.1",
"vue-json-pretty": "^2.0.6",
"xss": "^1.0.13"
@@ -113,8 +111,8 @@
"@types/sortablejs": "^1.10.7",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"@vitejs/plugin-legacy": "^1.8.1",
"@vitejs/plugin-vue": "^2.3.1",
"@vitejs/plugin-legacy": "^2.0.0",
"@vitejs/plugin-vue": "^3.0.1",
"@vitejs/plugin-vue-jsx": "^1.3.10",
"@vue/compiler-sfc": "^3.2.33",
"@vue/test-utils": "^2.0.0-rc.21",
@@ -159,28 +157,27 @@
"ts-jest": "^27.0.7",
"ts-node": "^10.7.0",
"typescript": "^4.6.3",
"vite": "^2.9.5",
"vite": "^3.0.2",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0",
"vite-plugin-imagemin": "^0.6.1",
"vite-plugin-mkcert": "1.6.0",
"vite-plugin-mkcert": "^1.10.1",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-optimize-persist": "^0.1.2",
"vite-plugin-package-config": "^0.1.1",
"vite-plugin-purge-icons": "^0.8.1",
"vite-plugin-pwa": "^0.11.13",
"vite-plugin-purge-icons": "^0.8.2",
"vite-plugin-pwa": "^0.12.3",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-theme": "^0.8.6",
"@rys-fe/vite-plugin-theme": "^0.8.6",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vite-plugin-windicss": "^1.8.4",
"vite-plugin-windicss": "^1.8.7",
"vue-eslint-parser": "^8.3.0",
"vue-tsc": "^0.33.9"
},
"resolutions": {
"//": "Used to install imagemin dependencies, because imagemin may not be installed in China. If it is abroad, you can delete it",
"bin-wrapper": "npm:bin-wrapper-china",
"rollup": "^2.56.3"
"rollup": "^2.72.0"
},
"repository": {
"type": "git",

16279
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

BIN
src/assets/images/link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -120,7 +120,7 @@
-webkit-transition: opacity 0.4s;
transition: opacity 0.4s;
::v-deep(svg) {
:deep(svg) {
margin: auto;
}
}

View File

@@ -113,15 +113,28 @@
const getSchema = computed((): FormSchema[] => {
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any);
for (const schema of schemas) {
const { defaultValue, component } = schema;
const { defaultValue, component, componentProps } = schema;
// handle date type
if (defaultValue && dateItemType.includes(component)) {
const { valueFormat } = componentProps
if (!Array.isArray(defaultValue)) {
schema.defaultValue = dateUtil(defaultValue);
//update-begin---author:wangshuai ---date:20221124 for[issues/215]列表页查询框(日期选择框)设置初始时间,一进入页面时,后台报日期转换类型错误的------------
if(valueFormat){
schema.defaultValue = dateUtil(defaultValue).format(valueFormat);
}else{
schema.defaultValue = dateUtil(defaultValue);
}
//update-end---author:wangshuai ---date:20221124 for[issues/215]列表页查询框(日期选择框)设置初始时间,一进入页面时,后台报日期转换类型错误的------------
} else {
const def: dayjs.Dayjs[] = [];
defaultValue.forEach((item) => {
def.push(dateUtil(item));
//update-begin---author:wangshuai ---date:20221124 for[issues/215]列表页查询框(日期选择框)设置初始时间,一进入页面时,后台报日期转换类型错误的------------
if(valueFormat){
def.push(dateUtil(item).format(valueFormat));
}else{
def.push(dateUtil(item));
}
//update-end---author:wangshuai ---date:20221124 for[issues/215]列表页查询框(日期选择框)设置初始时间,一进入页面时,后台报日期转换类型错误的------------
});
schema.defaultValue = def;
}
@@ -322,7 +335,24 @@
}
}
}
/*【美化表单】form的字体改小一号*/
.ant-form-item-label > label{
font-size: 13px;
}
.ant-form-item .ant-select {
font-size: 13px;
}
.ant-select-item-option-selected {
font-size: 13px;
}
.ant-select-item-option-content {
font-size: 13px;
}
.ant-input {
font-size: 13px;
}
/*【美化表单】form的字体改小一号*/
.ant-form-explain {
font-size: 14px;
}

View File

@@ -58,6 +58,7 @@ import JSearchSelect from './jeecg/components/JSearchSelect.vue';
import JAddInput from './jeecg/components/JAddInput.vue';
import { Time } from '/@/components/Time';
import JRangeNumber from './jeecg/components/JRangeNumber.vue';
import JRangeDate from './jeecg/components/JRangeDate.vue'
const componentMap = new Map<ComponentType, Component>();
@@ -125,6 +126,7 @@ componentMap.set('JUpload', JUpload);
componentMap.set('JSearchSelect', JSearchSelect);
componentMap.set('JAddInput', JAddInput);
componentMap.set('JRangeNumber', JRangeNumber);
componentMap.set('RangeDate', JRangeDate);
export function add(compName: ComponentType, component: Component) {
componentMap.set(compName, component);

View File

@@ -5,7 +5,8 @@
<RadioGroup v-bind="attrs" v-model:value="state" button-style="solid">
<template v-for="item in getOptions" :key="`${item.value}`">
<RadioButton :value="item.value" :disabled="item.disabled">
{{ item.label }}
<Icon v-if="item.icon" :icon="item.icon" />
{{ item.label ? item.label : '' }}
</RadioButton>
</template>
</RadioGroup>
@@ -16,8 +17,13 @@
import { isString } from '/@/utils/is';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useAttrs } from '/@/hooks/core/useAttrs';
type OptionsItem = { label: string; value: string | number | boolean; disabled?: boolean };
import { Icon } from '/@/components/Icon';
type OptionsItem = {
icon?: string;
label?: string;
value: string | number | boolean;
disabled?: boolean;
};
type RadioItem = string | OptionsItem;
export default defineComponent({
@@ -25,6 +31,7 @@
components: {
RadioGroup: Radio.Group,
RadioButton: Radio.Button,
Icon,
},
props: {
value: {

View File

@@ -6,6 +6,9 @@ import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
import { isProdMode } from '/@/utils/env';
import { error } from '/@/utils/log';
import { getDynamicProps, getValueType } from '/@/utils';
import { add } from "/@/components/Form/src/componentMap";
//集成online专用控件
import { OnlineSelectCascade, LinkTableCard, LinkTableSelect } from '@jeecg/online';
export declare type ValidateFields = (nameList?: NamePath[]) => Promise<Recordable>;
@@ -15,6 +18,11 @@ export function useForm(props?: Props): UseFormReturnType {
const formRef = ref<Nullable<FormActionType>>(null);
const loadedRef = ref<Nullable<boolean>>(false);
//集成online专用控件
add("OnlineSelectCascade", OnlineSelectCascade)
add("LinkTableCard", LinkTableCard)
add("LinkTableSelect", LinkTableSelect)
async function getForm() {
const form = unref(formRef);
if (!form) {
@@ -89,7 +97,12 @@ export function useForm(props?: Props): UseFormReturnType {
if(values){
Object.keys(values).map(key=>{
if (values[key] instanceof Array) {
values[key] = values[key].join(',');
// update-begin-author:sunjianlei date:20221205 for: 【issues/4330】判断如果是对象数组则不拼接
let isObject = typeof (values[key][0] || '') === 'object';
if (!isObject) {
values[key] = values[key].join(',');
}
// update-end-author:sunjianlei date:20221205 for: 【issues/4330】判断如果是对象数组则不拼接
}
});
}

View File

@@ -251,7 +251,11 @@ export function useFormEvents({
const res = handleFormValues(values);
emit('submit', res);
} catch (error) {
throw new Error(error);
//update-begin-author:taoyan date:2022-11-4 for: 列表查询表单会触发校验错误导致重置失败,原因不明
emit('submit', {});
console.error('query form validate error, please ignore!', error)
//throw new Error(error);
//update-end-author:taoyan date:2022-11-4 for: 列表查询表单会触发校验错误导致重置失败,原因不明
}
}

View File

@@ -10,7 +10,7 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<
const { labelCol = {}, wrapperCol = {} } = schemaItem.itemProps || {};
const { labelWidth, disabledLabelWidth } = schemaItem;
const { labelWidth: globalLabelWidth, labelCol: globalLabelCol, wrapperCol: globWrapperCol } = unref(propsRef);
const { labelWidth: globalLabelWidth, labelCol: globalLabelCol, wrapperCol: globWrapperCol,layout } = unref(propsRef);
// update-begin--author:sunjianlei---date:20211104---for: 禁用全局 labelWidth不自动设置 textAlign --------
if (disabledLabelWidth) {
@@ -34,8 +34,11 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<
}
return {
labelCol: { style: { width }, ...col },
wrapperCol: { style: { width: `calc(100% - ${width})` }, ...wrapCol },
labelCol: { style: { width: width ? width : '100%' }, ...col },
wrapperCol: {
style: { width: layout === 'vertical' ? '100%' : `calc(100% - ${width})` },
...wrapCol,
},
};
});
}

View File

@@ -58,8 +58,7 @@
}
function handleChange(array, ...args) {
emitData.value = args;
console.info(emitData);
// emitData.value = args;
//update-begin-author:taoyan date:2022-6-27 for: VUEN-1424【vue3】树表、单表、jvxe、erp 、内嵌子表省市县 选择不上
// 上面改的v-model:value导致选中数据没有显示
state.value = array;

View File

@@ -1,24 +1,26 @@
<template>
<div class="area-select">
<!--省份-->
<a-select v-model:value="province" @change="proChange" allowClear :disabled="disabled">
<template v-for="item in provinceOptions" :key="`${item.value}`">
<a-select-option :value="item.value">{{ item.label }}</a-select-option>
</template>
</a-select>
<!--城市-->
<a-select v-if="level >= 2" v-model:value="city" @change="cityChange" :disabled="disabled">
<template v-for="item in cityOptions" :key="`${item.value}`">
<a-select-option :value="item.value">{{ item.label }}</a-select-option>
</template>
</a-select>
<!--地区-->
<a-select v-if="level >= 3" v-model:value="area" @change="areaChange" :disabled="disabled">
<template v-for="item in areaOptions" :key="`${item.value}`">
<a-select-option :value="item.value">{{ item.label }}</a-select-option>
</template>
</a-select>
</div>
<a-form-item-rest>
<div class="area-select">
<!--省份-->
<a-select v-model:value="province" @change="proChange" allowClear :disabled="disabled">
<template v-for="item in provinceOptions" :key="`${item.value}`">
<a-select-option :value="item.value">{{ item.label }}</a-select-option>
</template>
</a-select>
<!--城市-->
<a-select v-if="level >= 2" v-model:value="city" @change="cityChange" :disabled="disabled">
<template v-for="item in cityOptions" :key="`${item.value}`">
<a-select-option :value="item.value">{{ item.label }}</a-select-option>
</template>
</a-select>
<!--地区-->
<a-select v-if="level >= 3" v-model:value="area" @change="areaChange" :disabled="disabled">
<template v-for="item in areaOptions" :key="`${item.value}`">
<a-select-option :value="item.value">{{ item.label }}</a-select-option>
</template>
</a-select>
</div>
</a-form-item-rest>
</template>
<script lang="ts">
import { defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted, onUnmounted, toRefs } from 'vue';
@@ -35,8 +37,17 @@
area: [String],
level: propTypes.number.def(3),
disabled: propTypes.bool.def(false),
codeField: propTypes.string,
size: propTypes.string,
placeholder: propTypes.string,
formValues: propTypes.any,
allowClear: propTypes.bool.def(false),
getPopupContainer: {
type: Function,
default: (node) => node.parentNode,
},
},
emits: ['change', 'update:value'],
emits: ['change', 'update:value','update:area','update:city','update:province'],
setup(props, { emit, refs }) {
const emitData = ref<any[]>([]);
//下拉框的选择值

View File

@@ -76,7 +76,8 @@
console.info(props);
const emitData = ref<any[]>([]);
const treeData = ref<any[]>([]);
const treeValue = ref('');
const treeValue = ref();
treeValue.value = '';
const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
watch(
@@ -118,7 +119,11 @@
function loadItemByCode() {
if (!props.value || props.value == '0') {
treeValue.value = [];
if(props.multiple){
treeValue.value = [];
}else{
treeValue.value = '';
}
} else {
loadDictItem({ ids: props.value }).then((res) => {
let values = props.value.split(',');
@@ -127,6 +132,9 @@
value: values[index],
label: item,
}));
if(!props.multiple){
treeValue.value = treeValue.value[0];
}
onLoadTriggleChange(res[0]);
});
}

View File

@@ -197,6 +197,15 @@
});
const getBindValue = Object.assign({}, unref(props), unref(attrs));
//update-begin-author:taoyan date:2022-10-18 for: VUEN-2480【严重bug】online vue3测试的问题 8、online js增强样式问题
function refresh(){
if(coder){
coder.refresh();
}
}
//update-end-author:taoyan date:2022-10-18 for: VUEN-2480【严重bug】online vue3测试的问题 8、online js增强样式问题
return {
state,
textarea,
@@ -206,6 +215,7 @@
isFullScreen,
fullScreenIcon,
onToggleFullScreen,
refresh
};
},
});
@@ -279,5 +289,10 @@
height: 100%;
}
}
/** VUEN-2344【vue3】这个样式有问题是不是加个边框 */
.CodeMirror{
border: 1px solid #ddd;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<a-radio-group v-if="compType === CompTypeEnum.Radio" v-bind="attrs" v-model:value="state" @change="handleChange">
<a-radio-group v-if="compType === CompTypeEnum.Radio" v-bind="attrs" v-model:value="state" @change="handleChangeRadio">
<template v-for="item in dictOptions" :key="`${item.value}`">
<a-radio :value="item.value">
{{ item.label }}
@@ -7,7 +7,13 @@
</template>
</a-radio-group>
<a-radio-group v-else-if="compType === CompTypeEnum.RadioButton" v-bind="attrs" v-model:value="state" buttonStyle="solid" @change="handleChange">
<a-radio-group
v-else-if="compType === CompTypeEnum.RadioButton"
v-bind="attrs"
v-model:value="state"
buttonStyle="solid"
@change="handleChangeRadio"
>
<template v-for="item in dictOptions" :key="`${item.value}`">
<a-radio-button :value="item.value">
{{ item.label }}
@@ -44,7 +50,6 @@
</template>
<script lang="ts">
import { defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted, nextTick } from 'vue';
import { Form } from 'ant-design-vue';
import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { initDictOptions } from '/@/utils/dict';
@@ -78,11 +83,9 @@
},
emits: ['options-change', 'change'],
setup(props, { emit, refs }) {
const { onFieldChange } = Form.useInjectFormItemContext();
const emitData = ref<any[]>([]);
const dictOptions = ref<any[]>([]);
const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData);
const [state, , , formItemContext] = useRuleFormItem(props, 'value', 'change');
const getBindValue = Object.assign({}, unref(props), unref(attrs));
// 是否正在加载回显数据
const loadingEcho = ref<boolean>(false);
@@ -118,7 +121,7 @@
() => {
if (props.value === '') {
emit('change', '');
nextTick(() => onFieldChange());
nextTick(() => formItemContext.onFieldChange());
}
}
);
@@ -142,14 +145,37 @@
}
function handleChange(e) {
emitData.value = [e?.target?.value || e];
nextTick(() => onFieldChange());
const { mode } = unref<Recordable>(getBindValue);
// 兼容多选模式
if (mode === 'multiple') {
state.value = e?.target?.value ?? e;
} else {
state.value = [e?.target?.value ?? e];
}
// 过滤掉空值
if (state.value == null || state.value === '') {
state.value = [];
}
if (Array.isArray(state.value)) {
state.value = state.value.filter((item) => item != null && item !== '');
}
//update-begin---author:wangshuai ---date:20221123 for单选模式要改成字符串------------
if(mode !== 'multiple' && state.value && state.value.length>0){
state.value = state.value[0];
}
//update-end---author:wangshuai ---date:20221123 for单选模式要改成字符串--------------
// nextTick(() => formItemContext.onFieldChange());
}
/** 单选radio的值变化事件 */
function handleChangeRadio(e) {
state.value = e?.target?.value ?? e;
}
/** 用于搜索下拉框中的内容 */
function handleFilterOption(input, option) {
// 在 label 中搜索
let labelIf = option?.children[0]?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
let labelIf = option.children()[0]?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
if (labelIf) {
return true;
}
@@ -166,6 +192,7 @@
dictOptions,
CompTypeEnum,
handleChange,
handleChangeRadio,
handleFilterOption,
};
},

View File

@@ -14,6 +14,11 @@
.item {
margin-top: 5px;
font-size: 14px;
span {
padding: 0 2px;
}
}
.choice {

View File

@@ -24,12 +24,13 @@
<InputNumber v-model:value="valueLoop.interval" v-bind="typeLoopAttrs" />
<span> </span>
</div>
<div class="item">
<a-radio :value="TypeEnum.work" v-bind="beforeRadioAttrs">工作日</a-radio>
<span> 本月 </span>
<InputNumber v-model:value="valueWork" v-bind="typeWorkAttrs" />
<span> 最近的工作日 </span>
</div>
<!-- 工作日暂不支持会报错先隐藏了 -->
<!-- <div class="item">-->
<!-- <a-radio :value="TypeEnum.work" v-bind="beforeRadioAttrs">工作日</a-radio>-->
<!-- <span> 本月 </span>-->
<!-- <InputNumber v-model:value="valueWork" v-bind="typeWorkAttrs" />-->
<!-- <span> 最近的工作日 </span>-->
<!-- </div>-->
<div class="item">
<a-radio :value="TypeEnum.last" v-bind="beforeRadioAttrs">最后一日</a-radio>
</div>

View File

@@ -21,7 +21,7 @@
});
</script>
<style lang="less" scoped>
<style lang="less">
.jeecg-form-container-disabled {
cursor: not-allowed;
@@ -42,6 +42,12 @@
.ant-upload-list {
cursor: grabbing;
}
fieldset[disabled]{
.anticon-delete{
display: none !important;
}
}
}
.jeecg-form-container-disabled fieldset[disabled] .ant-upload-list {

View File

@@ -182,6 +182,9 @@
if (file.status != 'uploading') {
fileList.forEach((file) => {
if (file.status === 'done') {
//update-begin---author:wangshuai ---date:20221121 for[issues/248]原生表单内使用图片组件,关闭弹窗图片组件值不会被清空------------
initTag.value = true;
//update-end---author:wangshuai ---date:20221121 for[issues/248]原生表单内使用图片组件,关闭弹窗图片组件值不会被清空------------
fileUrls.push(file.response.message);
}
});
@@ -189,7 +192,7 @@
handleDelete(file);
}
}
emitData.value = fileUrls.join(',');
// emitData.value = fileUrls.join(',');
state.value = fileUrls.join(',');
emit('update:value', fileUrls.join(','));
}

View File

@@ -21,6 +21,7 @@
:groupId="uniqGroupId"
:param="param"
@ok="callBack"
:getContainer="getContainer"
></JPopupOnlReportModal>
</div>
</template>
@@ -50,6 +51,7 @@
groupId: propTypes.string.def(''),
formElRef: propTypes.object,
setFieldsValue: propTypes.func,
getContainer: propTypes.func,
fieldConfig: {
type: Array,
default: () => [],

View File

@@ -0,0 +1,65 @@
<template>
<a-range-picker v-model:value="rangeValue" @change="handleChange" :show-time="datetime" :placeholder="placeholder" :valueFormat="valueFormat"/>
</template>
<script>
import { defineComponent, ref, watch, computed } from 'vue';
import { propTypes } from '/@/utils/propTypes';
import { Form } from 'ant-design-vue';
const placeholder = ['最小值', '最大值']
/**
* 用于范围查询
*/
export default defineComponent({
name: "JRangeDate",
props:{
value: propTypes.string.def(''),
datetime: propTypes.bool.def(false),
placeholder: propTypes.string.def(''),
},
emits:['change', 'update:value'],
setup(props, {emit}){
const rangeValue = ref([])
const formItemContext = Form.useInjectFormItemContext();
watch(()=>props.value, (val)=>{
if(val){
rangeValue.value = val.split(',')
}else{
rangeValue.value = []
}
}, {immediate: true});
const valueFormat = computed(()=>{
if(props.datetime === true){
return 'YYYY-MM-DD HH:mm:ss'
}else{
return 'YYYY-MM-DD'
}
});
function handleChange(arr){
let str = ''
if(arr && arr.length>0){
if(arr[1] && arr[0]){
str = arr.join(',')
}
}
emit('change', str);
emit('update:value', str);
formItemContext.onFieldChange();
}
return {
rangeValue,
placeholder,
valueFormat,
handleChange
}
}
});
</script>
<style scoped>
</style>

View File

@@ -1,8 +1,8 @@
<template>
<a-input-group>
<a-input :value="beginValue" style="width: calc(50% - 15px)" placeholder="请输入最小值" @change="handleChangeBegin" />
<a-input :value="beginValue" style="width: calc(50% - 15px)" placeholder="最小值" @change="handleChangeBegin" />
<a-input style="width: 30px; border-left: 0; pointer-events: none; background-color: #fff" placeholder="~" disabled />
<a-input :value="endValue" style="width: calc(50% - 15px); border-left: 0" placeholder="请输入最大值" @change="handleChangeEnd" />
<a-input :value="endValue" style="width: calc(50% - 15px); border-left: 0" placeholder="最大值" @change="handleChangeEnd" />
</a-input-group>
</template>
@@ -11,19 +11,20 @@
* 查询条件用-数值范围查询
*/
import { ref, watch } from 'vue';
import { Form } from 'ant-design-vue';
import { propTypes } from '/@/utils/propTypes';
export default {
name: 'JRangeNumber',
props: {
value: {
type: Array,
default: ['', ''],
},
value: propTypes.oneOfType([propTypes.string, propTypes.array]),
},
emits: ['change'],
emits: ['change', 'update:value'],
setup(props, { emit }) {
const beginValue = ref('');
const endValue = ref('');
const formItemContext = Form.useInjectFormItemContext();
function handleChangeBegin(e) {
beginValue.value = e.target.value;
emitArray();
@@ -41,19 +42,21 @@
arr.push(begin);
arr.push(end);
emit('change', arr);
emit('update:value', arr);
formItemContext.onFieldChange();
}
watch(
() => props.value,
(val) => {
if (val.length == 2) {
if (val && val.length == 2) {
beginValue.value = val[0];
endValue.value = val[1];
} else {
beginValue.value = '';
endValue.value = '';
}
}
}, {immediate: true}
);
return {

View File

@@ -260,7 +260,17 @@
* 过滤选中option
*/
function filterOption(input, option) {
return option?.children[0]?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
//update-begin-author:taoyan date:2022-11-8 for: issues/218 所有功能表单的下拉搜索框搜索无效
let value = '', label = '';
try {
value = option.value;
label = option.children()[0].children;
}catch (e) {
console.log('获取下拉项失败', e)
}
let str = input.toLowerCase();
return value.toLowerCase().indexOf(str) >= 0 || label.toLowerCase().indexOf(str) >= 0;
//update-end-author:taoyan date:2022-11-8 for: issues/218 所有功能表单的下拉搜索框搜索无效
}
function getParentContainer(node) {

View File

@@ -150,7 +150,7 @@
width: 100%;
}
::v-deep(.ant-select-search__field) {
:deep(.ant-select-search__field) {
display: none !important;
}
}

View File

@@ -146,7 +146,7 @@
//update-begin-author:taoyan date:2022-5-31 for: VUEN-1145 下拉多选,搜索时,查不到数据
function filterOption(input, option) {
return option.children[0].el.data.toLowerCase().indexOf(input.toLowerCase()) >= 0;
return option.children()[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
}
//update-end-author:taoyan date:2022-5-31 for: VUEN-1145 下拉多选,搜索时,查不到数据

View File

@@ -142,7 +142,7 @@
width: 100%;
}
::v-deep(.ant-select-search__field) {
:deep(.ant-select-search__field) {
display: none !important;
}
}

View File

@@ -147,7 +147,7 @@
width: 100%;
}
::v-deep(.ant-select-search__field) {
:deep(.ant-select-search__field) {
display: none !important;
}
}

View File

@@ -150,7 +150,7 @@
width: 100%;
}
::v-deep(.ant-select-search__field) {
:deep(.ant-select-search__field) {
display: none !important;
}
}

View File

@@ -146,7 +146,7 @@
width: 100%;
}
::v-deep(.ant-select-search__field) {
:deep(.ant-select-search__field) {
display: none !important;
}
}

View File

@@ -2,7 +2,7 @@
<div :class="prefixCls">
<a-select
v-if="query"
v-model:value="value"
v-model:value="state"
:options="selectOptions"
:disabled="disabled"
style="width: 100%"
@@ -18,7 +18,7 @@
import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useDesign } from '/@/hooks/web/useDesign';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
const { prefixCls } = useDesign('j-switch');
const props = defineProps({
// v-model:value
@@ -36,7 +36,7 @@
const emit = defineEmits(['change', 'update:value']);
const checked = ref<boolean>(false);
const [state] = useRuleFormItem(props, 'value', 'change');
watch(
() => props.value,
(val) => {

View File

@@ -48,6 +48,10 @@
multiple: propTypes.bool.def(false),
loadTriggleChange: propTypes.bool.def(false),
reload: propTypes.number.def(1),
//update-begin-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelect控件changeOptions方法未生效
url: propTypes.string.def(''),
params: propTypes.object.def({})
//update-end-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelect控件changeOptions方法未生效
});
const attrs = useAttrs();
const emit = defineEmits(['change', 'update:value']);
@@ -103,17 +107,23 @@
treeValue.value = null;
}
} else {
let params = { key: props.value };
let result = await defHttp.get({ url: `${Api.view}${props.dict}`, params }, { isTransformResponse: false });
if (result.success) {
let values = props.value.split(',');
treeValue.value = result.result.map((item, index) => ({
key: values[index],
value: values[index],
label: item,
}));
onLoadTriggleChange(result.result[0]);
//update-begin-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelect控件changeOptions方法未生效
if(props.url){
getItemFromTreeData();
}else{
let params = { key: props.value };
let result = await defHttp.get({ url: `${Api.view}${props.dict}`, params }, { isTransformResponse: false });
if (result.success) {
let values = props.value.split(',');
treeValue.value = result.result.map((item, index) => ({
key: values[index],
value: values[index],
label: item,
}));
onLoadTriggleChange(result.result[0]);
}
}
//update-end-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelect控件changeOptions方法未生效
}
}
@@ -167,6 +177,9 @@
if (treeNode.dataRef.children) {
return Promise.resolve();
}
if(props.url){
return Promise.resolve();
}
let pid = treeNode.dataRef.key;
let params = {
pid: pid,
@@ -262,6 +275,67 @@
});
}
//update-begin-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelect控件changeOptions方法未生效
watch(()=>props.url, async (val)=>{
if(val){
await loadRootByUrl();
}
});
/**
* 根据自定义的请求地址加载数据
*/
async function loadRootByUrl(){
let url = props.url;
let params = props.params;
let res = await defHttp.get({ url, params }, { isTransformResponse: false });
if (res.success && res.result) {
for (let i of res.result) {
i.key = i.value;
i.isLeaf = !!i.leaf;
}
treeData.value = [...res.result];
} else {
console.log('数根节点查询结果异常', res);
}
}
/**
* 根据已有的树数据 翻译选项
*/
function getItemFromTreeData(){
let data = treeData.value;
let arr = []
findChildrenNode(data, arr);
if(arr.length>0){
treeValue.value = arr
onLoadTriggleChange(arr[0]);
}
}
/**
* 递归找子节点
* @param data
* @param arr
*/
function findChildrenNode(data, arr){
let val = props.value;
if(data && data.length){
for(let item of data){
if(val===item.value){
arr.push({
key: item.key,
value: item.value,
label: item.label||item.title
})
}else{
findChildrenNode(item.children, arr)
}
}
}
}
//update-end-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelect控件changeOptions方法未生效
// onCreated
validateProp().then(() => {
initDictInfo();

View File

@@ -6,8 +6,8 @@
:action="uploadUrl"
:fileList="fileList"
:disabled="disabled"
:remove="onRemove"
v-bind="bindProps"
@remove="onRemove"
@change="onFileChange"
@preview="onFilePreview"
>
@@ -291,6 +291,8 @@
fileSize: item.size,
};
newFileList.push(fileJson);
} else {
return;
}
}
emitValue(newFileList);

View File

@@ -115,7 +115,7 @@
width: 100%;
}
::v-deep(.ant-select-search__field) {
:deep(.ant-select-search__field) {
display: none !important;
}
}

View File

@@ -84,7 +84,7 @@
width: 100%;
}
::v-deep(.ant-select-search__field) {
:deep(.ant-select-search__field) {
display: none !important;
}
}

View File

@@ -38,6 +38,7 @@
import { treeProps } from '/@/components/Form/src/jeecg/props/props';
import { BasicTree, TreeActionType } from '/@/components/Tree';
import { useTreeBiz } from '/@/components/Form/src/jeecg/hooks/useTreeBiz';
import {propTypes} from "/@/utils/propTypes";
export default defineComponent({
name: 'DeptSelectModal',
@@ -52,6 +53,7 @@
type: String,
default: '部门选择',
},
value: propTypes.oneOfType([propTypes.string, propTypes.array])
},
emits: ['register', 'getSelectResult'],
setup(props, { emit, refs }) {
@@ -59,7 +61,12 @@
const [register, { closeModal }] = useModalInner();
const attrs = useAttrs();
const treeRef = ref<Nullable<TreeActionType>>(null);
const getBindValue = Object.assign({}, unref(props), unref(attrs));
//update-begin-author:taoyan date:2022-10-28 for: 部门选择警告类型不匹配
let propValue = props.value === ''?[]:props.value;
const getBindValue = Object.assign({}, unref(props), unref(attrs), {value: propValue});
//update-end-author:taoyan date:2022-10-28 for: 部门选择警告类型不匹配
const queryUrl = getQueryUrl();
const [{ visibleChange, checkedKeys, getCheckStrictly, getSelectTreeData, onCheck, onLoadData, treeData, checkALL, expandAll, onSelect }] =
useTreeBiz(treeRef, queryUrl, getBindValue);

View File

@@ -68,6 +68,10 @@ export function useSelectBiz(getList, props) {
columnWidth: 20,
selectedRowKeys: checkedKeys,
onChange: onSelectChange,
//update-begin-author:wangshuai---date:20221102--for: [VUEN-2562]用户选择,跨页选择后,只有当前页人员 ---
//table4.4.0新增属性选中之后是否清空上一页下一页的数据默认false
preserveSelectedRowKeys:true,
//update-end-author:wangshuai---date:20221102--for: [VUEN-2562]用户选择,跨页选择后,只有当前页人员 ---
};
/**

View File

@@ -89,7 +89,8 @@ export function useTreeBiz(treeRef, getList, props) {
if (info.checked) {
//update-begin-author:taoyan date:20220408 for: 单选模式下设定rowKey无法选中数据-
checkedKeys.value = [info.node.eventKey];
let temp = info.checkedNodes.find((n) => n.key === info.node.eventKey);
let rowKey = props.rowKey;
let temp = info.checkedNodes.find((n) => n[rowKey] === info.node.eventKey);
selectRows.value = [temp];
//update-end-author:taoyan date:20220408 for: 单选模式下设定rowKey无法选中数据-
} else {

View File

@@ -141,4 +141,6 @@ export type ComponentType =
| 'JSearchSelect'
| 'JAddInput'
| 'Time'
| 'RangeDate'
| 'RangeNumber'
| 'JRangeNumber';

File diff suppressed because it is too large Load Diff

View File

@@ -22,4 +22,6 @@ export async function registerJVxeCustom() {
await registerAsyncComponent(JVxeTypes.userSelect, import('./src/components/JVxeUserSelectCell.vue'));
// 注册【部门选择】组件
await registerAsyncComponent(JVxeTypes.departSelect, import('./src/components/JVxeDepartSelectCell.vue'));
// 注册【省市区选择】组件
await registerAsyncComponent(JVxeTypes.pca, import('./src/components/JVxePcaCell.vue'));
}

View File

@@ -0,0 +1,77 @@
<template>
<a-cascader v-bind="getProps" class="pca-select" @change="handleChange" />
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
import { regionData, getRealCode } from '/@/components/Form/src/utils/areaDataUtil';
import { JVxeComponent } from '/@/components/jeecg/JVxeTable/types';
import { useJVxeComponent, useJVxeCompProps } from '/@/components/jeecg/JVxeTable/hooks';
import { dispatchEvent } from '/@/components/jeecg/JVxeTable/utils';
export default defineComponent({
name: 'JVxePcaCell',
props: useJVxeCompProps(),
setup(props: JVxeComponent.Props) {
const { innerValue, cellProps, handleChangeCommon } = useJVxeComponent(props);
const selectedValue = computed(() => {
let val: any = innerValue.value;
if (!val) {
return []
}
let arr = getRealCode(val, 3);
return arr;
});
const getProps = computed(() => {
return {
...cellProps.value,
options: regionData,
showOverflow: false,
value: selectedValue.value,
};
});
function handleChange(arr) {
let str = '';
if(arr && arr.length==3){
str = arr[2];
}
handleChangeCommon(str);
}
return {
handleChange,
selectedValue,
getProps
};
},
// 【组件增强】注释详见JVxeComponent.Enhanced
enhanced: {
switches: {
visible: true,
},
translate: {
enabled: false,
},
aopEvents: {
editActived({ $event }) {
dispatchEvent({
$event,
props: this.props,
className: '.ant-select .ant-select-selection-search-input',
isClick: true,
});
},
},
} as JVxeComponent.EnhancedPartial,
});
</script>
<style lang="less">
.pca-select{
.ant-select-selection-placeholder{
color: #bfbfbf !important;
}
}
</style>

View File

@@ -42,7 +42,8 @@ export const DictSearchInputCell = defineComponent({
// 筛选函数
const filterOption = computed(() => {
if (isAsync.value) {
return null;
//【jeecgboot-vue3/issues/I5QRT8】JVxeTypes.selectDictSearch sync问题
return ()=>true;
}
return (input, option) => option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0;
});

View File

@@ -15,6 +15,7 @@
import { defineComponent, computed } from 'vue';
import { Menu } from 'ant-design-vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { checkChildrenHidden } from '/@/utils/common/compUtils';
import { itemProps } from '../props';
import BasicMenuItem from './BasicMenuItem.vue';
import MenuItemContent from './MenuItemContent.vue';
@@ -38,11 +39,13 @@
Reflect.has(menuTreeItem, 'children') &&
!!menuTreeItem.children &&
menuTreeItem.children.length > 0
&&checkChildrenHidden(menuTreeItem)
);
}
return {
prefixCls,
menuHasChildren,
checkChildrenHidden,
getShowMenu,
};
},

View File

@@ -17,7 +17,7 @@
</template>
<!-- update-begin-author:taoyan date:2022-7-18 for: modal弹窗 支持评论 slot -->
<a-row v-if="getProps.enableComment" class="jeecg-modal-wrapper">
<a-row class="jeecg-modal-wrapper">
<a-col :span="24-commentSpan" class="jeecg-modal-content">
<ModalWrapper
:useWrapper="getProps.useWrapper"
@@ -36,31 +36,14 @@
<slot></slot>
</ModalWrapper>
</a-col>
<a-col :span="commentSpan" class="jeecg-comment-outer">
<slot name="comment"></slot>
</a-col>
</a-row>
<ModalWrapper
v-else
:useWrapper="getProps.useWrapper"
:footerOffset="wrapperFooterOffset"
:fullScreen="fullScreenRef"
ref="modalWrapperRef"
:loading="getProps.loading"
:loading-tip="getProps.loadingTip"
:minHeight="getProps.minHeight"
:height="getWrapperHeight"
:visible="visibleRef"
:modalFooterHeight="footer !== undefined && !footer ? 0 : undefined"
v-bind="omit(getProps.wrapperProps, 'visible', 'height', 'modalFooterHeight')"
@ext-height="handleExtHeight"
@height-change="handleHeightChange">
<slot></slot>
</ModalWrapper>
<!-- update-end-author:taoyan date:2022-7-18 for: modal弹窗 支持评论 slot -->
<template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
<slot :name="item" v-bind="data || {}"></slot>
</template>
@@ -282,4 +265,4 @@
.jeecg-modal-content {
height: 100%;
}
</style>
</style>

View File

@@ -122,8 +122,8 @@
if (isUrl(key)) {
// update-begin--author:sunjianlei---date:20220408---for: 【VUEN-656】配置外部网址打不开原因是带了#号,需要替换一下
let url = key.replace(URL_HASH_TAB, '#');
openWindow(url);
// openWindow(key);
window.open(url)
//openWindow(url);
// update-begin--author:sunjianlei---date:20220408---for: 【VUEN-656】配置外部网址打不开原因是带了#号,需要替换一下
return;
}

View File

@@ -36,7 +36,7 @@
import { defineComponent, computed } from 'vue';
import { useDesign } from '/@/hooks/web/useDesign';
import Icon from '/@/components/Icon/index';
import { checkChildrenHidden } from '/@/utils/common/compUtils';
import MenuItem from './components/MenuItem.vue';
import SubMenu from './components/SubMenuItem.vue';
import { propTypes } from '/@/utils/propTypes';
@@ -79,18 +79,20 @@
];
});
function menuHasChildren(menuTreeItem: Menu): boolean {
function menuHasChildren(menuTreeItem): boolean {
return (
!menuTreeItem.meta?.hideChildrenInMenu &&
Reflect.has(menuTreeItem, 'children') &&
!!menuTreeItem.children &&
menuTreeItem.children.length > 0
&&checkChildrenHidden(menuTreeItem)
);
}
return {
prefixCls,
menuHasChildren,
checkChildrenHidden,
getShowMenu,
getIcon,
getI18nName,

View File

@@ -17,7 +17,7 @@
<!-- antd v3 升级兼容阻止数据的收集防止控制台报错 -->
<!-- https://antdv.com/docs/vue/migration-v3-cn -->
<a-form-item-rest>
<Table ref="tableElRef" v-bind="getBindValues" :rowClassName="getRowClassName" v-show="getEmptyDataIsShowTable" @change="handleTableChange">
<Table ref="tableElRef" v-bind="getBindValues" :rowClassName="getRowClassName" v-show="getEmptyDataIsShowTable" @resizeColumn="handleResizeColumn" @change="handleTableChange">
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
<slot :name="item" v-bind="data || {}"></slot>
</template>
@@ -289,6 +289,9 @@
wrapRef,
tableAction,
redoHeight,
handleResizeColumn: (w, col) => {
col.width = w;
},
getFormProps: getFormProps as any,
replaceFormSlotKey,
getFormSlotKeys,
@@ -406,8 +409,8 @@
//表格选择工具栏样式
.alert {
height: 38px;
background-color: #f3f3f3;
border-color: #e3e3e3;
background-color: #e6f7ff;
border-color: #91d5ff;
}
&--inset {
.ant-table-wrapper {

View File

@@ -149,7 +149,10 @@
.@{prefix-cls} {
display: flex;
align-items: center;
/* update-begin-author:taoyan date:2022-11-18 for: 表格默认行高比官方示例多出2px*/
height: 22px;
/* update-end-author:taoyan date:2022-11-18 for: 表格默认行高比官方示例多出2px*/
.action-divider {
display: table;
}

View File

@@ -28,7 +28,10 @@
<a-alert type="info" show-icon class="alert" v-if="openRowSelection != null">
<template #message>
<template v-if="selectRowKeys.length > 0">
<span>已选中 {{ selectRowKeys.length }} 条记录(可跨页)</span>
<span>
<span>已选中 {{ selectRowKeys.length }} 条记录</span>
<span v-if="isAcrossPage">(可跨页)</span>
</span>
<a-divider type="vertical" />
<a @click="setSelectedRowKeys([])">清空</a>
<slot name="alertAfter" />
@@ -86,8 +89,10 @@
const { getSelectRowKeys, setSelectedRowKeys, getRowSelection } = useTableContext();
const selectRowKeys = computed(() => getSelectRowKeys());
const openRowSelection = computed(() => getRowSelection());
// 是否允许跨页选择
const isAcrossPage = computed(() => openRowSelection.value?.preserveSelectedRowKeys === true);
return { prefixCls, handleColumnChange, selectRowKeys, setSelectedRowKeys, openRowSelection };
return { prefixCls, handleColumnChange, selectRowKeys, setSelectedRowKeys, openRowSelection, isAcrossPage };
},
});
</script>

View File

@@ -142,8 +142,10 @@
setup(props, { emit, attrs }) {
const { t } = useI18n();
const table = useTableContext();
const popoverVisible = ref(false);
const popoverVisible = ref(true);
// update-begin--author:sunjianlei---date:20221101---for: 修复第一次进入时列表配置不能拖拽
nextTick(() => popoverVisible.value = false);
// update-end--author:sunjianlei---date:20221101---for: 修复第一次进入时列表配置不能拖拽
const defaultRowSelection = omit(table.getRowSelection(), 'selectedRowKeys');
let inited = false;

View File

@@ -172,11 +172,11 @@ export function useDataSource(
}
function insertTableDataRecord(record: Recordable, index: number): Recordable | undefined {
if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
//【issues/136】同步VbenBasicTable 调用插入函数异常插入两条记录]
// if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
index = index ?? dataSourceRef.value?.length;
unref(dataSourceRef).splice(index, 0, record);
unref(propsRef).dataSource?.splice(index, 0, record);
return unref(propsRef).dataSource;
return unref(dataSourceRef);
}
function findTableDataRecord(rowKey: string | number) {
if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;

View File

@@ -16,6 +16,10 @@ export function useRowSelection(propsRef: ComputedRef<BasicTableProps>, tableDat
}
return {
// AntDV3.0 之后使用远程加载数据进行分页时,
// 默认会清空上一页选择的行数据(导致无法跨页选择),
// 将此属性设置为 true 即可解决。
preserveSelectedRowKeys: true,
selectedRowKeys: unref(selectedRowKeysRef),
onChange: (selectedRowKeys: string[]) => {
setSelectedRowKeys(selectedRowKeys);

View File

@@ -61,9 +61,15 @@ export function useTable(tableProps?: Props): [
}
return table as TableActionType;
}
function getTableRef(){
return tableRef;
}
const methods: TableActionType & {
getForm: () => FormActionType;
} & {
getTableRef: () => any;
} = {
reload: async (opt?: FetchParams) => {
return await getTableInstance().reload(opt);
@@ -153,6 +159,9 @@ export function useTable(tableProps?: Props): [
collapseAll: () => {
getTableInstance().collapseAll();
},
getTableRef: () => {
return getTableRef();
}
};
return [register, methods];

View File

@@ -20,7 +20,7 @@ export const basicProps = {
},
showTableSetting: propTypes.bool,
autoCreateKey: propTypes.bool.def(true),
striped: propTypes.bool.def(true),
striped: propTypes.bool.def(false),
showSummary: propTypes.bool,
summaryFunc: {
type: [Function, Array] as PropType<(...arg: any[]) => any[]>,

View File

@@ -447,6 +447,8 @@ export interface BasicColumn extends ColumnProps {
auth?: RoleEnum | RoleEnum[] | string | string[];
// 业务控制是否显示
ifShow?: boolean | ((column: BasicColumn) => boolean);
//compType-用于记录类型
compType?: string;
}
export type ColumnChangeParam = {

View File

@@ -59,7 +59,8 @@
const collapsed = ref(true);
// 配置的按钮
const btns = computed(() => {
let btns = props.toolbarConfig?.btn || ['add', 'remove', 'clearSelection'];
let { btn, btns } = props.toolbarConfig || {};
btns = btn || btns || ['add', 'remove', 'clearSelection'];
// 排除掉没有授权的按钮
return btns.filter((btn) => {
// 系统默认的批量删除编码配置为 batch_delete 此处需要兼容一下

View File

@@ -45,7 +45,7 @@
<style scoped lang="less">
// 关闭进度条的动画,防止滚动时动态赋值出现问题
.j-vxe-progress.no-animation {
::v-deep(.ant-progress-bg) {
:deep(.ant-progress-bg) {
transition: none !important;
}
}

View File

@@ -39,6 +39,11 @@ export function useDragSort(props: JVxeTableProps, methods: JVxeTableMethods) {
if (oldIndex === newIndex) {
return;
}
// 【VUEN-2505】获取当前行数据
let rowNode = xTable.getRowNode(e.item);
if (!rowNode) {
return;
}
let from = e.from;
let element = startChildren[oldIndex];
let target = null;
@@ -54,6 +59,12 @@ export function useDragSort(props: JVxeTableProps, methods: JVxeTableMethods) {
from.removeChild(element);
from.insertBefore(element, target);
nextTick(() => {
// 【VUEN-2505】算出因虚拟滚动导致的偏移量
let diffIndex = rowNode!.index - oldIndex;
if (diffIndex > 0) {
oldIndex = oldIndex + diffIndex;
newIndex = newIndex + diffIndex;
}
methods.doSort(oldIndex, newIndex);
methods.trigger('dragged', { oldIndex, newIndex });
});

View File

@@ -28,8 +28,8 @@ export function useJVxeComponent(props: JVxeComponent.Props) {
const column = computed(() => props.params.column);
// 用户配置的原始 column
const originColumn = computed(() => column.value.params);
const rowIndex = computed(() => props.params.$rowIndex);
const columnIndex = computed(() => props.params.columnIndex);
const rowIndex = computed(() => props.params._rowIndex);
const columnIndex = computed(() => props.params._columnIndex);
// 表格数据长度
const fullDataLength = computed(() => props.params.$table.internalData.tableFullData.length);
// 是否正在滚动中

View File

@@ -94,5 +94,9 @@
width: 17px;
height: 17px;
}
/*【美化表单】行编辑table的title字体改小一号*/
.vxe-header--column.col--ellipsis>.vxe-cell .vxe-cell--title{
font-size: 13px;
}
}

View File

@@ -44,6 +44,8 @@ export enum JVxeTypes {
radio = 'radio',
image = 'image',
file = 'file',
// 省市区
pca = 'pca',
}
// 为了防止和 vxe 内置的类型冲突,所以加上一个前缀

View File

@@ -5,22 +5,22 @@
<a-row :gutter="24">
<template v-for="(item, index) in queryInfo">
<template v-if="item.hidden === '1'">
<a-col :md="8" :sm="24" :key="'query' + index" v-show="toggleSearchStatus">
<a-col :md="6" :sm="24" :key="'query' + index" v-show="toggleSearchStatus">
<SearchFormItem :formElRef="formRef" :queryParam="queryParam" :item="item" :dictOptions="dictOptions"></SearchFormItem>
</a-col>
</template>
<template v-else>
<a-col :md="8" :sm="24" :key="'query' + index">
<a-col :md="6" :sm="24" :key="'query' + index">
<SearchFormItem :formElRef="formRef" :queryParam="queryParam" :item="item" :dictOptions="dictOptions"></SearchFormItem>
</a-col>
</template>
</template>
<a-col :md="8" :sm="8">
<a-col :md="6" :sm="8">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6">
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset">重置</a-button>
<a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery" style="margin-left: 8px">查询</a-button>
<a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset" style="margin-left: 8px">重置</a-button>
<a @click="handleToggleSearch" style="margin-left: 8px">
{{ toggleSearchStatus ? '收起' : '展开' }}
<Icon :icon="toggleSearchStatus ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
@@ -63,7 +63,8 @@
import { useAttrs } from '/@/hooks/core/useAttrs';
import { usePopBiz } from '/@/components/jeecg/OnLine/hooks/usePopBiz';
import { useMessage } from '/@/hooks/web/useMessage';
import { useRoute } from 'vue-router';
export default defineComponent({
name: 'JPopupOnlReport',
components: {
@@ -89,7 +90,10 @@
const toggleSearchStatus = ref(false);
const attrs = useAttrs();
const tableScroll = ref({ x: true });
const getBindValue = Object.assign({}, unref(props), unref(attrs));
const route = useRoute();
console.log('route.query = ',route.query)
const getBindValue = Object.assign({}, {routeQuery: route.query}, unref(props), unref(attrs));
const [
{
visibleChange,

View File

@@ -44,7 +44,7 @@
</template>
<template v-else>
<a-date-picker
placeholder="1选择开始时间"
placeholder="选择开始时间"
:show-time="true"
valueFormat="YYYY-MM-DD HH:mm:ss"
v-model:value="queryParam[item.field + '_begin']"
@@ -52,7 +52,7 @@
></a-date-picker>
<span class="group-query-strig" style="width: auto; padding: 0 4px">~</span>
<a-date-picker
placeholder="2选择结束时间"
placeholder="选择结束时间"
:show-time="true"
valueFormat="YYYY-MM-DD HH:mm:ss"
v-model:value="queryParam[item.field + '_end']"
@@ -131,16 +131,8 @@
<template #label>
<span :title="item.label" class="label-text">{{ item.label }}</span>
</template>
<JDictSelectTag v-if="item.config === '1'" v-model:value="queryParam[item.field]" :placeholder="'请选择' + item.label" :dict="getDictCode(item)">
</JDictSelectTag>
<!--TODO 新需要的组件-->
<!-- <j-online-search-select
v-else
:ref="item.field+'_search'"
v-model="queryParam[item.field]"
:placeholder=" '请选择'+item.label "
:sql="getSqlByDictCode(item)">
</j-online-search-select>-->
<JOnlineSearchSelect v-model:value="queryParam[item.field]" :placeholder="'请选择' + item.label" :sql="item.sql">
</JOnlineSearchSelect>
</a-form-item>
<a-form-item v-else-if="item.view === CompTypeEnum.SelUser" :labelCol="labelCol" :class="'jeecg-online-search'">
@@ -202,7 +194,10 @@
<template #label>
<span :title="item.label" class="label-text">{{ item.label }}</span>
</template>
<template v-if="single_mode === item.mode">
<template v-if="single_mode === item.mode && 'string'== item.view">
<j-input :placeholder="'请输入' + item.label" v-model:value="queryParam[item.field]"></j-input>
</template>
<template v-else-if="single_mode === item.mode">
<a-input :placeholder="'请输入' + item.label" v-model:value="queryParam[item.field]"></a-input>
</template>
<template v-else>
@@ -218,7 +213,7 @@
import { defineComponent, ref } from 'vue';
import { DateTypeEnum } from '/@/enums/DateTypeEnum.ts';
import { CompTypeEnum } from '/@/enums/CompTypeEnum.ts';
import { JDictSelectTag, JTreeSelect, JCategorySelect, JSelectUserByDept, JSelectDept, JPopup, JAreaLinkage } from '/@/components/Form';
import { JDictSelectTag, JTreeSelect, JCategorySelect, JSelectUserByDept, JSelectDept, JPopup, JAreaLinkage,JInput,JSearchSelect } from '/@/components/Form';
export default defineComponent({
name: 'JPopupOnlReport',
components: {
@@ -230,6 +225,7 @@
JSelectDept,
JPopup,
JAreaLinkage,
JInput,
},
props: {
formElRef: {
@@ -313,16 +309,16 @@
}
/* 查询条件左对齐样式设置 */
.jeecg-online-search ::v-deep .ant-form-item-label {
.jeecg-online-search :deep(.ant-form-item-label) {
flex: 0 0 auto !important;
width: auto;
}
.jeecg-online-search ::v-deep .ant-form-item-control {
.jeecg-online-search :deep(.ant-form-item-control) {
max-width: 100%;
}
/* label显示宽度 超出显示... */
.jeecg-online-search ::v-deep .label-text {
.jeecg-online-search :deep(.label-text) {
max-width: v-bind(labelTextMaxWidth);
overflow: hidden;
white-space: nowrap;

View File

@@ -512,6 +512,8 @@ export function usePopBiz(props, tableRef?) {
//查询条件加载后再请求数据
if (data) {
setDataSource(data);
//传递路由参数和动态参数,不生效,
loadData(1);
} else {
//没有传递data时查询数据
loadData(1);
@@ -531,6 +533,7 @@ export function usePopBiz(props, tableRef?) {
pagination.current = 1;
}
let params = getQueryParams(); //查询条件
console.log('params', params);
loading.value = true;
let url = `${configUrl.getData}${unref(cgRpConfigId)}`;
//缓存key
@@ -597,6 +600,11 @@ export function usePopBiz(props, tableRef?) {
}
queryParam.value = { ...queryTemp };
}
// 合并路由参数
if (props.routeQuery) {
queryParam.value = Object.assign(queryParam.value, props.routeQuery);
}
let dynamicTemp = {};
if (props.param) {
Object.keys(props.param).map((key) => {

View File

@@ -75,15 +75,15 @@
/**
* 评论列表
*/
import { defineComponent, ref, onMounted, watch, watchEffect } from 'vue';
import { defineComponent, ref, onMounted, watch, watchEffect ,inject } from 'vue';
import { propTypes } from '/@/utils/propTypes';
import dayjs from 'dayjs';
import 'dayjs/locale/zh.js';
import relativeTime from 'dayjs/plugin/relativeTime';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.locale('zh');
dayjs.extend(relativeTime);
dayjs.extend(customParseFormat);
// import dayjs from 'dayjs';
// import relativeTime from 'dayjs/plugin/relativeTime';
// import customParseFormat from 'dayjs/plugin/customParseFormat';
// dayjs.locale('zh');
// dayjs.extend(relativeTime);
// dayjs.extend(customParseFormat);
import { MessageOutlined } from '@ant-design/icons-vue';
import { Comment, Tooltip } from 'ant-design-vue';
import { useUserStore } from '/@/store/modules/user';
@@ -113,6 +113,8 @@
const { createMessage } = useMessage();
const dataList = ref([]);
const { userInfo } = useUserStore();
const dayjs = inject('$dayjs')
/**
* 获取当前用户名称
*/
@@ -245,7 +247,8 @@
}
});
const { getHtml } = useEmojiHtml();
const storageEmojiIndex = inject('$globalEmojiIndex')
const { getHtml } = useEmojiHtml(storageEmojiIndex);
const bottomCommentRef = ref()
function handleClickItem(){
bottomCommentRef.value.changeActive()

View File

@@ -87,7 +87,7 @@
}
}
//antd3升级后表单右侧讨论样式调整
::v-deep(.ant-tabs-top .ant-tabs-nav, .ant-tabs-bottom .ant-tabs-nav, .ant-tabs-top div .ant-tabs-nav, .ant-tabs-bottom div .ant-tabs-nav) {
:deep(.ant-tabs-top .ant-tabs-nav, .ant-tabs-bottom .ant-tabs-nav, .ant-tabs-top div .ant-tabs-nav, .ant-tabs-bottom div .ant-tabs-nav) {
margin: 0 16px 0;
}
</style>

View File

@@ -28,16 +28,15 @@
<script>
import { PlusOutlined, EditOutlined } from '@ant-design/icons-vue';
import { getModalHeight, getLogList } from './useComment'
import {ref, watchEffect} from 'vue'
import {inject, ref, watchEffect} from 'vue'
import { propTypes } from '/@/utils/propTypes';
import { Tooltip } from 'ant-design-vue';
import dayjs from 'dayjs';
import 'dayjs/locale/zh.js';
import relativeTime from 'dayjs/plugin/relativeTime';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.locale('zh');
dayjs.extend(relativeTime);
dayjs.extend(customParseFormat);
// import dayjs from 'dayjs';
// import relativeTime from 'dayjs/plugin/relativeTime';
// import customParseFormat from 'dayjs/plugin/customParseFormat';
// dayjs.locale('zh');
// dayjs.extend(relativeTime);
// dayjs.extend(customParseFormat);
export default {
name: "DataLogList",
@@ -52,6 +51,7 @@
datetime: propTypes.number.def(1),
},
setup(props){
const dayjs = inject('$dayjs')
const winHeight = getModalHeight();
const height = ref(300);
height.value = winHeight - 46 - 57 -53 - 30;
@@ -174,4 +174,4 @@
}
}
</style>
</style>

View File

@@ -45,14 +45,13 @@
</template>
<script lang="ts">
import { ref, watch, computed } from 'vue';
import {ref, watch, computed, inject} from 'vue';
import { propTypes } from '/@/utils/propTypes';
import { UserAddOutlined, PaperClipOutlined, SmileOutlined } from '@ant-design/icons-vue';
import { Tooltip } from 'ant-design-vue';
import UserSelectModal from '/@/components/Form/src/jeecg/components/modal/UserSelectModal.vue';
import { useModal } from '/@/components/Modal';
import UploadChunk from './UploadChunk.vue';
import { Picker } from 'emoji-mart-vue-fast/src';
import 'emoji-mart-vue-fast/css/emoji-mart.css';
import { useEmojiHtml } from './useComment';
@@ -79,7 +78,6 @@
PaperClipOutlined,
UploadChunk,
SmileOutlined,
Picker,
},
props: {
inner: propTypes.bool.def(false),
@@ -221,8 +219,9 @@
e.stopPropagation();
visibleEmoji.value = !visibleEmoji.value;
}
const { emojiIndex, getHtml } = useEmojiHtml();
const emojiIndex = inject('$globalEmojiIndex')
const { getHtml } = useEmojiHtml(emojiIndex);
const commentHtml = computed(() => {
let temp = myComment.value;

View File

@@ -13,8 +13,6 @@ import txt from '/@/assets/svg/fileType/txt.svg';
import word from '/@/assets/svg/fileType/word.svg';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { createImgPreview } from '/@/components/Preview';
import {EmojiIndex} from "emoji-mart-vue-fast/src";
import data from "emoji-mart-vue-fast/data/apple.json";
enum Api {
list = '/sys/comment/listByForm',
@@ -365,16 +363,9 @@ export function useFileList() {
/**
* 用于emoji渲染
*/
export function useEmojiHtml(){
export function useEmojiHtml(globalEmojiIndex){
const COLONS_REGEX = new RegExp('([^:]+)?(:[a-zA-Z0-9-_+]+:(:skin-tone-[2-6]:)?)','g');
let emojisToShowFilter = function() {
return true;
}
let emojiIndex = new EmojiIndex(data, {
emojisToShowFilter,
exclude:['recent','people','nature','foods','activity','places','objects','symbols','flags']
});
function getHtml(text) {
if(!text){
return ''
@@ -384,7 +375,7 @@ export function useEmojiHtml(){
if (endsWith(before, 'alt="') || endsWith(before, 'data-text="')) {
return match
}
let emoji = emojiIndex.findEmoji(p2)
let emoji = globalEmojiIndex.findEmoji(p2)
if (!emoji) {
return match
}
@@ -403,7 +394,7 @@ export function useEmojiHtml(){
}
return {
emojiIndex,
globalEmojiIndex,
getHtml
}
}

View File

@@ -50,7 +50,9 @@ html[data-theme='dark'] {
.ant-pagination-next,
.ant-pagination-item {
margin: 0 4px !important;
background-color: #f4f4f5 !important;
//update-begin---author:scott ---date:2022-09-30 for【美化】Table分页页面默认背景色丑去掉-----------
//background-color: #f4f4f5 !important;
//update-end---author:scott ---date::2022-09-30 for【美化】Table分页页面默认背景色丑去掉------------
border: none;
border-radius: none !important;

View File

@@ -6,7 +6,23 @@ html[data-theme='light'] {
.text-secondary {
color: rgba(0, 0, 0, 0.45);
}
/*【美化】自定义table字体颜色*/
.ant-table {
color: rgba(0, 0, 0, 0.65);
}
/*【美化】自定义table字体颜色*/
/*【美化】自定义form字体颜色*/
.ant-select-multiple .ant-select-selection-item-content {
color: rgba(0, 0, 0, 0.65);
}
.ant-input-affix-wrapper > input.ant-input {
color: rgba(0, 0, 0, 0.65);
}
.ant-select-single.ant-select-show-arrow .ant-select-selection-item, .ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{
color: rgba(0, 0, 0, 0.65);
}
/*【美化】自定义form字体颜色*/
.ant-alert-success {
background-color: #f6ffed;
border: 1px solid #b7eb8f;

View File

@@ -17,7 +17,7 @@ export enum CompTypeEnum {
//分类字典树
CatTree = 'cat_tree',
//下拉搜索
SelSearch = 'sel_search',
SelSearch = 'search',
//用户现在框
SelUser = 'sel_user',
//复选框

View File

@@ -1,5 +1,7 @@
import type { UnwrapRef, Ref, WritableComputedRef, DeepReadonly } from 'vue';
import { reactive, readonly, computed, getCurrentInstance, watchEffect, unref, nextTick, toRaw } from 'vue';
import { Form } from 'ant-design-vue';
import { FormItemContext } from 'ant-design-vue/es/form/FormItemContext';
import { isEqual } from 'lodash-es';
export function useRuleFormItem<T extends Recordable, K extends keyof T, V = UnwrapRef<T[K]>>(
@@ -7,10 +9,11 @@ export function useRuleFormItem<T extends Recordable, K extends keyof T, V = Unw
key?: K,
changeEvent?,
emitData?: Ref<any[] | undefined>
): [WritableComputedRef<V>, (val: V) => void, DeepReadonly<V>];
): [WritableComputedRef<V>, (val: V) => void, DeepReadonly<V>, FormItemContext];
export function useRuleFormItem<T extends Recordable>(props: T, key: keyof T = 'value', changeEvent = 'change', emitData?: Ref<any[]>) {
const instance = getCurrentInstance();
const emit = instance?.emit;
const formItemContext = Form.useInjectFormItemContext();
const innerState = reactive({
value: props[key],
@@ -28,8 +31,8 @@ export function useRuleFormItem<T extends Recordable>(props: T, key: keyof T = '
const state: any = computed({
get() {
//修复多选时空值显示问题
return innerState.value === '' ? [] : innerState.value;
//修复多选时空值显示问题兼容值为0的情况
return innerState.value == null || innerState.value === '' ? [] : innerState.value;
},
set(value) {
if (isEqual(value, defaultState.value)) return;
@@ -37,9 +40,12 @@ export function useRuleFormItem<T extends Recordable>(props: T, key: keyof T = '
innerState.value = value as T[keyof T];
nextTick(() => {
emit?.(changeEvent, value, ...(toRaw(unref(emitData)) || []));
// https://antdv.com/docs/vue/migration-v3-cn
// antDv3升级后需要调用这个方法更新校验的值
nextTick(() => formItemContext.onFieldChange());
});
},
});
return [state, setState, defaultState];
return [state, setState, defaultState, formItemContext];
}

View File

@@ -50,6 +50,9 @@ export function useHeaderSetting() {
const getShowBread = computed(() => {
return unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit);
});
const getShowBreadTitle = computed(() => {
return unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && !unref(getShowBreadCrumb) && !unref(getSplit);
});
const getShowHeaderLogo = computed(() => {
return unref(getShowLogo) && !unref(getIsSidebarType) && !unref(getIsMixSidebar);
@@ -82,5 +85,6 @@ export function useHeaderSetting() {
getShowInsetHeaderRef,
getUnFixedAndFull,
getHeaderBgColor,
getShowBreadTitle
};
}

View File

@@ -44,7 +44,7 @@ export function useJvxeMethod(requestAddOrEdit, classifyIntoFormData, tableRefs,
getAllTable()
.then((tables) => {
let values = formRef.value.getFieldsValue();
return validateFormModelAndTables(formRef.value.validate, values, tables, formRef.value.getProps);
return validateFormModelAndTables(formRef.value.validate, values, tables, formRef.value.getProps, false);
})
.then((allValues) => {
/** 一次性验证一对一的所有子表 */
@@ -61,7 +61,13 @@ export function useJvxeMethod(requestAddOrEdit, classifyIntoFormData, tableRefs,
.catch((e) => {
if (e.error === VALIDATE_FAILED) {
// 如果有未通过表单验证的子表就自动跳转到它所在的tab
activeKey.value = e.index == null ? unref(activeKey) : refKeys.value[e.index];
//update-begin-author:taoyan date:2022-11-22 for: VUEN-2866【代码生成】Tab风格 一对多子表校验不通过时,点击提交表单空白了,流程附加页面也有此问题
if(e.paneKey){
activeKey.value = e.paneKey
}else{
activeKey.value = e.index == null ? unref(activeKey) : refKeys.value[e.index];
}
//update-end-author:taoyan date:2022-11-22 for: VUEN-2866【代码生成】Tab风格 一对多子表校验不通过时,点击提交表单空白了,流程附加页面也有此问题
} else {
console.error(e);
}

View File

@@ -235,7 +235,7 @@ export function useListTable(tableProps: TableProps): [
},
},
// 斑马纹
striped: true,
striped: false,
// 是否可以自适应高度
canResize: true,
// 表格最小高度

View File

@@ -47,8 +47,15 @@ export const useRedo = (_router?: Router) => {
return;
}
if (name && Object.keys(params).length > 0) {
params['_redirect_type'] = 'name';
params['path'] = String(name);
//update-begin-author:taoyan date:2022-10-19 for: VUEN-2356 【vue3】online表单、表单设计器 功能测试 右键刷新时 404
if(isDynamicRoute(params, name)){
params['_redirect_type'] = 'path';
params['path'] = fullPath;
}else{
params['_redirect_type'] = 'name';
params['path'] = String(name);
}
//update-end-author:taoyan date:2022-10-19 for: VUEN-2356 【vue3】online表单、表单设计器 功能测试 右键刷新时 404
} else {
params['_redirect_type'] = 'path';
params['path'] = fullPath;
@@ -58,3 +65,21 @@ export const useRedo = (_router?: Router) => {
}
return redo;
};
/**
* 判断是不是动态路由的跳转
* @param params
* @param name
*/
function isDynamicRoute(params, name){
let arr = Object.keys(params);
let flag = false;
for(let i=0;i<arr.length;i++){
let key = '@'+arr[i];
if((name as string).indexOf(key)>0){
flag = true;
break;
}
}
return flag;
}

View File

@@ -162,7 +162,7 @@
display: none;
}
::v-deep(.ant-pagination-disabled) {
:deep(.ant-pagination-disabled) {
display: inline-block !important;
}

View File

@@ -57,7 +57,6 @@
}
return count;
});
const chatRef = ref();
const [registerMessageModal, { openModal: openMessageModal }] = useModal();
function clickBadge(){
@@ -96,7 +95,6 @@
//update-begin-author:taoyan date:2022-8-30 for: 消息数量改变触发chat组件事件
let msgCount = anntMsgTotal+sysMsgTotal;
//update-begin-author:wangshuai date:2022-09-02 for: 消息未读数为0也需要传递因为聊天需要计算总数
chatRef.value.updateMessageCount(msgCount);
messageCount.value = msgCount
//update-end-author:wangshuai date:2022-09-02 for: 消息未读数为0也需要传递因为聊天需要计算总数
//update-end-author:taoyan date:2022-8-30 for: 消息数量改变触发chat组件事件
@@ -164,12 +162,6 @@
}
}
/**
* 获取消息未读数
*/
function getSystemUnreadNum() {
chatRef.value.updateMessageCount(messageCount.value);
}
return {
prefixCls,
@@ -184,8 +176,6 @@
popoverVisible,
registerDetail,
dynamicNoticeProps,
chatRef,
getSystemUnreadNum
};
},
});

View File

@@ -57,7 +57,7 @@
setModalProps({ confirmLoading: true });
//提交表单
let params = Object.assign({ username: unref(username) }, values);
defHttp.put({ url: 'sys/user/updatePassword', params }, { isTransformResponse: false }).then((res) => {
defHttp.put({ url: '/sys/user/updatePassword', params }, { isTransformResponse: false }).then((res) => {
if (res.success) {
$message.createMessage.success(res.message);
//关闭弹窗

View File

@@ -10,6 +10,8 @@
:sider="false"
/>
<LayoutBreadcrumb v-if="getShowContent && getShowBread" :theme="getHeaderTheme" />
<!-- 欢迎语 -->
<span v-if="getShowContent && getShowBreadTitle" :class="[prefixCls, `${prefixCls}--${getHeaderTheme}`,'headerIntroductionClass']"> 欢迎进入 {{ title }} </span>
</div>
<!-- left end -->
@@ -42,7 +44,7 @@
</template>
<script lang="ts">
import { defineComponent, unref, computed, ref, onMounted, toRaw } from 'vue';
import { useGlobSetting } from '/@/hooks/setting';
import { propTypes } from '/@/utils/propTypes';
import { Layout } from 'ant-design-vue';
@@ -98,7 +100,8 @@
const userStore = useUserStore();
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getIsMixMode, getMenuWidth, getIsMixSidebar } = useMenuSetting();
const { getUseErrorHandle, getShowSettingButton, getSettingButtonPosition } = useRootSetting();
const { title } = useGlobSetting();
const {
getHeaderTheme,
getShowFullScreen,
@@ -109,6 +112,7 @@
getShowHeader,
getShowSearch,
getUseLockPage,
getShowBreadTitle,
} = useHeaderSetting();
const { getShowLocalePicker } = useLocale();
@@ -185,6 +189,7 @@
getHeaderTheme,
getShowHeaderTrigger,
getIsMobile,
getShowBreadTitle,
getShowBread,
getShowContent,
getSplitType,
@@ -203,10 +208,43 @@
getUseLockPage,
loginSelectOk,
loginSelectRef,
title
};
},
});
</script>
<style lang="less">
@import './index.less';
//update-begin---author:scott ---date:2022-09-30 for默认隐藏顶部菜单面包屑-----------
//顶部欢迎语展示样式
@prefix-cls: ~'@{namespace}-layout-header';
.@{prefix-cls} {
display: flex;
padding: 0 8px;
align-items: center;
.headerIntroductionClass {
margin-right: 4px;
margin-bottom: 2px;
border-bottom: 0px;
border-left: 0px;
}
&--light {
.headerIntroductionClass {
color: @breadcrumb-item-normal-color;
}
}
&--dark {
.headerIntroductionClass {
color: rgba(255, 255, 255, 0.6);
}
.anticon {
color: rgba(255, 255, 255, 0.8);
}
}
//update-end---author:scott ---date::2022-09-30 for默认隐藏顶部菜单面包屑--------------
}
</style>

View File

@@ -201,3 +201,28 @@ html[data-theme='light'] {
}
}
}
.ant-tabs-dropdown-menu {
&-title-content {
display: flex;
align-items: center;
.@{prefix-cls} {
&-content__info {
width: auto;
margin-left: 0;
line-height: 28px;
}
}
}
&-item-remove {
margin-left: auto;
}
}
.multiple-tabs__dropdown {
.ant-dropdown-content {
width: 172px;
}
}

View File

@@ -2,10 +2,10 @@ import { genMessage } from '../helper';
import antdLocale from 'ant-design-vue/es/locale/en_US';
//import momentLocale from 'moment/dist/locale/eu';
const modules = import.meta.globEager('./en/**/*.ts');
const modules = import.meta.glob('./en/**/*.ts', { eager: true });
export default {
message: {
...genMessage(modules, 'en'),
...genMessage(modules as Recordable<Recordable>, 'en'),
antdLocale,
},
dateLocale: null,

View File

@@ -1,10 +1,10 @@
import { genMessage } from '../helper';
import antdLocale from 'ant-design-vue/es/locale/zh_CN';
const modules = import.meta.globEager('./zh-CN/**/*.ts');
const modules = import.meta.glob('./zh-CN/**/*.ts', { eager: true });
export default {
message: {
...genMessage(modules, 'zh-CN'),
...genMessage(modules as Recordable<Recordable>, 'zh-CN'),
antdLocale,
},
};

View File

@@ -1,4 +1,4 @@
import { darkCssIsReady, loadDarkThemeCss } from 'vite-plugin-theme/es/client';
import { darkCssIsReady, loadDarkThemeCss } from '@rys-fe/vite-plugin-theme/es/client';
import { addClass, hasClass, removeClass } from '/@/utils/domUtils';
export async function updateDarkTheme(mode: string | null = 'light') {

View File

@@ -1,7 +1,7 @@
import { getThemeColors, generateColors } from '../../../build/config/themeConfig';
import { replaceStyleVariables } from 'vite-plugin-theme/es/client';
import { mixLighten, mixDarken, tinycolor } from 'vite-plugin-theme/es/colorUtils';
import { replaceStyleVariables } from '@rys-fe/vite-plugin-theme/es/client';
import { mixLighten, mixDarken, tinycolor } from '@rys-fe/vite-plugin-theme/es/colorUtils';
export async function changeTheme(color: string) {
const colors = generateColors({

View File

@@ -61,6 +61,7 @@ export function transformRouteToMenu(routeModList: AppRouteModule[], routerMappi
meta: node.meta,
name: title,
hideMenu,
alwaysShow:node.alwaysShow||false,
path: node.path,
...(node.redirect ? { redirect: node.redirect } : {}),
};

View File

@@ -8,6 +8,7 @@ import { createRouter, createWebHashHistory } from 'vue-router';
import { getTenantId, getToken } from '/@/utils/auth';
import { URL_HASH_TAB } from '/@/utils';
import { packageViews } from '/@/utils/monorepo/dynamicRouter';
import {useI18n} from "/@/hooks/web/useI18n";
export type LayoutMapKey = 'LAYOUT';
const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue');
@@ -31,6 +32,17 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
}
if (!routes) return;
routes.forEach((item) => {
//【jeecg-boot/issues/I5N2PN】左侧动态菜单怎么做国际化处理 2022-10-09
//菜单支持国际化翻译
if (item?.meta?.title) {
const { t } = useI18n();
if(item.meta.title.includes('t(\'') && t){
item.meta.title = eval(item.meta.title);
//console.log('译后: ',item.meta.title)
}
}
// update-begin--author:sunjianlei---date:20210918---for:适配旧版路由选项 --------
// @ts-ignore 适配隐藏路由
if (item?.hidden) {

View File

@@ -10,12 +10,12 @@ import { router } from '/@/router';
import { PermissionModeEnum } from '/@/enums/appEnum';
import { pathToRegexp } from 'path-to-regexp';
const modules = import.meta.globEager('./modules/**/*.ts');
const modules = import.meta.glob('./modules/**/*.ts', { eager: true });
const menuModules: MenuModule[] = [];
Object.keys(modules).forEach((key) => {
const mod = modules[key].default || {};
const mod = (modules as Recordable)[key].default || {};
const modList = Array.isArray(mod) ? [...mod] : [mod];
menuModules.push(...modList);
});

Some files were not shown because too many files have changed in this diff Show More