3.7.0里程碑版本发布(合并springboot3 sas分支)

springboot3_sas
JEECG 2024-06-22 19:31:55 +08:00
commit b296c8f6d5
308 changed files with 18437 additions and 6903 deletions

4
.env
View File

@ -4,8 +4,8 @@ VITE_PORT = 3100
# 网站标题 # 网站标题
VITE_GLOB_APP_TITLE = JeecgBoot 企业级低代码平台 VITE_GLOB_APP_TITLE = JeecgBoot 企业级低代码平台
# 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符 # 简称,此变量只能是字符/下划线
VITE_GLOB_APP_SHORT_NAME = JeecgBootAdmin VITE_GLOB_APP_SHORT_NAME = JeecgBoot_Pro
# 单点登录服务端地址 # 单点登录服务端地址
VITE_GLOB_APP_CAS_BASE_URL=http://cas.test.com:8443/cas VITE_GLOB_APP_CAS_BASE_URL=http://cas.test.com:8443/cas

View File

@ -7,7 +7,13 @@
##### 截图&代码: ##### 截图&代码:
##### 前端安装环境:
> 如果你是启动报错,请说明你的前端环境
- 采用的是pnpm安装还是yarn?
- node版本号
- pnpm版本号
#### 友情提示为了提高issue处理效率 #### 友情提示为了提高issue处理效率
- 未按格式要求发帖,会被直接删掉; - 未按格式要求发帖,会被直接删掉;

View File

@ -1,11 +1,11 @@
JEECG BOOT 低代码开发平台Vue3前端 JeecgBoot 企业级低代码开发平台
=============== ===============
当前最新版本: 3.6.2发布时间2024-01-08 当前最新版本: 3.7.0发布时间2024-06-17
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE) [![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://jeecg.com/aboutusIndex) [![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](http://jeecg.com/aboutusIndex)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net) [![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.6.2-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot) [![](https://img.shields.io/badge/version-3.7.0-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 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) [![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
@ -13,28 +13,25 @@ JEECG BOOT 低代码开发平台Vue3前端
## 简介 ## 简介
JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue4、TypeScript 等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。 JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue4、TypeScript 等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。
是采用Vben实现的 JeecgBoot低代码平台的全新vue3版本。
> 强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性 > 强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性
## 技术支持 ## 技术支持
关闭Gitee的issue通道使用中遇到问题或BUG可以在 [Github上提Issues](https://github.com/jeecgboot/jeecgboot-vue3/issues/new) 使用中遇到问题或BUG可以在主项目的 [Github上提Issues](https://github.com/jeecgboot/JeecgBoot/issues/new)
官方支持: http://jeecg.com/doc/help ##### 源码下载
- JAVA后台源码https://github.com/jeecgboot/JeecgBoot
## 源码下载
- 后台源码 https://github.com/jeecgboot/jeecg-boot
- 前端源码 https://github.com/jeecgboot/jeecgboot-vue3
##### 项目说明 ##### 项目说明
| 项目名 | 说明 | | 项目名 | 说明 |
|--------------------|-----------------------------------------| |--------------------|-----------------------------------------|
| `jeecgboot-vue3` | 前端源码Vue3版下载 | | `jeecgboot-vue3` | 前端源码Vue3 |
| `jeecg-boot` | 后端JAVA源码下载SpringBoot+SpringCloud | | `jeecg-boot` | 后端源码JAVASpringBoot+SpringCloud |
## 开发环境搭建 ## 开发环境搭建
@ -45,10 +42,9 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue4、TypeScript 等新技术
## 技术文档 ## 技术文档
- 官方文档:[https://help.jeecg.com](https://help.jeecg.com) - 官方文档:[https://help.jeecg.com](https://help.jeecg.com)
- 官方网站: [https://www.jeecg.com](https://www.jeecg.com)
- 快速入门:[快速入门](http://jeecg.com/doc/quickstart) | [常见问题](http://help.jeecg.com/qa.html) | [视频教程](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://help.jeecg.com/vue3/codegen/online.html) - 快速入门:[快速入门](http://jeecg.com/doc/quickstart) | [常见问题](http://help.jeecg.com/qa.html) | [视频教程](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://help.jeecg.com/vue3/codegen/online.html)
- QQ交流群⑧825232878、⑦791696430(满)、683903138(满) - QQ交流群⑨808791225、⑧825232878(满)、⑦791696430(满)、683903138(满)、其他满
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)| [敲敲云零代码](https://www.qiaoqiaoyun.com) - 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取 > 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
@ -86,7 +82,7 @@ VITE_GLOB_DOMAIN_URL=http://localhost:8080/jeecg-boot
- run - run
```bash ```bash
pnpm serve pnpm dev
``` ```

View File

@ -50,7 +50,9 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
*/ */
function getConfFiles() { function getConfFiles() {
const script = process.env.npm_lifecycle_script; const script = process.env.npm_lifecycle_script;
const reg = new RegExp('--mode ([a-z_\\d]+)'); // update-begin--author:liaozhiyang---date:20240326---for【QQYUN-8690】修正获取当前环境下的文件名
const reg = new RegExp('NODE_ENV=([a-z_\\d]+)');
// update-end--author:liaozhiyang---date:20240326---for【QQYUN-8690】修正获取当前环境下的文件名
const result = reg.exec(script as string) as any; const result = reg.exec(script as string) as any;
if (result) { if (result) {
const mode = result[1] as string; const mode = result[1] as string;

View File

@ -5,6 +5,7 @@ import purgeIcons from 'vite-plugin-purge-icons';
import UnoCSS from 'unocss/vite'; import UnoCSS from 'unocss/vite';
import { presetTypography, presetUno } from 'unocss'; import { presetTypography, presetUno } from 'unocss';
// 本地调试https配置方法
import VitePluginCertificate from 'vite-plugin-mkcert'; import VitePluginCertificate from 'vite-plugin-mkcert';
//[issues/555]开发环境vscode断点调试文件或行数对不上 //[issues/555]开发环境vscode断点调试文件或行数对不上
import vueSetupExtend from 'vite-plugin-vue-setup-extend-plus'; import vueSetupExtend from 'vite-plugin-vue-setup-extend-plus';

View File

@ -6,10 +6,19 @@ const demoList = (keyword, count = 20) => {
list: [] as any[], list: [] as any[],
}; };
for (let index = 0; index < count; index++) { for (let index = 0; index < count; index++) {
result.list.push({ //根据搜索关键词做一下匹配
name: `${keyword ?? ''}选项${index}`, let name = `选项${index}`;
id: `${index}`, if(keyword && name.indexOf(keyword)!=-1){
}); result.list.push({
name: `选项${index}`,
id: `${index}`,
});
}else if(!keyword){
result.list.push({
name: `选项${index}`,
id: `${index}`,
});
}
} }
return result; return result;
}; };

View File

@ -30,6 +30,8 @@ const demoList = (() => {
avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()), avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()),
imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1), imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1),
imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1), imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1),
age: Math.ceil(Math.random() * 30) + 1,
score: Math.ceil(Math.random() * 80) + 1,
date: `@date('yyyy-MM-dd')`, date: `@date('yyyy-MM-dd')`,
time: `@time('HH:mm')`, time: `@time('HH:mm')`,
'no|100000-10000000': 100000, 'no|100000-10000000': 100000,

View File

@ -1,10 +1,10 @@
{ {
"name": "jeecgboot-vue3", "name": "jeecgboot-vue3",
"version": "3.6.2", "version": "3.7.0",
"author": { "author": {
"name": "北京国炬信息技术有限公司", "name": "北京国炬信息技术有限公司",
"email": "jeecgos@163.com", "email": "jeecgos@163.com",
"url": "https://github.com/jeecgboot/jeecgboot-vue3" "url": "https://www.jeecg.com"
}, },
"scripts": { "scripts": {
"pinstall": "pnpm install", "pinstall": "pnpm install",
@ -21,149 +21,150 @@
"husky:install": "husky install" "husky:install": "husky install"
}, },
"dependencies": { "dependencies": {
"@jeecg/online": "3.6.2-beta", "@jeecg/online": "3.7.0-beta",
"@iconify/iconify": "^3.1.1", "@iconify/iconify": "^3.1.1",
"@ant-design/colors": "^7.0.0", "@ant-design/colors": "^7.0.2",
"@ant-design/icons-vue": "^7.0.1", "@ant-design/icons-vue": "^7.0.1",
"@logicflow/core": "^1.2.12", "@vue/shared": "^3.4.19",
"@logicflow/extension": "^1.2.13", "@vueuse/core": "^10.8.0",
"@vue/runtime-core": "^3.3.4", "@tinymce/tinymce-vue": "4.0.7",
"@vue/shared": "^3.3.4", "@zxcvbn-ts/core": "^3.0.4",
"@vueuse/shared": "^10.4.1", "ant-design-vue": "^4.1.2",
"@vueuse/core": "^10.4.1", "axios": "^1.6.7",
"@tinymce/tinymce-vue": "^4.0.7",
"@zxcvbn-ts/core": "^3.0.3",
"ant-design-vue": "^4.0.8",
"axios": "^1.5.0",
"china-area-data": "^5.0.1", "china-area-data": "^5.0.1",
"clipboard": "^2.0.11", "clipboard": "^2.0.11",
"codemirror": "^5.65.3", "codemirror": "^5.65.3",
"cron-parser": "^4.9.0", "cron-parser": "^4.9.0",
"cropperjs": "^1.5.13", "cropperjs": "^1.6.1",
"crypto-js": "^4.1.1", "crypto-js": "^4.2.0",
"dayjs": "^1.11.9", "dayjs": "^1.11.10",
"dom-align": "^1.12.4", "dom-align": "^1.12.4",
"echarts": "^5.4.3", "echarts": "^5.4.3",
"emoji-mart-vue-fast": "^15.0.0", "emoji-mart-vue-fast": "^15.0.1",
"enquire.js": "^2.1.6", "enquire.js": "^2.1.6",
"intro.js": "^7.2.0", "intro.js": "^7.2.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lodash.get": "^4.4.2", "lodash.get": "^4.4.2",
"markdown-it": "^14.0.0",
"markdown-it-link-attributes": "^4.0.1",
"event-source-polyfill": "^1.0.31",
"highlight.js": "^11.9.0",
"@traptitech/markdown-it-katex": "^3.6.0",
"md5": "^2.3.0", "md5": "^2.3.0",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"path-to-regexp": "^6.2.1", "path-to-regexp": "^6.2.1",
"pinia": "2.1.6", "pinia": "2.1.7",
"print-js": "^1.6.0", "print-js": "^1.6.0",
"qs": "^6.11.2", "qs": "^6.11.2",
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"qrcodejs2": "0.0.2",
"resize-observer-polyfill": "^1.5.1", "resize-observer-polyfill": "^1.5.1",
"showdown": "^2.1.0", "showdown": "^2.1.0",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.2",
"tinymce": "^6.6.2", "tinymce": "6.6.2",
"vditor": "^3.9.5", "vditor": "^3.9.9",
"vue": "3.3.11", "vue": "^3.4.19",
"vue-cropper": "^0.6.2", "vue-cropper": "^0.6.4",
"vue-cropperjs": "^5.0.0", "vue-cropperjs": "^5.0.0",
"vue-i18n": "9.2.2", "vue-i18n": "^9.9.1",
"vue-infinite-scroll": "^2.0.2", "vue-infinite-scroll": "^2.0.2",
"vue-print-nb-jeecg": "^1.0.12", "vue-print-nb-jeecg": "^1.0.12",
"vue-router": "^4.2.4", "vue-router": "^4.3.0",
"vue-types": "^5.1.1", "vue-types": "^5.1.1",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"vxe-table": "4.5.12", "vxe-table": "4.6.17",
"vxe-table-plugin-antd": "3.1.0", "vxe-table-plugin-antd": "4.0.7",
"xe-utils": "3.5.13", "xe-utils": "3.5.26",
"vue-json-pretty": "^2.2.4",
"xss": "^1.0.14" "xss": "^1.0.14"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.7.1", "@commitlint/cli": "^18.6.1",
"@commitlint/config-conventional": "^17.7.0", "@commitlint/config-conventional": "^18.6.2",
"@iconify/json": "^2.2.107", "@iconify/json": "^2.2.185",
"@purge-icons/generated": "^0.9.0", "@purge-icons/generated": "^0.10.0",
"@types/codemirror": "^5.60.9", "@types/codemirror": "^5.60.15",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.2.2",
"@types/fs-extra": "^11.0.1", "@types/fs-extra": "^11.0.4",
"@types/inquirer": "^9.0.3", "@types/inquirer": "^9.0.7",
"@types/intro.js": "^5.1.1", "@types/intro.js": "^5.1.5",
"@types/jest": "^29.5.4", "@types/jest": "^29.5.12",
"@types/lodash-es": "^4.17.8", "@types/lodash-es": "^4.17.12",
"@types/mockjs": "^1.0.7", "@types/mockjs": "^1.0.10",
"@types/node": "^20.5.6", "@types/node": "^20.11.19",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.3",
"@types/qrcode": "^1.5.1", "@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.11",
"@types/showdown": "^2.0.1", "@types/showdown": "^2.0.6",
"@types/sortablejs": "^1.15.1", "@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^6.4.1", "@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.5.0", "@typescript-eslint/parser": "^6.17.0",
"@vitejs/plugin-vue": "^4.3.3", "@vitejs/plugin-vue": "^4.3.3",
"@vitejs/plugin-vue-jsx": "^3.0.2", "@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "^3.3.4", "@vue/compiler-sfc": "^3.4.4",
"@vue/test-utils": "^2.4.1", "@vue/test-utils": "^2.4.4",
"autoprefixer": "^10.4.15", "autoprefixer": "^10.4.17",
"commitizen": "^4.3.0", "commitizen": "^4.3.0",
"conventional-changelog-cli": "^3.0.0", "conventional-changelog-cli": "^4.1.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"cz-git": "^1.7.1", "cz-git": "^1.8.0",
"czg": "^1.7.1", "czg": "^1.8.0",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"eslint": "^8.47.0", "eslint": "^8.56.0",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^1.23.0", "eslint-define-config": "^2.1.0",
"eslint-plugin-jest": "^27.2.3", "eslint-plugin-jest": "^27.9.0",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-vue": "^9.17.0", "eslint-plugin-vue": "^9.21.1",
"esno": "^0.17.0", "esno": "^4.0.0",
"fs-extra": "^11.1.1", "fs-extra": "^11.2.0",
"http-server": "^14.1.1", "http-server": "^14.1.1",
"husky": "^8.0.3", "husky": "^8.0.3",
"inquirer": "^9.2.10", "inquirer": "^9.2.15",
"is-ci": "^3.0.1", "is-ci": "^3.0.1",
"jest": "^29.6.4", "jest": "^29.7.0",
"less": "^4.2.0", "less": "^4.2.0",
"lint-staged": "14.0.1", "lint-staged": "15.2.2",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"postcss": "^8.4.28", "postcss": "^8.4.35",
"postcss-html": "^1.5.0", "postcss-html": "^1.6.0",
"postcss-less": "^6.0.0", "postcss-less": "^6.0.0",
"prettier": "^3.0.2", "prettier": "^3.2.5",
"pretty-quick": "^3.1.3", "pretty-quick": "^4.0.0",
"rimraf": "^5.0.1", "rimraf": "^5.0.5",
"rollup": "^3.28.1", "rollup": "^4.12.0",
"rollup-plugin-visualizer": "^5.9.2", "rollup-plugin-visualizer": "^5.12.0",
"stylelint": "^15.10.3", "stylelint": "^16.2.1",
"stylelint-config-prettier": "^9.0.5", "stylelint-config-prettier": "^9.0.5",
"stylelint-config-recommended": "^13.0.0", "stylelint-config-recommended": "^14.0.0",
"stylelint-config-recommended-vue": "^1.5.0", "stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard": "^34.0.0", "stylelint-config-standard": "^36.0.0",
"stylelint-order": "^6.0.3", "stylelint-order": "^6.0.4",
"ts-jest": "^29.1.1", "ts-jest": "^29.1.2",
"ts-node": "^10.9.1", "ts-node": "^10.9.2",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"vite": "^4.4.9", "vite": "^5.2.11",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0", "vite-plugin-html": "^3.2.2",
"vite-plugin-mkcert": "^1.16.0", "vite-plugin-mkcert": "^1.17.3",
"vite-plugin-mock": "^2.9.6", "vite-plugin-mock": "^2.9.6",
"vite-plugin-purge-icons": "^0.9.2", "vite-plugin-optimize-persist": "^0.1.2",
"vite-plugin-package-config": "^0.1.1",
"vite-plugin-purge-icons": "^0.10.0",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svg-icons": "^2.0.1",
"@rys-fe/vite-plugin-theme": "^0.8.6", "@rys-fe/vite-plugin-theme": "^0.8.6",
"vite-plugin-vue-setup-extend-plus": "^0.1.0", "vite-plugin-vue-setup-extend-plus": "^0.1.0",
"unocss": "^0.55.3", "unocss": "^0.58.5",
"vue-eslint-parser": "^9.3.1", "vue-eslint-parser": "^9.4.2",
"vue-tsc": "^1.8.8" "vue-tsc": "^1.8.27"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/jeecgboot/jeecgboot-vue3.git" "url": "git+https://github.com/jeecgboot/JeecgBoot.git"
}, },
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/jeecgboot/jeecgboot-vue3/issues" "url": "https://github.com/jeecgboot/JeecgBoot/issues"
}, },
"homepage": "https://www.jeecg.com", "homepage": "https://www.jeecg.com",
"engines": { "engines": {

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,20 @@
const { getAntdLocale } = useLocale(); const { getAntdLocale } = useLocale();
useTitle(); useTitle();
/**
* 2024-04-07
* liaozhiyang
* 暗黑模式下默认文字白色白天模式默认文字 #333
* */
const modeAction = (data) => {
if (data.token) {
if (getDarkMode.value === ThemeEnum.DARK) {
Object.assign(data.token, { colorTextBase: 'fff' });
} else {
Object.assign(data.token, { colorTextBase: '#333' });
}
}
};
// update-begin--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x // update-begin--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x
const appTheme: any = ref({}); const appTheme: any = ref({});
const { getDarkMode } = useRootSetting(); const { getDarkMode } = useRootSetting();
@ -35,6 +49,12 @@
if (newValue === ThemeEnum.DARK) { if (newValue === ThemeEnum.DARK) {
appTheme.value.algorithm = theme.darkAlgorithm; appTheme.value.algorithm = theme.darkAlgorithm;
} }
// update-begin--author:liaozhiyang---date:20240322---forQQYUN-8570
if (import.meta.env.PROD) {
changeTheme(appStore.getProjectConfig.themeColor);
}
// update-end--author:liaozhiyang---date:20240322---forQQYUN-8570
modeAction(appTheme.value);
appTheme.value = { appTheme.value = {
...appTheme.value, ...appTheme.value,
}; };
@ -45,23 +65,28 @@
appStore.getProjectConfig, appStore.getProjectConfig,
(newValue) => { (newValue) => {
const primary = newValue.themeColor; const primary = newValue.themeColor;
appTheme.value = { const result = {
...appTheme.value, ...appTheme.value,
...{ ...{
token: { token: {
colorPrimary: primary, colorPrimary: primary,
wireframe: true, wireframe: true,
fontSize: 14, fontSize: 14,
colorTextBase: '#333',
colorSuccess: '#55D187', colorSuccess: '#55D187',
colorInfo: primary, colorInfo: primary,
borderRadius: 2, borderRadius: 4,
sizeStep: 4, sizeStep: 4,
sizeUnit: 4, sizeUnit: 4,
colorWarning: '#EFBD47', colorWarning: '#EFBD47',
colorError: '#ED6F6F', colorError: '#ED6F6F',
fontFamily:
'-apple-system,BlinkMacSystemFont,Segoe UI,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol',
}, },
}, },
}; };
appTheme.value = result;
modeAction(result);
}, },
{ immediate: true } { immediate: true }
); );
@ -69,6 +94,7 @@
appStore.getProjectConfig?.themeColor && changeTheme(appStore.getProjectConfig.themeColor); appStore.getProjectConfig?.themeColor && changeTheme(appStore.getProjectConfig.themeColor);
}, 300); }, 300);
// update-end--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x // update-end--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x
</script> </script>
<style lang="less"> <style lang="less">
// update-begin--author:liaozhiyang---date:20230803---forQQYUN-5839windihtml2canvas // update-begin--author:liaozhiyang---date:20230803---forQQYUN-5839windihtml2canvas

View File

@ -3,7 +3,8 @@ import { getMenuListResultModel } from './model/menuModel';
enum Api { enum Api {
GetMenuList = '/sys/permission/getUserPermissionByToken', GetMenuList = '/sys/permission/getUserPermissionByToken',
SwitchVue3Menu = '/sys/switchVue3Menu', // 【QQYUN-8487】
// SwitchVue3Menu = '/sys/switchVue3Menu',
} }
/** /**
@ -23,11 +24,20 @@ export const getMenuList = () => {
}); });
}; };
/**
* @description:
*/
export function getBackMenuAndPerms() {
return defHttp.get({ url: Api.GetMenuList });
}
/** /**
* vue3 * vue3
*/ */
export const switchVue3Menu = () => { // update-begin--author:liaozhiyang---date:20240313---for【QQYUN-8487】注释掉判断菜单是否vue2版本逻辑代码
return new Promise((resolve) => { // export const switchVue3Menu = () => {
defHttp.get({ url: Api.SwitchVue3Menu }); // return new Promise((resolve) => {
}); // defHttp.get({ url: Api.SwitchVue3Menu });
}; // });
// };
// update-end--author:liaozhiyang---date:20240313---for【QQYUN-8487】注释掉判断菜单是否vue2版本逻辑代码

View File

@ -8,6 +8,7 @@ import { setAuthCache } from '/@/utils/auth';
import { TOKEN_KEY } from '/@/enums/cacheEnum'; import { TOKEN_KEY } from '/@/enums/cacheEnum';
import { router } from '/@/router'; import { router } from '/@/router';
import { PageEnum } from '/@/enums/pageEnum'; import { PageEnum } from '/@/enums/pageEnum';
import { ExceptionEnum } from "@/enums/exceptionEnum";
const { createErrorModal } = useMessage(); const { createErrorModal } = useMessage();
enum Api { enum Api {
@ -132,9 +133,17 @@ export function getCaptcha(params) {
if (res.success) { if (res.success) {
resolve(true); resolve(true);
} else { } else {
createErrorModal({ title: '错误提示', content: res.message || '未知问题' }); //update-begin---author:wangshuai---date:2024-04-18---for:【QQYUN-9005】同一个IP1分钟超过5次短信则提示需要验证码---
reject(); if(res.code != ExceptionEnum.PHONE_SMS_FAIL_CODE){
createErrorModal({ title: '错误提示', content: res.message || '未知问题' });
reject();
}
reject(res);
//update-end---author:wangshuai---date:2024-04-18---for:【QQYUN-9005】同一个IP1分钟超过5次短信则提示需要验证码---
} }
}).catch((res)=>{
createErrorModal({ title: '错误提示', content: res.message || '未知问题' });
reject();
}); });
}); });
} }

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1713356465646" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5683" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M320.067666 286.437731c53.150524-53.15564 126.532835-86.077447 207.455889-86.077447 89.598644 0 172.483376 40.805358 227.39501 108.063181l-101.596909 101.603049 251.597225 0L904.918881 158.424172l-90.333378 90.361007C743.985562 166.207439 639.765919 116.493178 527.524578 116.493178c-104.055914 0-198.409862 42.322921-266.757506 110.670565-49.444109 49.455365-84.98865 112.251573-100.999298 182.862771l86.263689 0C260.052804 362.352725 285.750069 320.744072 320.067666 286.437731L320.067666 286.437731z" fill="#272636" p-id="5684"></path><path d="M734.974327 701.344393c-53.151547 53.15564-126.533858 86.083587-207.450772 86.083587-89.599667 0-172.488493-40.810474-227.402173-108.069321l101.603049-101.596909L150.122089 577.76175 150.122089 829.358975l90.333378-90.333378c70.601988 82.555228 174.820608 132.270513 287.067065 132.270513 104.055914 0 198.402699-42.306548 266.750343-110.650099 49.360198-49.397037 84.866876-112.477724 100.920504-182.883237L808.689213 577.762773C794.560424 624.99654 768.983909 667.338904 734.974327 701.344393L734.974327 701.344393z" fill="#272636" p-id="5685"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -6,7 +6,7 @@
<div class="anticon" :class="getAppLogoClass" @click="goHome"> <div class="anticon" :class="getAppLogoClass" @click="goHome">
<img src="../../../assets/images/logo.png" /> <img src="../../../assets/images/logo.png" />
<div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle"> <div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
{{ title }} {{ shortTitle }}
</div> </div>
</div> </div>
</template> </template>
@ -37,7 +37,8 @@
const { prefixCls } = useDesign('app-logo'); const { prefixCls } = useDesign('app-logo');
const { getCollapsedShowTitle } = useMenuSetting(); const { getCollapsedShowTitle } = useMenuSetting();
const userStore = useUserStore(); const userStore = useUserStore();
const { title } = useGlobSetting(); const { title, shortTitle } = useGlobSetting();
const go = useGo(); const go = useGo();
const getAppLogoClass = computed(() => [prefixCls, props.theme, { 'collapsed-show-title': unref(getCollapsedShowTitle) }]); const getAppLogoClass = computed(() => [prefixCls, props.theme, { 'collapsed-show-title': unref(getCollapsedShowTitle) }]);
@ -83,8 +84,8 @@
} }
&__title { &__title {
font-size: 16px; font-size: 18px;
font-weight: 700; font-weight: 600;
transition: all 0.5s; transition: all 0.5s;
line-height: normal; line-height: normal;
} }

View File

@ -7,11 +7,13 @@ import { useGo } from '/@/hooks/web/usePage';
import { useScrollTo } from '/@/hooks/event/useScrollTo'; import { useScrollTo } from '/@/hooks/event/useScrollTo';
import { onKeyStroke, useDebounceFn } from '@vueuse/core'; import { onKeyStroke, useDebounceFn } from '@vueuse/core';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { URL_HASH_TAB } from '/@/utils';
export interface SearchResult { export interface SearchResult {
name: string; name: string;
path: string; path: string;
icon?: string; icon?: string;
internalOrExternal: boolean;
} }
// Translate special characters // Translate special characters
@ -23,7 +25,7 @@ function transform(c: string) {
function createSearchReg(key: string) { function createSearchReg(key: string) {
const keys = [...key].map((item) => transform(item)); const keys = [...key].map((item) => transform(item));
const str = ['', ...keys, ''].join('.*'); const str = ['', ...keys, ''].join('.*');
return new RegExp(str); return new RegExp(str, 'i');
} }
export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>, emit: EmitType) { export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>, emit: EmitType) {
@ -68,12 +70,13 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) { function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) {
const ret: SearchResult[] = []; const ret: SearchResult[] = [];
filterMenu.forEach((item) => { filterMenu.forEach((item) => {
const { name, path, icon, children, hideMenu, meta } = item; const { name, path, icon, children, hideMenu, meta, internalOrExternal } = item;
if (!hideMenu && reg.test(name) && (!children?.length || meta?.hideChildrenInMenu)) { if (!hideMenu && reg.test(name) && (!children?.length || meta?.hideChildrenInMenu)) {
ret.push({ ret.push({
name: parent?.name ? `${parent.name} > ${name}` : name, name: parent?.name ? `${parent.name} > ${name}` : name,
path, path,
icon, icon,
internalOrExternal
}); });
} }
if (!meta?.hideChildrenInMenu && Array.isArray(children) && children.length) { if (!meta?.hideChildrenInMenu && Array.isArray(children) && children.length) {
@ -149,7 +152,17 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
const to = result[index]; const to = result[index];
handleClose(); handleClose();
await nextTick(); await nextTick();
go(to.path);
// update-begin--author:liaozhiyang---date:20230803---for【QQYUN-8369】搜索区分大小写外部链接新页打开
if (to.internalOrExternal) {
// update-begin--author:liaozhiyang---date:20240402---for:【QQYUN-8773】配置外部网址在顶部菜单模式和搜索打不开
const path = to.path.replace(URL_HASH_TAB, '#');
window.open(path, '_blank');
// update-end--author:liaozhiyang---date:20240402---for:【QQYUN-8773】配置外部网址在顶部菜单模式和搜索打不开
} else {
go(to.path);
}
// update-end--author:liaozhiyang---date:20230803---for【QQYUN-8369】搜索区分大小写外部链接新页打开
} }
// close search modal // close search modal

View File

@ -1,6 +1,4 @@
import { withInstall } from '/@/utils'; import { withInstall } from '/@/utils';
import codeEditor from './src/CodeEditor.vue'; import codeEditor from './src/CodeEditor.vue';
import jsonPreview from './src/json-preview/JsonPreview.vue';
export const CodeEditor = withInstall(codeEditor); export const CodeEditor = withInstall(codeEditor);
export const JsonPreview = withInstall(jsonPreview);

View File

@ -1,12 +0,0 @@
<template>
<vue-json-pretty :path="'res'" :deep="3" :showLength="true" :data="data" />
</template>
<script lang="ts" setup>
import VueJsonPretty from 'vue-json-pretty';
import 'vue-json-pretty/lib/styles.css';
defineProps({
data: Object,
});
</script>

View File

@ -2,6 +2,8 @@
<Button v-bind="$attrs" :disabled="isStart" @click="handleStart" :loading="loading"> <Button v-bind="$attrs" :disabled="isStart" @click="handleStart" :loading="loading">
{{ getButtonText }} {{ getButtonText }}
</Button> </Button>
<!-- 图片验证码弹窗 -->
<CaptchaModal @register="captchaRegisterModal" @ok="handleStart" />
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, watchEffect, computed, unref } from 'vue'; import { defineComponent, ref, watchEffect, computed, unref } from 'vue';
@ -9,6 +11,11 @@
import { useCountdown } from './useCountdown'; import { useCountdown } from './useCountdown';
import { isFunction } from '/@/utils/is'; import { isFunction } from '/@/utils/is';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useModal } from "@/components/Modal";
import { createAsyncComponent } from "@/utils/factory/createAsyncComponent";
import { ExceptionEnum } from "@/enums/exceptionEnum";
const CaptchaModal = createAsyncComponent(() => import('/@/components/jeecg/captcha/CaptchaModal.vue'));
const [captchaRegisterModal, { openModal: openCaptchaModal }] = useModal();
const props = { const props = {
value: { type: [Object, Number, String, Array] }, value: { type: [Object, Number, String, Array] },
@ -21,7 +28,7 @@
export default defineComponent({ export default defineComponent({
name: 'CountButton', name: 'CountButton',
components: { Button }, components: { Button, CaptchaModal },
props, props,
setup(props) { setup(props) {
const loading = ref(false); const loading = ref(false);
@ -45,7 +52,13 @@
if (beforeStartFunc && isFunction(beforeStartFunc)) { if (beforeStartFunc && isFunction(beforeStartFunc)) {
loading.value = true; loading.value = true;
try { try {
const canStart = await beforeStartFunc(); //update-begin---author:wangshuai---date:2024-04-18---for:QQYUN-9005IP15---
const canStart = await beforeStartFunc().catch((res) =>{
if(res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE){
openCaptchaModal(true, {});
}
});
//update-end---author:wangshuai---date:2024-04-18---for:QQYUN-9005IP15---
canStart && start(); canStart && start();
} finally { } finally {
loading.value = false; loading.value = false;
@ -54,7 +67,7 @@
start(); start();
} }
} }
return { handleStart, currentCount, loading, getButtonText, isStart }; return { handleStart, currentCount, loading, getButtonText, isStart, captchaRegisterModal };
}, },
}); });
</script> </script>

View File

@ -9,7 +9,7 @@
import Cropper from 'cropperjs'; import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css'; import 'cropperjs/dist/cropper.css';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useDebounceFn } from '@vueuse/shared'; import { useDebounceFn } from '@vueuse/core';
type Options = Cropper.Options; type Options = Cropper.Options;

View File

@ -35,6 +35,7 @@
import { basicProps } from './props'; import { basicProps } from './props';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { cloneDeep } from 'lodash-es';
export default defineComponent({ export default defineComponent({
components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader }, components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader },
@ -59,7 +60,9 @@
instance && emit('register', drawerInstance, instance.uid); instance && emit('register', drawerInstance, instance.uid);
const getMergeProps = computed((): DrawerProps => { const getMergeProps = computed((): DrawerProps => {
return deepMerge(toRaw(props), unref(propsRef)); // update-begin--author:liaozhiyang---date:20240320---forQQYUN-8389vue3.4footertoRawcloneDeeppropscomputed
return { ...deepMerge(cloneDeep(props), unref(propsRef)) };
// update-end--author:liaozhiyang---date:20240320---forQQYUN-8389vue3.4footertoRawcloneDeeppropscomputed
}); });
const getProps = computed((): DrawerProps => { const getProps = computed((): DrawerProps => {
@ -86,6 +89,7 @@
opt.getContainer = `.${prefixVar}-layout-content` as any; opt.getContainer = `.${prefixVar}-layout-content` as any;
} }
} }
console.log('getProps:opt',opt);
return opt as DrawerProps; return opt as DrawerProps;
}); });

View File

@ -12,6 +12,8 @@
:formModel="formModel" :formModel="formModel"
:setFormModel="setFormModel" :setFormModel="setFormModel"
:validateFields="validateFields" :validateFields="validateFields"
:clearValidate="clearValidate"
v-auth="schema.auth"
> >
<template #[item]="data" v-for="item in Object.keys($slots)"> <template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data || {}"></slot> <slot :name="item" v-bind="data || {}"></slot>
@ -109,6 +111,7 @@
prefixCls, prefixCls,
{ {
[`${prefixCls}--compact`]: unref(getProps).compact, [`${prefixCls}--compact`]: unref(getProps).compact,
'jeecg-form-detail-effect': unref(getProps).disabled
}, },
]; ];
}); });
@ -142,7 +145,10 @@
if (!Array.isArray(defaultValue)) { if (!Array.isArray(defaultValue)) {
//update-begin---author:wangshuai ---date:20221124 for[issues/215]------------ //update-begin---author:wangshuai ---date:20221124 for[issues/215]------------
if(valueFormat){ if(valueFormat){
schema.defaultValue = dateUtil(defaultValue).format(valueFormat); // schema.defaultValue = dateUtil(defaultValue).format(valueFormat);
// update-begin--author:liaozhiyang---date:20240529---forTV360X-346
schema.defaultValue = dateUtil(defaultValue, valueFormat).format(valueFormat);
// update-end--author:liaozhiyang---date:20240529---forTV360X-346
}else{ }else{
schema.defaultValue = dateUtil(defaultValue); schema.defaultValue = dateUtil(defaultValue);
} }
@ -152,13 +158,19 @@
defaultValue.forEach((item) => { defaultValue.forEach((item) => {
//update-begin---author:wangshuai ---date:20221124 for[issues/215]------------ //update-begin---author:wangshuai ---date:20221124 for[issues/215]------------
if(valueFormat){ if(valueFormat){
def.push(dateUtil(item).format(valueFormat)); // update-begin--author:liaozhiyang---date:20240529---forTV360X-346
def.push(dateUtil(item, valueFormat).format(valueFormat));
// update-end--author:liaozhiyang---date:20240529---forTV360X-346
}else{ }else{
def.push(dateUtil(item)); def.push(dateUtil(item));
} }
//update-end---author:wangshuai ---date:20221124 for[issues/215]------------ //update-end---author:wangshuai ---date:20221124 for[issues/215]------------
}); });
schema.defaultValue = def; // update-begin--author:liaozhiyang---date:20240328---forissues/1114rangepickervue3.4
def.forEach((item, index) => {
defaultValue[index] = item;
});
// update-end--author:liaozhiyang---date:20240328---forissues/1114rangepickervue3.4
} }
} }
} }
@ -342,11 +354,16 @@
&-with-help { &-with-help {
margin-bottom: 0; margin-bottom: 0;
} }
// update-begin--author:liaozhiyang---date:20240514---forQQYUN-9241form
&:not(.ant-form-item-with-help) { //&:not(.ant-form-item-with-help) {
margin-bottom: 20px; // margin-bottom: 24px;
//}
// update-begin--author:liaozhiyang---date:20240514---forQQYUN-9241form
// update-begin--author:liaozhiyang---date:20240620---forTV360X-1420
&-has-error {
margin-bottom: 24px;
} }
// update-end--author:liaozhiyang---date:20240620---forTV360X-1420
&.suffix-item { &.suffix-item {
.ant-form-item-children { .ant-form-item-children {
display: flex; display: flex;
@ -366,7 +383,7 @@
} }
} }
/*【美化表单】form的字体改小一号*/ /*【美化表单】form的字体改小一号*/
.ant-form-item-label > label{ /* .ant-form-item-label > label{
font-size: 13px; font-size: 13px;
} }
.ant-form-item .ant-select { .ant-form-item .ant-select {
@ -380,7 +397,7 @@
} }
.ant-input { .ant-input {
font-size: 13px; font-size: 13px;
} }*/
/*【美化表单】form的字体改小一号*/ /*【美化表单】form的字体改小一号*/
.ant-form-explain { .ant-form-explain {

View File

@ -1,6 +1,14 @@
/**
*
* JAreaLinkage
* JEditor
* JMarkdownEditor
* JCodeEditor
* JEasyCron
*/
import type { Component } from 'vue'; import type { Component } from 'vue';
import type { ComponentType } from './types/index'; import type { ComponentType } from './types/index';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
/** /**
* Component list, register here to setting it in the form * Component list, register here to setting it in the form
*/ */
@ -29,7 +37,7 @@ import { StrengthMeter } from '/@/components/StrengthMeter';
import { IconPicker } from '/@/components/Icon'; import { IconPicker } from '/@/components/Icon';
import { CountdownInput } from '/@/components/CountDown'; import { CountdownInput } from '/@/components/CountDown';
//自定义组件 //自定义组件
import JAreaLinkage from './jeecg/components/JAreaLinkage.vue'; // import JAreaLinkage from './jeecg/components/JAreaLinkage.vue';
import JSelectUser from './jeecg/components/JSelectUser.vue'; import JSelectUser from './jeecg/components/JSelectUser.vue';
import JSelectPosition from './jeecg/components/JSelectPosition.vue'; import JSelectPosition from './jeecg/components/JSelectPosition.vue';
import JSelectRole from './jeecg/components/JSelectRole.vue'; import JSelectRole from './jeecg/components/JSelectRole.vue';
@ -38,16 +46,19 @@ import JDictSelectTag from './jeecg/components/JDictSelectTag.vue';
import JSelectDept from './jeecg/components/JSelectDept.vue'; import JSelectDept from './jeecg/components/JSelectDept.vue';
import JAreaSelect from './jeecg/components/JAreaSelect.vue'; import JAreaSelect from './jeecg/components/JAreaSelect.vue';
import JEditor from './jeecg/components/JEditor.vue'; import JEditor from './jeecg/components/JEditor.vue';
import JMarkdownEditor from './jeecg/components/JMarkdownEditor.vue'; // import JMarkdownEditor from './jeecg/components/JMarkdownEditor.vue';
import JSelectInput from './jeecg/components/JSelectInput.vue'; import JSelectInput from './jeecg/components/JSelectInput.vue';
import JCodeEditor from './jeecg/components/JCodeEditor.vue'; // import JCodeEditor from './jeecg/components/JCodeEditor.vue';
import JCategorySelect from './jeecg/components/JCategorySelect.vue'; import JCategorySelect from './jeecg/components/JCategorySelect.vue';
import JSelectMultiple from './jeecg/components/JSelectMultiple.vue'; import JSelectMultiple from './jeecg/components/JSelectMultiple.vue';
import JPopup from './jeecg/components/JPopup.vue'; import JPopup from './jeecg/components/JPopup.vue';
// update-begin--author:liaozhiyang---date:20240130---for【QQYUN-7961】popupDict字典
import JPopupDict from './jeecg/components/JPopupDict.vue';
// update-end--author:liaozhiyang---date:20240130---for【QQYUN-7961】popupDict字典
import JSwitch from './jeecg/components/JSwitch.vue'; import JSwitch from './jeecg/components/JSwitch.vue';
import JTreeDict from './jeecg/components/JTreeDict.vue'; import JTreeDict from './jeecg/components/JTreeDict.vue';
import JInputPop from './jeecg/components/JInputPop.vue'; import JInputPop from './jeecg/components/JInputPop.vue';
import { JEasyCron } from './jeecg/components/JEasyCron'; // import { JEasyCron } from './jeecg/components/JEasyCron';
import JCheckbox from './jeecg/components/JCheckbox.vue'; import JCheckbox from './jeecg/components/JCheckbox.vue';
import JInput from './jeecg/components/JInput.vue'; import JInput from './jeecg/components/JInput.vue';
import JTreeSelect from './jeecg/components/JTreeSelect.vue'; import JTreeSelect from './jeecg/components/JTreeSelect.vue';
@ -61,7 +72,9 @@ import JRangeNumber from './jeecg/components/JRangeNumber.vue';
import UserSelect from './jeecg/components/userSelect/index.vue'; import UserSelect from './jeecg/components/userSelect/index.vue';
import JRangeDate from './jeecg/components/JRangeDate.vue' import JRangeDate from './jeecg/components/JRangeDate.vue'
import JRangeTime from './jeecg/components/JRangeTime.vue' import JRangeTime from './jeecg/components/JRangeTime.vue'
import JInputSelect from './jeecg/components/JInputSelect.vue'
import RoleSelectInput from './jeecg/components/roleSelect/RoleSelectInput.vue'; import RoleSelectInput from './jeecg/components/roleSelect/RoleSelectInput.vue';
import {DatePickerInFilter, CascaderPcaInFilter} from "@/components/InFilter";
const componentMap = new Map<ComponentType, Component>(); const componentMap = new Map<ComponentType, Component>();
@ -93,6 +106,7 @@ componentMap.set('MonthPicker', DatePicker.MonthPicker);
componentMap.set('RangePicker', DatePicker.RangePicker); componentMap.set('RangePicker', DatePicker.RangePicker);
componentMap.set('WeekPicker', DatePicker.WeekPicker); componentMap.set('WeekPicker', DatePicker.WeekPicker);
componentMap.set('TimePicker', TimePicker); componentMap.set('TimePicker', TimePicker);
componentMap.set('DatePickerInFilter', DatePickerInFilter);
componentMap.set('StrengthMeter', StrengthMeter); componentMap.set('StrengthMeter', StrengthMeter);
componentMap.set('IconPicker', IconPicker); componentMap.set('IconPicker', IconPicker);
componentMap.set('InputCountDown', CountdownInput); componentMap.set('InputCountDown', CountdownInput);
@ -101,7 +115,11 @@ componentMap.set('Upload', BasicUpload);
componentMap.set('Divider', Divider); componentMap.set('Divider', Divider);
//注册自定义组件 //注册自定义组件
componentMap.set('JAreaLinkage', JAreaLinkage);
componentMap.set(
'JAreaLinkage',
createAsyncComponent(() => import('./jeecg/components/JAreaLinkage.vue'))
);
componentMap.set('JSelectPosition', JSelectPosition); componentMap.set('JSelectPosition', JSelectPosition);
componentMap.set('JSelectUser', JSelectUser); componentMap.set('JSelectUser', JSelectUser);
componentMap.set('JSelectRole', JSelectRole); componentMap.set('JSelectRole', JSelectRole);
@ -109,17 +127,33 @@ componentMap.set('JImageUpload', JImageUpload);
componentMap.set('JDictSelectTag', JDictSelectTag); componentMap.set('JDictSelectTag', JDictSelectTag);
componentMap.set('JSelectDept', JSelectDept); componentMap.set('JSelectDept', JSelectDept);
componentMap.set('JAreaSelect', JAreaSelect); componentMap.set('JAreaSelect', JAreaSelect);
// componentMap.set(
// 'JEditor',
// createAsyncComponent(() => import('./jeecg/components/JEditor.vue'))
// );
componentMap.set('JEditor', JEditor); componentMap.set('JEditor', JEditor);
componentMap.set('JMarkdownEditor', JMarkdownEditor); componentMap.set(
'JMarkdownEditor',
createAsyncComponent(() => import('./jeecg/components/JMarkdownEditor.vue'))
);
componentMap.set('JSelectInput', JSelectInput); componentMap.set('JSelectInput', JSelectInput);
componentMap.set('JCodeEditor', JCodeEditor); componentMap.set(
'JCodeEditor',
createAsyncComponent(() => import('./jeecg/components/JCodeEditor.vue'))
);
componentMap.set('JCategorySelect', JCategorySelect); componentMap.set('JCategorySelect', JCategorySelect);
componentMap.set('JSelectMultiple', JSelectMultiple); componentMap.set('JSelectMultiple', JSelectMultiple);
componentMap.set('JPopup', JPopup); componentMap.set('JPopup', JPopup);
// update-begin--author:liaozhiyang---date:20240130---for【QQYUN-7961】popupDict字典
componentMap.set('JPopupDict', JPopupDict);
// update-end--author:liaozhiyang---date:20240130---for【QQYUN-7961】popupDict字典
componentMap.set('JSwitch', JSwitch); componentMap.set('JSwitch', JSwitch);
componentMap.set('JTreeDict', JTreeDict); componentMap.set('JTreeDict', JTreeDict);
componentMap.set('JInputPop', JInputPop); componentMap.set('JInputPop', JInputPop);
componentMap.set('JEasyCron', JEasyCron); componentMap.set(
'JEasyCron',
createAsyncComponent(() => import('./jeecg/components/JEasyCron/EasyCronInput.vue'))
);
componentMap.set('JCheckbox', JCheckbox); componentMap.set('JCheckbox', JCheckbox);
componentMap.set('JInput', JInput); componentMap.set('JInput', JInput);
componentMap.set('JTreeSelect', JTreeSelect); componentMap.set('JTreeSelect', JTreeSelect);
@ -129,10 +163,12 @@ componentMap.set('JUpload', JUpload);
componentMap.set('JSearchSelect', JSearchSelect); componentMap.set('JSearchSelect', JSearchSelect);
componentMap.set('JAddInput', JAddInput); componentMap.set('JAddInput', JAddInput);
componentMap.set('JRangeNumber', JRangeNumber); componentMap.set('JRangeNumber', JRangeNumber);
componentMap.set('CascaderPcaInFilter', CascaderPcaInFilter);
componentMap.set('UserSelect', UserSelect); componentMap.set('UserSelect', UserSelect);
componentMap.set('RangeDate', JRangeDate); componentMap.set('RangeDate', JRangeDate);
componentMap.set('RangeTime', JRangeTime); componentMap.set('RangeTime', JRangeTime);
componentMap.set('RoleSelect', RoleSelectInput); componentMap.set('RoleSelect', RoleSelectInput);
componentMap.set('JInputSelect', JInputSelect);

View File

@ -101,10 +101,9 @@
return prev; return prev;
}, [] as OptionsItem[]); }, [] as OptionsItem[]);
}); });
// update-begin--author:liaozhiyang---date:20240509---forissues/6191apiSelect
watchEffect(() => { props.immediate && fetch();
props.immediate && fetch(); // update-end--author:liaozhiyang---date:20240509---forissues/6191apiSelect
});
watch( watch(
() => props.params, () => props.params,

View File

@ -44,7 +44,9 @@
watch( watch(
() => props.params, () => props.params,
() => { () => {
!unref(isFirstLoaded) && fetch(); //update-begin---author:wangshuai---date:2024-02-28---for:QQYUN-8346 ApiTreeSelect #1054---
unref(isFirstLoaded) && fetch();
//update-end---author:wangshuai---date:2024-02-28---for:QQYUN-8346 ApiTreeSelect #1054---
}, },
{ deep: true } { deep: true }
); );

View File

@ -16,7 +16,8 @@
import { useItemLabelWidth } from '../hooks/useLabelWidth'; import { useItemLabelWidth } from '../hooks/useLabelWidth';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useAppInject } from '/@/hooks/web/useAppInject'; import { useAppInject } from '/@/hooks/web/useAppInject';
import { usePermission } from '/@/hooks/web/usePermission';
import Middleware from './Middleware.vue';
export default defineComponent({ export default defineComponent({
name: 'BasicFormItem', name: 'BasicFormItem',
inheritAttrs: false, inheritAttrs: false,
@ -51,6 +52,12 @@
formActionType: { formActionType: {
type: Object as PropType<FormActionType>, type: Object as PropType<FormActionType>,
}, },
// update-begin--author:liaozhiyang---date:20240605---forTV360X-857
clearValidate: {
type: Function,
default: null,
},
// update-end-author:liaozhiyang---date:20240605---forTV360X-857
}, },
setup(props, { slots }) { setup(props, { slots }) {
const { t } = useI18n(); const { t } = useI18n();
@ -93,6 +100,11 @@
const getDisable = computed(() => { const getDisable = computed(() => {
const { disabled: globDisabled } = props.formProps; const { disabled: globDisabled } = props.formProps;
// update-begin--author:liaozhiyang---date:20240530---forTV360X-594dynamicDisabled
if (!!globDisabled) {
return globDisabled;
}
// update-end--author:liaozhiyang---date:20240530---forTV360X-594dynamicDisabled
const { dynamicDisabled } = props.schema; const { dynamicDisabled } = props.schema;
const { disabled: itemDisabled = false } = unref(getComponentsProps); const { disabled: itemDisabled = false } = unref(getComponentsProps);
let disabled = !!globDisabled || itemDisabled; let disabled = !!globDisabled || itemDisabled;
@ -105,6 +117,22 @@
return disabled; return disabled;
}); });
// update-begin--author:liaozhiyang---date:20240308---forQQYUN-8377formSchema props
const getDynamicPropsValue = computed(() => {
const { dynamicPropsVal, dynamicPropskey } = props.schema;
if (dynamicPropskey == null) {
return null;
} else {
const { [dynamicPropskey]: itemValue } = unref(getComponentsProps);
let value = itemValue;
if (isFunction(dynamicPropsVal)) {
value = dynamicPropsVal(unref(getValues));
return value;
}
}
});
// update-end--author:liaozhiyang---date:20240308---forQQYUN-8377formSchema props
function getShow(): { isShow: boolean; isIfShow: boolean } { function getShow(): { isShow: boolean; isIfShow: boolean } {
const { show, ifShow } = props.schema; const { show, ifShow } = props.schema;
const { showAdvancedButton } = props.formProps; const { showAdvancedButton } = props.formProps;
@ -128,12 +156,62 @@
isShow = isShow && itemIsAdvanced; isShow = isShow && itemIsAdvanced;
return { isShow, isIfShow }; return { isShow, isIfShow };
} }
// update-begin--author:liaozhiyang---date:20240530---forTV360X-434validator
let vSwitchArr: any = [],
prevValidatorArr: any = [];
const hijackValidator = (rules) => {
vSwitchArr = [];
prevValidatorArr = [];
rules.forEach((item, index) => {
const fn = item.validator;
vSwitchArr.push(true);
prevValidatorArr.push(null);
if (isFunction(fn)) {
item.validator = (rule, value, callback) => {
if (vSwitchArr[index]) {
vSwitchArr[index] = false;
setTimeout(() => {
vSwitchArr[index] = true;
}, 100);
const result = fn(rule, value, callback);
prevValidatorArr[index] = result;
return result;
} else {
return prevValidatorArr[index];
}
};
}
});
};
// update-end--author:liaozhiyang---date:20240530---forTV360X-434validator
function handleRules(): ValidationRule[] { function handleRules(): ValidationRule[] {
const { rules: defRules = [], component, rulesMessageJoinLabel, label, dynamicRules, required } = props.schema; const { rules: defRules = [], component, rulesMessageJoinLabel, label, dynamicRules, required, auth, field } = props.schema;
// update-begin--author:liaozhiyang---date:20240605---forTV360X-857
const { disabled: globDisabled } = props.formProps;
const { disabled: itemDisabled = false } = unref(getComponentsProps);
if (!!globDisabled || !!itemDisabled) {
props.clearValidate(field);
return [];
}
// update-end--author:liaozhiyang---date:20240605---forTV360X-857
// update-begin--author:liaozhiyang---date:20240531---forTV360X-842v-authshow
const { hasPermission } = usePermission();
const { isShow } = getShow();
if ((auth && !hasPermission(auth)) || !isShow) {
return [];
}
// update-end--author:liaozhiyang---date:20240531---forTV360X-842v-authshow
if (isFunction(dynamicRules)) { if (isFunction(dynamicRules)) {
return dynamicRules(unref(getValues)) as ValidationRule[]; // update-begin--author:liaozhiyang---date:20240514---forissues/1244
const ruleArr = dynamicRules(unref(getValues)) as ValidationRule[];
if (required) {
ruleArr.unshift({ required: true });
}
// update-begin--author:liaozhiyang---date:20240530---forTV360X-434validator
hijackValidator(ruleArr);
// update-end--author:liaozhiyang---date:20240530---forTV360X-434validator
return ruleArr;
// update-end--author:liaozhiyang---date:20240514---forissues/1244
} }
let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[]; let rules: ValidationRule[] = cloneDeep(defRules) as ValidationRule[];
@ -183,9 +261,12 @@
rule.required = false; rule.required = false;
} }
if (component) { if (component) {
if (!Reflect.has(rule, 'type')) { //update-begin---author:wangshuai---date:2024-02-01---for:QQYUN-8176,,ApiSelect,,使,---
//https://github.com/vbenjs/vue-vben-admin/pull/3082 github
/*if (!Reflect.has(rule, 'type')) {
rule.type = component === 'InputNumber' ? 'number' : 'string'; rule.type = component === 'InputNumber' ? 'number' : 'string';
} }*/
//update-end---author:wangshuai---date:2024-02-01---for:QQYUN-8176,,ApiSelect,,使,---
rule.message = rule.message || defaultMsg; rule.message = rule.message || defaultMsg;
@ -218,11 +299,14 @@
} }
}); });
// update-end--author:liaozhiyang---date:20231226---forQQYUN-7495patternantd使InputNumber // update-end--author:liaozhiyang---date:20231226---forQQYUN-7495patternantd使InputNumber
// update-begin--author:liaozhiyang---date:20240530---forTV360X-434validator
hijackValidator(rules);
// update-end--author:liaozhiyang---date:20240530---forTV360X-434validator
return rules; return rules;
} }
function renderComponent() { function renderComponent() {
const { renderComponentContent, component, field, changeEvent = 'change', valueField, componentProps } = props.schema; const { renderComponentContent, component, field, changeEvent = 'change', valueField, componentProps, dynamicRules } = props.schema;
const isCheck = component && ['Switch', 'Checkbox'].includes(component); const isCheck = component && ['Switch', 'Checkbox'].includes(component);
// update-begin--author:liaozhiyang---date:20231013---forQQYUN-6679input // update-begin--author:liaozhiyang---date:20231013---forQQYUN-6679input
@ -253,7 +337,9 @@
} }
// update-end--author:liaozhiyang---date:20231013---forQQYUN-6679input // update-end--author:liaozhiyang---date:20231013---forQQYUN-6679input
props.setFormModel(field, value); props.setFormModel(field, value);
//props.validateFields([field], { triggerName: 'change' }).catch((_) => {}); // update-begin--author:liaozhiyang---date:20240522---forTV360X-341
props.validateFields([field]).catch((_) => {});
// update-end--author:liaozhiyang---date:20240522--forTV360X-341
}, },
// onBlur: () => { // onBlur: () => {
// props.validateFields([field], { triggerName: 'blur' }).catch((_) => {}); // props.validateFields([field], { triggerName: 'blur' }).catch((_) => {});
@ -273,6 +359,12 @@
...unref(getComponentsProps), ...unref(getComponentsProps),
disabled: unref(getDisable), disabled: unref(getDisable),
}; };
// update-begin--author:liaozhiyang---date:20240308---forQQYUN-8377formSchema props
const dynamicPropskey = props.schema.dynamicPropskey;
if (dynamicPropskey) {
propsData[dynamicPropskey] = unref(getDynamicPropsValue);
}
// update-end--author:liaozhiyang---date:20240308---forQQYUN-8377formSchema props
const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder; const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder;
// RangePicker place // RangePicker place
@ -312,21 +404,21 @@
//update-begin-author:taoyan date:2022-9-7 for: VUEN-2061online4 .. //update-begin-author:taoyan date:2022-9-7 for: VUEN-2061online4 ..
//label //label
const { label, helpMessage, helpComponentProps, subLabel, labelLength } = props.schema; const { label, helpMessage, helpComponentProps, subLabel, labelLength } = props.schema;
let showLabel:string = (label+'') let showLabel: string = label + '';
if(labelLength && showLabel.length>4){ // update-begin--author:liaozhiyang---date:20240517---forTV360X-98labellabelLength
if (labelLength) {
showLabel = showLabel.substr(0, labelLength); showLabel = showLabel.substr(0, labelLength);
} }
const titleObj = {title: label} // update-end--author:liaozhiyang---date:20240517---forTV360X-98labellabelLength
const titleObj = { title: label };
const renderLabel = subLabel ? ( const renderLabel = subLabel ? (
<span> <span>
{label} <span class="text-secondary">{subLabel}</span> {label} <span class="text-secondary">{subLabel}</span>
</span> </span>
) : labelLength ? (
<label {...titleObj}>{showLabel}</label>
) : ( ) : (
labelLength ? ( label
<label {...titleObj}>{showLabel}</label>
) : (
label
)
); );
//update-end-author:taoyan date:2022-9-7 for: VUEN-2061online4 .. //update-end-author:taoyan date:2022-9-7 for: VUEN-2061online4 ..
const getHelpMessage = isFunction(helpMessage) ? helpMessage(unref(getValues)) : helpMessage; const getHelpMessage = isFunction(helpMessage) ? helpMessage(unref(getValues)) : helpMessage;
@ -368,12 +460,17 @@
{...(itemProps as Recordable)} {...(itemProps as Recordable)}
label={renderLabelHelpMessage()} label={renderLabelHelpMessage()}
rules={handleRules()} rules={handleRules()}
// update-begin--author:liaozhiyang---date:20240514---forissues/1244
validateFirst = { true }
// update-end--author:liaozhiyang---date:20240514---forissues/1244
labelCol={labelCol} labelCol={labelCol}
wrapperCol={wrapperCol} wrapperCol={wrapperCol}
> >
<div style="display:flex"> <div style="display:flex">
{/* author: sunjianlei for: 【VUEN-744】此处加上 width: 100%; 因为要防止组件宽度超出 FormItem */} {/* author: sunjianlei for: 【VUEN-744】此处加上 width: 100%; 因为要防止组件宽度超出 FormItem */}
<div style="flex:1; width: 100%;">{getContent()}</div> {/* update-begin--author:liaozhiyang---date:20240510---for【TV360X-719】表单校验不通过项滚动到可视区内 */}
<Middleware>{getContent()}</Middleware>
{/* update-end--author:liaozhiyang---date:20240510---for【TV360X-719】表单校验不通过项滚动到可视区内 */}
{showSuffix && <span class="suffix">{getSuffix}</span>} {showSuffix && <span class="suffix">{getSuffix}</span>}
</div> </div>
</Form.Item> </Form.Item>

View File

@ -0,0 +1,16 @@
<template>
<div :id="formItemId" style="flex: 1; width: 100%">
<slot></slot>
</div>
</template>
<script setup>
import { Form } from 'ant-design-vue';
import { computed } from 'vue';
const formItemContext = Form.useInjectFormItemContext();
const formItemId = computed(() => {
return formItemContext.id.value;
});
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,204 @@
<template>
<div :class="formDisabled ? 'jeecg-form-container-disabled jeecg-form-detail-effect' : ''">
<fieldset :disabled="formDisabled">
<slot name="detail"></slot>
</fieldset>
<slot name="edit"> </slot>
<fieldset disabled>
<slot></slot>
</fieldset>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from 'vue';
export default defineComponent({
name: 'JForm',
props: {
disabled: {
type: Boolean,
default: false,
required: false,
},
},
setup(props, { emit }) {
const formDisabled = ref<boolean>(props.disabled);
watch(
() => props.disabled,
(value) => {
formDisabled.value = value;
}
);
return {
formDisabled,
};
},
});
</script>
<style scoped lang="less">
.jeecg-form-container-disabled {
cursor: not-allowed;
}
.jeecg-form-container-disabled fieldset[disabled] {
-ms-pointer-events: none;
pointer-events: none;
}
.jeecg-form-container-disabled :deep(.ant-select) {
-ms-pointer-events: none;
pointer-events: none;
}
// update-begin--author:liaozhiyang---date:20240605---forTV360X-857online
// begin antdv
// .jeecg-form-container-disabled :deep(.ant-input-number),
// .jeecg-form-container-disabled :deep(.ant-input),
// .jeecg-form-container-disabled :deep(.ant-input-password),
// .jeecg-form-container-disabled :deep(.ant-select-single .ant-select-selector),
// .jeecg-form-container-disabled :deep(.ant-radio-wrapper .ant-radio-checked .ant-radio-inner),
// .jeecg-form-container-disabled :deep(.ant-switch),
// .jeecg-form-container-disabled :deep(.ant-picker),
// .jeecg-form-container-disabled :deep(.ant-select:not(.ant-select-customize-input) .ant-select-selector),
// .jeecg-form-container-disabled :deep(.ant-input-affix-wrapper),
// .jeecg-form-container-disabled :deep(.tox .tox-toolbar__group),
// .jeecg-form-container-disabled :deep(.tox .tox-edit-area__iframe),
// .jeecg-form-container-disabled :deep(.vditor-toolbar),
// .jeecg-form-container-disabled :deep(.vditor-preview),
// .jeecg-form-container-disabled :deep(.jeecg-tinymce-img-upload) {
// background: rgba(51, 51, 51, 0.04);
// }
// .jeecg-form-container-disabled :deep(.ant-radio-wrapper),
// .jeecg-form-container-disabled :deep(.ant-checkbox-wrapper),
// .jeecg-form-container-disabled :deep(.ant-btn) {
// color: rgba(0, 0, 0, 0.65);
// }
// .jeecg-form-container-disabled :deep(.ant-radio-wrapper .ant-radio-inner:after),
// .jeecg-form-container-disabled :deep(.ant-checkbox-checked .ant-checkbox-inner) {
// background-color: rgba(51, 51, 51, 0.25);
// }
// .jeecg-form-container-disabled :deep(.ant-radio-inner),
// .jeecg-form-container-disabled :deep(.ant-checkbox-inner) {
// border-color: rgba(51, 51, 51, 0.25) !important;
// }
// .jeecg-form-container-disabled :deep(.ant-input-password > .ant-input),
// .jeecg-form-container-disabled :deep(.ant-input-affix-wrapper .ant-input) {
// background: none;
// }
html[data-theme='light'] {
.jeecg-form-detail-effect {
:deep(.ant-select-selector),
:deep(.ant-btn),
:deep(.ant-input),
:deep(.ant-input-affix-wrapper),
:deep(.ant-picker),
:deep(.ant-input-number) {
color: #606266 !important;
}
:deep(.ant-select) {
color: #606266 !important;
}
:deep(.ant-select-selection-item-content),:deep(.ant-select-selection-item),:deep(input) {
color: #606266 !important;
}
:deep(.ant-radio-wrapper),
:deep(.ant-checkbox-wrapper),
:deep(.ant-btn) {
color: rgba(0, 0, 0, 0.65);
}
:deep(.ant-radio-wrapper .ant-radio-inner:after),
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
color: #606266 !important;
}
:deep(.ant-radio-inner),
:deep(.ant-checkbox-inner) {
border-color: rgba(51, 51, 51, 0.25) !important;
background-color: rgba(51, 51, 51, 0.04) !important;
}
:deep(.ant-checkbox-checked .ant-checkbox-inner::after), :deep(.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after){
border-color: rgba(51, 51, 51, 0.25) !important;
}
:deep(.ant-switch) {
background-color: rgba(51, 51, 51, 0.25);
}
:deep(.tox .tox-toolbar__group),
:deep(.tox .tox-edit-area__iframe),
:deep(.vditor-toolbar),
:deep(.vditor-preview),
:deep(.jeecg-tinymce-img-upload) {
background: rgba(51, 51, 51, 0.04);
}
}
}
html[data-theme='dark'] {
.jeecg-form-detail-effect {
:deep(.ant-select-selector),
:deep(.ant-btn),
:deep(.ant-input),
:deep(.ant-input-affix-wrapper),
:deep(.ant-picker),
:deep(.ant-input-number) {
color: rgba(255, 255, 255, 0.25) !important;
//background-color: rgba(255, 255, 255, 0.08) !important;
}
:deep(.ant-select) {
color: rgba(255, 255, 255, 0.25) !important;
}
:deep(.ant-select-selection-item-content),:deep(.ant-select-selection-item),:deep(input) {
color: rgba(255, 255, 255, 0.25) !important;
}
:deep(.ant-radio-wrapper),
:deep(.ant-checkbox-wrapper){
color: rgba(255, 255, 255, 0.25);
}
:deep(.ant-radio-wrapper .ant-radio-inner:after),
:deep(.ant-checkbox-checked .ant-checkbox-inner) {
background-color: rgba(255, 255, 255, 0.08);
}
:deep(.ant-radio-inner),
:deep(.ant-checkbox-inner) {
border-color: #424242 !important;
background-color: rgba(255, 255, 255, 0.08);
}
:deep(.ant-switch) {
background-color: rgba(51, 51, 51, 0.25);
opacity: 0.65;
}
:deep(.tox .tox-toolbar__group),
:deep(.tox .tox-edit-area__iframe),
:deep(.vditor-toolbar),
:deep(.vditor-preview),
:deep(.jeecg-tinymce-img-upload) {
background: rgba(51, 51, 51, 0.04);
}
}
}
// end antdv
// update-begin--author:liaozhiyang---date:20240605---forTV360X-857online
.jeecg-form-container-disabled :deep(.ant-upload-select) {
cursor: grabbing;
}
.jeecg-form-container-disabled :deep(.ant-upload-list) {
cursor: grabbing;
}
.jeecg-form-container-disabled fieldset[disabled] :deep(.ant-upload-list){
// -ms-pointer-events: auto !important;
// pointer-events: auto !important;
}
.jeecg-form-container-disabled fieldset[disabled] iframe {
-ms-pointer-events: auto !important;
pointer-events: auto !important;
}
.jeecg-form-container-disabled :deep(.ant-upload-list-item-actions .anticon-delete),
.jeecg-form-container-disabled :deep(.ant-upload-list-item .anticon-close) {
display: none;
}
.jeecg-form-container-disabled :deep(.vditor-sv) {
display: none !important;
background: rgba(51, 51, 51, 0.04);
}
</style>

View File

@ -36,6 +36,12 @@ function genType() {
} }
export function setComponentRuleType(rule: ValidationRule, component: ComponentType, valueFormat: string) { export function setComponentRuleType(rule: ValidationRule, component: ComponentType, valueFormat: string) {
//update-begin---author:wangshuai---date:2024-02-01---for:【QQYUN-8176】编辑表单中,校验必填时,如果组件是ApiSelect,打开编辑页面时,即使该字段有值,也会提示请选择---
//https://github.com/vbenjs/vue-vben-admin/pull/3082 github修复原文
if (Reflect.has(rule, 'type')) {
return;
}
//update-end---author:wangshuai---date:2024-02-01---for:【QQYUN-8176】编辑表单中,校验必填时,如果组件是ApiSelect,打开编辑页面时,即使该字段有值,也会提示请选择---
if (['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'].includes(component)) { if (['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'].includes(component)) {
rule.type = valueFormat ? 'string' : 'object'; rule.type = valueFormat ? 'string' : 'object';
} else if (['RangePicker', 'Upload', 'CheckboxGroup', 'TimePicker'].includes(component)) { } else if (['RangePicker', 'Upload', 'CheckboxGroup', 'TimePicker'].includes(component)) {
@ -68,9 +74,11 @@ export function handleInputNumberValue(component?: ComponentType, val?: any) {
*/ */
export function handleInputStringValue(component?: ComponentType, val?: any) { export function handleInputStringValue(component?: ComponentType, val?: any) {
if (!component) return val; if (!component) return val;
if (['InputNumber'].includes(component) && typeof val === 'string') { // update-begin--author:liaozhiyang---date:20240517---for【TV360X-13】InputNumber设置精确3位小数传入''变成了0.00
if (['InputNumber'].includes(component) && typeof val === 'string' && val != '') {
return Number(val); return Number(val);
} }
// update-end--author:liaozhiyang---date:20240517---for【TV360X-13】InputNumber设置精确3位小数传入''变成了0.00
return val; return val;
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<Cascader v-bind="attrs" :value="state" :options="getOptions" @change="handleChange" /> <Cascader v-bind="attrs" :value="cascaderValue" :options="getOptions" @change="handleChange" />
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted } from 'vue'; import { defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted } from 'vue';
@ -8,6 +8,8 @@
import { useRuleFormItem } from '/@/hooks/component/useFormItem'; import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { isArray } from '/@/utils/is';
export default defineComponent({ export default defineComponent({
name: 'JAreaLinkage', name: 'JAreaLinkage',
components: { components: {
@ -20,12 +22,15 @@
showArea: propTypes.bool.def(true), showArea: propTypes.bool.def(true),
// //
showAll: propTypes.bool.def(false), showAll: propTypes.bool.def(false),
//
saveCode: propTypes.oneOf(['province', 'city', 'region', 'all']).def('all'),
}, },
emits: ['options-change', 'change'], emits: ['options-change', 'change', 'update:value'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
const emitData = ref<any[]>([]); const emitData = ref<any[]>([]);
const attrs = useAttrs(); const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData); // const [state] = useRuleFormItem(props, 'value', 'change', emitData);
const cascaderValue = ref([]);
const getOptions = computed(() => { const getOptions = computed(() => {
if (props.showArea && props.showAll) { if (props.showArea && props.showAll) {
return regionDataPlus; return regionDataPlus;
@ -44,7 +49,13 @@
* 监听value变化 * 监听value变化
*/ */
watchEffect(() => { watchEffect(() => {
props.value && initValue(); // update-begin--author:liaozhiyang---date:20240612--forTV360X-1223
if (props.value) {
initValue();
} else {
cascaderValue.value = [];
}
// update-end--author:liaozhiyang---date:20240612---forTV360X-1223
}); });
/** /**
@ -52,20 +63,69 @@
*/ */
function initValue() { function initValue() {
let value = props.value ? props.value : []; let value = props.value ? props.value : [];
// update-begin--author:liaozhiyang---date:20240607---forTV360X-501
if (value && typeof value === 'string' && value != 'null' && value != 'undefined') { if (value && typeof value === 'string' && value != 'null' && value != 'undefined') {
state.value = value.split(','); const arr = value.split(',');
cascaderValue.value = transform(arr);
} else if (isArray(value)) {
if (value.length) {
cascaderValue.value = transform(value);
} else {
cascaderValue.value = [];
}
} }
// update-end--author:liaozhiyang---date:20240607---forTV360X-501
} }
function transform(arr) {
function handleChange(array, ...args) { let result: any = [];
if (props.saveCode === 'region') {
// 81 82
const regionCode = arr[0];
if (['82', '81'].includes(regionCode.substring(0, 2))) {
result = [`${regionCode.substring(0, 2)}0000`, regionCode];
} else {
result = [`${regionCode.substring(0, 2)}0000`, `${regionCode.substring(0, 2)}${regionCode.substring(2, 4)}00`, regionCode];
}
} else if (props.saveCode === 'city') {
const cityCode = arr[0];
result = [`${cityCode.substring(0, 2)}0000`, cityCode];
} else if (props.saveCode === 'province') {
const provinceCode = arr[0];
result = [provinceCode];
} else {
result = arr;
}
return result;
}
function handleChange(arr, ...args) {
// update-begin--author:liaozhiyang---date:20240607---forTV360X-501
if (arr?.length) {
let result: any = [];
if (props.saveCode === 'region') {
//
result = [arr[arr.length - 1]];
} else if (props.saveCode === 'city') {
result = [arr[1]];
} else if (props.saveCode === 'province') {
result = [arr[0]];
} else {
result = arr;
}
emit('change', result);
emit('update:value', result);
} else {
emit('change', arr);
emit('update:value', arr);
}
// update-end--author:liaozhiyang---date:20240607---forTV360X-501
// emitData.value = args; // emitData.value = args;
//update-begin-author:taoyan date:2022-6-27 for: VUEN-1424vue3jvxeerp //update-begin-author:taoyan date:2022-6-27 for: VUEN-1424vue3jvxeerp
// v-model:value // v-model:value
state.value = array; // state.value = result;
//update-end-author:taoyan date:2022-6-27 for: VUEN-1424vue3jvxeerp //update-end-author:taoyan date:2022-6-27 for: VUEN-1424vue3jvxeerp
} }
return { return {
state, cascaderValue,
attrs, attrs,
regionData, regionData,
getOptions, getOptions,

View File

@ -16,7 +16,7 @@
</a-tree-select> </a-tree-select>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, unref, watch } from 'vue'; import { defineComponent, ref, unref, watch, nextTick } from 'vue';
import { useRuleFormItem } from '/@/hooks/component/useFormItem'; import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
@ -78,7 +78,7 @@
const treeData = ref<any[]>([]); const treeData = ref<any[]>([]);
const treeValue = ref(); const treeValue = ref();
const attrs = useAttrs(); const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData); const [state, , , formItemContext] = useRuleFormItem(props, 'value', 'change', emitData);
watch( watch(
() => props.value, () => props.value,
() => { () => {
@ -218,6 +218,11 @@
backValue(value.value, value.label); backValue(value.value, value.label);
treeValue.value = value; treeValue.value = value;
} }
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9110
nextTick(() => {
formItemContext?.onFieldChange();
});
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9110
} }
function getCurrTreeData() { function getCurrTreeData() {

View File

@ -1,5 +1,9 @@
<template> <template>
<a-checkbox-group v-bind="attrs" v-model:value="checkboxArray" :options="checkOptions" @change="handleChange"></a-checkbox-group> <a-checkbox-group v-bind="attrs" v-model:value="checkboxArray" :options="checkOptions" @change="handleChange">
<template #label="{label, value}">
<span :class="[useDicColor && getDicColor(value) ? 'colorText' : '']" :style="{ backgroundColor: `${getDicColor(value)}` }">{{ label }}</span>
</template>
</a-checkbox-group>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -13,6 +17,7 @@
props: { props: {
value:propTypes.oneOfType([propTypes.string, propTypes.number]), value:propTypes.oneOfType([propTypes.string, propTypes.number]),
dictCode: propTypes.string, dictCode: propTypes.string,
useDicColor: propTypes.bool.def(false),
options: { options: {
type: Array, type: Array,
default: () => [], default: () => [],
@ -69,6 +74,7 @@
prev.push({ prev.push({
label: next['text'], label: next['text'],
value: value, value: value,
color: next['color'],
}); });
} }
return prev; return prev;
@ -84,8 +90,30 @@
emit('update:value', $event.join(',')); emit('update:value', $event.join(','));
emit('change', $event.join(',')); emit('change', $event.join(','));
} }
const getDicColor = (value) => {
return { checkboxArray, checkOptions, attrs, handleChange }; if (props.useDicColor) {
const findItem = checkOptions.value.find((item) => item.value == value);
if (findItem) {
return findItem.color;
}
}
return null;
};
return { checkboxArray, checkOptions, attrs, handleChange, getDicColor };
}, },
}); });
</script> </script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20230110---forQQYUN-7799
.colorText {
display: inline-block;
height: 20px;
line-height: 20px;
padding: 0 6px;
border-radius: 8px;
background-color: red;
color: #fff;
font-size: 12px;
}
// update-begin--author:liaozhiyang---date:20230110---forQQYUN-7799
</style>

View File

@ -42,12 +42,16 @@
import 'codemirror/addon/hint/show-hint.css'; import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/hint/show-hint.js'; import 'codemirror/addon/hint/show-hint.js';
import 'codemirror/addon/hint/anyword-hint.js'; import 'codemirror/addon/hint/anyword-hint.js';
//
import 'codemirror/addon/edit/matchbrackets';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { isJsonObjectString } from '/@/utils/is.ts'; import { isJsonObjectString } from '/@/utils/is.ts';
// //
import { useCodeHinting } from '../hooks/useCodeHinting'; import { useCodeHinting } from '../hooks/useCodeHinting';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { ThemeEnum } from '/@/enums/appEnum';
export default defineComponent({ export default defineComponent({
name: 'JCodeEditor', name: 'JCodeEditor',
// attrs html // attrs html
@ -68,6 +72,7 @@
}, },
emits: ['change', 'update:value'], emits: ['change', 'update:value'],
setup(props, { emit }) { setup(props, { emit }) {
const { getDarkMode } = useRootSetting();
const containerRef = ref(null); const containerRef = ref(null);
const { prefixCls } = useDesign('code-editer'); const { prefixCls } = useDesign('code-editer');
const CodeMirror = window.CodeMirror || _CodeMirror; const CodeMirror = window.CodeMirror || _CodeMirror;
@ -82,7 +87,9 @@
// //
tabSize: 2, tabSize: 2,
// JS // JS
theme: props.theme, // update-begin--author:liaozhiyang---date:20240327---forQQYUN-8639
theme: getDarkMode.value == ThemeEnum.DARK ? 'monokai' : props.theme,
// update-end--author:liaozhiyang---date:20240327---forQQYUN-8639
smartIndent: true, // smartIndent: true, //
// //
lineNumbers: true, lineNumbers: true,
@ -97,13 +104,19 @@
// update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode // update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode
mode: props.language, mode: props.language,
// update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode // update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode
// // update-begin--author:liaozhiyang---date:20240603---forTV360X-898
readOnly: props.disabled,
// update-end--author:liaozhiyang---date:20240603---forTV360X-898
//
matchBrackets: true,
extraKeys: { extraKeys: {
Tab: function autoFormat(editor) { // Tab: function autoFormat(editor) {
//var totalLines = editor.lineCount(); // //var totalLines = editor.lineCount();
//editor.autoFormatRange({line:0, ch:0}, {line:totalLines}); // //editor.autoFormatRange({line:0, ch:0}, {line:totalLines});
setValue(innerValue, false); // setValue(innerValue, false);
}, // },
'Cmd-/': (cm) => comment(cm),
'Ctrl-/': (cm) => comment(cm),
}, },
}); });
// props.value // props.value
@ -146,6 +159,11 @@
); );
onMounted(() => { onMounted(() => {
initialize(); initialize();
// update-begin--author:liaozhiyang---date:20240318---forQQYUN-8473
setTimeout(() => {
refresh();
}, 150);
// update-end--author:liaozhiyang---date:20240318---forQQYUN-8473
}); });
/** /**
@ -160,6 +178,15 @@
coder?.setValue(value ?? ''); coder?.setValue(value ?? '');
innerValue = value; innerValue = value;
trigger && emitChange(innerValue); trigger && emitChange(innerValue);
// update-begin--author:liaozhiyang---date:20240510---forQQYUN-9231
setTimeout(() => {
refresh();
//
setTimeout(() => {
refresh();
}, 600);
}, 400);
// update-end--author:liaozhiyang---date:20240510---forQQYUN-9231
} }
// //
@ -221,6 +248,24 @@
} }
//update-end-author:taoyan date:2022-10-18 for: VUEN-2480bugonline vue3 8online js //update-end-author:taoyan date:2022-10-18 for: VUEN-2480bugonline vue3 8online js
/**
* 2024-04-01
* liaozhiyang
* 代码批量注释
*/
function comment(cm) {
var selection = cm.getSelection();
var start = cm.getCursor('start');
var end = cm.getCursor('end');
var isCommented = selection.startsWith('//');
if (isCommented) {
//
cm.replaceRange(selection.replace(/\n\/\/\s/g, '\n').replace(/^\/\/\s/, ''), start, end);
} else {
//
cm.replaceRange('// ' + selection.replace(/\n(?=.)/g, '\n// '), start, end);
}
}
return { return {
state, state,
@ -312,9 +357,19 @@
border: 1px solid #ddd; border: 1px solid #ddd;
} }
} }
.CodeMirror-hints.idea { .CodeMirror-hints.idea,
.CodeMirror-hints.monokai {
z-index: 1001; z-index: 1001;
max-width: 600px; max-width: 600px;
max-height: 300px; max-height: 300px;
} }
// update-begin--author:liaozhiyang---date:20240327---forQQYUN-8639
html[data-theme='dark'] {
.@{prefix-cls} {
.CodeMirror {
border: 1px solid #3a3a3a;
}
}
}
// update-end--author:liaozhiyang---date:20240327---forQQYUN-8639
</style> </style>

View File

@ -2,7 +2,9 @@
<a-radio-group v-if="compType === CompTypeEnum.Radio" v-bind="attrs" v-model:value="state" @change="handleChangeRadio"> <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}`"> <template v-for="item in dictOptions" :key="`${item.value}`">
<a-radio :value="item.value"> <a-radio :value="item.value">
{{ item.label }} <span :class="[useDicColor && item.color ? 'colorText' : '']" :style="{ backgroundColor: `${useDicColor && item.color}` }">
{{ item.label }}
</span>
</a-radio> </a-radio>
</template> </template>
</a-radio-group> </a-radio-group>
@ -41,7 +43,11 @@
<a-select-option v-if="showChooseOption" :value="null"></a-select-option> <a-select-option v-if="showChooseOption" :value="null"></a-select-option>
<template v-for="item in dictOptions" :key="`${item.value}`"> <template v-for="item in dictOptions" :key="`${item.value}`">
<a-select-option :value="item.value"> <a-select-option :value="item.value">
<span style="display: inline-block; width: 100%" :title="item.label"> <span
:class="[useDicColor && item.color ? 'colorText' : '']"
:style="{ backgroundColor: `${useDicColor && item.color}` }"
:title="item.label"
>
{{ item.label }} {{ item.label }}
</span> </span>
</a-select-option> </a-select-option>
@ -69,6 +75,7 @@
type: propTypes.string, type: propTypes.string,
placeholder: propTypes.string, placeholder: propTypes.string,
stringToNumber: propTypes.bool, stringToNumber: propTypes.bool,
useDicColor: propTypes.bool.def(false),
getPopupContainer: { getPopupContainer: {
type: Function, type: Function,
default: (node) => node?.parentNode, default: (node) => node?.parentNode,
@ -139,7 +146,8 @@
prev.push({ prev.push({
label: next['text'] || next['label'], label: next['text'] || next['label'],
value: stringToNumber ? +value : value, value: stringToNumber ? +value : value,
...omit(next, ['text', 'value']), color: next['color'],
...omit(next, ['text', 'value', 'color']),
}); });
} }
return prev; return prev;
@ -213,3 +221,17 @@
}, },
}); });
</script> </script>
<style scoped lang="less">
// update-begin--author:liaozhiyang---date:20230110---forQQYUN-7799
.colorText {
display: inline-block;
height: 20px;
line-height: 20px;
padding: 0 6px;
border-radius: 8px;
background-color: red;
color: #fff;
font-size: 12px;
}
// update-begin--author:liaozhiyang---date:20230110---forQQYUN-7799
</style>

View File

@ -3,10 +3,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from 'vue'; import { computed, defineComponent, nextTick } from 'vue';
import { Tinymce } from '/@/components/Tinymce'; import { Tinymce } from '/@/components/Tinymce';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { Form } from 'ant-design-vue';
export default defineComponent({ export default defineComponent({
name: 'JEditor', name: 'JEditor',
@ -21,11 +22,16 @@
setup(props, { emit, attrs }) { setup(props, { emit, attrs }) {
// props attrs // props attrs
const bindProps = computed(() => Object.assign({}, props, attrs)); const bindProps = computed(() => Object.assign({}, props, attrs));
const formItemContext = Form.useInjectFormItemContext();
// value change // value change
function onChange(value) { function onChange(value) {
emit('change', value); emit('change', value);
emit('update:value', value); emit('update:value', value);
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9110
nextTick(() => {
formItemContext?.onFieldChange();
});
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9110
} }
return { return {

View File

@ -108,11 +108,14 @@
// //
const multiple = computed(() => { const multiple = computed(() => {
return props['fileMax'] > 1; return props['fileMax'] > 1 || props['fileMax'] === 0;
}); });
// //
const uploadVisible = computed(() => { const uploadVisible = computed(() => {
if (props['fileMax'] === 0) {
return true;
}
return uploadFileList.value.length < props['fileMax']; return uploadFileList.value.length < props['fileMax'];
}); });

View File

@ -30,6 +30,7 @@
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { useGlobSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { isObject } from '/@/utils/is';
export default defineComponent({ export default defineComponent({
name: 'JImportModal', name: 'JImportModal',
@ -116,6 +117,11 @@
if (unref(foreignKeys) && unref(foreignKeys).length > 0) { if (unref(foreignKeys) && unref(foreignKeys).length > 0) {
formData.append('foreignKeys', unref(foreignKeys)); formData.append('foreignKeys', unref(foreignKeys));
} }
// update-begin--author:liaozhiyang---date:20240429---forissues/6124Online
if (isObject(foreignKeys.value)) {
formData.append('foreignKeys', JSON.stringify(foreignKeys.value));
}
// update-end--author:liaozhiyang---date:20240429---forissues/6124Online
if (!!online) { if (!!online) {
formData.append('validateStatus', unref(validateStatus)); formData.append('validateStatus', unref(validateStatus));
} }

View File

@ -7,7 +7,7 @@
:placement="position" :placement="position"
> >
<template #title> <template #title>
<span>{{ title }}</span> <span :class="title ? 'title' : 'emptyTitle'">{{ title }}</span>
<span style="float: right" title="关闭"> <span style="float: right" title="关闭">
<Icon icon="ant-design:close-outlined" @click="visible = false" /> <Icon icon="ant-design:close-outlined" @click="visible = false" />
</span> </span>
@ -100,6 +100,11 @@
.@{prefix-cls} { .@{prefix-cls} {
&-popover { &-popover {
// update-begin--author:liaozhiyang---date:20240520---forTV360X-144jVxetabletitle线
.ant-popover-title:has(.emptyTitle) {
border-bottom: none;
}
// update-end--author:liaozhiyang---date:20240520---forTV360X-144jVxetabletitle线
} }
&-input { &-input {

View File

@ -0,0 +1,75 @@
<template>
<div class="JInputSelect">
<a-input-group compact>
<a-select
v-bind="$attrs"
:placeholder="selectPlaceholder"
v-if="selectLocation === 'left'"
v-model:value="selectVal"
@change="handleSelectChange"
>
<a-select-option v-for="item in options" :key="item.value">{{ item.label }}</a-select-option>
</a-select>
<a-input v-bind="$attrs" :placeholder="inputPlaceholder" v-model:value="inputVal" @change="handleInputChange" />
<a-select
v-bind="$attrs"
:placeholder="selectPlaceholder"
v-if="selectLocation === 'right'"
v-model:value="selectVal"
@change="handleSelectChange"
>
<a-select-option v-for="item in options" :key="item.value">{{ item.label }}</a-select-option>
</a-select>
</a-input-group>
</div>
</template>
<script setup name="JInputSelect" lang="ts">
import { ref, watchEffect } from 'vue';
import { propTypes } from '/@/utils/propTypes';
const props = defineProps({
value: propTypes.string.def(''),
options: propTypes.array.def([]),
selectLocation: propTypes.oneOf(['left', 'right']).def('right'),
selectPlaceholder: propTypes.string.def(''),
inputPlaceholder: propTypes.string.def(''),
});
const emit = defineEmits(['update:value', 'change']);
const selectVal = ref<string>();
const inputVal = ref<string>();
const handleInputChange = (e) => {
const val = e.target.value;
setSelectValByInputVal(val);
emits(val);
};
const handleSelectChange = (val) => {
inputVal.value = val;
emits(val);
};
const setSelectValByInputVal = (val) => {
const findItem = props.options.find((item) => item.value === val);
if (findItem) {
selectVal.value = val;
} else {
selectVal.value = undefined;
}
}
watchEffect(() => {
inputVal.value = props.value;
setSelectValByInputVal(props.value);
});
const emits = (val) => {
emit('update:value', val);
emit('change', val);
};
</script>
<style lang="less" scoped>
.JInputSelect {
.ant-input-group {
display: flex;
}
}
</style>

View File

@ -3,10 +3,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, watch } from 'vue'; import { computed, defineComponent, watch, nextTick } from 'vue';
import { MarkDown } from '/@/components/Markdown'; import { MarkDown } from '/@/components/Markdown';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { Form } from 'ant-design-vue';
export default defineComponent({ export default defineComponent({
name: 'JMarkdownEditor', name: 'JMarkdownEditor',
// attrs html // attrs html
@ -24,7 +24,7 @@
let vditorRef: any = null; let vditorRef: any = null;
// props attrs // props attrs
const bindProps = computed(() => Object.assign({}, props, attrs)); const bindProps = computed(() => Object.assign({}, props, attrs));
const formItemContext = Form.useInjectFormItemContext();
// onMounted // onMounted
function onGetVditor(instance) { function onGetVditor(instance) {
mdRef = instance; mdRef = instance;
@ -42,6 +42,11 @@
function onChange(value) { function onChange(value) {
emit('change', value); emit('change', value);
emit('update:value', value); emit('update:value', value);
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9110
nextTick(() => {
formItemContext?.onFieldChange();
});
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9110
} }
return { return {

View File

@ -1,6 +1,6 @@
<!--popup组件--> <!--popup组件-->
<template> <template>
<div class="components-input-demo-presuffix" v-if="avalid"> <div class="JPopup components-input-demo-presuffix" v-if="avalid">
<!--输入框--> <!--输入框-->
<a-input @click="handleOpen" v-model:value="showText" :placeholder="placeholder" readOnly v-bind="attrs"> <a-input @click="handleOpen" v-model:value="showText" :placeholder="placeholder" readOnly v-bind="attrs">
<template #prefix> <template #prefix>
@ -12,17 +12,22 @@
</template>--> </template>-->
<!-- update-begin-author:taoyan date:2022-5-31 for: VUEN-1157 popup 选中后有两个清除图标后边这个清除只是把输入框中数据清除实际值并没有清除 --> <!-- update-begin-author:taoyan date:2022-5-31 for: VUEN-1157 popup 选中后有两个清除图标后边这个清除只是把输入框中数据清除实际值并没有清除 -->
</a-input> </a-input>
<!--popup弹窗--> <!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<JPopupOnlReportModal <a-form-item>
@register="regModal" <!--popup弹窗-->
:code="code" <JPopupOnlReportModal
:multi="multi" @register="regModal"
:sorter="sorter" :code="code"
:groupId="uniqGroupId" :multi="multi"
:param="param" :sorter="sorter"
@ok="callBack" :groupId="uniqGroupId"
:getContainer="getContainer" :param="param"
></JPopupOnlReportModal> :showAdvancedButton="showAdvancedButton"
@ok="callBack"
:getContainer="getContainer"
></JPopupOnlReportModal>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -56,6 +61,7 @@
type: Array, type: Array,
default: () => [], default: () => [],
}, },
showAdvancedButton: propTypes.bool.def(true),
}, },
emits: ['update:value', 'register', 'popUpChange', 'focus'], emits: ['update:value', 'register', 'popUpChange', 'focus'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
@ -97,7 +103,9 @@
*/ */
function handleOpen() { function handleOpen() {
emit('focus'); emit('focus');
!props.disabled && openModal(true); // update-begin--author:liaozhiyang---date:20240528---forTV360X-317JPopupJPopupdic
!attrs.value.disabled && openModal(true);
// update-end--author:liaozhiyang---date:20240528---forTV360X-317JPopupJPopupdic
} }
/** /**
@ -148,6 +156,13 @@
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JPopup {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.components-input-demo-presuffix .anticon-close-circle { .components-input-demo-presuffix .anticon-close-circle {
cursor: pointer; cursor: pointer;
color: #ccc; color: #ccc;

View File

@ -0,0 +1,232 @@
<!--popup组件-->
<template>
<div class="JPopupDict components-input-demo-presuffix">
<!--输入框-->
<a-select v-model:value="showText" v-bind="attrs" :mode="multi ? 'multiple' : ''" @click="handleOpen" readOnly :loading="loading">
<a-select-option v-for="item in options" :value="item.value">{{ item.text }}</a-select-option>
</a-select>
<!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<!--popup弹窗-->
<JPopupOnlReportModal
@register="regModal"
:code="code"
:multi="multi"
:sorter="sorter"
:groupId="''"
:param="param"
@ok="callBack"
:getContainer="getContainer"
:showAdvancedButton="showAdvancedButton"
/>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div>
</template>
<script lang="ts">
import JPopupOnlReportModal from './modal/JPopupOnlReportModal.vue';
import { defineComponent, ref, nextTick, watch, reactive, unref } from 'vue';
import { useModal } from '/@/components/Modal';
import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
//url
const configUrl = reactive({
getColumns: '/online/cgreport/api/getRpColumns/',
getData: '/online/cgreport/api/getData/',
});
export default defineComponent({
name: 'JPopupDict',
components: {
JPopupOnlReportModal,
},
inheritAttrs: false,
props: {
/**
* 示例demo,name,id
* demo: online报表编码
* name: online报表的字段用户显示的label
* id: online报表的字段用于存储key
*/
dictCode: propTypes.string.def(''),
value: propTypes.string.def(''),
sorter: propTypes.string.def(''),
multi: propTypes.bool.def(false),
param: propTypes.object.def({}),
spliter: propTypes.string.def(','),
getContainer: propTypes.func,
showAdvancedButton: propTypes.bool.def(true),
},
emits: ['update:value', 'register', 'change'],
setup(props, { emit }) {
const { createMessage } = useMessage();
const attrs = useAttrs();
const showText = ref<any>(props.multi ? [] : '');
const options = ref<any>([]);
const cgRpConfigId = ref('');
const loading = ref(false);
const code = props.dictCode.split(',')[0];
const labelFiled = props.dictCode.split(',')[1];
const valueFiled = props.dictCode.split(',')[2];
if (!code || !valueFiled || !labelFiled) {
createMessage.error('popupDict参数未正确配置!');
}
//model
const [regModal, { openModal }] = useModal();
/**
* 打开pop弹出框
*/
function handleOpen() {
// update-begin--author:liaozhiyang---date:20240528---forTV360X-317JPopupJPopupdic
!attrs.value.disabled && openModal(true);
// update-end--author:liaozhiyang---date:20240528---forTV360X-317JPopupJPopupdic
}
/**
* 监听value数值
*/
watch(
() => props.value,
(val) => {
const callBack = () => {
if (props.multi) {
showText.value = val && val.length > 0 ? val.split(props.spliter) : [];
} else {
showText.value = val ?? '';
}
};
if (props.value || props.defaultValue) {
if (cgRpConfigId.value) {
loadData({ callBack });
} else {
loadColumnsInfo({ callBack });
}
} else {
callBack();
}
},
{ immediate: true }
);
watch(
() => showText.value,
(val) => {
let result;
if (props.multi) {
result = val.join(',');
} else {
result = val;
}
nextTick(() => {
emit('change', result);
emit('update:value', result);
});
}
);
/**
* 加载列信息
*/
function loadColumnsInfo({ callBack }) {
loading.value = true;
let url = `${configUrl.getColumns}${code}`;
defHttp
.get({ url }, { isTransformResponse: false, successMessageMode: 'none' })
.then((res) => {
if (res.success) {
cgRpConfigId.value = res.result.cgRpConfigId;
loadData({ callBack });
}
})
.catch((err) => {
loading.value = false;
callBack?.();
});
}
function loadData({ callBack }) {
loading.value = true;
let url = `${configUrl.getData}${unref(cgRpConfigId)}`;
defHttp
.get(
{ url, params: { ['force_' + valueFiled]: props.value || props.defaultValue } },
{ isTransformResponse: false, successMessageMode: 'none' }
)
.then((res) => {
let data = res.result;
if (data.records?.length) {
options.value = data.records.map((item) => {
return { value: item[valueFiled], text: item[labelFiled] };
});
}
})
.finally(() => {
loading.value = false;
callBack?.();
});
}
/**
* 传值回调
*/
function callBack(rows) {
const dataOptions: any = [];
const dataValue: any = [];
let result;
rows.forEach((item) => {
dataOptions.push({ value: item[valueFiled], text: item[labelFiled] });
dataValue.push(item[valueFiled]);
});
options.value = dataOptions;
if (props.multi) {
showText.value = dataValue;
result = dataValue.join(props.spliter);
} else {
showText.value = dataValue[0];
result = dataValue[0];
}
nextTick(() => {
emit('change', result);
emit('update:value', result);
});
}
return {
showText,
attrs,
regModal,
handleOpen,
callBack,
code,
options,
loading,
};
},
});
</script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JPopupDict {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.components-input-demo-presuffix {
:deep(.ant-select-dropdown) {
display: none !important;
}
}
.components-input-demo-presuffix .anticon-close-circle {
cursor: pointer;
color: #ccc;
transition: color 0.3s;
font-size: 12px;
}
.components-input-demo-presuffix .anticon-close-circle:hover {
color: #f5222d;
}
.components-input-demo-presuffix .anticon-close-circle:active {
color: #666;
}
</style>

View File

@ -1,8 +1,8 @@
<template> <template>
<a-input-group> <a-input-group>
<a-input :value="beginValue" style="width: calc(50% - 15px)" placeholder="最小值" @change="handleChangeBegin" /> <a-input-number v-bind="attrs" :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 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-number v-bind="attrs" :value="endValue" style="width: calc(50% - 15px); border-left: 0" placeholder="最大值" @change="handleChangeEnd" />
</a-input-group> </a-input-group>
</template> </template>
@ -13,25 +13,27 @@
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { Form } from 'ant-design-vue'; import { Form } from 'ant-design-vue';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
export default { export default {
name: 'JRangeNumber', name: 'JRangeNumber',
props: { props: {
value: propTypes.oneOfType([propTypes.string, propTypes.array]), value: propTypes.oneOfType([propTypes.string, propTypes.array]),
}, },
emits: ['change', 'update:value'], emits: ['change', 'update:value', 'blur'],
setup(props, { emit }) { setup(props, { emit }) {
const beginValue = ref(''); const beginValue = ref('');
const endValue = ref(''); const endValue = ref('');
const attrs = useAttrs();
const formItemContext = Form.useInjectFormItemContext(); const formItemContext = Form.useInjectFormItemContext();
function handleChangeBegin(e) { function handleChangeBegin(e) {
beginValue.value = e.target.value; beginValue.value = e;
emitArray(); emitArray();
} }
function handleChangeEnd(e) { function handleChangeEnd(e) {
endValue.value = e.target.value; endValue.value = e;
emitArray(); emitArray();
} }
@ -64,9 +66,26 @@
endValue, endValue,
handleChangeBegin, handleChangeBegin,
handleChangeEnd, handleChangeEnd,
attrs,
}; };
}, },
}; };
</script> </script>
<style scoped></style> <style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240607---forTV360X-214
.ant-input-group {
display: flex;
.ant-input-number {
&:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
&:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
}
// update-end--author:liaozhiyang---date:20240607---forTV360X-214
</style>

View File

@ -11,6 +11,7 @@
:placeholder="placeholder" :placeholder="placeholder"
:filterOption="isDictTable ? false : filterOption" :filterOption="isDictTable ? false : filterOption"
:notFoundContent="loading ? undefined : null" :notFoundContent="loading ? undefined : null"
@focus="handleAsyncFocus"
@search="loadData" @search="loadData"
@change="handleAsyncChange" @change="handleAsyncChange"
> >
@ -46,6 +47,8 @@
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { initDictOptions } from '/@/utils/dict/index'; import { initDictOptions } from '/@/utils/dict/index';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { debounce } from 'lodash-es';
import { setPopContainer } from '/@/utils';
export default defineComponent({ export default defineComponent({
name: 'JSearchSelect', name: 'JSearchSelect',
@ -144,7 +147,7 @@
/** /**
* 异步查询数据 * 异步查询数据
*/ */
async function loadData(value) { const loadData = debounce(async function loadData(value) {
if (!isDictTable.value) { if (!isDictTable.value) {
return; return;
} }
@ -153,6 +156,9 @@
options.value = []; options.value = [];
loading.value = true; loading.value = true;
let keywordInfo = getKeywordParam(value); let keywordInfo = getKeywordParam(value);
//update-begin---author:chenrui ---date:2024/4/7 for[QQYUN-8800]JSearchSelectsearchSQL #6049------------
keywordInfo = keywordInfo.replaceAll("'", '');
//update-end---author:chenrui ---date:2024/4/7 for[QQYUN-8800]JSearchSelectsearchSQL #6049------------
// codetable,text,code // codetable,text,code
defHttp defHttp
.get({ .get({
@ -168,7 +174,7 @@
options.value = res; options.value = res;
} }
}); });
} }, 300);
/** /**
* 初始化value * 初始化value
*/ */
@ -282,6 +288,10 @@
loadData(''); loadData('');
} }
callback(); callback();
// update-begin--author:liaozhiyang---date:20240524---forTV360X-426
// xloadSelectTexttrue
selectedObj ?? (loadSelectText.value = true);
// update-end--author:liaozhiyang---date:20240524---forTV360X-426
} }
/** /**
*回调方法 *回调方法
@ -311,7 +321,9 @@
function getParentContainer(node) { function getParentContainer(node) {
// update-begin-author:taoyan date:20220407 for: getPopupContainer popContainer // update-begin-author:taoyan date:20220407 for: getPopupContainer popContainer
if (props.popContainer) { if (props.popContainer) {
return document.querySelector(props.popContainer); // update-begin--author:liaozhiyang---date:20240517---forQQYUN-9339modalmodaloptions
return setPopContainer(node, props.popContainer);
// update-end--author:liaozhiyang---date:20240517---forQQYUN-9339modalmodaloptions
} else { } else {
if (typeof props.getPopupContainer === 'function') { if (typeof props.getPopupContainer === 'function') {
return props.getPopupContainer(node); return props.getPopupContainer(node);
@ -339,7 +351,12 @@
} }
} }
//update-end-author:taoyan date:2022-8-15 for: VUEN-1971 online 1 //update-end-author:taoyan date:2022-8-15 for: VUEN-1971 online 1
// update-begin--author:liaozhiyang---date:20240523---forTV360X-26
const handleAsyncFocus = () => {
options.value.length && initDictCodeData();
attrs.onFocus?.();
};
// update-end--author:liaozhiyang---date:20240523---forTV360X-26
return { return {
attrs, attrs,
options, options,
@ -352,6 +369,7 @@
filterOption, filterOption,
handleChange, handleChange,
handleAsyncChange, handleAsyncChange,
handleAsyncFocus,
}; };
}, },
}); });

View File

@ -1,8 +1,12 @@
<!--部门选择组件--> <!--部门选择组件-->
<template> <template>
<div> <div class="JSelectDept">
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" @change="handleChange"/> <JSelectBiz @change="handleSelectChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"/>
<DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :multiple="multiple" /> <!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :multiple="multiple" @close="handleClose"/>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -14,6 +18,7 @@
import { useRuleFormItem } from '/@/hooks/component/useFormItem'; import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { SelectValue } from 'ant-design-vue/es/select'; import { SelectValue } from 'ant-design-vue/es/select';
import { cloneDeep } from 'lodash-es';
export default defineComponent({ export default defineComponent({
name: 'JSelectDept', name: 'JSelectDept',
@ -33,13 +38,15 @@
//model //model
const [regModal, { openModal }] = useModal(); const [regModal, { openModal }] = useModal();
// //
const [state] = useRuleFormItem(props, 'value', 'change', emitData); // const [state] = useRuleFormItem(props, 'value', 'change', emitData);
// //
const selectOptions = ref<SelectValue>([]); const selectOptions = ref<SelectValue>([]);
// //
let selectValues = reactive<Recordable>({ let selectValues = reactive<Recordable>({
value: [], value: [],
}); });
let tempSave: any = [];
// //
const loadingEcho = ref<boolean>(false); const loadingEcho = ref<boolean>(false);
// selectOptions,xxxBiz // selectOptions,xxxBiz
@ -56,6 +63,11 @@
* 监听组件值 * 监听组件值
*/ */
watchEffect(() => { watchEffect(() => {
// update-begin--author:liaozhiyang---date:20240611---forTV360X-576JSelectDept
//update-begin-author:liusq---date:2024-06-03--for: [TV360X-840]
tempSave = [];
//update-end-author:liusq---date:2024-06-03--for:[TV360X-840]
// update-end--author:liaozhiyang---date:20240611---forTV360X-576JSelectDept
props.value && initValue(); props.value && initValue();
}); });
@ -70,11 +82,13 @@
/** /**
* 监听selectValues变化 * 监听selectValues变化
*/ */
watch(selectValues, () => { // update-begin--author:liaozhiyang---date:20240527---forTV360X-414(JSelectUser)
if (selectValues) { // watch(selectValues, () => {
state.value = selectValues.value; // if (selectValues) {
} // state.value = selectValues.value;
}); // }
// });
// update-end--author:liaozhiyang---date:20240527---forTV360X-414(JSelectUser)
/** /**
* 监听selectOptions变化 * 监听selectOptions变化
*/ */
@ -100,11 +114,13 @@
function initValue() { function initValue() {
let value = props.value ? props.value : []; let value = props.value ? props.value : [];
if (value && typeof value === 'string') { if (value && typeof value === 'string') {
state.value = value.split(','); // state.value = value.split(',');
selectValues.value = value.split(','); selectValues.value = value.split(',');
tempSave = value.split(',');
} else { } else {
// VUEN-857 // VUEN-857
selectValues.value = value; selectValues.value = value;
tempSave = cloneDeep(value);
} }
} }
@ -114,24 +130,33 @@
function setValue(options, values) { function setValue(options, values) {
selectOptions.value = options; selectOptions.value = options;
//emitData.value = values.join(","); //emitData.value = values.join(",");
state.value = values; // state.value = values;
selectValues.value = values; selectValues.value = values;
emit('update:value', values.join(',')); send(values);
} }
const getBindValue = Object.assign({}, unref(props), unref(attrs)); const getBindValue = Object.assign({}, unref(props), unref(attrs));
//update-begin---author:wangshuai ---date:20230406 forissues/397使v-model:valueJSelectDept------------ // update-begin--author:liaozhiyang---date:20240527---forTV360X-414(JSelectUser)
/** const handleClose = () => {
* 值改变事件更新value值 if (tempSave.length) {
* @param values selectValues.value = cloneDeep(tempSave);
*/ } else {
function handleChange(values) { send(tempSave);
emit('update:value', values); }
} };
//update-end---author:wangshuai ---date:20230406 forissues/397使v-model:valueJSelectDept------------ const handleSelectChange = (values) => {
tempSave = cloneDeep(values);
send(tempSave);
};
const send = (values) => {
let result = typeof props.value == 'string' ? values.join(',') : values;
emit('update:value', result);
emit('change', result);
};
// update-end--author:liaozhiyang---date:20240527---forTV360X-414(JSelectUser)
return { return {
state, // state,
attrs, attrs,
selectOptions, selectOptions,
selectValues, selectValues,
@ -141,12 +166,20 @@
regModal, regModal,
setValue, setValue,
handleOpen, handleOpen,
handleChange handleClose,
handleSelectChange,
}; };
}, },
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JSelectDept {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.j-select-row { .j-select-row {
@width: 82px; @width: 82px;

View File

@ -11,7 +11,7 @@
:getPopupContainer="getParentContainer" :getPopupContainer="getParentContainer"
> >
<a-select-option v-for="(item, index) in dictOptions" :key="index" :getPopupContainer="getParentContainer" :value="item.value"> <a-select-option v-for="(item, index) in dictOptions" :key="index" :getPopupContainer="getParentContainer" :value="item.value">
{{ item.text || item.label }} <span :class="[useDicColor && item.color ? 'colorText' : '']" :style="{ backgroundColor: `${useDicColor && item.color}` }">{{ item.text || item.label }}</span>
</a-select-option> </a-select-option>
</a-select> </a-select>
</template> </template>
@ -22,6 +22,7 @@
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { getDictItems } from '/@/api/common/api'; import { getDictItems } from '/@/api/common/api';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { setPopContainer } from '/@/utils';
const { createMessage, createErrorModal } = useMessage(); const { createMessage, createErrorModal } = useMessage();
export default defineComponent({ export default defineComponent({
@ -68,6 +69,10 @@
type: Boolean, type: Boolean,
default: false, default: false,
}, },
useDicColor: {
type: Boolean,
default: false,
},
}, },
emits: ['options-change', 'change', 'input', 'update:value'], emits: ['options-change', 'change', 'input', 'update:value'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
@ -76,7 +81,7 @@
const arrayValue = ref<any[]>(!props.value ? [] : props.value.split(props.spliter)); const arrayValue = ref<any[]>(!props.value ? [] : props.value.split(props.spliter));
const dictOptions = ref<any[]>([]); const dictOptions = ref<any[]>([]);
const attrs = useAttrs(); const attrs = useAttrs();
const [state] = useRuleFormItem(props, 'value', 'change', emitData); const [state, , , formItemContext] = useRuleFormItem(props, 'value', 'change', emitData);
onMounted(() => { onMounted(() => {
if (props.dictCode) { if (props.dictCode) {
@ -114,13 +119,20 @@
emit('input', selectedValue.join(props.spliter)); emit('input', selectedValue.join(props.spliter));
emit('update:value', selectedValue.join(props.spliter)); emit('update:value', selectedValue.join(props.spliter));
} }
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9110
nextTick(() => {
formItemContext?.onFieldChange();
});
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9110
} }
function getParentContainer(node) { function getParentContainer(node) {
if (!props.popContainer) { if (!props.popContainer) {
return node?.parentNode; return node?.parentNode;
} else { } else {
return document.querySelector(props.popContainer); // update-begin--author:liaozhiyang---date:20240517---forQQYUN-9339modalmodaloptions
return setPopContainer(node, props.popContainer);
// update-end--author:liaozhiyang---date:20240517---forQQYUN-9339modalmodaloptions
} }
} }
@ -135,7 +147,7 @@
//update-end-author:taoyan date:2022-6-21 for: //update-end-author:taoyan date:2022-6-21 for:
getDictItems(temp).then((res) => { getDictItems(temp).then((res) => {
if (res) { if (res) {
dictOptions.value = res.map((item) => ({ value: item.value, label: item.text })); dictOptions.value = res.map((item) => ({ value: item.value, label: item.text, color:item.color }));
//console.info('res', dictOptions.value); //console.info('res', dictOptions.value);
} else { } else {
console.error('getDictItems error: : ', res); console.error('getDictItems error: : ', res);
@ -162,3 +174,15 @@
}, },
}); });
</script> </script>
<style scoped lang='less'>
.colorText{
display: inline-block;
height: 20px;
line-height: 20px;
padding: 0 6px;
border-radius: 8px;
background-color: red;
color: #fff;
font-size: 12px;
}
</style>

View File

@ -1,8 +1,12 @@
<!--职务选择组件--> <!--职务选择组件-->
<template> <template>
<div> <div class="JSelectPosition">
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz> <JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<PositionSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></PositionSelectModal> <!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<PositionSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></PositionSelectModal>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -131,6 +135,13 @@
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JSelectPosition {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.j-select-row { .j-select-row {
@width: 82px; @width: 82px;

View File

@ -1,8 +1,12 @@
<!--角色选择组件--> <!--角色选择组件-->
<template> <template>
<div> <div class="JSelectRole">
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz> <JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<RoleSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></RoleSelectModal> <!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<RoleSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></RoleSelectModal>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -132,6 +136,13 @@
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JSelectRole {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.j-select-row { .j-select-row {
@width: 82px; @width: 82px;

View File

@ -1,8 +1,19 @@
<!--用户选择组件--> <!--用户选择组件-->
<template> <template>
<div> <div class="JselectUser">
<JSelectBiz @change="handleChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz> <JSelectBiz @change="handleSelectChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<UserSelectModal :rowKey="rowKey" @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :excludeUserIdList="excludeUserIdList"></UserSelectModal> <!-- update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
<a-form-item>
<UserSelectModal
:rowKey="rowKey"
@register="regModal"
@getSelectResult="setValue"
v-bind="getBindValue"
:excludeUserIdList="excludeUserIdList"
@close="handleClose"
/>
</a-form-item>
<!-- update-end--author:liaozhiyang---date:20240515---forQQYUN-9260必填模式下会影响到弹窗内antd组件的样式 -->
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -15,7 +26,7 @@
import { useRuleFormItem } from '/@/hooks/component/useFormItem'; import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { SelectValue } from 'ant-design-vue/es/select'; import { SelectValue } from 'ant-design-vue/es/select';
import { cloneDeep } from 'lodash-es';
export default defineComponent({ export default defineComponent({
name: 'JSelectUser', name: 'JSelectUser',
components: { components: {
@ -51,7 +62,7 @@
//model //model
const [regModal, { openModal }] = useModal(); const [regModal, { openModal }] = useModal();
// //
const [state] = useRuleFormItem(props, 'value', 'change', emitData); // const [state] = useRuleFormItem(props, 'value', 'change', emitData);
// //
const selectOptions = ref<SelectValue>([]); const selectOptions = ref<SelectValue>([]);
// //
@ -59,6 +70,7 @@
value: [], value: [],
change: false, change: false,
}); });
let tempSave: any = [];
// //
const loadingEcho = ref<boolean>(false); const loadingEcho = ref<boolean>(false);
// selectOptions,xxxBiz // selectOptions,xxxBiz
@ -75,6 +87,11 @@
* 监听组件值 * 监听组件值
*/ */
watchEffect(() => { watchEffect(() => {
// update-begin--author:liaozhiyang---date:20240611---forTV360X-576
//update-begin-author:liusq---date:2024-06-03--for: [TV360X-840]
tempSave = [];
//update-end-author:liusq---date:2024-06-03--for:[TV360X-840]
// update-end--author:liaozhiyang---date:20240611---forTV360X-576
props.value && initValue(); props.value && initValue();
// //
if (!props.value) { if (!props.value) {
@ -85,11 +102,11 @@
/** /**
* 监听selectValues变化 * 监听selectValues变化
*/ */
watch(selectValues, () => { // watch(selectValues, () => {
if (selectValues) { // if (selectValues) {
state.value = selectValues.value; // state.value = selectValues.value;
} // }
}); // });
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------ //update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
const excludeUserIdList = ref<any>([]); const excludeUserIdList = ref<any>([]);
@ -118,11 +135,13 @@
function initValue() { function initValue() {
let value = props.value ? props.value : []; let value = props.value ? props.value : [];
if (value && typeof value === 'string' && value != 'null' && value != 'undefined') { if (value && typeof value === 'string' && value != 'null' && value != 'undefined') {
state.value = value.split(','); // state.value = value.split(',');
selectValues.value = value.split(','); selectValues.value = value.split(',');
tempSave = value.split(',');
} else { } else {
// VUEN-857 // VUEN-857
selectValues.value = value; selectValues.value = value;
tempSave = cloneDeep(value);
} }
} }
@ -132,24 +151,31 @@
function setValue(options, values) { function setValue(options, values) {
selectOptions.value = options; selectOptions.value = options;
//emitData.value = values.join(","); //emitData.value = values.join(",");
state.value = values; // state.value = values;
selectValues.value = values; selectValues.value = values;
emit('update:value', values.join(',')); send(values);
} }
const getBindValue = Object.assign({}, unref(props), unref(attrs)); const getBindValue = Object.assign({}, unref(props), unref(attrs));
// update-begin--author:liaozhiyang---date:20240517---forQQYUN-9366
//update-begin---author:wangshuai ---date:20230711 for------------ const handleClose = () => {
/** if (tempSave.length) {
* 下拉框值改变回调事件 selectValues.value = cloneDeep(tempSave);
* @param values } else {
*/ send(tempSave);
function handleChange(values) { }
emit('update:value', values); };
} const handleSelectChange = (values) => {
//update-end---author:wangshuai ---date:20230711 for------------ tempSave = cloneDeep(values);
send(tempSave);
};
const send = (values) => {
let result = typeof props.value == "string" ? values.join(',') : values;
emit('update:value', result);
emit('change', result);
};
// update-end--author:liaozhiyang---date:20240517---forQQYUN-9366
return { return {
state, // state,
attrs, attrs,
selectOptions, selectOptions,
getBindValue, getBindValue,
@ -160,12 +186,20 @@
setValue, setValue,
handleOpen, handleOpen,
excludeUserIdList, excludeUserIdList,
handleChange, handleClose,
handleSelectChange,
}; };
}, },
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.JselectUser {
> .ant-form-item {
display: none;
}
}
// update-end--author:liaozhiyang---date:20240515---forQQYUN-9260antd
.j-select-row { .j-select-row {
@width: 82px; @width: 82px;

View File

@ -1,5 +1,6 @@
<template> <template>
<a-tree-select <a-tree-select
v-if="show"
allowClear allowClear
labelInValue labelInValue
style="width: 100%" style="width: 100%"
@ -22,7 +23,7 @@
* 异步树加载组件 通过传入表名 显示字段 存储字段 加载一个树控件 * 异步树加载组件 通过传入表名 显示字段 存储字段 加载一个树控件
* <j-tree-select dict="aa_tree_test,aad,id" pid-field="pid" ></j-tree-select> * <j-tree-select dict="aa_tree_test,aad,id" pid-field="pid" ></j-tree-select>
* */ * */
import { ref, watch, unref } from 'vue'; import { ref, watch, unref, nextTick } from 'vue';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
@ -57,6 +58,7 @@
// //
treeCheckAble: propTypes.bool.def(false), treeCheckAble: propTypes.bool.def(false),
//update-end---author:wangshuai date: 20230202 for: //update-end---author:wangshuai date: 20230202 for:
hiddenNodeKey: propTypes.string.def(''),
}); });
const attrs = useAttrs(); const attrs = useAttrs();
const emit = defineEmits(['change', 'update:value']); const emit = defineEmits(['change', 'update:value']);
@ -68,6 +70,7 @@
const tableName = ref<any>(''); const tableName = ref<any>('');
const text = ref<any>(''); const text = ref<any>('');
const code = ref<any>(''); const code = ref<any>('');
const show = ref<boolean>(true);
/** /**
* 监听value数据并初始化 * 监听value数据并初始化
*/ */
@ -87,12 +90,29 @@
}, },
{ deep: true, immediate: true } { deep: true, immediate: true }
); );
// update-begin--author:liaozhiyang---date:20240529---forTV360X-87
watch(
() => props.hiddenNodeKey,
() => {
if (treeData.value?.length && props.hiddenNodeKey) {
handleHiddenNode(treeData.value);
treeData.value = [...treeData.value];
}
}
);
// update-end--author:liaozhiyang---date:20240529---forTV360X-87
//update-begin-author:taoyan date:2022-5-25 for: VUEN-1056 15online //update-begin-author:taoyan date:2022-5-25 for: VUEN-1056 15online
watch( watch(
() => props.reload, () => props.reload,
async () => { async () => {
treeData.value = []; treeData.value = [];
// update-begin--author:liaozhiyang---date:20240524---forTV360X-88online
show.value = false;
nextTick(() => {
show.value = true;
});
// update-end--author:liaozhiyang---date:20240524---forTV360X-88online
await loadRoot(); await loadRoot();
}, },
{ {
@ -175,6 +195,9 @@
i.value = i.key; i.value = i.key;
i.isLeaf = !!i.leaf; i.isLeaf = !!i.leaf;
} }
// update-begin--author:liaozhiyang---date:20240523---forTV360X-87
handleHiddenNode(res.result);
// update-end--author:liaozhiyang---date:20240523---forTV360X-87
treeData.value = [...res.result]; treeData.value = [...res.result];
} else { } else {
console.log('数根节点查询结果异常', res); console.log('数根节点查询结果异常', res);
@ -208,6 +231,9 @@
i.value = i.key; i.value = i.key;
i.isLeaf = !!i.leaf; i.isLeaf = !!i.leaf;
} }
// update-begin--author:liaozhiyang---date:20240523---forTV360X-87
handleHiddenNode(res.result);
// update-end--author:liaozhiyang---date:20240523---forTV360X-87
// //
addChildren(pid, res.result, treeData.value); addChildren(pid, res.result, treeData.value);
treeData.value = [...treeData.value]; treeData.value = [...treeData.value];
@ -305,6 +331,9 @@
i.key = i.value; i.key = i.value;
i.isLeaf = !!i.leaf; i.isLeaf = !!i.leaf;
} }
// update-begin--author:liaozhiyang---date:20240523---forTV360X-87
handleHiddenNode(res.result);
// update-end--author:liaozhiyang---date:20240523---forTV360X-87
treeData.value = [...res.result]; treeData.value = [...res.result];
} else { } else {
console.log('数根节点查询结果异常', res); console.log('数根节点查询结果异常', res);
@ -347,6 +376,24 @@
} }
//update-end-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelectchangeOptions //update-end-author:taoyan date:2022-11-8 for: issues/4173 Online JTreeSelectchangeOptions
/**
* 2024-05-23
* liaozhiyang
* 过滤掉指定节点(包含其子孙节点)
*/
function handleHiddenNode(data) {
if (props.hiddenNodeKey && data?.length) {
for (let i = 0, len = data.length; i < len; i++) {
const item = data[i];
if (item.key == props.hiddenNodeKey) {
data.splice(i, 1);
i--;
len--;
return;
}
}
}
}
// onCreated // onCreated
validateProp().then(() => { validateProp().then(() => {
initDictInfo(); initDictInfo();

View File

@ -408,7 +408,9 @@
} }
/* update-end-author:taoyan date:2022-5-24 for:VUEN-1093详情界面 图片下载按钮显示不全*/ /* update-end-author:taoyan date:2022-5-24 for:VUEN-1093详情界面 图片下载按钮显示不全*/
} }
.ant-upload-text-icon {
color: @primary-color;
}
.ant-upload-list-item { .ant-upload-list-item {
.upload-actions-container { .upload-actions-container {
position: absolute; position: absolute;

View File

@ -63,7 +63,7 @@
// update-end--author:liaozhiyang---date:20231220---forQQYUN-7678 // update-end--author:liaozhiyang---date:20231220---forQQYUN-7678
value: propTypes.oneOfType([propTypes.string, propTypes.array]) value: propTypes.oneOfType([propTypes.string, propTypes.array])
}, },
emits: ['register', 'getSelectResult'], emits: ['register', 'getSelectResult', 'close'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
// //
const [register, { closeModal }] = useModalInner(); const [register, { closeModal }] = useModalInner();

View File

@ -28,7 +28,7 @@
</template> </template>
</template> </template>
<a-col :md="8" :sm="8"> <a-col :md="8" :sm="8" v-if="showAdvancedButton">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons"> <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6"> <a-col :lg="6">
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset"></a-button> <a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset"></a-button>
@ -82,7 +82,7 @@
loading: true, loading: true,
}), }),
}, },
props: ['multi', 'code', 'sorter', 'groupId', 'param'], props: ['multi', 'code', 'sorter', 'groupId', 'param','showAdvancedButton'],
emits: ['ok', 'register'], emits: ['ok', 'register'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
const { createMessage } = useMessage(); const { createMessage } = useMessage();

View File

@ -8,8 +8,12 @@
:width="showSelected ? '1200px' : '900px'" :width="showSelected ? '1200px' : '900px'"
wrapClassName="j-user-select-modal" wrapClassName="j-user-select-modal"
@ok="handleOk" @ok="handleOk"
@cancel="handleCancel"
:maxHeight="maxHeight"
:centered="true"
destroyOnClose destroyOnClose
@visible-change="visibleChange" @visible-change="visibleChange"
> >
<a-row> <a-row>
<a-col :span="showSelected ? 18 : 24"> <a-col :span="showSelected ? 18 : 24">
@ -81,11 +85,13 @@
}, },
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------ //update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
}, },
emits: ['register', 'getSelectResult'], emits: ['register', 'getSelectResult', 'close'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
// update-begin-author:taoyan date:2022-5-24 for: VUEN-1086 // update-begin-author:taoyan date:2022-5-24 for: VUEN-1086
const tableScroll = ref<any>({ x: false }); const tableScroll = ref<any>({ x: false });
const tableRef = ref(); const tableRef = ref();
const maxHeight = ref(600);
// //
const [register, { closeModal }] = useModalInner(() => { const [register, { closeModal }] = useModalInner(() => {
if (window.innerWidth < 900) { if (window.innerWidth < 900) {
@ -112,7 +118,8 @@
const getBindValue = Object.assign({}, unref(props), unref(attrs), config); const getBindValue = Object.assign({}, unref(props), unref(attrs), config);
const [{ rowSelection, visibleChange, selectValues, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows }] = useSelectBiz( const [{ rowSelection, visibleChange, selectValues, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows }] = useSelectBiz(
getUserList, getUserList,
getBindValue getBindValue,
emit
); );
const searchInfo = ref(props.params); const searchInfo = ref(props.params);
// update-begin--author:liaozhiyang---date:20230811---forissues/657 // update-begin--author:liaozhiyang---date:20230811---forissues/657
@ -248,8 +255,18 @@
} }
return record; return record;
} }
// update-begin--author:liaozhiyang---date:20240517---forQQYUN-9366
const handleCancel = () => {
emit('close');
};
// update-end--author:liaozhiyang---date:20240517---forQQYUN-9366
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------ //update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
// update-begin--author:liaozhiyang---date:20240607---forTV360X-30510
const clientHeight = document.documentElement.clientHeight * 200;
maxHeight.value = clientHeight > 600 ? 600 : clientHeight;
// update-end--author:liaozhiyang---date:20240607---forTV360X-30510
return { return {
//config, //config,
handleOk, handleOk,
@ -268,6 +285,8 @@
tableScroll, tableScroll,
tableRef, tableRef,
afterFetch, afterFetch,
handleCancel,
maxHeight,
}; };
}, },
}); });

View File

@ -137,8 +137,8 @@
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
//update-begin---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
function records2DataList() { /* function records2DataList() {
let arr:any[] = []; let arr:any[] = [];
let excludeList = props.excludeUserIdList; let excludeList = props.excludeUserIdList;
let records = props.dataList; let records = props.dataList;
@ -150,13 +150,14 @@
} }
} }
return arr; return arr;
} }*/
const showDataList = computed(()=>{ const showDataList = computed(()=>{
let excludeList = props.excludeUserIdList; /* let excludeList = props.excludeUserIdList;
if(excludeList && excludeList.length>0){ if(excludeList && excludeList.length>0){
return records2DataList(); return records2DataList();
} }*/
//update-end---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
return props.dataList; return props.dataList;
}); });

View File

@ -141,7 +141,7 @@
const url = '/sys/user/selectUserList'; const url = '/sys/user/selectUserList';
let params = { let params = {
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 99,
}; };
if (props.searchText) { if (props.searchText) {
params['keyword'] = props.searchText; params['keyword'] = props.searchText;
@ -149,6 +149,11 @@
if (selectedDepartId.value) { if (selectedDepartId.value) {
params['departId'] = selectedDepartId.value; params['departId'] = selectedDepartId.value;
} }
//update-begin---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
if(props.excludeUserIdList && props.excludeUserIdList.length>0){
params['excludeUserIdList'] = props.excludeUserIdList.join(",");
}
//update-end---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
const data = await defHttp.get({ url, params }, { isTransformResponse: false }); const data = await defHttp.get({ url, params }, { isTransformResponse: false });
if (data.success) { if (data.success) {
const { records } = data.result; const { records } = data.result;

View File

@ -90,7 +90,7 @@
const url = '/sys/user/selectUserList'; const url = '/sys/user/selectUserList';
let params = { let params = {
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 99,
}; };
if (props.searchText) { if (props.searchText) {
params['keyword'] = props.searchText; params['keyword'] = props.searchText;
@ -98,6 +98,11 @@
if (selectedRoleId.value) { if (selectedRoleId.value) {
params['roleId'] = selectedRoleId.value; params['roleId'] = selectedRoleId.value;
} }
//update-begin---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
if(props.excludeUserIdList && props.excludeUserIdList.length>0){
params['excludeUserIdList'] = props.excludeUserIdList.join(",");
}
//update-end---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
const data = await defHttp.get({ url, params }, { isTransformResponse: false }); const data = await defHttp.get({ url, params }, { isTransformResponse: false });
if (data.success) { if (data.success) {
const { records } = data.result; const { records } = data.result;

View File

@ -190,12 +190,17 @@
e && prevent(e); e && prevent(e);
searchInputStatus.value = true; searchInputStatus.value = true;
} }
//
function onSearchUser() { function onSearchUser() {
console.log('onSearchUser'); pageNo.value = 1;
loadUserList(); loadUserList();
} }
//
function clearSearch(e) { function clearSearch(e) {
e && prevent(e); e && prevent(e);
pageNo.value = 1;
searchText.value = ''; searchText.value = '';
searchInputStatus.value = false; searchInputStatus.value = false;
loadUserList(); loadUserList();
@ -222,13 +227,16 @@
if (selectedDepart.value) { if (selectedDepart.value) {
params['departId'] = selectedDepart.value; params['departId'] = selectedDepart.value;
} }
//update-begin---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
if(unref(excludeUserIdList) && unref(excludeUserIdList).length>0){
params['excludeUserIdList'] = excludeUserIdList.value.join(",");
}
//update-end---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
const data = await defHttp.get({ url, params }, { isTransformResponse: false }); const data = await defHttp.get({ url, params }, { isTransformResponse: false });
if (data.success) { if (data.success) {
let { records, total } = data.result; let { records, total } = data.result;
//id0
if(unref(excludeUserIdList) && unref(excludeUserIdList).length>0){
total = total - unref(excludeUserIdList).length;
}
totalRecord.value = total; totalRecord.value = total;
initCurrentUserData(records); initCurrentUserData(records);
userDataList.value = records; userDataList.value = records;

View File

@ -13,7 +13,16 @@ export const useCodeHinting = (CodeMirror, keywords, language) => {
}, 1e3); }, 1e3);
} }
}; };
const codeHintingRegistry = () => { const codeHintingRegistry = () => {
// 自定义关键词(.的上一级)
const customKeywords: string[] = [];
currentKeywords.forEach((item) => {
if (item.superiors) {
customKeywords.push(item.superiors);
}
});
const funcsHint = (cm, callback) => { const funcsHint = (cm, callback) => {
// 获取光标位置 // 获取光标位置
const cur = cm.getCursor(); const cur = cm.getCursor();
@ -22,38 +31,93 @@ export const useCodeHinting = (CodeMirror, keywords, language) => {
const start = token.start; const start = token.start;
const end = cur.ch; const end = cur.ch;
const str = token.string; const str = token.string;
let recordKeyword = null;
console.log('光标位置:', cur, '单词信息:', token, `start:${start},end:${end},str:${str}`);
if (str.length) { if (str.length) {
const findIdx = (a, b) => a.toLowerCase().indexOf(b.toLowerCase()); if (str === '.') {
let list = currentKeywords // 查找.前面是否有定义的关键词
.filter((item) => { const curLineCode = cm.getLine(cur.line);
const index = findIdx(item, str); for (let i = 0, len = customKeywords.length; i < len; i++) {
return (index === 0 || index === 1) && (item.length != str.length || item.length - 1 != str.length); const k = curLineCode.substring(-1, customKeywords[i].length);
}) if (customKeywords.includes(k)) {
.sort((a, b) => { recordKeyword = k;
if (findIdx(a, str) < findIdx(b, str)) { break;
return -1;
} else {
return 1;
} }
}); }
}
const findIdx = (a, b) => a.toLowerCase().indexOf(b.toLowerCase());
let list = currentKeywords.filter((item) => {
if (recordKeyword) {
// 查特定对象下的属性or方法
return item.superiors === recordKeyword;
} else {
// 查全局属性或者方法
return item.superiors == undefined;
}
});
if (str === '.') {
if (recordKeyword == null) {
list = [];
}
} else {
list = list
.filter((item) => {
const { text } = item;
const index = findIdx(text, str);
let result = text.startsWith('.') ? index === 1 : index === 0;
return result;
})
.sort((a, b) => {
if (findIdx(a.text, str) < findIdx(b.text, str)) {
return -1;
} else {
return 1;
}
});
}
// 有点去掉点 if (list.length === 1) {
// list = list.map(item => { // 只有一个时可能是自己输入,输到最后需要去掉提示。
// if(item.indexOf(".") === 0){ const item = list[0];
// return item.substring(1); if (item.text === str || item.text.substring(1) === str) {
// } list = [];
// return item; }
// });
if (list.length === 1 && (list[0] === str || list[0].substring(1) === str)) {
list = [];
} }
if (list.length) { if (list.length) {
// 当str不是点时去掉点
if (str != '.') {
list = list.map((item) => {
if (item.text.indexOf('.') === 0) {
return { ...item, text: item.text.substring(1) };
}
return item;
});
}
callback({ callback({
list: list, list: list,
from: CodeMirror.Pos(cur.line, start), from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end), to: CodeMirror.Pos(cur.line, end),
}); });
// update-begin--author:liaozhiyang---date:20240429---for【QQYUN-8865】js增强加上鼠标移入提示
const item = currentKeywords[0];
if (item?.desc) {
setTimeout(() => {
const elem: HTMLUListElement = document.querySelector('.CodeMirror-hints')!;
if (elem) {
const childElems = elem.children;
Array.from(childElems).forEach((item) => {
const displayText = item.textContent;
const findItem = currentKeywords.find((item) => item.displayText === displayText);
if (findItem) {
item.setAttribute('title', findItem.desc);
}
});
}
}, 0);
}
// update-end--author:liaozhiyang---date:20240429---for【QQYUN-8865】js增强加上鼠标移入提示
} else {
} }
} }
}; };

View File

@ -2,7 +2,7 @@ import { inject, reactive, ref, watch, unref, Ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { isEmpty } from '@/utils/is'; import { isEmpty } from '@/utils/is';
export function useSelectBiz(getList, props) { export function useSelectBiz(getList, props, emit) {
//接收下拉框选项 //接收下拉框选项
const selectOptions = inject('selectOptions', ref<Array<object>>([])); const selectOptions = inject('selectOptions', ref<Array<object>>([]));
//接收已选择的值 //接收已选择的值
@ -118,6 +118,10 @@ export function useSelectBiz(getList, props) {
if (visible) { if (visible) {
//设置列表默认选中 //设置列表默认选中
props.showSelected && initSelectRows(); props.showSelected && initSelectRows();
} else {
// update-begin--author:liaozhiyang---date:20240517---for【QQYUN-9366】用户选择组件取消和关闭会把选择数据带入
emit('close');
// update-end--author:liaozhiyang---date:20240517---for【QQYUN-9366】用户选择组件取消和关闭会把选择数据带入
} }
} }

View File

@ -3,7 +3,7 @@ import { inject, reactive, ref, computed, unref, watch, nextTick } from 'vue';
import { TreeActionType } from '/@/components/Tree'; import { TreeActionType } from '/@/components/Tree';
import { listToTree } from '/@/utils/common/compUtils'; import { listToTree } from '/@/utils/common/compUtils';
export function useTreeBiz(treeRef, getList, props, realProps) { export function useTreeBiz(treeRef, getList, props, realProps, emit) {
//接收下拉框选项 //接收下拉框选项
const selectOptions = inject('selectOptions', ref<Array<object>>([])); const selectOptions = inject('selectOptions', ref<Array<object>>([]));
//接收已选择的值 //接收已选择的值
@ -199,7 +199,7 @@ export function useTreeBiz(treeRef, getList, props, realProps) {
const options = <any[]>[]; const options = <any[]>[];
optionData.forEach((item) => { optionData.forEach((item) => {
//update-begin-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑查看数据应该显示部门名称不是部门代码 //update-begin-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑查看数据应该显示部门名称不是部门代码
options.push({ label: item[props.titleKey], value: item[props.rowKey] }); options.push({ label: item[props.labelKey], value: item[props.rowKey] });
//update-end-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑查看数据应该显示部门名称不是部门代码 //update-end-author:taoyan date:2022-7-4 for: issues/I5F3P4 online配置部门选择后编辑查看数据应该显示部门名称不是部门代码
}); });
selectOptions.value = options; selectOptions.value = options;
@ -252,6 +252,9 @@ export function useTreeBiz(treeRef, getList, props, realProps) {
await onLoadData(null, null); await onLoadData(null, null);
} else { } else {
openModal.value = false; openModal.value = false;
// update-begin--author:liaozhiyang---date:20240527---for【TV360X-414】部门设置了默认值查询重置变成空了(同步JSelectUser组件改法)
emit?.('close');
// update-end--author:liaozhiyang---date:20240527---for【TV360X-414】部门设置了默认值查询重置变成空了(同步JSelectUser组件改法)
} }
} }

View File

@ -192,12 +192,20 @@ export interface FormSchema {
dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean); dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[]; dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
// update-begin--author:liaozhiyang---date:20240308---for【QQYUN-8377】formSchema props支持动态修改
// 设置组件props的key
dynamicPropskey?: string;
dynamicPropsVal?: ((renderCallbackParams: RenderCallbackParams) => any);
// update-end--author:liaozhiyang---date:20240308---for【QQYUN-8377】formSchema props支持动态修改
// 这个属性自定义的 用于自定义的业务 比如在表单打开的时候修改表单的禁用状态但是又不能重写componentProps因为他的内容太多了所以使用dynamicDisabled和buss实现 // 这个属性自定义的 用于自定义的业务 比如在表单打开的时候修改表单的禁用状态但是又不能重写componentProps因为他的内容太多了所以使用dynamicDisabled和buss实现
buss?: any; buss?: any;
//label字数控制label宽度 //label字数控制label宽度
labelLength?: number labelLength?: number;
// update-begin--author:liaozhiyang---date:20240529---for【TV360X-460】basicForm支持v-auth指令(权限控制显隐)
auth?: string;
// update-end--author:liaozhiyang---date:20240529---for【TV360X-460】basicForm支持v-auth指令(权限控制显隐)
} }
export interface HelpComponentProps { export interface HelpComponentProps {
maxWidth: string; maxWidth: string;

View File

@ -105,6 +105,7 @@ export type ComponentType =
| 'RangePicker' | 'RangePicker'
| 'WeekPicker' | 'WeekPicker'
| 'TimePicker' | 'TimePicker'
| 'DatePickerInFilter'
| 'Switch' | 'Switch'
| 'StrengthMeter' | 'StrengthMeter'
| 'Upload' | 'Upload'
@ -128,6 +129,7 @@ export type ComponentType =
| 'JCategorySelect' | 'JCategorySelect'
| 'JSelectMultiple' | 'JSelectMultiple'
| 'JPopup' | 'JPopup'
| 'JPopupDict'
| 'JSwitch' | 'JSwitch'
| 'JEasyCron' | 'JEasyCron'
| 'JTreeDict' | 'JTreeDict'
@ -146,10 +148,13 @@ export type ComponentType =
| 'LinkTableSelect' | 'LinkTableSelect'
| 'LinkTableForQuery' | 'LinkTableForQuery'
| 'CascaderPcaForQuery' | 'CascaderPcaForQuery'
| 'CascaderPcaInFilter'
| 'UserSelect' | 'UserSelect'
| 'RoleSelect' | 'RoleSelect'
| 'RangeDate' | 'RangeDate'
| 'RangeNumber' | 'RangeNumber'
| 'linkRecordSelect' | 'linkRecordSelect'
| 'RangeTime' | 'RangeTime'
| 'JRangeNumber'; | 'JRangeNumber'
| 'JInputSelect';

View File

@ -0,0 +1,198 @@
<template>
<div class="flex justify-between ml-4 mr-5 mb-1" v-if="isSearch">
<a-input :placeholder="t('component.icon.search')" v-model:value="searchIconValue" @change="debounceHandleSearchChange" allowClear />
</div>
<div v-if="getPaginationList.length > 0">
<ScrollContainer>
<ul class="px-2 icon-list" style="padding-right: 0">
<li
v-for="icon in getPaginationList"
:key="icon"
:class="currentSelect === icon ? 'icon-border' : ''"
class="p-2 w-1/8 cursor-pointer mr-1 mt-1 flex justify-center items-center border border-solid hover:border-primary"
@click="handleClick(icon)"
:title="icon"
>
<SvgIcon v-if="isSvgMode" :name="icon" />
<Icon :icon="icon" v-else />
</li>
</ul>
</ScrollContainer>
<div class="flex py-2 items-center justify-content-right mr-10 mt-5" v-if="getTotal >= pageSize && isPage">
<Pagination
showLessItems
v-model:current="current"
:page-size-options="pageSizeOptions"
size="small"
v-model:pageSize="pageSize"
v-model:total="getTotal"
@change="handlePageChange"
/>
</div>
</div>
<template v-else
><div class="p-5"><empty /></div>
</template>
</template>
<script lang="ts" name="icon-list">
import { ScrollContainer } from '@/components/Container';
import SvgIcon from '@/components/Icon/src/SvgIcon.vue';
import Icon from '@/components/Icon/src/Icon.vue';
import { defineComponent, ref, unref, watchEffect} from 'vue';
import { useDebounceFn } from '@vueuse/core';
import { usePagination } from '@/hooks/web/usePagination';
import { propTypes } from '@/utils/propTypes';
import { useCopyToClipboard } from '@/hooks/web/useCopyToClipboard';
import { useI18n } from '@/hooks/web/useI18n';
import { useMessage } from '@/hooks/web/useMessage';
import { Empty, Pagination } from 'ant-design-vue';
export default defineComponent({
components: {
ScrollContainer,
SvgIcon,
Icon,
Empty,
Pagination,
},
props: {
currentList: propTypes.any.def([]),
clearSelect: propTypes.bool.def(false),
copy: propTypes.bool.def(false),
isSvgMode: propTypes.bool.def(false),
isPage: propTypes.bool.def(false),
isSearch: propTypes.bool.def(false),
value: propTypes.string.def(''),
},
setup(props, { emit }) {
//
const currentSelect = ref('');
//
const current = ref<number>(1);
//
const pageSize = ref<number>(140);
//
const pageSizeOptions = ref<any>(['10', '20', '50', '100', '140']);
//
const searchIconValue = ref<string>('');
const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
const currentList = ref<any>(props.currentList);
const { getPaginationList, getTotal, setCurrentPage, setPageSize } = usePagination(currentList, pageSize.value);
const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
const { t } = useI18n();
const { createMessage } = useMessage();
/**
* 搜索
* @param e
*/
function handleSearchChange(e: ChangeEvent) {
const value = e.target.value;
console.log("value::::",value)
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
setCurrentPage(1);
current.value = 1;
//update-end---author:wangshuai ---date:20230522 forissues/4947------------
if (!value) {
currentList.value = props.currentList;
return;
}
currentList.value = props.currentList.filter((item) => item.includes(value));
}
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
/**
* 图标点击重置页数
*/
function currentSelectClick() {
setCurrentPage(1);
setPageSize(140);
current.value = 1;
pageSize.value = 140;
currentList.value = props.currentList;
searchIconValue.value = '';
}
//update-end---author:wangshuai ---date:20230522 forissues/4947------------
function handlePageChange(page: number, size: number) {
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
current.value = page;
pageSize.value = size;
setPageSize(size);
//update-end---author:wangshuai ---date:20230522 forissues/4947------------
setCurrentPage(page);
}
/**
* 图标点击事件
* @param icon
*/
function handleClick(icon: string) {
if (props.clearSelect === true) {
if (currentSelect.value === icon) {
currentSelect.value = '';
} else {
currentSelect.value = icon;
}
} else {
currentSelect.value = icon;
if (props.copy) {
clipboardRef.value = icon;
if (unref(isSuccessRef)) {
createMessage.success(t('component.icon.copy'));
}
}
}
}
/**
* 获取图标
*/
function getIcon() {
return currentSelect.value;
}
watchEffect(() => {
currentSelect.value = props.value;
});
return {
searchIconValue,
debounceHandleSearchChange,
getTotal,
getPaginationList,
handlePageChange,
handleClick,
currentSelect,
t,
pageSize,
pageSizeOptions,
current,
getIcon,
currentSelectClick,
};
},
});
</script>
<style scoped lang="less">
ul li {
width: 32px;
height: 32px;
float: left;
display: flex;
margin: 6px;
}
ul span {
font-size: 1.5rem !important;
border: 1px solid #f1f1f1;
padding: 0.2rem;
margin: 0.3rem;
}
.icon-border span {
border: 1px solid rgba(24, 144, 255) !important;
}
.justify-content-right {
justify-content: right;
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,39 @@
<!-- 省市县选择组件在筛选中的用法 -->
<template>
<a-space :class="[prefixCls]" direction="vertical">
</a-space>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
name: 'CascaderPcaInFilter',
inheritAttrs: false,
})
</script>
<script lang="ts" setup>
</script>
<style lang="less">
//noinspection LessUnresolvedVariable
@prefix-cls: ~'@{namespace}-j-cascader-pca-in-filter';
.@{prefix-cls} {
width: 100%;
}
.@{prefix-cls}-menu-item-icon {
width: 16px;
height: 16px;
display: inline-block;
margin-right: 6px;
&, & + span {
vertical-align: middle;
}
}
</style>

View File

@ -0,0 +1,142 @@
<!-- 在筛选中使用的日期选择器可选择今天本周等范围 -->
<template>
<a-space :id="formItemId" :class="[prefixCls]" direction="vertical">
<a-space-compact block>
<!-- 日期范围下拉 -->
<a-select v-if="isRange" v-model:value="innerValue">
<a-select-option v-for="opt of RANGE_OPTIONS" :key="opt.key" :value="opt.key">
{{ opt.label }}
</a-select-option>
<a-select-option key="custom" value="custom">
自定义日期
</a-select-option>
</a-select>
<!-- 自定义日期选择器 -->
<DatePicker v-else v-model:value="innerValue" v-model:open="datePickerIsOpen" v-bind="attrs"/>
<!-- 右侧下拉菜单 -->
<a-dropdown v-if="allowSelectRange" :trigger="['click']">
<a-button preIcon="ant-design:menu-unfold"/>
<template #overlay>
<a-menu @click="onMenuClick">
<a-menu-item v-for="opt of RANGE_OPTIONS" :key="opt.key">
{{ opt.label }}
</a-menu-item>
<a-menu-item key="custom">
自定义日期
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</a-space-compact>
</a-space>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
name: 'DatePickerInFilter',
inheritAttrs: false,
})
</script>
<script lang="ts" setup>
import {ref, watch, computed, nextTick, useAttrs, defineProps} from 'vue'
import {DatePicker} from 'ant-design-vue'
import {useDesign} from '/@/hooks/web/useDesign';
import { Form } from 'ant-design-vue';
const formItemContext = Form.useInjectFormItemContext();
//
const RANGE_OPTIONS = [
{key: 'TODAY', label: '今天'},
{key: 'YESTERDAY', label: '昨天'},
{key: 'TOMORROW', label: '明天'},
{key: 'THIS_WEEK', label: '本周'},
{key: 'LAST_WEEK', label: '上周'},
{key: 'NEXT_WEEK', label: '下周'},
{key: 'LAST_7_DAYS', label: '过去七天'},
{key: 'THIS_MONTH', label: '本月'},
{key: 'LAST_MONTH', label: '上月'},
{key: 'NEXT_MONTH', label: '下月'},
];
const RANGE_OPTION_KEYS = RANGE_OPTIONS.map(item => item.key)
const {prefixCls} = useDesign('j-data-picker-in-filter');
const props = defineProps({
value: {
type: [String],
default: ''
},
//
allowSelectRange: {
type: Boolean,
default: true,
}
})
const emit = defineEmits(['change', 'update:value'])
const attrs = useAttrs()
// id
const formItemId = computed(() => formItemContext.id.value)
const innerValue = ref(props.value)
//
const datePickerIsOpen = ref(false)
//
const isRange = computed(() => RANGE_OPTION_KEYS.includes(innerValue.value));
// value
watch(() => props.value, (val) => {
innerValue.value = val
})
// emit
watch(innerValue, (val) => {
if (val === 'custom') {
val = ''
openDatePicker()
}
emit('change', val)
emit('update:value', val)
// update-begin--author:liaozhiyang---date:20240509---forQQYUN-9227
formItemContext?.onFieldChange();
// update-end--author:liaozhiyang---date:20240509---forQQYUN-9227
})
watch(() => props.allowSelectRange, (allow) => {
//
if (!allow && isRange.value) {
innerValue.value = ''
}
}, {immediate: true});
//
function onMenuClick(event: Recordable) {
if (event.key === 'custom') {
if (isRange.value) {
innerValue.value = '';
}
openDatePicker()
} else {
innerValue.value = event.key
}
}
//
async function openDatePicker() {
await nextTick()
datePickerIsOpen.value = true
}
</script>
<style lang="less">
//noinspection LessUnresolvedVariable
@prefix-cls: ~'@{namespace}-j-data-picker-in-filter';
.@{prefix-cls} {
width: 100%;
}
</style>

View File

@ -0,0 +1,2 @@
export {default as DatePickerInFilter} from './DatePickerInFilter.vue';
export {default as CascaderPcaInFilter} from './CascaderPcaInFilter.vue';

View File

@ -1,7 +1,7 @@
import { registerComponent, registerAsyncComponent } from '/@/components/jeecg/JVxeTable'; import { registerComponent, registerAsyncComponent, registerASyncComponentReal } from '/@/components/jeecg/JVxeTable';
import { JVxeTypes } from '/@/components/jeecg/JVxeTable/types'; import { JVxeTypes } from '/@/components/jeecg/JVxeTable/types';
import { DictSearchSpanCell, DictSearchInputCell } from './src/components/JVxeSelectDictSearchCell'; import { DictSearchSpanCell, DictSearchInputCell } from './src/components/JVxeSelectDictSearchCell';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export async function registerJVxeCustom() { export async function registerJVxeCustom() {
// ----------------- ⚠ 注意事项 ⚠ ----------------- // ----------------- ⚠ 注意事项 ⚠ -----------------
// 当组件内包含 BasicModal 时,必须使用异步引入! // 当组件内包含 BasicModal 时,必须使用异步引入!
@ -23,5 +23,11 @@ export async function registerJVxeCustom() {
// 注册【部门选择】组件 // 注册【部门选择】组件
await registerAsyncComponent(JVxeTypes.departSelect, import('./src/components/JVxeDepartSelectCell.vue')); await registerAsyncComponent(JVxeTypes.departSelect, import('./src/components/JVxeDepartSelectCell.vue'));
// 注册【省市区选择】组件 // 注册【省市区选择】组件
await registerAsyncComponent(JVxeTypes.pca, import('./src/components/JVxePcaCell.vue')); // await registerAsyncComponent(JVxeTypes.pca, import('./src/components/JVxePcaCell.vue'));
// update-begin--author:liaozhiyang---date:20240308---for【QQYUN-8241】为避免首次加载china-area-dataJVxePcaCell组件需异步加载
registerASyncComponentReal(
JVxeTypes.pca,
createAsyncComponent(() => import('./src/components/JVxePcaCell.vue'))
);
// update-end--author:liaozhiyang---date:20240308---for【QQYUN-8241】为避免首次加载china-area-dataJVxePcaCell组件需异步加载
} }

View File

@ -17,7 +17,7 @@
<span style="margin-left: 5px">{{ ellipsisFileName }}</span> <span style="margin-left: 5px">{{ ellipsisFileName }}</span>
</a-tooltip> </a-tooltip>
<Dropdown :trigger="['click']" placement="bottomRight" style="margin-left: 10px" :disabled="cellProps.disabled"> <Dropdown :trigger="['click']" placement="bottomRight" style="margin-left: 10px">
<a-tooltip title="操作"> <a-tooltip title="操作">
<Icon v-if="file.status !== 'uploading'" icon="ant-design:setting" style="cursor: pointer" /> <Icon v-if="file.status !== 'uploading'" icon="ant-design:setting" style="cursor: pointer" />
</a-tooltip> </a-tooltip>
@ -26,10 +26,10 @@
<a-menu-item v-if="originColumn.allowDownload !== false" @click="handleClickDownloadFile"> <a-menu-item v-if="originColumn.allowDownload !== false" @click="handleClickDownloadFile">
<span><Icon icon="ant-design:download" />&nbsp;下载</span> <span><Icon icon="ant-design:download" />&nbsp;下载</span>
</a-menu-item> </a-menu-item>
<a-menu-item v-if="originColumn.allowRemove !== false" @click="handleClickDeleteFile"> <a-menu-item :disabled="cellProps.disabled" v-if="originColumn.allowRemove !== false" @click="handleClickDeleteFile">
<span><Icon icon="ant-design:delete" />&nbsp;删除</span> <span><Icon icon="ant-design:delete" />&nbsp;删除</span>
</a-menu-item> </a-menu-item>
<a-menu-item @click="handleMoreOperation"> <a-menu-item :disabled="cellProps.disabled" @click="handleMoreOperation">
<span><Icon icon="ant-design:bars" />&nbsp;更多</span> <span><Icon icon="ant-design:bars" />&nbsp;更多</span>
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
@ -39,6 +39,7 @@
</template> </template>
<a-upload <a-upload
v-if="!cellProps.disabledTable"
v-show="!hasFile" v-show="!hasFile"
name="file" name="file"
:data="{ isup: 1 }" :data="{ isup: 1 }"

View File

@ -9,7 +9,7 @@
</template> </template>
<template v-else-if="file['path']"> <template v-else-if="file['path']">
<template v-for="src of imgList"> <template v-for="src of imgList">
<img class="j-vxe-image" :src="src" alt="图片错误" @[clickEvent]="handleMoreOperation" /> <img class="j-vxe-image" :src="src" alt="图片错误" @[clickEvent]="handleMoreOperation" @click="handlePreview" />
</template> </template>
</template> </template>
<a-tooltip v-else :title="file.message || '上传失败'" @[clickEvent]="handleClickShowImageError"> <a-tooltip v-else :title="file.message || '上传失败'" @[clickEvent]="handleClickShowImageError">
@ -17,8 +17,9 @@
</a-tooltip> </a-tooltip>
</div> </div>
</template> </template>
<div class="j-vxe-image-upload"> <div class="j-vxe-image-upload" v-if="!cellProps.disabledTable">
<a-upload <a-upload
:accept="acceptFileType"
name="file" name="file"
:data="{ isup: 1 }" :data="{ isup: 1 }"
:multiple="false" :multiple="false"
@ -45,6 +46,7 @@
import { UploadTypeEnum } from '/@/components/Form/src/jeecg/components/JUpload'; import { UploadTypeEnum } from '/@/components/Form/src/jeecg/components/JUpload';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { components, enhanced, useFileCell } from '../hooks/useFileCell'; import { components, enhanced, useFileCell } from '../hooks/useFileCell';
import { createImgPreview } from '/@/components/Preview/index';
export default defineComponent({ export default defineComponent({
name: 'JVxeImageCell', name: 'JVxeImageCell',
@ -54,6 +56,9 @@
const { createErrorModal } = useMessage(); const { createErrorModal } = useMessage();
const setup = useFileCell(props, UploadTypeEnum.image, { multiple: true }); const setup = useFileCell(props, UploadTypeEnum.image, { multiple: true });
// update-begin--author:liaozhiyang---date:20240604---forTV360X-470jVxetable
const acceptFileType = 'image/*';
// update-end--author:liaozhiyang---date:20240604---forTV360X-470jVxetable
// update-begin--author:liaozhiyang---date:20240105---forissues/953onlinevxe-table // update-begin--author:liaozhiyang---date:20240105---forissues/953onlinevxe-table
const clickEvent = computed(() => { const clickEvent = computed(() => {
return unref(setup.cellProps).disabled ? null : 'click'; return unref(setup.cellProps).disabled ? null : 'click';
@ -84,13 +89,21 @@
}); });
} }
} }
// update-begin--author:liaozhiyang---date:20240523---forTV360X-121jvxetable()
const handlePreview = () => {
if (unref(setup.cellProps).disabled) {
createImgPreview({ imageList: imgList.value });
}
};
// update-end--author:liaozhiyang---date:20240523---forTV360X-121jvxetable()
return { return {
...setup, ...setup,
imgList, imgList,
maxCount, maxCount,
handleClickShowImageError, handleClickShowImageError,
clickEvent clickEvent,
handlePreview,
acceptFileType,
}; };
}, },
// JVxeComponent.Enhanced // JVxeComponent.Enhanced

View File

@ -63,6 +63,11 @@ export function useFileCell(props, fileType: UploadTypeEnum, options?) {
// 更多上传回调 // 更多上传回调
function onModalChange(path) { function onModalChange(path) {
if (path) { if (path) {
// update-begin--author:liaozhiyang---date:20240524---for【TV360X-235】富文本禁用状态下图片上传按钮文字看不清
if (innerFile.value === null) {
innerFile.value = {};
}
// update-end-author:liaozhiyang---date:20240524---for【TV360X-235】富文本禁用状态下图片上传按钮文字看不清
innerFile.value.path = path; innerFile.value.path = path;
handleChangeCommon(innerFile.value); handleChangeCommon(innerFile.value);
} else { } else {

View File

@ -112,8 +112,46 @@
const insEditor = new Vditor(wrapEl, { const insEditor = new Vditor(wrapEl, {
theme: getDarkMode.value === 'dark' ? 'dark' : 'classic', theme: getDarkMode.value === 'dark' ? 'dark' : 'classic',
lang: unref(getCurrentLang), lang: unref(getCurrentLang),
// update-begin--author:liaozhiyang---date:20240520---forTV360X-146Markdown
toolbar: [
'emoji',
'headings',
'bold',
'italic',
'strike',
'link',
'|',
'list',
'ordered-list',
'check',
'outdent',
'indent',
'|',
'quote',
'line',
'code',
'inline-code',
'insert-before',
'insert-after',
'|',
'upload',
// 'record',
'table',
'|',
'undo',
'redo',
'|',
'fullscreen',
'edit-mode',
{
name: 'more',
toolbar: ['both', 'code-theme', 'content-theme', 'export', 'outline', 'preview', 'devtools', 'info', 'help'],
},
],
// update-end--author:liaozhiyang---date:20240520---forTV360X-146Markdown
mode: 'sv', mode: 'sv',
cdn: 'https://cdn.jsdelivr.net/npm/vditor@3.9.6', // cdn: 'https://cdn.jsdelivr.net/npm/vditor@3.9.6',
cdn: 'https://unpkg.com/vditor@3.10.1',
fullscreen: { fullscreen: {
index: 520, index: 520,
}, },
@ -186,3 +224,10 @@
}, },
}); });
</script> </script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20240527---forTV360X-318markdown
:deep(.vditor-menu--disabled) {
pointer-events: none;
}
// update-end--author:liaozhiyang---date:20240527---forTV360X-318markdown
</style>

View File

@ -25,7 +25,7 @@
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { useOpenKeys } from './useOpenKeys'; import { useOpenKeys } from './useOpenKeys';
import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router'; import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router';
import { isFunction } from '/@/utils/is'; import { isFunction, isUrl } from '/@/utils/is';
import { basicProps } from './props'; import { basicProps } from './props';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { REDIRECT_NAME } from '/@/router/constant'; import { REDIRECT_NAME } from '/@/router/constant';
@ -33,6 +33,9 @@
import { getCurrentParentPath } from '/@/router/menus'; import { getCurrentParentPath } from '/@/router/menus';
import { listenerRouteChange } from '/@/logics/mitt/routeChange'; import { listenerRouteChange } from '/@/logics/mitt/routeChange';
import { getAllParentPath } from '/@/router/helper/menuHelper'; import { getAllParentPath } from '/@/router/helper/menuHelper';
import { createBasicRootMenuContext } from './useBasicMenuContext';
import { URL_HASH_TAB } from '/@/utils';
import { getMenus } from '/@/router/menus';
export default defineComponent({ export default defineComponent({
name: 'BasicMenu', name: 'BasicMenu',
@ -52,7 +55,9 @@
selectedKeys: [], selectedKeys: [],
collapsedOpenKeys: [], collapsedOpenKeys: [],
}); });
// update-begin--author:liaozhiyang---date:20230326---forQQYUN-8691onlineauto线
createBasicRootMenuContext({ menuState: menuState });
// update-end--author:liaozhiyang---date:20230326---forQQYUN-8691onlineauto线
const { prefixCls } = useDesign('basic-menu'); const { prefixCls } = useDesign('basic-menu');
const { items, mode, accordion } = toRefs(props); const { items, mode, accordion } = toRefs(props);
@ -112,11 +117,43 @@
//update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online //update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online
async function handleMenuClick({ item, key }: { item: any; key: string; keyPath: string[] }) { async function handleMenuClick({ item, key }: { item: any; key: string; keyPath: string[] }) {
const { beforeClickFn } = props; const { beforeClickFn } = props;
// update-begin--author:liaozhiyang---date:20240402---for:QQYUN-8773
if (isUrl(key)) {
key = key.replace(URL_HASH_TAB, '#');
window.open(key);
return;
}
// update-end--author:liaozhiyang---date:20240402---for:QQYUN-8773
if (beforeClickFn && isFunction(beforeClickFn)) { if (beforeClickFn && isFunction(beforeClickFn)) {
const flag = await beforeClickFn(key); const flag = await beforeClickFn(key);
if (!flag) return; if (!flag) return;
} }
emit('menuClick', key, item); // update-begin--author:liaozhiyang---date:20240418---for:QQYUN-8773()redirect
if (props.type === MenuTypeEnum.MIX) {
const menus = await getMenus();
const menuItem = getMatchingPath(menus, key);
if (menuItem && !menuItem.redirect && menuItem.children?.length) {
const subMenuItem = getSubMenu(menuItem.children);
if (subMenuItem?.path) {
const path = subMenuItem.redirect ?? subMenuItem.path;
let _key = path;
if (isUrl(path)) {
window.open(path);
// emitkeyurl
_key = key;
}
emit('menuClick', _key, { title: subMenuItem.title });
} else {
emit('menuClick', key, item);
}
} else {
emit('menuClick', key, item);
}
} else {
emit('menuClick', key, item);
}
// emit('menuClick', key, item);
// update-begin--author:liaozhiyang---date:20240418---for:QQYUN-8773()redirect
//update-end-author:taoyan date:2022-6-1 for: VUEN-1144 online //update-end-author:taoyan date:2022-6-1 for: VUEN-1144 online
isClickGo.value = true; isClickGo.value = true;
@ -142,6 +179,45 @@
menuState.selectedKeys = parentPaths; menuState.selectedKeys = parentPaths;
} }
} }
/**
* liaozhiyang
* 2024-05-18
* 获取指定菜单下的第一个菜单
*/
function getSubMenu(menus) {
for (let i = 0, len = menus.length; i < len; i++) {
const item = menus[i];
if (item.path && !item.children?.length) {
return item;
} else if (item.children?.length) {
const result = getSubMenu(item.children);
if (result) {
return result;
}
}
}
return null;
}
/**
* liaozhiyang
* 2024-05-18
* 获取匹配path的菜单
*/
function getMatchingPath(menus, path) {
for (let i = 0, len = menus.length; i < len; i++) {
const item = menus[i];
if (item.path === path) {
return item;
} else if (item.children?.length) {
const result = getMatchingPath(item.children, path);
if (result) {
return result;
}
}
}
return null;
}
return { return {
handleMenuClick, handleMenuClick,

View File

@ -1,6 +1,6 @@
<template> <template>
<BasicMenuItem v-if="!menuHasChildren(item) && getShowMenu" v-bind="$props" /> <BasicMenuItem v-if="!menuHasChildren(item) && getShowMenu" v-bind="$props" />
<SubMenu v-if="menuHasChildren(item) && getShowMenu" :class="[theme]" :key="`submenu-${item.path}`" popupClassName="app-top-menu-popup"> <SubMenu v-if="menuHasChildren(item) && getShowMenu" :class="[theme]" :key="`submenu-${item.path}`" :popupClassName="prefixCls">
<template #title> <template #title>
<MenuItemContent v-bind="$props" :item="item" /> <MenuItemContent v-bind="$props" :item="item" />
</template> </template>
@ -12,13 +12,16 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import type { Menu as MenuType } from '/@/router/types'; import type { Menu as MenuType } from '/@/router/types';
import { defineComponent, computed } from 'vue'; import { defineComponent, computed, watch } from 'vue';
import { Menu } from 'ant-design-vue'; import { Menu } from 'ant-design-vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { checkChildrenHidden } from '/@/utils/common/compUtils'; import { checkChildrenHidden } from '/@/utils/common/compUtils';
import { itemProps } from '../props'; import { itemProps } from '../props';
import BasicMenuItem from './BasicMenuItem.vue'; import BasicMenuItem from './BasicMenuItem.vue';
import MenuItemContent from './MenuItemContent.vue'; import MenuItemContent from './MenuItemContent.vue';
import { useBasicRootMenuContext } from '../useBasicMenuContext';
import { useLocaleStore } from '/@/store/modules/locale';
import { getMenus } from '/@/router/menus';
export default defineComponent({ export default defineComponent({
name: 'BasicSubMenuItem', name: 'BasicSubMenuItem',
@ -30,7 +33,9 @@
}, },
props: itemProps, props: itemProps,
setup(props) { setup(props) {
const { prefixCls } = useDesign('basic-menu-item'); const { prefixCls } = useDesign('basic-subMenu');
const { menuState } = useBasicRootMenuContext();
const localeStore = useLocaleStore();
const getShowMenu = computed(() => !props.item.meta?.hideMenu); const getShowMenu = computed(() => !props.item.meta?.hideMenu);
function menuHasChildren(menuTreeItem: MenuType): boolean { function menuHasChildren(menuTreeItem: MenuType): boolean {
@ -42,6 +47,34 @@
&&checkChildrenHidden(menuTreeItem) &&checkChildrenHidden(menuTreeItem)
); );
} }
// update-begin--author:liaozhiyang---date:20230326---forQQYUN-8691onlineauto线
const getMatchingRouterName = (menus, path) => {
for (let i = 0, len = menus.length; i < len; i++) {
const item = menus[i];
if (item.path === path && !item.redirect && !item.paramPath) {
return item.meta?.title;
} else if (item.children?.length) {
const result = getMatchingRouterName(item.children, path);
if (result) {
return result;
}
}
}
return '';
};
watch(
() => menuState.selectedKeys,
async (value) => {
if (value.length && value.includes(props.item.path)) {
const menus = await getMenus();
const getTitle = getMatchingRouterName(menus, props.item.path);
localeStore.setPathTitle(props.item.path, getTitle ? getTitle : props.item.name);
}
},
{ immediate: true }
);
// update-end--author:liaozhiyang---date:20230326---forQQYUN-8691onlineauto线
return { return {
prefixCls, prefixCls,
menuHasChildren, menuHasChildren,
@ -51,3 +84,51 @@
}, },
}); });
</script> </script>
<style lang="less">
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762
@prefix-cls: ~'@{namespace}-basic-subMenu';
html[data-theme='light'] {
.@{prefix-cls}.ant-menu-dark {
background-color: var(--header-bg-color);
color: rgba(255, 255, 255, 0.9);
&.ant-menu-submenu {
> .ant-menu {
background-color: var(--header-bg-color);
}
}
.ant-menu-item-selected {
background-color: var(--header-active-menu-bg-color);
}
}
//QQYUN-8922
.ant-menu-submenu-placement-bottomLeft.ant-menu-dark.ant-menu-submenu-popup {
background-color: var(--header-bg-color);
&.ant-menu-dark.ant-menu-submenu > .ant-menu {
background-color: var(--header-bg-color);
color: rgba(255, 255, 255, 0.9);
}
}
}
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762
// update-begin--author:liaozhiyang---date:20240429---forQQYUN-9128
html[data-theme='dark'] {
@bgcolor:#212121;
.@{prefix-cls}.ant-menu-dark {
background-color: @bgcolor;
&.ant-menu-submenu {
> .ant-menu {
background-color: @bgcolor;
}
}
}
//QQYUN-8922
.ant-menu-submenu-placement-bottomLeft.ant-menu-dark.ant-menu-submenu-popup {
background-color: @bgcolor;
&.ant-menu-dark.ant-menu-submenu > .ant-menu {
background-color: @bgcolor;
color: rgba(255, 255, 255, 0.9);
}
}
}
// update-end--author:liaozhiyang---date:20240429---forQQYUN-9128
</style>

View File

@ -18,7 +18,9 @@
&.ant-menu-dark { &.ant-menu-dark {
background-color: transparent; background-color: transparent;
// update-begin--author:liaozhiyang---date:20240407---for【QQYUN-8762】顶部菜单模式文字调整
color: rgba(255 ,255 ,255, 1);
// update-end--author:liaozhiyang---date:20240407---for【QQYUN-8762】顶部菜单模式文字调整
.ant-menu-submenu:hover, .ant-menu-submenu:hover,
.ant-menu-item-open, .ant-menu-item-open,
.ant-menu-submenu-open, .ant-menu-submenu-open,

View File

@ -0,0 +1,16 @@
import type { InjectionKey, Ref } from 'vue';
import { createContext, useContext } from '/@/hooks/core/useContext';
export interface BasicRootMenuContextProps {
menuState: any;
}
const key: InjectionKey<BasicRootMenuContextProps> = Symbol();
export function createBasicRootMenuContext(context: BasicRootMenuContextProps) {
return createContext<BasicRootMenuContextProps>(context, key, { readonly: false, native: true });
}
export function useBasicRootMenuContext() {
return useContext<BasicRootMenuContextProps>(key);
}

View File

@ -65,12 +65,15 @@
import { useFullScreen } from './hooks/useModalFullScreen'; import { useFullScreen } from './hooks/useModalFullScreen';
import { omit } from 'lodash-es'; import { omit } from 'lodash-es';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useAppInject } from '/@/hooks/web/useAppInject';
export default defineComponent({ export default defineComponent({
name: 'BasicModal', name: 'BasicModal',
components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader }, components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
inheritAttrs: false, inheritAttrs: false,
props: basicProps, props: basicProps,
emits: ['visible-change', 'open-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible', 'update:open', 'fullScreen'], emits: ['visible-change', 'open-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible', 'update:open', 'fullScreen','comment-open'],
setup(props, { emit, attrs , slots}) { setup(props, { emit, attrs , slots}) {
const visibleRef = ref(false); const visibleRef = ref(false);
const propsRef = ref<Partial<ModalProps> | null>(null); const propsRef = ref<Partial<ModalProps> | null>(null);
@ -94,13 +97,21 @@
if (instance) { if (instance) {
emit('register', modalMethods, instance.uid); emit('register', modalMethods, instance.uid);
} }
const { getIsMobile } = useAppInject();
// Custom title component: get title // Custom title component: get title
const getMergeProps = computed((): Recordable => { const getMergeProps = computed((): Recordable => {
return { const result = {
...props, ...props,
...(unref(propsRef) as any), ...(unref(propsRef) as any),
}; };
// update-begin--author:liaozhiyang---date:20240326---forQQYUN-8643
if (getIsMobile.value) {
result.canFullscreen = false;
result.defaultFullscreen = true;
}
// update-end--author:liaozhiyang---date:20240326---forQQYUN-8643
return result;
}); });
//update-begin-author:liusq date:2023-05-25 for:issues/4856Modal :title = null //update-begin-author:liusq date:2023-05-25 for:issues/4856Modal :title = null
// //
@ -153,6 +164,11 @@
watchEffect(() => { watchEffect(() => {
fullScreenRef.value = !!props.defaultFullscreen; fullScreenRef.value = !!props.defaultFullscreen;
// update-begin--author:liaozhiyang---date:20240326---forQQYUN-8643
if (getIsMobile.value) {
fullScreenRef.value = true
}
// update-end--author:liaozhiyang---date:20240326---forQQYUN-8643
}); });
watchEffect(() => { watchEffect(() => {
@ -167,6 +183,7 @@
() => unref(visibleRef), () => unref(visibleRef),
(v) => { (v) => {
emit('visible-change', v); emit('visible-change', v);
emit('open-change', v);
emit('update:visible', v); emit('update:visible', v);
emit('update:open', v); emit('update:open', v);
instance && modalMethods.emitVisible?.(v, instance.uid); instance && modalMethods.emitVisible?.(v, instance.uid);
@ -210,6 +227,11 @@
} }
if (Reflect.has(props, 'defaultFullscreen')) { if (Reflect.has(props, 'defaultFullscreen')) {
fullScreenRef.value = !!props.defaultFullscreen; fullScreenRef.value = !!props.defaultFullscreen;
// update-begin--author:liaozhiyang---date:20240326---forQQYUN-8643
if (getIsMobile.value) {
fullScreenRef.value = true
}
// update-end--author:liaozhiyang---date:20240326---forQQYUN-8643
} }
} }
@ -242,6 +264,9 @@
}else{ }else{
commentSpan.value = 0 commentSpan.value = 0
} }
// update-begin--author:liaozhiyang---date:20240528---forTV360X-485
emit('comment-open', commentSpan.value === 0, commentSpan.value);
// update-end--author:liaozhiyang---date:20240528---forTV360X-485
} }
//update-end-author:taoyan date:2022-7-18 for: modal slot //update-end-author:taoyan date:2022-7-18 for: modal slot
@ -295,4 +320,9 @@
.jeecg-modal-content { .jeecg-modal-content {
height: 100%; height: 100%;
} }
html[data-theme='dark'] {
.jeecg-comment-outer {
border-left: 1px solid rgba(253, 253, 253, 0.12);
}
}
</style> </style>

View File

@ -0,0 +1,327 @@
<template>
<a-modal v-bind="getBindValue" @cancel="handleCancel" :body-style="!fullScreenRef ? bodyStyle : {}">
<slot></slot>
<template #closeIcon v-if="!$slots.closeIcon">
<div class="jeecg-basic-modal-close" v-if="canFullscreen">
<Tooltip :title="t('component.modal.restore')" placement="bottom" v-if="fullScreenRef">
<FullscreenExitOutlined role="full" @click="handleFullScreen" />
</Tooltip>
<Tooltip :title="t('component.modal.maximize')" placement="bottom" v-else>
<FullscreenOutlined role="close" @click="handleFullScreen" />
</Tooltip>
<Tooltip :title="t('component.modal.close')" placement="bottom">
<CloseOutlined @click="handleCancel" />
</Tooltip>
</div>
</template>
<template #title v-if="!isNoTitle">
<ModalHeader :helpMessage="getProps.helpMessage" :title="getMergeProps.title" @dblclick="handleTitleDbClick" />
</template>
<template #footer v-if="!$slots.footer">
<ModalFooter v-bind="getBindValue" @ok="handleOk" @cancel="handleCancel">
<template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data || {}"></slot>
</template>
</ModalFooter>
</template>
<template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
<slot :name="item" v-bind="data || {}"></slot>
</template>
</a-modal>
</template>
<script lang="ts" name="j-modal">
import { computed, defineComponent, getCurrentInstance, ref, toRef, unref, watch, watchEffect } from 'vue';
import ModalFooter from '@/components/Modal/src/components/ModalFooter.vue';
import ModalClose from '@/components/Modal/src/components/ModalClose.vue';
import ModalHeader from '@/components/Modal/src/components/ModalHeader.vue';
import { omit } from 'lodash-es';
import { useAppInject } from '@/hooks/web/useAppInject';
import type { ModalMethods, ModalProps } from '@/components/Modal';
import { CloseOutlined, FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons-vue';
import { Tooltip } from 'ant-design-vue';
import { useI18n } from '@/hooks/web/useI18n';
import { deepMerge } from '@/utils';
import { basicProps } from '@/components/Modal/src/props';
import Modal from '/@/components/Modal/src/components/Modal';
import { isFunction } from '@/utils/is';
export default defineComponent({
name: 'JModal',
methods: { omit },
components: {
CloseOutlined,
Tooltip,
FullscreenExitOutlined,
FullscreenOutlined,
ModalHeader,
ModalClose,
ModalFooter,
Modal,
},
props: {
//
fullscreen: {
type: Boolean,
default: false,
},
...basicProps,
},
emits: ['visible-change', 'open-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible', 'update:open', 'fullScreen'],
setup(props, { emit, attrs, slots }) {
const { getIsMobile } = useAppInject();
const visibleRef = ref(false);
const propsRef = ref<Partial<ModalProps> | null>(null);
const fullScreenRef = ref<any>(props.fullscreen);
const fullScreen = ref<boolean>(false);
const { t } = useI18n();
const bodyStyle = ref<any>({
height: props.maxHeight ? props.maxHeight : '600px',
'overflow-y': 'auto',
});
const modalMethods: ModalMethods = {
setModalProps,
emitVisible: undefined,
};
const getMergeProps = computed((): Recordable => {
const result = {
...props,
...(unref(propsRef) as any),
};
if (getIsMobile.value) {
result.fullscreen = false;
}
return result;
});
const getBindValue = computed((): Recordable => {
const attr = {
...attrs,
...unref(getMergeProps),
open: unref(visibleRef),
wrapClassName: unref(getWrapClassName),
};
if (unref(fullScreenRef)) {
return omit(attr, ['height', 'visible']);
}
return omit(attr, ['visible']);
});
//warpClassName
const getWrapClassName = computed(() => {
const clsName = toRef(getMergeProps.value, 'wrapClassName').value || '';
return unref(fullScreenRef) ? `jeecg-full-screen-modal-code-generate ${clsName} ` : unref(clsName);
});
//props
const getProps = computed((): Recordable => {
const opt = {
...unref(getMergeProps),
visible: unref(visibleRef),
okButtonProps: undefined,
cancelButtonProps: undefined,
title: undefined,
};
return {
...opt,
wrapClassName: unref(getWrapClassName),
};
});
//model,instance.uid model
const instance = getCurrentInstance();
if (instance) {
emit('register', modalMethods, instance.uid);
}
/**
* 是否含有标题
*/
function isNoTitle() {
//
return !unref(getMergeProps).title && !slots.title;
}
/**
* 放大缩小事件
* @param e
*/
function handleFullScreen(e: Event) {
e?.stopPropagation();
e?.preventDefault();
fullScreenRef.value = !unref(fullScreenRef);
}
//
async function handleCancel(e: Event) {
e?.stopPropagation();
//
if (props.closeFunc && isFunction(props.closeFunc)) {
const isClose: boolean = await props.closeFunc();
visibleRef.value = !isClose;
return;
}
visibleRef.value = false;
emit('cancel', e);
}
/**
* 确定事件
* @param e
*/
function handleOk(e: Event) {
emit('ok', e);
}
function handleTitleDbClick(e) {
if (!props.fullscreen) return;
e.stopPropagation();
handleFullScreen(e);
}
/**
* 设置modal参数
*/
function setModalProps(props: Partial<ModalProps>): void {
// Keep the last setModalProps
propsRef.value = deepMerge(unref(propsRef) || ({} as any), props);
if (Reflect.has(props, 'visible')) {
visibleRef.value = !!props.visible;
}
if (Reflect.has(props, 'open')) {
visibleRef.value = !!props.open;
}
if (Reflect.has(props, 'defaultFullscreen')) {
fullScreenRef.value = !!props.defaultFullscreen;
if (getIsMobile.value) {
fullScreenRef.value = true;
}
}
}
/**
* 监听放大缩小
*/
watchEffect(() => {
fullScreenRef.value = props.fullscreen;
if (getIsMobile.value) {
fullScreenRef.value = true;
}
});
/**
* 监听model的显示隐藏
*/
watchEffect(() => {
visibleRef.value = !!props.visible;
});
/**
* 监听model的显示隐藏
*/
watchEffect(() => {
visibleRef.value = !!props.open;
});
watch(
() => unref(visibleRef),
(v) => {
emit('visible-change', v);
emit('open-change', v);
emit('update:visible', v);
emit('update:open', v);
instance && modalMethods.emitVisible?.(v, instance.uid);
},
{
immediate: false,
}
);
return {
isNoTitle,
getBindValue,
fullScreenRef,
handleFullScreen,
fullScreen,
t,
handleCancel,
handleOk,
getProps,
getMergeProps,
handleTitleDbClick,
bodyStyle,
};
},
});
</script>
<style lang="less" scoped>
/*begin 放大关闭按钮样式*/
.jeecg-basic-modal-close {
display: flex;
height: 95%;
align-items: center;
> span {
margin-left: 10px;
font-size: 16px;
}
&--can-full {
> span {
margin-left: 12px;
}
}
&:not(&--can-full) {
> span:nth-child(1) {
&:hover {
font-weight: 700;
}
}
}
& span:nth-child(1) {
display: inline-block;
padding: 10px;
&:hover {
color: @primary-color;
}
}
& span:last-child {
padding: 10px 10px 10px 0;
&:hover {
color: @error-color;
}
}
}
/*end 放大关闭按钮样式*/
</style>
<style lang="less">
/*begin 全屏弹窗modal样式*/
.jeecg-full-screen-modal-code-generate {
.ant-modal {
max-width: 100%;
top: 0 !important;
padding-bottom: 0 !important;
margin: 0 !important;
width: 100% !important;
overflow-y: auto;
}
.ant-modal-content {
display: flex;
flex-direction: column;
height: calc(100vh);
}
.ant-modal-body {
flex: 1;
overflow-y: auto;
}
}
/*end 全屏弹窗modal样式*/
</style>

View File

@ -45,16 +45,52 @@
useWindowSizeFn(setModalHeight.bind(null, false)); useWindowSizeFn(setModalHeight.bind(null, false));
useMutationObserver( // update-begin--author:liaozhiyang---date:2024-04-18---forQQYUN-9035basicModalmaxHeightheightsetModalHeight使MutationObserver
spinRef, // update-begin--author:liaozhiyang---date:2024-05-30---forTV360X-145
let observer,
recordCount: any = {};
watch(
() => props.visible,
() => { () => {
setModalHeight(); if (props.visible && !observer && !(props.maxHeight || props.height)) {
recordCount = {};
observer = useMutationObserver(
spinRef,
() => {
setModalHeight({
source: 'muob',
callBack: (height) => {
const count = recordCount[height];
if (count) {
recordCount[height] = ++recordCount[height];
if (count > 10) {
observer.stop();
recordCount = {};
observer = null;
}
} else {
recordCount = {};
recordCount[height] = 1;
}
},
});
},
{
attributes: true,
subtree: true,
}
);
} else {
if (observer) {
observer.stop();
observer = null;
}
}
}, },
{ { immediate: true }
attributes: true,
subtree: true,
}
); );
// update-end--author:liaozhiyang---date:2024-05-30---forTV360X-145
// update-end--author:liaozhiyang---date:2024-04-18---forQQYUN-9035basicModalmaxHeightheightsetModalHeight使MutationObserver
createModalContext({ createModalContext({
redoModalHeight: setModalHeight, redoModalHeight: setModalHeight,
@ -124,16 +160,21 @@
}); });
} }
async function setModalHeight() { async function setModalHeight(option?) {
console.log("---------性能监控--------setModalHeight----------")
const options = option || {};
const source = options.source;
const callBack = options.callBack;
// , // ,
// ,使visible // ,使visible
if (!props.visible) return; if (!props.visible) return;
const wrapperRefDom = unref(wrapperRef); const wrapperRefDom = unref(wrapperRef);
if (!wrapperRefDom) return; if (!wrapperRefDom) return;
// update-begin--author:liaozhiyang---date:20240320---forQQYUN-8573BasicModal
const bodyDom = wrapperRefDom.$el.parentElement; const bodyDom = wrapperRefDom.$el.parentElement?.parentElement?.parentElement;
// update-end--author:liaozhiyang---date:20240320---forBasicModal
if (!bodyDom) return; if (!bodyDom) return;
bodyDom.style.padding = '0'; // bodyDom.style.padding = '0';
await nextTick(); await nextTick();
try { try {
@ -162,6 +203,12 @@
} else { } else {
realHeightRef.value = props.height ? props.height : realHeight > maxHeight ? maxHeight : realHeight; realHeightRef.value = props.height ? props.height : realHeight > maxHeight ? maxHeight : realHeight;
} }
// update-begin--author:liaozhiyang---date:2024-04-18---forQQYUN-9035basicModalmaxHeightheightsetModalHeight使MutationObserver
if (source == 'muob') {
callBack(realHeightRef.value);
}
// update-end--author:liaozhiyang---date:2024-04-18---forQQYUN-9035basicModalmaxHeightheightsetModalHeight使MutationObserver
emit('height-change', unref(realHeightRef)); emit('height-change', unref(realHeightRef));
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View File

@ -3,12 +3,12 @@
v-bind="getBindValues" v-bind="getBindValues"
:activeName="activeName" :activeName="activeName"
:openNames="getOpenKeys" :openNames="getOpenKeys"
:class="prefixCls" :class="`${prefixCls} ${isThemeBright ? 'bright' : ''}`"
:activeSubMenuNames="activeSubMenuNames" :activeSubMenuNames="activeSubMenuNames"
@select="handleSelect" @select="handleSelect"
> >
<template v-for="item in items" :key="item.path"> <template v-for="item in items" :key="item.path">
<SimpleSubMenu :item="item" :parent="true" :collapsedShowTitle="collapsedShowTitle" :collapse="collapse" /> <SimpleSubMenu :isThemeBright="isThemeBright" :item="item" :parent="true" :collapsedShowTitle="collapsedShowTitle" :collapse="collapse" />
</template> </template>
</Menu> </Menu>
</template> </template>
@ -29,6 +29,7 @@
import { useOpenKeys } from './useOpenKeys'; import { useOpenKeys } from './useOpenKeys';
import { URL_HASH_TAB } from '/@/utils'; import { URL_HASH_TAB } from '/@/utils';
import { useAppStore } from '/@/store/modules/app';
export default defineComponent({ export default defineComponent({
name: 'SimpleMenu', name: 'SimpleMenu',
@ -56,6 +57,8 @@
setup(props, { attrs, emit }) { setup(props, { attrs, emit }) {
const currentActiveMenu = ref(''); const currentActiveMenu = ref('');
const isClickGo = ref(false); const isClickGo = ref(false);
const appStore = useAppStore();
const isThemeBright = ref(false);
const menuState = reactive<MenuState>({ const menuState = reactive<MenuState>({
activeName: '', activeName: '',
@ -93,7 +96,15 @@
}, },
{ flush: 'post' } { flush: 'post' }
); );
// update-begin--author:liaozhiyang---date:20240408---forQQYUN-8922
watch(
() => appStore.getProjectConfig.menuSetting,
(menuSetting) => {
isThemeBright.value = !!menuSetting?.isThemeBright;
},
{ immediate: true, deep: true }
);
// update-end--author:liaozhiyang---date:20240408---forQQYUN-8922
listenerRouteChange((route) => { listenerRouteChange((route) => {
if (route.name === REDIRECT_NAME) return; if (route.name === REDIRECT_NAME) return;
@ -127,6 +138,14 @@
// update-begin--author:sunjianlei---date:20220408---for: VUEN-656# // update-begin--author:sunjianlei---date:20220408---for: VUEN-656#
return; return;
} }
// update-begin--author:liaozhiyang---date:20240227---forQQYUN-6366tab
const findItem = getMatchingMenu(props.items, key);
if (findItem?.internalOrExternal == true) {
window.open(location.origin + key);
return;
}
// update-end--author:liaozhiyang---date:20240227---forQQYUN-6366tab
const { beforeClickFn } = props; const { beforeClickFn } = props;
if (beforeClickFn && isFunction(beforeClickFn)) { if (beforeClickFn && isFunction(beforeClickFn)) {
const flag = await beforeClickFn(key); const flag = await beforeClickFn(key);
@ -140,12 +159,33 @@
menuState.activeName = key; menuState.activeName = key;
} }
/**
* 2024-02-27
* liaozhiyang
* 获取菜单中匹配的path所在的项
*/
const getMatchingMenu = (menus, path) => {
for (let i = 0, len = menus.length; i < len; i++) {
const item = menus[i];
if (item.path === path && !item.redirect && !item.paramPath) {
return item;
} else if (item.children?.length) {
const result = getMatchingMenu(item.children, path);
if (result) {
return result;
}
}
}
return '';
}
return { return {
prefixCls, prefixCls,
getBindValues, getBindValues,
handleSelect, handleSelect,
getOpenKeys, getOpenKeys,
...toRefs(menuState), ...toRefs(menuState),
isThemeBright,
}; };
}, },
}); });

View File

@ -11,7 +11,13 @@
<SimpleMenuTag :item="item" :collapseParent="getIsCollapseParent" /> <SimpleMenuTag :item="item" :collapseParent="getIsCollapseParent" />
</template> </template>
</MenuItem> </MenuItem>
<SubMenu :name="item.path" v-if="menuHasChildren(item) && getShowMenu" :class="[getLevelClass, theme]" :collapsedShowTitle="collapsedShowTitle"> <SubMenu
:isThemeBright="isThemeBright"
:name="item.path"
v-if="menuHasChildren(item) && getShowMenu"
:class="[getLevelClass, theme]"
:collapsedShowTitle="collapsedShowTitle"
>
<template #title> <template #title>
<Icon v-if="getIcon" :icon="getIcon" :size="16" /> <Icon v-if="getIcon" :icon="getIcon" :size="16" />
@ -25,7 +31,7 @@
<SimpleMenuTag :item="item" :collapseParent="!!collapse && !!parent" /> <SimpleMenuTag :item="item" :collapseParent="!!collapse && !!parent" />
</template> </template>
<template v-for="childrenItem in item.children || []" :key="childrenItem.path"> <template v-for="childrenItem in item.children || []" :key="childrenItem.path">
<SimpleSubMenu v-bind="$props" :item="childrenItem" :parent="false" /> <SimpleSubMenu v-bind="$props" :isThemeBright="isThemeBright" :item="childrenItem" :parent="false" />
</template> </template>
</SubMenu> </SubMenu>
</template> </template>
@ -60,6 +66,12 @@
collapsedShowTitle: propTypes.bool, collapsedShowTitle: propTypes.bool,
collapse: propTypes.bool, collapse: propTypes.bool,
theme: propTypes.oneOf(['dark', 'light']), theme: propTypes.oneOf(['dark', 'light']),
// update-begin--author:liaozhiyang---date:20240417---for:QQYUN-8927
isThemeBright: {
type: Boolean,
default: false,
},
// update-end--author:liaozhiyang---date:20240417---for:QQYUN-8927
}, },
setup(props) { setup(props) {
const { t } = useI18n(); const { t } = useI18n();

View File

@ -37,7 +37,7 @@
<!-- eslint-disable-next-line --> <!-- eslint-disable-next-line -->
<template #content v-show="opened"> <template #content v-show="opened">
<div v-bind="getEvents(true)"> <div v-bind="getEvents(true)">
<ul :class="[prefixCls, `${prefixCls}-${getTheme}`, `${prefixCls}-popup`]"> <ul :class="[prefixCls, `${prefixCls}-${getTheme}`, `${prefixCls}-popup`, `${isThemeBright && 'bright'}`]">
<slot></slot> <slot></slot>
</ul> </ul>
</div> </div>
@ -75,6 +75,12 @@
}, },
disabled: propTypes.bool, disabled: propTypes.bool,
collapsedShowTitle: propTypes.bool, collapsedShowTitle: propTypes.bool,
// update-begin--author:liaozhiyang---date:20240417---for:QQYUN-8927
isThemeBright: {
type: Boolean,
default: false,
},
// update-end--author:liaozhiyang---date:20240417---for:QQYUN-8927
}, },
setup(props) { setup(props) {
const instance = getCurrentInstance(); const instance = getCurrentInstance();
@ -128,9 +134,11 @@
const getTheme = computed(() => rootProps.theme); const getTheme = computed(() => rootProps.theme);
const getOverlayStyle = computed((): CSSProperties => { const getOverlayStyle = computed((): CSSProperties => {
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8774
return { return {
minWidth: '200px', minWidth: '150px',
}; };
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8774
}); });
const getIsOpend = computed(() => { const getIsOpend = computed(() => {

View File

@ -36,7 +36,7 @@
&-submenu-title { &-submenu-title {
position: relative; position: relative;
z-index: 1; z-index: 1;
padding: 12px 20px; padding: 10px 14px;
color: @menu-dark-subsidiary-color; color: @menu-dark-subsidiary-color;
cursor: pointer; cursor: pointer;
transition: all @transition-time @ease-in-out; transition: all @transition-time @ease-in-out;
@ -65,6 +65,16 @@
background-color: @primary-color !important; background-color: @primary-color !important;
} }
} }
// 彩色模式(绿色,橘红等)
&.bright {
.@{menu-prefix-cls}-item,
.@{menu-prefix-cls}-submenu-title {
color: #fff;
&:hover {
color: rgba(255, 255, 255, 0.8);
}
}
}
} }
&-light { &-light {
@ -108,7 +118,15 @@
&-light { &-light {
background-color: #fff; background-color: #fff;
color: rgba(0, 0, 0, 0.65);
.@{menu-prefix-cls} {
color: rgba(0, 0, 0, 0.65);
}
.@{namespace}-menu-submenu:not(.@{namespace}-menu-item-active) .@{namespace}-menu-submenu-title {
.anticon {
color: rgba(0, 0, 0, 0.9);
}
}
.@{menu-prefix-cls}-submenu-active { .@{menu-prefix-cls}-submenu-active {
color: @primary-color !important; color: @primary-color !important;
@ -129,7 +147,6 @@
z-index: 1; z-index: 1;
display: flex; display: flex;
font-size: @font-size-base; font-size: @font-size-base;
color: inherit;
list-style: none; list-style: none;
cursor: pointer; cursor: pointer;
outline: none; outline: none;
@ -262,6 +279,20 @@
color: #fff; color: #fff;
} }
} }
// update-begin--author:liaozhiyang---date:20240408---for【QQYUN-8922】左侧导航栏文字颜色调整区分彩色和暗黑
&-dark&-vertical&.bright &-item,
&-dark&-vertical.bright &-submenu-title {
color: rgba(255, 255, 255, 1);
&-active:not(.@{menu-prefix-cls}-submenu) {
color: #fff !important;
background-color: @primary-color !important;
}
&:hover {
color: rgba(255, 255, 255, 0.8);
}
}
// update-end--author:liaozhiyang---date:20240408---for【QQYUN-8922】左侧导航栏文字颜色调整区分彩色和暗黑
&-dark&-vertical&-collapse { &-dark&-vertical&-collapse {
> li.@{menu-prefix-cls}-item-active, > li.@{menu-prefix-cls}-item-active,

View File

@ -1,6 +1,7 @@
<template> <template>
<div ref="wrapRef" :class="getWrapperClass"> <div ref="wrapRef" :class="getWrapperClass">
<BasicForm <BasicForm
:class="{ 'table-search-area-hidden': !getBindValues.formConfig?.schemas?.length }"
submitOnReset submitOnReset
v-bind="getFormProps" v-bind="getFormProps"
v-if="getBindValues.useSearchForm" v-if="getBindValues.useSearchForm"
@ -17,31 +18,47 @@
<!-- antd v3 升级兼容阻止数据的收集防止控制台报错 --> <!-- antd v3 升级兼容阻止数据的收集防止控制台报错 -->
<!-- https://antdv.com/docs/vue/migration-v3-cn --> <!-- https://antdv.com/docs/vue/migration-v3-cn -->
<a-form-item-rest> <a-form-item-rest>
<Table ref="tableElRef" v-bind="getBindValues" :rowClassName="getRowClassName" v-show="getEmptyDataIsShowTable" @resizeColumn="handleResizeColumn" @change="handleTableChange"> <!-- TV360X-377关联记录必填影响到了table的输入框和页码样式 -->
<!-- antd的原生插槽直接传递 --> <a-form-item>
<template #[item]="data" v-for="item in slotNamesGroup.native" :key="item"> <Table ref="tableElRef" v-bind="getBindValues" :rowClassName="getRowClassName" v-show="getEmptyDataIsShowTable" @resizeColumn="handleResizeColumn" @change="handleTableChange">
<slot :name="item" v-bind="data || {}"></slot> <!-- antd的原生插槽直接传递 -->
</template> <template #[item]="data" v-for="item in slotNamesGroup.native" :key="item">
<template #headerCell="{ column }"> <!-- update-begin--author:liaozhiyang---date:20240424---forissues/1146BasicTable使用headerCell全选框出不来 -->
<!-- update-begin--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 --> <template v-if="item === 'headerCell'">
<CustomSelectHeader v-if="isCustomSelection(column)" v-bind="selectHeaderProps"/> <CustomSelectHeader v-if="isCustomSelection(data.column)" v-bind="selectHeaderProps" />
<HeaderCell v-else :column="column" /> <slot v-else :name="item" v-bind="data || {}"></slot>
<!-- update-end--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 --> </template>
</template> <slot v-else :name="item" v-bind="data || {}"></slot>
<!-- 增加对antdv3.x兼容 --> <!-- update-begin--author:liaozhiyang---date:20240424---forissues/1146BasicTable使用headerCell全选框出不来 -->
<template #bodyCell="data">
<!-- update-begin--author:liaozhiyang---date:220230717---forissues-179antd3 一些警告以及报错(针对表格) -->
<!-- update-begin--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<template v-if="data.column?.slotsBak?.customRender">
<!-- update-end--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<slot :name="data.column.slotsBak.customRender" v-bind="data || {}"></slot>
</template> </template>
<template v-else> <template #headerCell="{ column }">
<slot name="bodyCell" v-bind="data || {}"></slot> <!-- update-begin--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 -->
<CustomSelectHeader v-if="isCustomSelection(column)" v-bind="selectHeaderProps"/>
<HeaderCell v-else :column="column" />
<!-- update-end--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 -->
</template> </template>
<!-- update-begin--author:liaozhiyang---date:22030717---forissues-179antd3 一些警告以及报错(针对表格) --> <!-- 增加对antdv3.x兼容 -->
</template> <template #bodyCell="data">
</Table> <!-- update-begin--author:liaozhiyang---date:220230717---forissues-179antd3 一些警告以及报错(针对表格) -->
<!-- update-begin--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<template v-if="data.column?.slotsBak?.customRender">
<!-- update-end--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<slot :name="data.column.slotsBak.customRender" v-bind="data || {}"></slot>
</template>
<template v-else>
<slot name="bodyCell" v-bind="data || {}"></slot>
</template>
<!-- update-begin--author:liaozhiyang---date:22030717---forissues-179antd3 一些警告以及报错(针对表格) -->
</template>
<!-- update-begin--author:liaozhiyang---date:20240425---forpull/1201添加antd的TableSummary功能兼容老的summary表尾合计 -->
<template v-if="showSummaryRef && !getBindValues.showSummary" #summary="data">
<slot name="summary" v-bind="data || {}">
<TableSummary :data="data || {}" v-bind="getSummaryProps" />
</slot>
</template>
<!-- update-end--author:liaozhiyang---date:20240425---forpull/1201添加antd的TableSummary功能兼容老的summary表尾合计 -->
</Table>
</a-form-item>
</a-form-item-rest> </a-form-item-rest>
</div> </div>
</template> </template>
@ -55,6 +72,7 @@
import CustomSelectHeader from './components/CustomSelectHeader.vue' import CustomSelectHeader from './components/CustomSelectHeader.vue'
import expandIcon from './components/ExpandIcon'; import expandIcon from './components/ExpandIcon';
import HeaderCell from './components/HeaderCell.vue'; import HeaderCell from './components/HeaderCell.vue';
import TableSummary from './components/TableSummary';
import { InnerHandlers } from './types/table'; import { InnerHandlers } from './types/table';
import { usePagination } from './hooks/usePagination'; import { usePagination } from './hooks/usePagination';
import { useColumns } from './hooks/useColumns'; import { useColumns } from './hooks/useColumns';
@ -72,7 +90,7 @@
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useCustomSelection } from "./hooks/useCustomSelection"; import { useCustomSelection } from "./hooks/useCustomSelection";
import { omit } from 'lodash-es'; import { omit, pick } from 'lodash-es';
import { basicProps } from './props'; import { basicProps } from './props';
import { isFunction } from '/@/utils/is'; import { isFunction } from '/@/utils/is';
import { warn } from '/@/utils/log'; import { warn } from '/@/utils/log';
@ -82,6 +100,7 @@
Table, Table,
BasicForm, BasicForm,
HeaderCell, HeaderCell,
TableSummary,
CustomSelectHeader, CustomSelectHeader,
}, },
props: basicProps, props: basicProps,
@ -226,6 +245,18 @@
}; };
const { getHeaderProps } = useTableHeader(getProps, slots, handlers); const { getHeaderProps } = useTableHeader(getProps, slots, handlers);
// update-begin--author:liaozhiyang---date:20240425---forpull/1201antdTableSummarysummary
const getSummaryProps = computed(() => {
return pick(unref(getProps), ['summaryFunc', 'summaryData', 'hasExpandedRow', 'rowKey']);
});
const getIsEmptyData = computed(() => {
return (unref(getDataSourceRef) || []).length === 0;
});
const showSummaryRef = computed(() => {
const summaryProps = unref(getSummaryProps);
return (summaryProps.summaryFunc || summaryProps.summaryData) && !unref(getIsEmptyData);
});
// update-end--author:liaozhiyang---date:20240425---forpull/1201antdTableSummarysummary
const { getFooterProps } = useTableFooter(getProps, slots, getScrollRef, tableElRef, getDataSourceRef); const { getFooterProps } = useTableFooter(getProps, slots, getScrollRef, tableElRef, getDataSourceRef);
@ -393,6 +424,7 @@
tableAction, tableAction,
redoHeight, redoHeight,
handleResizeColumn: (w, col) => { handleResizeColumn: (w, col) => {
console.log('col',col);
col.width = w; col.width = w;
}, },
getFormProps: getFormProps as any, getFormProps: getFormProps as any,
@ -407,6 +439,10 @@
isCustomSelection, isCustomSelection,
// update-end--author:sunjianlei---date:220230630---forQQYUN-5571 // update-end--author:sunjianlei---date:220230630---forQQYUN-5571
slotNamesGroup, slotNamesGroup,
// update-begin--author:liaozhiyang---date:20240425---forpull/1201antdTableSummarysummary
getSummaryProps,
showSummaryRef,
// update-end--author:liaozhiyang---date:20240425---forpull/1201antdTableSummarysummary
}; };
}, },
}); });
@ -439,7 +475,11 @@
background-color: @app-content-background; background-color: @app-content-background;
} }
} }
// update-begin--author:liaozhiyang---date:20240613---forTV360X-1232(css)
> .table-search-area-hidden {
display: none;
}
// update-end--author:liaozhiyang---date:20240613---forTV360X-1232(css)
&-form-container { &-form-container {
padding: 10px; padding: 10px;
@ -556,5 +596,10 @@
} }
} }
// update-end--author:sunjianlei---date:220230718---forissues/622 // update-end--author:sunjianlei---date:220230718---forissues/622
// update-begin--author:liaozhiyang---date:20240604---forTV360X-377table
> .ant-form-item {
margin-bottom: 0;
}
// update-end--author:liaozhiyang---date:20240604---forTV360X-377table
} }
</style> </style>

View File

@ -19,7 +19,13 @@
<Divider type="vertical" class="action-divider" v-if="divider && index < getActions.length - 1" /> <Divider type="vertical" class="action-divider" v-if="divider && index < getActions.length - 1" />
</template> </template>
<Dropdown :trigger="['hover']" :dropMenuList="getDropdownList" popconfirm v-if="dropDownActions && getDropdownList.length > 0"> <Dropdown
:overlayClassName="dropdownCls"
:trigger="['hover']"
:dropMenuList="getDropdownList"
popconfirm
v-if="dropDownActions && getDropdownList.length > 0"
>
<slot name="more"></slot> <slot name="more"></slot>
<!-- 设置插槽 --> <!-- 设置插槽 -->
<template v-slot:[item.slot] v-for="(item, index) in getDropdownSlotList" :key="`${index}-${item.label}`"> <template v-slot:[item.slot] v-for="(item, index) in getDropdownSlotList" :key="`${index}-${item.label}`">
@ -63,6 +69,7 @@
}, },
setup(props) { setup(props) {
const { prefixCls } = useDesign('basic-table-action'); const { prefixCls } = useDesign('basic-table-action');
const dropdownCls = `${prefixCls}-dropdown`;
let table: Partial<TableActionType> = {}; let table: Partial<TableActionType> = {};
if (!props.outside) { if (!props.outside) {
table = useTableContext(); table = useTableContext();
@ -190,7 +197,7 @@
isInButton && e.stopPropagation(); isInButton && e.stopPropagation();
} }
return { prefixCls, getActions, getDropdownList, getDropdownSlotList, getAlign, onCellClick, getTooltip }; return { prefixCls, getActions, getDropdownList, getDropdownSlotList, getAlign, onCellClick, getTooltip, dropdownCls };
}, },
}); });
</script> </script>
@ -251,7 +258,26 @@
&-popconfirm { &-popconfirm {
.ant-popconfirm-buttons { .ant-popconfirm-buttons {
min-width: 120px; min-width: 120px;
// update-begin--author:liaozhiyang---date:20240124---forissues/1019popConfirm
display: flex;
align-items: center;
justify-content: center;
// update-end--author:liaozhiyang---date:20240124---forissues/1019popConfirm
} }
} }
// update-begin--author:liaozhiyang---date:20240407---forQQYUN-8762tableant-dropdown
&-dropdown {
.ant-dropdown-menu .ant-dropdown-menu-item-divider {
margin: 2px 0;
}
.ant-dropdown-menu .ant-dropdown-menu-item {
padding: 3px 8px;
font-size: 13.6px;
}
.dropdown-event-area {
padding: 0 !important;
}
}
// update-end--author:liaozhiyang---date:20240407---forQQYUN-8762tableant-dropdown
} }
</style> </style>

View File

@ -57,7 +57,9 @@
if (!isFunction(summaryFunc)) { if (!isFunction(summaryFunc)) {
return []; return [];
} }
let dataSource = toRaw(unref(table.getDataSource())); // update-begin--author:liaozhiyang---date:20230227---forQQYUN-8172
let dataSource = cloneDeep(unref(table.getDataSource()));
// update-end--author:liaozhiyang---date:20230227---forQQYUN-8172
dataSource = summaryFunc(dataSource); dataSource = summaryFunc(dataSource);
dataSource.forEach((item, i) => { dataSource.forEach((item, i) => {
item[props.rowKey] = `${i}`; item[props.rowKey] = `${i}`;

View File

@ -0,0 +1,163 @@
import type { PropType, VNode } from 'vue';
import { defineComponent, unref, computed, isVNode } from 'vue';
import { cloneDeep, pick } from 'lodash-es';
import { isFunction } from '/@/utils/is';
import type { BasicColumn } from '../types/table';
import { INDEX_COLUMN_FLAG } from '../const';
import { propTypes } from '/@/utils/propTypes';
import { useTableContext } from '../hooks/useTableContext';
import { TableSummary, TableSummaryRow, TableSummaryCell } from 'ant-design-vue';
const SUMMARY_ROW_KEY = '_row';
const SUMMARY_INDEX_KEY = '_index';
export default defineComponent({
name: 'BasicTableSummary',
components: { TableSummary, TableSummaryRow, TableSummaryCell },
props: {
summaryFunc: {
type: Function as PropType<Fn>,
},
summaryData: {
type: Array as PropType<Recordable[]>,
},
rowKey: propTypes.string.def('key'),
// 是否有展开列
hasExpandedRow: propTypes.bool,
data: {
type: Object as PropType<Recordable>,
default: () => {},
},
},
setup(props) {
const table = useTableContext();
const getDataSource = computed((): Recordable[] => {
const {
summaryFunc,
summaryData,
data: { pageData },
} = props;
if (summaryData?.length) {
summaryData.forEach((item, i) => (item[props.rowKey] = `${i}`));
return summaryData;
}
if (!isFunction(summaryFunc)) {
return [];
}
let dataSource = cloneDeep(unref(pageData));
dataSource = summaryFunc(dataSource);
dataSource.forEach((item, i) => {
item[props.rowKey] = `${i}`;
});
return dataSource;
});
const getColumns = computed(() => {
const dataSource = unref(getDataSource);
let columns: BasicColumn[] = cloneDeep(table.getColumns({ sort: true }));
columns = columns.filter((item) => !item.defaultHidden);
const index = columns.findIndex((item) => item.flag === INDEX_COLUMN_FLAG);
const hasRowSummary = dataSource.some((item) => Reflect.has(item, SUMMARY_ROW_KEY));
const hasIndexSummary = dataSource.some((item) => Reflect.has(item, SUMMARY_INDEX_KEY));
// 是否有序号列
let hasIndexCol = false;
// 是否有选择列
const hasSelection = table.getRowSelection() && hasRowSummary;
if (index !== -1) {
if (hasIndexSummary) {
hasIndexCol = true;
columns[index].customSummaryRender = ({ record }) => record[SUMMARY_INDEX_KEY];
columns[index].ellipsis = false;
} else {
Reflect.deleteProperty(columns[index], 'customSummaryRender');
}
}
if (hasSelection) {
const isFixed = columns.some((col) => col.fixed === 'left' || col.fixed === true);
columns.unshift({
width: 60,
title: 'selection',
key: 'selectionKey',
align: 'center',
...(isFixed ? { fixed: 'left' } : {}),
customSummaryRender: ({ record }) => (hasIndexCol ? '' : record[SUMMARY_ROW_KEY]),
});
}
if (props.hasExpandedRow) {
const isFixed = columns.some((col) => col.fixed === 'left');
columns.unshift({
width: 50,
title: 'expandedRow',
key: 'expandedRowKey',
align: 'center',
...(isFixed ? { fixed: 'left' } : {}),
customSummaryRender: () => '',
});
}
return columns;
});
function isRenderCell(data: any) {
return data && typeof data === 'object' && !Array.isArray(data) && !isVNode(data);
}
const getValues = (row: Recordable, col: BasicColumn, index: number) => {
const value = row[col.dataIndex as string];
let childNode: VNode | JSX.Element | string | number | undefined | null;
childNode = value;
if (col.customSummaryRender) {
const renderData = col.customSummaryRender({
text: value,
value,
record: row,
index,
column: cloneDeep(col),
});
if (isRenderCell(renderData)) {
childNode = renderData.children;
} else {
childNode = renderData;
}
if (typeof childNode === 'object' && !Array.isArray(childNode) && !isVNode(childNode)) {
childNode = null;
}
if (Array.isArray(childNode) && childNode.length === 1) {
childNode = childNode[0];
}
return childNode;
}
return childNode;
};
const getCellProps = (col: BasicColumn) => {
const cellProps = pick(col, ['colSpan', 'rowSpan', 'align']);
return {
...cellProps,
};
};
return () => {
return (
<TableSummary fixed>
{(unref(getDataSource) || []).map((row) => {
return (
<TableSummaryRow key={row[props.rowKey]}>
{unref(getColumns).map((col, index) => {
return (
<TableSummaryCell {...getCellProps(col)} index={index} key={`${row[props.rowKey]}_${col.dataIndex}_${index}`}>
{getValues(row, col, index)}
</TableSummaryCell>
);
})}
</TableSummaryRow>
);
})}
</TableSummary>
);
};
},
});

View File

@ -336,7 +336,20 @@
function initCbs(cbs: 'submitCbs' | 'validCbs' | 'cancelCbs', handle: Fn) { function initCbs(cbs: 'submitCbs' | 'validCbs' | 'cancelCbs', handle: Fn) {
if (props.record) { if (props.record) {
/* eslint-disable */ /* eslint-disable */
isArray(props.record[cbs]) ? props.record[cbs]?.push(handle) : (props.record[cbs] = [handle]); // update-begin--author:liaozhiyang---date:20240424---forissues/1165canResizetrue
const { dataIndex, key } = props.column;
const field: any = dataIndex || key;
if (isArray(props.record[cbs])) {
const findItem = props.record[cbs]?.find((item) => item[field]);
if (findItem) {
findItem[field] = handle;
} else {
props.record[cbs]?.push({ [field]: handle });
}
} else {
props.record[cbs] = [{ [field]: handle }];
}
// update-end--author:liaozhiyang---date:20240424---forissues/1165canResizetrue
} }
} }
@ -351,14 +364,25 @@
} }
/* eslint-disable */ /* eslint-disable */
props.record.onCancelEdit = () => { props.record.onCancelEdit = () => {
isArray(props.record?.cancelCbs) && props.record?.cancelCbs.forEach((fn) => fn()); // update-begin--author:liaozhiyang---date:20240424---forissues/1165canResizetrue
isArray(props.record?.cancelCbs) &&
props.record?.cancelCbs.forEach((item) => {
const [fn] = Object.values(item);
fn();
});
// update-end--author:liaozhiyang---date:20240424---forissues/1165canResizetrue
}; };
/* eslint-disable */ /* eslint-disable */
props.record.onSubmitEdit = async () => { props.record.onSubmitEdit = async () => {
if (isArray(props.record?.submitCbs)) { if (isArray(props.record?.submitCbs)) {
if (!props.record?.onValid?.()) return; if (!props.record?.onValid?.()) return;
const submitFns = props.record?.submitCbs || []; const submitFns = props.record?.submitCbs || [];
submitFns.forEach((fn) => fn(false, false)); // update-begin--author:liaozhiyang---date:20240424---forissues/1165canResizetrue
submitFns.forEach((item) => {
const [fn] = Object.values(item);
fn(false, false);
});
// update-end--author:liaozhiyang---date:20240424---forissues/1165canResizetrue
table.emit?.('edit-row-end'); table.emit?.('edit-row-end');
return true; return true;
} }

View File

@ -15,7 +15,13 @@ export function renderEditCell(column: BasicColumn) {
return ({ text: value, record, index }: Params) => { return ({ text: value, record, index }: Params) => {
toRaw(record).onValid = async () => { toRaw(record).onValid = async () => {
if (isArray(record?.validCbs)) { if (isArray(record?.validCbs)) {
const validFns = (record?.validCbs || []).map((fn) => fn()); // update-begin--author:liaozhiyang---date:20240424---for【issues/1165】解决canResize为true时第一行校验不过
const validFns = (record?.validCbs || []).map((item) => {
const [fn] = Object.values(item);
// @ts-ignore
return fn();
});
// update-end--author:liaozhiyang---date:20240424---for【issues/1165】解决canResize为true时第一行校验不过
const res = await Promise.all(validFns); const res = await Promise.all(validFns);
return res.every((item) => !!item); return res.every((item) => !!item);
} else { } else {
@ -53,6 +59,10 @@ export function renderEditCell(column: BasicColumn) {
}; };
} }
interface Cbs {
[key: string]: Fn;
}
export type EditRecordRow<T = Recordable> = Partial< export type EditRecordRow<T = Recordable> = Partial<
{ {
onEdit: (editable: boolean, submit?: boolean) => Promise<boolean>; onEdit: (editable: boolean, submit?: boolean) => Promise<boolean>;
@ -60,9 +70,9 @@ export type EditRecordRow<T = Recordable> = Partial<
editable: boolean; editable: boolean;
onCancel: Fn; onCancel: Fn;
onSubmit: Fn; onSubmit: Fn;
submitCbs: Fn[]; submitCbs: Cbs[];
cancelCbs: Fn[]; cancelCbs: Cbs[];
validCbs: Fn[]; validCbs: Cbs[];
editValueRefs: Recordable<Ref>; editValueRefs: Recordable<Ref>;
} & T } & T
>; >;

View File

@ -1,5 +1,5 @@
<template> <template>
<Tooltip placement="top" v-bind="getBindProps"> <Tooltip placement="top" v-bind="getBindProps" >
<template #title> <template #title>
<span>{{ t('component.table.settingColumn') }}</span> <span>{{ t('component.table.settingColumn') }}</span>
</template> </template>
@ -142,9 +142,9 @@
setup(props, { emit, attrs }) { setup(props, { emit, attrs }) {
const { t } = useI18n(); const { t } = useI18n();
const table = useTableContext(); const table = useTableContext();
const popoverVisible = ref(true); const popoverVisible = ref(false);
// update-begin--author:sunjianlei---date:20221101---for: // update-begin--author:sunjianlei---date:20221101---for:
nextTick(() => popoverVisible.value = false); // nextTick(() => popoverVisible.value = false);
// update-end--author:sunjianlei---date:20221101---for: // update-end--author:sunjianlei---date:20221101---for:
const defaultRowSelection = omit(table.getRowSelection(), 'selectedRowKeys'); const defaultRowSelection = omit(table.getRowSelection(), 'selectedRowKeys');
let inited = false; let inited = false;
@ -311,7 +311,9 @@
// Open the pop-up window for drag and drop initialization // Open the pop-up window for drag and drop initialization
function handleVisibleChange() { function handleVisibleChange() {
if (inited) return; if (inited) return;
nextTick(() => { // update-begin--author:liaozhiyang---date:20240529---forTV360X-254
setTimeout(() => {
// update-begin--author:liaozhiyang---date:20240529---forTV360X-254
const columnListEl = unref(columnListRef); const columnListEl = unref(columnListRef);
if (!columnListEl) return; if (!columnListEl) return;
const el = columnListEl.$el as any; const el = columnListEl.$el as any;
@ -340,14 +342,14 @@
plainSortOptions.value = columns; plainSortOptions.value = columns;
// update-begin--author:liaozhiyang---date:20230904---forQQYUN-6424table // update-begin--author:liaozhiyang---date:20230904---forQQYUN-6424table
if(state.checkedList.length != columns.length){ // update-begin--author:liaozhiyang---date:20240522---forTV360X-108
const cols = columns.map(item => item.value); const cols = columns.map((item) => item.value);
const arr = cols.filter((cItem) => state.checkedList.find((lItem) => lItem === cItem)); const arr = cols.filter((cItem) => state.checkedList.find((lItem) => lItem === cItem));
setColumns(arr); setColumns(arr);
} else { //
setColumns(columns); // setColumns(columns);
} // update-end--author:liaozhiyang---date:20240522---forTV360X-108
// update-begin--author:liaozhiyang---date:20230904---forQQYUN-6424table // update-end--author:liaozhiyang---date:20230904---forQQYUN-6424table
}, },
}); });
// order // order
@ -355,7 +357,7 @@
sortableOrder.value = sortable.toArray(); sortableOrder.value = sortable.toArray();
} }
inited = true; inited = true;
}); }, 2000);
} }
// Control whether the serial number column is displayed // Control whether the serial number column is displayed
@ -508,11 +510,24 @@
} }
.ant-checkbox-group { .ant-checkbox-group {
width: 100%; // update-begin--author:liaozhiyang---date:20240118---forQQYUN-7887
// width: 100%;
min-width: 260px; min-width: 260px;
max-width: min-content;
// update-end--author:liaozhiyang---date:20240118---forQQYUN-7887
// flex-wrap: wrap; // flex-wrap: wrap;
} }
// update-begin--author:liaozhiyang---date:20240529---forTV360X-254
&.ant-popover,
.ant-popover-content,
.ant-popover-inner,
.ant-popover-inner-content,
.scroll-container,
.scrollbar__wrap {
max-width: min-content;
}
// update-end--author:liaozhiyang---date:20240529---forTV360X-254
.scrollbar { .scrollbar {
height: 220px; height: 220px;
} }

View File

@ -8,8 +8,8 @@
<ColumnHeightOutlined /> <ColumnHeightOutlined />
<template #overlay> <template #overlay>
<Menu @click="handleTitleClick" selectable v-model:selectedKeys="selectedKeysRef"> <Menu @click="handleTitleClick" selectable v-model:selectedKeys="selectedKeysRef">
<MenuItem key="default"> <MenuItem key="large">
<span>{{ t('component.table.settingDensDefault') }}</span> <span>{{ t('component.table.settingDensLarge') }}</span>
</MenuItem> </MenuItem>
<MenuItem key="middle"> <MenuItem key="middle">
<span>{{ t('component.table.settingDensMiddle') }}</span> <span>{{ t('component.table.settingDensMiddle') }}</span>
@ -30,6 +30,8 @@
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useTableContext } from '../../hooks/useTableContext'; import { useTableContext } from '../../hooks/useTableContext';
import { getPopupContainer } from '/@/utils'; import { getPopupContainer } from '/@/utils';
import { useRoute } from 'vue-router';
import { createLocalStorage } from '/@/utils/cache';
export default defineComponent({ export default defineComponent({
name: 'SizeSetting', name: 'SizeSetting',
@ -46,6 +48,8 @@
setup(props) { setup(props) {
const table = useTableContext(); const table = useTableContext();
const { t } = useI18n(); const { t } = useI18n();
const $ls = createLocalStorage();
const route = useRoute();
const selectedKeysRef = ref<SizeType[]>([table.getSize()]); const selectedKeysRef = ref<SizeType[]>([table.getSize()]);
const getBindProps = computed(() => { const getBindProps = computed(() => {
@ -60,7 +64,28 @@
table.setProps({ table.setProps({
size: key, size: key,
}); });
// update-begin--author:liaozhiyang---date:20240604---forTV360X-100
$ls.set(cacheKey.value, key);
// update-end--author:liaozhiyang---date:20240604---forTV360X-100
} }
// update-begin--author:liaozhiyang---date:20240604---forTV360X-100
const cacheKey = computed(() => {
const path = route.path;
let key = path.replace(/[\/\\]/g, '_');
let cacheKey = table.getBindValues.value.tableSetting?.cacheKey;
if (cacheKey) {
key += ':' + cacheKey;
}
return 'tableSizeCache:' + key;
});
const local: SizeType | null = $ls.get(cacheKey.value);
if (local) {
selectedKeysRef.value = [local];
table.setProps({
size: local,
});
}
// update-end--author:liaozhiyang---date:20240604---forTV360X-100
return { return {
getBindProps, getBindProps,

View File

@ -1,5 +1,6 @@
import { computed, nextTick, unref, watchEffect } from 'vue'; import { computed, nextTick, unref, watchEffect } from 'vue';
import { router } from '/@/router'; import { router } from '/@/router';
import { useRoute } from 'vue-router';
import { createLocalStorage } from '/@/utils/cache'; import { createLocalStorage } from '/@/utils/cache';
import { useTableContext } from './useTableContext'; import { useTableContext } from './useTableContext';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
@ -12,10 +13,13 @@ export function useColumnsCache(opt, setColumns, handleColumnFixed) {
const table = useTableContext(); const table = useTableContext();
const $ls = createLocalStorage(); const $ls = createLocalStorage();
const { createMessage: $message } = useMessage(); const { createMessage: $message } = useMessage();
const route = useRoute();
// 列表配置缓存key // 列表配置缓存key
const cacheKey = computed(() => { const cacheKey = computed(() => {
let { fullPath } = router.currentRoute.value; // update-begin--author:liaozhiyang---date:20240226---for【QQYUN-8367】online报表配置列展示保存影响到其他页面的table字段的显示隐藏开发环境热更新会有此问题生产环境无问题
let key = fullPath.replace(/[\/\\]/g, '_'); const path = route.path;
let key = path.replace(/[\/\\]/g, '_');
// update-end--author:liaozhiyang---date:20240226---for【QQYUN-8367】online报表配置列展示保存影响到其他页面的table字段的显示隐藏开发环境热更新会有此问题生产环境无问题
let cacheKey = table.getBindValues.value.tableSetting?.cacheKey; let cacheKey = table.getBindValues.value.tableSetting?.cacheKey;
if (cacheKey) { if (cacheKey) {
key += ':' + cacheKey; key += ':' + cacheKey;

View File

@ -75,6 +75,11 @@ export function useCustomRow(
} }
setSelectedRowKeys([key]); setSelectedRowKeys([key]);
return; return;
} else {
// update-begin--author:liaozhiyang---date:20240527---for【TV360X-359】erp主表点击已选中的选到了最后一个
// 点击已经选中的直接return不在做操作
return;
// update-end--author:liaozhiyang---date:20240527---for【TV360X-359】erp主表点击已选中的选到了最后一个
} }
clearSelectedRowKeys(); clearSelectedRowKeys();
} }

View File

@ -2,7 +2,7 @@ import type { BasicColumn } from '/@/components/Table';
import type { Ref, ComputedRef } from 'vue'; import type { Ref, ComputedRef } from 'vue';
import type { BasicTableProps, PaginationProps, TableRowSelection } from '/@/components/Table'; import type { BasicTableProps, PaginationProps, TableRowSelection } from '/@/components/Table';
import { computed, nextTick, onUnmounted, ref, toRaw, unref, watch, watchEffect } from 'vue'; import { computed, nextTick, onUnmounted, ref, toRaw, unref, watch, watchEffect } from 'vue';
import { omit } from 'lodash-es'; import { omit, isEqual } from 'lodash-es';
import { throttle } from 'lodash-es'; import { throttle } from 'lodash-es';
import { Checkbox, Radio } from 'ant-design-vue'; import { Checkbox, Radio } from 'ant-design-vue';
import { isFunction } from '/@/utils/is'; import { isFunction } from '/@/utils/is';
@ -120,7 +120,10 @@ export function useCustomSelection(
onSelectAll, onSelectAll,
isRadio: isRadio.value, isRadio: isRadio.value,
selectedLength: flattedData.value.filter((data) => selectedKeys.value.includes(getRecordKey(data))).length, selectedLength: flattedData.value.filter((data) => selectedKeys.value.includes(getRecordKey(data))).length,
pageSize: currentPageSize.value, // update-begin--author:liaozhiyang---date:20240511---for【QQYUN-9289】解决表格条数不足pageSize数量时行数全部勾选但是全选框不勾选
// 【TV360X-53】为空时会报错加强判断
pageSize: tableData.value?.length ?? 0,
// update-end--author:liaozhiyang---date:20240511---for【QQYUN-9289】解决表格条数不足pageSize数量时行数全部勾选但是全选框不勾选
// 【QQYUN-6774】解决checkbox禁用后全选仍能勾选问题 // 【QQYUN-6774】解决checkbox禁用后全选仍能勾选问题
disabled: flattedData.value.length == 0, disabled: flattedData.value.length == 0,
hideSelectAll: unref(propsRef)?.rowSelection?.hideSelectAll, hideSelectAll: unref(propsRef)?.rowSelection?.hideSelectAll,
@ -128,17 +131,44 @@ export function useCustomSelection(
}); });
// 监听传入的selectedRowKeys // 监听传入的selectedRowKeys
// update-begin--author:liaozhiyang---date:20240306---for【QQYUN-8390】部门人员组件点击重置未清空selectedRowKeys.value=[]watch没监听到加deep
watch( watch(
() => unref(propsRef)?.rowSelection?.selectedRowKeys, () => unref(propsRef)?.rowSelection?.selectedRowKeys,
(val: string[]) => { (val: string[]) => {
// 解决selectedRowKeys在页面调用处使用ref失效 // 解决selectedRowKeys在页面调用处使用ref失效
const value = unref(val); const value = unref(val);
if (Array.isArray(value)) { if (Array.isArray(value) && !sameArray(value, selectedKeys.value)) {
setSelectedRowKeys(value); setSelectedRowKeys(value);
} }
}, },
{ immediate: true } {
immediate: true,
deep: true
}
); );
// update-end--author:liaozhiyang---date:20240306---for【QQYUN-8390】部门人员组件点击重置未清空selectedRowKeys.value=[]watch没监听到加deep
/**
* 2024-03-06
* liaozhiyang
* ()
*/
function sameArray(a, b) {
if (a === b) {
if (a.length === b.length) {
return a.toString() === b.toString();
} else {
return false;
}
} else {
// update-begin--author:liaozhiyang---date:20240425---for【QQYUN-9123】popupdict打开弹窗打开程序运行
if (isEqual(a, b)) {
return true;
}
// update-end--author:liaozhiyang---date:20240425---for【QQYUN-9123】popupdict打开弹窗打开程序运行
return false;
}
}
// 当任意一个变化时,触发同步检测 // 当任意一个变化时,触发同步检测
watch([selectedKeys, selectedRows], () => { watch([selectedKeys, selectedRows], () => {
@ -198,9 +228,14 @@ export function useCustomSelection(
// update-end--author:liaozhiyang---date:20231122---for【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件 // update-end--author:liaozhiyang---date:20231122---for【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件
// 取消全选 // 取消全选
if (!checked) { if (!checked) {
selectedKeys.value = []; // update-begin--author:liaozhiyang---date:20240510---for【issues/1173】取消全选只是当前页面取消
selectedRows.value = []; // selectedKeys.value = [];
emitChange('all'); // selectedRows.value = [];
// emitChange('all');
flattedData.value.forEach((item) => {
updateSelected(item, false);
});
// update-end--author:liaozhiyang---date:20240510---for【issues/1173】取消全选只是当前页面取消
return; return;
} }
let modal: Nullable<ReturnType<ModalFunc>> = null; let modal: Nullable<ReturnType<ModalFunc>> = null;
@ -387,6 +422,9 @@ export function useCustomSelection(
key={'j-select__' + recordKey} key={'j-select__' + recordKey}
checked={selectedKeys.value.includes(recordKey)} checked={selectedKeys.value.includes(recordKey)}
onUpdate:checked={(checked) => onSelect(record, checked)} onUpdate:checked={(checked) => onSelect(record, checked)}
// update-begin--author:liaozhiyang---date:20230326---for【QQYUN-8694】BasicTable在使用clickToRowSelect=true下selection-change 事件在触发多次
onClick={(e) => e.stopPropagation()}
// update-end--author:liaozhiyang---date:20230326---for【QQYUN-8694】BasicTable在使用clickToRowSelect=true下selection-change 事件在触发多次
/> />
); );
} }
@ -412,6 +450,9 @@ export function useCustomSelection(
key={'j-select__' + recordKey} key={'j-select__' + recordKey}
checked={selectedKeys.value.includes(recordKey)} checked={selectedKeys.value.includes(recordKey)}
onUpdate:checked={(checked) => onSelect(record, checked)} onUpdate:checked={(checked) => onSelect(record, checked)}
// update-begin--author:liaozhiyang---date:20230326---for【QQYUN-8694】BasicTable在使用clickToRowSelect=true下selection-change 事件在触发多次
onClick={(e) => e.stopPropagation()}
// update-end--author:liaozhiyang---date:20230326---for【QQYUN-8694】BasicTable在使用clickToRowSelect=true下selection-change 事件在触发多次
/> />
); );
} }
@ -592,3 +633,4 @@ function flattenData<RecordType>(data: RecordType[] | undefined, childrenColumnN
return list; return list;
} }

View File

@ -133,6 +133,11 @@ export function useDataSource(
if (row) { if (row) {
for (const field in row) { for (const field in row) {
if (Reflect.has(record, field)) row[field] = record[field]; if (Reflect.has(record, field)) row[field] = record[field];
//update-begin---author:wangshuai---date:2024-06-11---for:【TV360X-437】树表 部分组件编辑完后,列表未刷新---
if (Reflect.has(record, field + '_dictText')) {
row[field + '_dictText'] = record[field + '_dictText'];
}
//update-end---author:wangshuai---date:2024-06-11---for:【TV360X-437】树表 部分组件编辑完后,列表未刷新---
} }
return row; return row;
} }
@ -248,7 +253,14 @@ export function useDataSource(
if (beforeFetch && isFunction(beforeFetch)) { if (beforeFetch && isFunction(beforeFetch)) {
params = (await beforeFetch(params)) || params; params = (await beforeFetch(params)) || params;
} }
// update-begin--author:liaozhiyang---date:20240227---for【QQYUN-8316】table查询条件,请求剔除空字符串字段
for (let item of Object.entries(params)) {
const [key, val] = item;
if (val === '') {
delete params[key];
};
};
// update-end--author:liaozhiyang---date:20240227---for【QQYUN-8316】table查询条件,请求剔除空字符串字段
const res = await api(params); const res = await api(params);
rawDataSourceRef.value = res; rawDataSourceRef.value = res;

View File

@ -7,6 +7,7 @@ import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
import { useModalContext } from '/@/components/Modal'; import { useModalContext } from '/@/components/Modal';
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated'; import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
import { useDebounceFn } from '@vueuse/core'; import { useDebounceFn } from '@vueuse/core';
import componentSetting from '/@/settings/componentSetting';
export function useTableScroll( export function useTableScroll(
propsRef: ComputedRef<BasicTableProps>, propsRef: ComputedRef<BasicTableProps>,
@ -118,14 +119,13 @@ export function useTableScroll(
} }
let footerHeight = 0; let footerHeight = 0;
if (!isBoolean(pagination)) { // update-begin--author:liaozhiyang---date:20240424---for【issues/1137】BasicTable自适应高度计算没有减去尾部高度
if (!footerEl) { footerEl = tableEl.querySelector('.ant-table-footer');
footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement; if (footerEl) {
} else { const offsetHeight = footerEl.offsetHeight;
const offsetHeight = footerEl.offsetHeight; footerHeight = offsetHeight || 0;
footerHeight += offsetHeight || 0;
}
} }
// update-end--author:liaozhiyang---date:20240424---for【issues/1137】BasicTable自适应高度计算没有减去尾部高度
let headerHeight = 0; let headerHeight = 0;
if (headEl) { if (headEl) {
@ -133,6 +133,10 @@ export function useTableScroll(
} }
let height = bottomIncludeBody - (resizeHeightOffset || 0) - paddingHeight - paginationHeight - footerHeight - headerHeight; let height = bottomIncludeBody - (resizeHeightOffset || 0) - paddingHeight - paginationHeight - footerHeight - headerHeight;
// update-begin--author:liaozhiyang---date:20240603---for【TV360X-861】列表查询区域不可往上滚动
// 10+6(外层边距padding:10 + 内层padding-bottom:6)
height -= 16;
// update-end--author:liaozhiyang---date:20240603---for【TV360X-861】列表查询区域不可往上滚动
height = (height < minHeight! ? (minHeight as number) : height) ?? height; height = (height < minHeight! ? (minHeight as number) : height) ?? height;
height = (height > maxHeight! ? (maxHeight as number) : height) ?? height; height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
@ -180,10 +184,13 @@ export function useTableScroll(
const getScrollRef = computed(() => { const getScrollRef = computed(() => {
const tableHeight = unref(tableHeightRef); const tableHeight = unref(tableHeightRef);
const { canResize, scroll } = unref(propsRef); const { canResize, scroll } = unref(propsRef);
const { table } = componentSetting;
return { return {
x: unref(getScrollX), x: unref(getScrollX),
y: canResize ? tableHeight : null, y: canResize ? tableHeight : null,
scrollToFirstRowOnChange: false, // update-begin--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
scrollToFirstRowOnChange: table.scrollToFirstRowOnChange,
// update-end--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
...scroll, ...scroll,
}; };
}); });

View File

@ -128,7 +128,9 @@ export const basicProps = {
type: Function as PropType<(record: TableCustomRecord<any>, index: number) => string>, type: Function as PropType<(record: TableCustomRecord<any>, index: number) => string>,
}, },
scroll: { scroll: {
type: Object as PropType<{ x: number | true; y: number }>, // update-begin--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
type: Object as PropType<{ x?: number | true; y?: number; scrollToFirstRowOnChange?: boolean }>,
// update-end--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
default: null, default: null,
}, },
beforeEditSubmit: { beforeEditSubmit: {

View File

@ -173,6 +173,9 @@ export interface ColumnProps<T> {
* @type object * @type object
*/ */
customHeaderCell?: (column: ColumnProps<T>) => object; customHeaderCell?: (column: ColumnProps<T>) => object;
// update-begin--author:liaozhiyang---date:20240425---for【pull/1201】添加antd的TableSummary功能兼容老的summary表尾合计
customSummaryRender?: CustomRenderFunction<T> | VNodeChild | JSX.Element;
// update-end--author:liaozhiyang---date:20240425---for【pull/1201】添加antd的TableSummary功能兼容老的summary表尾合计
/** /**
* Callback executed when the confirm filter button is clicked, Use as a filter event when using template or jsx * Callback executed when the confirm filter button is clicked, Use as a filter event when using template or jsx

View File

@ -81,7 +81,7 @@ export interface GetColumnsParams {
sort?: boolean; sort?: boolean;
} }
export type SizeType = 'default' | 'middle' | 'small' | 'large'; export type SizeType = 'middle' | 'small' | 'large';
export interface TableActionType { export interface TableActionType {
reload: (opt?: FetchParams) => Promise<void>; reload: (opt?: FetchParams) => Promise<void>;
@ -152,6 +152,7 @@ export interface BasicTableProps<T = any> {
inset?: boolean; inset?: boolean;
// 显示表格设置 // 显示表格设置
showTableSetting?: boolean; showTableSetting?: boolean;
// 表格上方操作按钮设置
tableSetting?: TableSetting; tableSetting?: TableSetting;
// 斑马纹 // 斑马纹
striped?: boolean; striped?: boolean;
@ -205,7 +206,6 @@ export interface BasicTableProps<T = any> {
canResize?: boolean; canResize?: boolean;
// 自适应高度偏移, 计算结果-偏移量 // 自适应高度偏移, 计算结果-偏移量
resizeHeightOffset?: number; resizeHeightOffset?: number;
// 在分页改变的时候清空选项 // 在分页改变的时候清空选项
clearSelectOnPageChange?: boolean; clearSelectOnPageChange?: boolean;
// //
@ -319,7 +319,9 @@ export interface BasicTableProps<T = any> {
* you need to add style .ant-table td { white-space: nowrap; }. * you need to add style .ant-table td { white-space: nowrap; }.
* @type object * @type object
*/ */
scroll?: { x?: number | true | 'max-content'; y?: number }; // update-begin--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
scroll?: { x?: number | true | 'max-content'; y?: number; scrollToFirstRowOnChange?: boolean };
// update-end--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
/** /**
* Whether to show table header * Whether to show table header
@ -453,6 +455,16 @@ export interface BasicColumn extends ColumnProps<Recordable> {
ifShow?: boolean | ((column: BasicColumn) => boolean); ifShow?: boolean | ((column: BasicColumn) => boolean);
//compType-用于记录类型 //compType-用于记录类型
compType?: string; compType?: string;
// update-begin--author:liaozhiyang---date:20240425---for【pull/1201】添加antd的TableSummary功能兼容老的summary表尾合计
customSummaryRender?: (opt: {
value: any;
text: any;
record: Recordable;
index: number;
renderIndex?: number;
column: BasicColumn;
}) => any | VNodeChild | JSX.Element;
// update-end--author:liaozhiyang---date:20240425---for【pull/1201】添加antd的TableSummary功能兼容老的summary表尾合计
} }
export type ColumnChangeParam = { export type ColumnChangeParam = {

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