This commit is contained in:
zhouwentao 2024-03-19 16:53:55 +08:00
parent 7925080ea2
commit 525ba6f454
460 changed files with 21801 additions and 10754 deletions

4
.env
View File

@ -2,10 +2,10 @@
VITE_PORT = 3100 VITE_PORT = 3100
# 网站标题 # 网站标题
VITE_GLOB_APP_TITLE = 后台管理系统 VITE_GLOB_APP_TITLE = 艺体志愿宝 管理平台
# 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符 # 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符
VITE_GLOB_APP_SHORT_NAME = JeecgBootAdmin VITE_GLOB_APP_SHORT_NAME = YitishengAdmin
# 单点登录服务端地址 # 单点登录服务端地址
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

@ -4,17 +4,14 @@ VITE_USE_MOCK = true
# 发布路径 # 发布路径
VITE_PUBLIC_PATH = / VITE_PUBLIC_PATH = /
# 跨域代理,您可以配置多个 ,请注意,没有换行符 # 跨域代理,您可以配置多个 ,请注意,没有换行符
VITE_PROXY = [["/jeecgboot","http://localhost:8080/jeecg-boot"],["/upload","http://localhost:3300/upload"]] VITE_PROXY = [["/jeecgboot","http://localhost:8080/jeecg-boot"],["/upload","http://localhost:3300/upload"]]
# 控制台不输出
VITE_DROP_CONSOLE = false
#后台接口父地址(必填)
VITE_GLOB_API_URL=/jeecgboot
#后台接口全路径地址(必填) #后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=http://localhost:8080/jeecg-boot VITE_GLOB_DOMAIN_URL=http://localhost:8080/jeecg-boot/
#后台接口父地址(必填)
VITE_GLOB_API_URL=http://localhost:8080/jeecg-boot/
# 接口前缀 # 接口前缀
VITE_GLOB_API_URL_PREFIX= VITE_GLOB_API_URL_PREFIX=

View File

@ -4,9 +4,6 @@ VITE_USE_MOCK = true
# 发布路径 # 发布路径
VITE_PUBLIC_PATH = / VITE_PUBLIC_PATH = /
# 控制台不输出
VITE_DROP_CONSOLE = true
# 是否启用gzip或brotli压缩 # 是否启用gzip或brotli压缩
# 选项值: gzip | brotli | none # 选项值: gzip | brotli | none
# 如果需要多个可以使用“,”分隔 # 如果需要多个可以使用“,”分隔
@ -16,19 +13,10 @@ VITE_BUILD_COMPRESS = 'gzip'
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
#后台接口父地址(必填) #后台接口父地址(必填)
VITE_GLOB_API_URL=/jeecgboot VITE_GLOB_API_URL=https://yitisheng.vip/jbttest
#后台接口全路径地址(必填) #后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=http://jeecg-boot-system:8080/jeecg-boot VITE_GLOB_DOMAIN_URL=https://yitisheng.vip/jbttest
# 接口父路径前缀 # 接口父路径前缀
VITE_GLOB_API_URL_PREFIX= VITE_GLOB_API_URL_PREFIX=
# 是否启用图像压缩
VITE_USE_IMAGEMIN= true
# 使用pwa
VITE_USE_PWA = false
# 是否兼容旧浏览器
VITE_LEGACY = false

2
.gitignore vendored
View File

@ -22,6 +22,7 @@ pnpm-debug.log*
# Editor directories and files # Editor directories and files
.idea .idea
.svn
# .vscode # .vscode
*.suo *.suo
*.ntvs* *.ntvs*
@ -29,6 +30,7 @@ pnpm-debug.log*
*.sln *.sln
*.sw? *.sw?
/os_del.cmd /os_del.cmd
os_del.cmd
/.vscode/ /.vscode/
/.history/ /.history/
/svn clear.bat /svn clear.bat

View File

@ -23,7 +23,7 @@ SOFTWARE.
开源协议补充 开源协议补充
JeecgBoot 是由 北京敲敲云科技有限公司 发行的软件。 总部位于北京地址中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱jeecgos@163.com JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京地址中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱jeecgos@163.com
本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。 本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。
1.允许基于本平台软件开展业务系统开发。 1.允许基于本平台软件开展业务系统开发。
@ -32,4 +32,6 @@ SOFTWARE.
违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。 违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。
总结在遵循Apache开源协议和开源协议补充条款下允许商用使用不会造成侵权行为 总结在遵循Apache开源协议和开源协议补充条款下允许商用使用不会造成侵权行为
解释权归http://www.jeecg.com 解释权归:
http://www.jeecg.com
http://guojusoft.com

View File

@ -1,18 +1,18 @@
JEECG BOOT 低代码开发平台Vue3前端 JEECG BOOT 低代码开发平台Vue3前端
=============== ===============
当前最新版本: 3.5.3发布时间2023-07-24 当前最新版本: 3.6.3发布时间2024-03-11
[![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://www.jeecg.com) [![](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.5.3-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot) [![](https://img.shields.io/badge/version-3.6.3-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)
## 简介 ## 简介
JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue3、TypeScript 等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。 JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue4、TypeScript 等新技术方案包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。
是采用Vben实现的 JeecgBoot低代码平台的全新vue3版本。 是采用Vben实现的 JeecgBoot低代码平台的全新vue3版本。
> 强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性 > 强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性
@ -31,10 +31,10 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue3、TypeScript 等新技术
##### 项目说明 ##### 项目说明
| 项目名 | 说明 | | 项目名 | 说明 |
|--------------------|------------------------| |--------------------|-----------------------------------------|
| `jeecgboot-vue3` | Vue3版前端代码 | | `jeecgboot-vue3` | 前端源码Vue3版下载 |
| `jeecg-boot` | SpringBoot后台项目支持微服务 | | `jeecg-boot` | 后端JAVA源码下载SpringBoot+SpringCloud |
## 开发环境搭建 ## 开发环境搭建
@ -44,11 +44,11 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue3、TypeScript 等新技术
## 技术文档 ## 技术文档
- 官方文档:[http://help.jeecg.com](http://help.jeecg.com) - 官方文档:[https://help.jeecg.com](https://help.jeecg.com)
- 官方网站: [http://www.jeecg.com](http://www.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交流群⑦791696430、683903138 - QQ交流群⑧825232878、⑦791696430(满)、683903138(满)
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [Vue2演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex) - 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)| [敲敲云零代码](https://www.qiaoqiaoyun.com)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取 > 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取

View File

@ -1,11 +1,21 @@
import { generateAntColors, primaryColor } from '../config/themeConfig'; import { primaryColor } from '../config/themeConfig';
import { getThemeVariables } from 'ant-design-vue/dist/theme'; // import { getThemeVariables } from 'ant-design-vue/dist/theme';
import { resolve } from 'path'; import { resolve } from 'path';
import { generate } from '@ant-design/colors';
import { theme } from 'ant-design-vue/lib';
import convertLegacyToken from 'ant-design-vue/lib/theme/convertLegacyToken';
const { defaultAlgorithm, defaultSeed } = theme;
function generateAntColors(color: string, theme: 'default' | 'dark' = 'default') {
return generate(color, {
theme,
});
}
/** /**
* less global variable * less global variable
*/ */
export function generateModifyVars(dark = false) { export function generateModifyVars() {
const palettes = generateAntColors(primaryColor); const palettes = generateAntColors(primaryColor);
const primary = palettes[5]; const primary = palettes[5];
@ -15,12 +25,14 @@ export function generateModifyVars(dark = false) {
primaryColorObj[`primary-${index + 1}`] = palettes[index]; primaryColorObj[`primary-${index + 1}`] = palettes[index];
} }
const modifyVars = getThemeVariables({ dark }); const mapToken = defaultAlgorithm(defaultSeed);
const v3Token = convertLegacyToken(mapToken);
return { return {
...modifyVars, ...v3Token,
// ...modifyVars,
// Used for global import to avoid the need to import each style file separately // Used for global import to avoid the need to import each style file separately
// reference: Avoid repeated references // reference: Avoid repeated references
hack: `${modifyVars.hack} @import (reference) "${resolve('src/design/config.less')}";`, hack: `true; @import (reference) "${resolve('src/design/config.less')}";`,
'primary-color': primary, 'primary-color': primary,
...primaryColorObj, ...primaryColorObj,
'info-color': primary, 'info-color': primary,

View File

@ -1,5 +1,5 @@
/** /**
* Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging *
*/ */
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant'; import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant';
import fs, { writeFileSync } from 'fs-extra'; import fs, { writeFileSync } from 'fs-extra';

View File

@ -13,6 +13,10 @@ export function configCompressPlugin(compress: 'gzip' | 'brotli' | 'none', delet
if (compressList.includes('gzip')) { if (compressList.includes('gzip')) {
plugins.push( plugins.push(
compressPlugin({ compressPlugin({
verbose: true,
disable: false,
threshold: 10240,
algorithm: 'gzip',
ext: '.gz', ext: '.gz',
deleteOriginFile, deleteOriginFile,
}) })

View File

@ -19,11 +19,11 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
const htmlPlugin: PluginOption[] = createHtmlPlugin({ const htmlPlugin: PluginOption[] = createHtmlPlugin({
minify: isBuild, minify: isBuild,
inject: { inject: {
// Inject data into ejs template // 修改模板html的标题
data: { data: {
title: VITE_GLOB_APP_TITLE, title: VITE_GLOB_APP_TITLE,
}, },
// Embed the generated app.config.js file // 将app.config.js文件注入到模板html中
tags: isBuild tags: isBuild
? [ ? [
{ {

View File

@ -1,3 +1,4 @@
// 【图片压缩插件】
// Image resource files used to compress the output of the production environment // Image resource files used to compress the output of the production environment
// https://github.com/anncwb/vite-plugin-imagemin // https://github.com/anncwb/vite-plugin-imagemin
import viteImagemin from 'vite-plugin-imagemin'; import viteImagemin from 'vite-plugin-imagemin';

View File

@ -1,27 +1,26 @@
import { PluginOption } from 'vite'; import { PluginOption } from 'vite';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'; import vueJsx from '@vitejs/plugin-vue-jsx';
import legacy from '@vitejs/plugin-legacy';
import purgeIcons from 'vite-plugin-purge-icons'; import purgeIcons from 'vite-plugin-purge-icons';
import windiCSS from 'vite-plugin-windicss'; import UnoCSS from 'unocss/vite';
import { presetTypography, presetUno } from 'unocss';
// 本地调试https配置方法
import VitePluginCertificate from 'vite-plugin-mkcert'; import VitePluginCertificate from 'vite-plugin-mkcert';
//update-begin-author:liusq date:2023-06-06 for: [issues/555]开发环境vscode断点调试文件或行数对不上 //[issues/555]开发环境vscode断点调试文件或行数对不上
import vueSetupExtend from 'vite-plugin-vue-setup-extend-plus'; import vueSetupExtend from 'vite-plugin-vue-setup-extend-plus';
//update-end-author:liusq date:2023-06-06 for: [issues/555]开发环境vscode断点调试文件或行数对不上
import { configHtmlPlugin } from './html'; import { configHtmlPlugin } from './html';
import { configPwaConfig } from './pwa';
import { configMockPlugin } from './mock'; import { configMockPlugin } from './mock';
import { configCompressPlugin } from './compress'; import { configCompressPlugin } from './compress';
import { configStyleImportPlugin } from './styleImport';
import { configVisualizerConfig } from './visualizer'; import { configVisualizerConfig } from './visualizer';
import { configThemePlugin } from './theme'; import { configThemePlugin } from './theme';
import { configImageminPlugin } from './imagemin';
import { configSvgIconsPlugin } from './svgSprite'; import { configSvgIconsPlugin } from './svgSprite';
import OptimizationPersist from 'vite-plugin-optimize-persist' // //预编译加载插件(不支持vite3作废)
import PkgConfig from 'vite-plugin-package-config' // import OptimizationPersist from 'vite-plugin-optimize-persist';
// import PkgConfig from 'vite-plugin-package-config';
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const { VITE_USE_IMAGEMIN, VITE_USE_MOCK, VITE_LEGACY, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv; const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv;
const vitePlugins: (PluginOption | PluginOption[])[] = [ const vitePlugins: (PluginOption | PluginOption[])[] = [
// have to // have to
@ -36,11 +35,7 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
}), }),
]; ];
// vite-plugin-windicss vitePlugins.push(UnoCSS({ presets: [presetUno(), presetTypography()] }));
vitePlugins.push(windiCSS());
// @vitejs/plugin-legacy
VITE_LEGACY && isBuild && vitePlugins.push(legacy());
// vite-plugin-html // vite-plugin-html
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild)); vitePlugins.push(configHtmlPlugin(viteEnv, isBuild));
@ -54,9 +49,6 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
// vite-plugin-purge-icons // vite-plugin-purge-icons
vitePlugins.push(purgeIcons()); vitePlugins.push(purgeIcons());
// vite-plugin-style-import
vitePlugins.push(configStyleImportPlugin(isBuild));
// rollup-plugin-visualizer // rollup-plugin-visualizer
vitePlugins.push(configVisualizerConfig()); vitePlugins.push(configVisualizerConfig());
@ -65,18 +57,14 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
// The following plugins only work in the production environment // The following plugins only work in the production environment
if (isBuild) { if (isBuild) {
// vite-plugin-imagemin
VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
// rollup-plugin-gzip // rollup-plugin-gzip
vitePlugins.push(configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE)); vitePlugins.push(configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE));
// vite-plugin-pwa
vitePlugins.push(configPwaConfig(viteEnv));
} }
//vite-plugin-theme【解决vite首次打开界面加载慢问题】 // //vite-plugin-theme【预编译加载插件,解决vite首次打开界面加载慢问题】
vitePlugins.push(PkgConfig()); // vitePlugins.push(PkgConfig());
vitePlugins.push(OptimizationPersist()); // vitePlugins.push(OptimizationPersist());
return vitePlugins; return vitePlugins;
} }

View File

@ -1,34 +0,0 @@
/**
* Zero-config PWA for Vite
* https://github.com/antfu/vite-plugin-pwa
* vite-plugin-pwa是vite的一个官方插件vite项目变成pwa应用
*/
import { VitePWA } from 'vite-plugin-pwa';
export function configPwaConfig(env: ViteEnv) {
const { VITE_USE_PWA, VITE_GLOB_APP_TITLE, VITE_GLOB_APP_SHORT_NAME } = env;
if (VITE_USE_PWA) {
// vite-plugin-pwa
const pwaPlugin = VitePWA({
manifest: {
name: VITE_GLOB_APP_TITLE,
short_name: VITE_GLOB_APP_SHORT_NAME,
icons: [
{
src: './resource/img/pwa-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: './resource/img/pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
},
],
},
});
return pwaPlugin;
}
return [];
}

View File

@ -1,4 +1,5 @@
/** /**
* antd的样式
* Introduces component library styles on demand. * Introduces component library styles on demand.
* https://github.com/anncwb/vite-plugin-style-import * https://github.com/anncwb/vite-plugin-style-import
*/ */

View File

@ -57,7 +57,7 @@ export function configThemePlugin(isBuild: boolean): PluginOption[] {
vite_theme_plugin, vite_theme_plugin,
antdDarkThemePlugin({ antdDarkThemePlugin({
preloadFiles: [ preloadFiles: [
path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.less'), // path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/reset.css'),
//path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.dark.less'), //path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.dark.less'),
path.resolve(process.cwd(), 'src/design/index.less'), path.resolve(process.cwd(), 'src/design/index.less'),
], ],

View File

@ -166,5 +166,16 @@
</div> </div>
</div> </div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
<!-- 百度统计 -->
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?0febd9e3cacb3f627ddac64d52caac39";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</body> </body>
</html> </html>

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;
}; };
@ -21,7 +30,7 @@ export default [
method: 'get', method: 'get',
response: ({ query }) => { response: ({ query }) => {
const { keyword,count} = query; const { keyword,count} = query;
console.log(keyword); console.log("查询条件:", keyword);
return resultSuccess(demoList(keyword,count)); return resultSuccess(demoList(keyword,count));
}, },
}, },

View File

@ -31,7 +31,7 @@ export default [
method: 'get', method: 'get',
response: ({ query }) => { response: ({ query }) => {
const { keyword } = query; const { keyword } = query;
console.log(keyword); console.log("查询条件:", keyword);
return resultSuccess(demoTreeList(keyword)); return resultSuccess(demoTreeList(keyword));
}, },
}, },

View File

@ -1,185 +1,159 @@
{ {
"name": "jeecgboot-vue3", "name": "jeecgboot-vue3",
"version": "3.5.3", "version": "3.6.3",
"author": { "author": {
"name": "jeecg", "name": "北京国炬信息技术有限公司",
"email": "jeecgos@163.com", "email": "jeecgos@163.com",
"url": "https://github.com/jeecgboot/jeecgboot-vue3" "url": "https://github.com/jeecgboot/jeecgboot-vue3"
}, },
"scripts": { "scripts": {
"bootstrap": "pnpm install", "pinstall": "pnpm install",
"serve": "npm run dev",
"dev": "vite",
"clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite", "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
"clean:lib": "rimraf node_modules", "dev": "vite",
"build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 vite build && esno ./build/script/postBuild.ts", "build": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=8192 vite build && esno ./build/script/postBuild.ts",
"build:no-cache": "pnpm clean:cache && npm run build", "build:report": "pnpm clean:cache && cross-env REPORT=true npm run build",
"report": "cross-env REPORT=true npm run build",
"type:check": "vue-tsc --noEmit --skipLibCheck",
"preview": "npm run build && vite preview", "preview": "npm run build && vite preview",
"preview:dist": "vite preview", "reinstall": "rimraf pnpm-lock.yaml && rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run install",
"log": "conventional-changelog -p angular -i CHANGELOG.md -s", "clean:lib": "rimraf node_modules",
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", "gen:icon": "esno ./build/generate/icon/index.ts",
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", "batch:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", "upgrade:log": "conventional-changelog -p angular -i CHANGELOG.md -s",
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js", "husky:install": "husky install"
"lint:pretty": "pretty-quick --staged",
"test:unit": "jest",
"test:unit-coverage": "jest --coverage",
"test:gzip": "http-server dist --cors --gzip -c-1",
"test:br": "http-server dist --cors --brotli -c-1",
"reinstall": "rimraf pnpm-lock.yaml && yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
"prepare": "husky install",
"gen:icon": "esno ./build/generate/icon/index.ts"
}, },
"dependencies": { "dependencies": {
"@jeecg/online": "3.5.3-beta3", "@jeecg/online": "3.6.2-beta",
"@qiaoqiaoyun/drag-free": "^1.0.52", "@iconify/iconify": "^3.1.1",
"@iconify/iconify": "^2.2.1", "@ant-design/colors": "^7.0.2",
"@ant-design/colors": "^6.0.0", "@ant-design/icons-vue": "^7.0.1",
"@ant-design/icons-vue": "^6.1.0", "@vue/shared": "^3.3.4",
"@logicflow/core": "^1.1.13", "@vueuse/core": "^10.7.1",
"@logicflow/extension": "^1.1.13", "@zxcvbn-ts/core": "^3.0.4",
"@vue/shared": "^3.2.33", "ant-design-vue": "^4.1.2",
"@vue/runtime-core": "^3.2.33", "axios": "^1.6.4",
"@vueuse/shared": "^8.3.0",
"@vueuse/core": "^8.3.0",
"@zxcvbn-ts/core": "^2.0.1",
"ant-design-vue": "^3.2.20",
"axios": "^0.26.1",
"china-area-data": "^5.0.1", "china-area-data": "^5.0.1",
"clipboard": "^2.0.8", "clipboard": "^2.0.11",
"codemirror": "^5.65.3", "codemirror": "^5.65.3",
"cron-parser": "^3.5.0", "cron-parser": "^4.9.0",
"cropperjs": "^1.5.12", "cropperjs": "^1.6.1",
"crypto-js": "^4.1.1", "crypto-js": "^4.2.0",
"dayjs": "^1.11.1", "dayjs": "^1.11.10",
"dom-align": "^1.12.2", "dom-align": "^1.12.4",
"echarts": "^5.3.2", "echarts": "^5.4.3",
"emoji-mart-vue-fast": "^11.1.1", "emoji-mart-vue-fast": "^15.0.0",
"enquire.js": "^2.1.6", "enquire.js": "^2.1.6",
"intro.js": "^5.1.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",
"@traptitech/markdown-it-katex": "^3.6.0",
"event-source-polyfill": "^1.0.31",
"highlight.js": "^11.9.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.0", "path-to-regexp": "^6.2.1",
"pinia": "2.0.12", "pinia": "2.1.7",
"print-js": "^1.6.0", "print-js": "^1.6.0",
"pinyin-pro": "^3.11.0", "qs": "^6.11.2",
"qs": "^6.10.3", "qrcode": "^1.5.3",
"qrcode": "^1.5.0",
"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.1",
"tinymce": "^5.10.3", "tinymce": "^5.10.3",
"vditor": "^3.8.13", "vditor": "^3.9.8",
"vue": "^3.2.47", "vue": "^3.4.15",
"vue-cropper": "^0.5.6", "vue-cropper": "^0.6.4",
"vue-cropperjs": "^5.0.0", "vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.1.9", "vue-i18n": "^9.8.0",
"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.0.14", "vue-router": "^4.2.5",
"vue-types": "^4.1.1", "vue-types": "^5.1.1",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"vxe-table": "4.1.0", "vxe-table": "4.5.17",
"vxe-table-plugin-antd": "3.0.5", "vxe-table-plugin-antd": "3.1.0",
"xe-utils": "^3.3.1", "xe-utils": "3.5.14",
"vue-json-pretty": "^2.0.6", "xss": "^1.0.14"
"xss": "^1.0.13"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^16.2.3", "@commitlint/cli": "^18.4.3",
"@commitlint/config-conventional": "^16.2.1", "@commitlint/config-conventional": "^18.4.3",
"@iconify/json": "^2.1.30", "@iconify/json": "^2.2.164",
"@purge-icons/generated": "^0.8.1", "@purge-icons/generated": "^0.10.0",
"@types/codemirror": "^5.60.5", "@types/codemirror": "^5.60.15",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.2.1",
"@types/fs-extra": "^9.0.13", "@types/fs-extra": "^11.0.4",
"@types/inquirer": "^8.2.1", "@types/inquirer": "^9.0.7",
"@types/intro.js": "^3.0.2", "@types/intro.js": "^5.1.5",
"@types/jest": "^27.0.2", "@types/jest": "^29.5.11",
"@types/lodash-es": "^4.17.6", "@types/lodash-es": "^4.17.12",
"@types/mockjs": "^1.0.6", "@types/mockjs": "^1.0.10",
"@types/node": "^17.0.25", "@types/node": "^20.10.6",
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.3",
"@types/qrcode": "^1.4.2", "@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.11",
"@types/pinyin": "^2.10.0", "@types/showdown": "^2.0.6",
"@types/showdown": "^1.9.4", "@types/sortablejs": "^1.15.7",
"@types/sortablejs": "^1.10.7", "@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/eslint-plugin": "^5.20.0", "@typescript-eslint/parser": "^6.17.0",
"@typescript-eslint/parser": "^5.20.0", "@vitejs/plugin-vue": "^4.3.3",
"@vitejs/plugin-legacy": "^2.0.0", "@vitejs/plugin-vue-jsx": "^3.1.0",
"@vitejs/plugin-vue": "^3.0.1", "@vue/compiler-sfc": "^3.4.4",
"@vitejs/plugin-vue-jsx": "^1.3.10", "@vue/test-utils": "^2.4.3",
"@vue/compiler-sfc": "^3.2.33", "autoprefixer": "^10.4.16",
"@vue/test-utils": "^2.0.0-rc.21", "commitizen": "^4.3.0",
"autoprefixer": "^10.4.4", "conventional-changelog-cli": "^4.1.0",
"commitizen": "^4.2.4",
"conventional-changelog-cli": "^2.2.2",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"cz-git": "^1.3.9", "cz-git": "^1.8.0",
"czg": "^1.3.9", "czg": "^1.8.0",
"dotenv": "^16.0.0", "dotenv": "^16.3.1",
"eslint": "^8.22.0", "eslint": "^8.56.0",
"eslint-config-prettier": "^8.6.0", "eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^1.14.0", "eslint-define-config": "^2.1.0",
"eslint-plugin-jest": "^27.2.1", "eslint-plugin-jest": "^27.6.1",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^5.1.2",
"eslint-plugin-vue": "^9.9.0", "eslint-plugin-vue": "^9.19.2",
"esno": "^0.14.1", "esno": "^4.0.0",
"fs-extra": "^10.1.0", "fs-extra": "^11.2.0",
"http-server": "^14.0.0", "http-server": "^14.1.1",
"husky": "^7.0.4", "husky": "^8.0.3",
"inquirer": "^8.2.2", "inquirer": "^9.2.12",
"is-ci": "^3.0.0", "is-ci": "^3.0.1",
"jest": "^27.3.1", "jest": "^29.7.0",
"less": "^4.1.2", "less": "^4.2.0",
"lint-staged": "12.3.7", "lint-staged": "15.2.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
"postcss": "^8.4.12", "postcss": "^8.4.32",
"postcss-html": "^1.4.1", "postcss-html": "^1.5.0",
"postcss-less": "^6.0.0", "postcss-less": "^6.0.0",
"prettier": "^2.6.2", "prettier": "^3.1.1",
"pretty-quick": "^3.1.1", "pretty-quick": "^3.1.3",
"rimraf": "^3.0.2", "rimraf": "^5.0.5",
"rollup": "^2.70.2", "rollup": "^4.9.2",
"rollup-plugin-visualizer": "^5.6.0", "rollup-plugin-visualizer": "^5.12.0",
"stylelint": "^14.7.1", "stylelint": "^16.1.0",
"stylelint-config-prettier": "^9.0.3", "stylelint-config-prettier": "^9.0.5",
"stylelint-config-recommended": "^7.0.0", "stylelint-config-recommended": "^14.0.0",
"stylelint-config-recommended-vue": "^1.4.0", "stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard": "^25.0.0", "stylelint-config-standard": "^36.0.0",
"stylelint-order": "^5.0.0", "stylelint-order": "^6.0.4",
"ts-jest": "^27.0.7", "ts-jest": "^29.1.1",
"ts-node": "^10.7.0", "ts-node": "^10.9.2",
"typescript": "^4.6.3", "typescript": "^4.9.5",
"vite": "^3.2.3", "vite": "^4.4.9",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0", "vite-plugin-html": "^3.2.1",
"vite-plugin-imagemin": "^0.6.1", "vite-plugin-mkcert": "^1.17.1",
"vite-plugin-mkcert": "^1.10.1",
"vite-plugin-mock": "^2.9.6", "vite-plugin-mock": "^2.9.6",
"vite-plugin-optimize-persist": "^0.1.2", "vite-plugin-purge-icons": "^0.10.0",
"vite-plugin-package-config": "^0.1.1",
"vite-plugin-purge-icons": "^0.8.2",
"vite-plugin-pwa": "^0.12.3",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-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",
"vite-plugin-windicss": "^1.8.7", "unocss": "^0.58.3",
"vue-eslint-parser": "^8.3.0", "vue-eslint-parser": "^9.3.2",
"vue-tsc": "^0.33.9" "vue-tsc": "^1.8.27"
},
"resolutions": {
"bin-wrapper": "npm:bin-wrapper-china",
"rollup": "^2.72.0"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -189,69 +163,13 @@
"bugs": { "bugs": {
"url": "https://github.com/jeecgboot/jeecgboot-vue3/issues" "url": "https://github.com/jeecgboot/jeecgboot-vue3/issues"
}, },
"homepage": "https://github.com/jeecgboot/jeecgboot-vue3", "homepage": "https://www.jeecg.com",
"engines": { "engines": {
"node": "^12 || >=14" "node": "^12 || >=14"
}, },
"vite": { "vite": {
"optimizeDeps": { "optimizeDeps": {
"include": [ "include": [
"@ant-design/colors",
"@ant-design/icons-vue",
"@vueuse/core",
"@vueuse/shared",
"@zxcvbn-ts/core",
"ant-design-vue",
"axios",
"china-area-data",
"clipboard",
"codemirror",
"codemirror/addon/fold/brace-fold.js",
"codemirror/addon/fold/comment-fold.js",
"codemirror/addon/fold/foldcode.js",
"codemirror/addon/fold/foldgutter.js",
"codemirror/addon/fold/indent-fold.js",
"codemirror/addon/hint/anyword-hint.js",
"codemirror/addon/hint/show-hint.js",
"codemirror/addon/selection/active-line.js",
"codemirror/mode/clike/clike.js",
"codemirror/mode/css/css.js",
"codemirror/mode/javascript/javascript.js",
"codemirror/mode/markdown/markdown.js",
"codemirror/mode/python/python.js",
"codemirror/mode/r/r.js",
"codemirror/mode/shell/shell.js",
"codemirror/mode/sql/sql.js",
"codemirror/mode/swift/swift.js",
"codemirror/mode/vue/vue.js",
"codemirror/mode/xml/xml.js",
"cron-parser",
"cropperjs",
"crypto-js/aes",
"crypto-js/enc-base64",
"crypto-js/enc-utf8",
"crypto-js/md5",
"crypto-js/mode-ecb",
"crypto-js/pad-pkcs7",
"dom-align",
"echarts",
"echarts/charts",
"echarts/components",
"echarts/core",
"echarts/renderers",
"emoji-mart-vue-fast/src",
"intro.js",
"lodash-es",
"md5",
"nprogress",
"path-to-regexp",
"pinia",
"print-js",
"qrcode",
"qs",
"resize-observer-polyfill",
"showdown",
"sortablejs",
"tinymce/icons/default/icons", "tinymce/icons/default/icons",
"tinymce/plugins/advlist", "tinymce/plugins/advlist",
"tinymce/plugins/anchor", "tinymce/plugins/anchor",

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
<template> <template>
<ConfigProvider :locale="getAntdLocale"> <ConfigProvider :theme="appTheme" :locale="getAntdLocale">
<AppProvider> <AppProvider>
<RouterView /> <RouterView />
</AppProvider> </AppProvider>
@ -7,15 +7,73 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { watch, ref } from 'vue';
import { theme } from 'ant-design-vue';
import { ConfigProvider } from 'ant-design-vue'; import { ConfigProvider } from 'ant-design-vue';
import { AppProvider } from '/@/components/Application'; import { AppProvider } from '/@/components/Application';
import { useTitle } from '/@/hooks/web/useTitle'; import { useTitle } from '/@/hooks/web/useTitle';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
import { useAppStore } from '/@/store/modules/app';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { ThemeEnum } from '/@/enums/appEnum';
import { changeTheme } from '/@/logics/theme/index';
const appStore = useAppStore();
// //
import 'dayjs/locale/zh-cn'; import 'dayjs/locale/zh-cn';
// support Multi-language // support Multi-language
const { getAntdLocale } = useLocale(); const { getAntdLocale } = useLocale();
useTitle(); useTitle();
// update-begin--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x
const appTheme: any = ref({});
const { getDarkMode } = useRootSetting();
watch(
() => getDarkMode.value,
(newValue) => {
delete appTheme.value.algorithm;
if (newValue === ThemeEnum.DARK) {
appTheme.value.algorithm = theme.darkAlgorithm;
}
appTheme.value = {
...appTheme.value,
};
},
{ immediate: true }
);
watch(
appStore.getProjectConfig,
(newValue) => {
const primary = newValue.themeColor;
appTheme.value = {
...appTheme.value,
...{
token: {
colorPrimary: primary,
wireframe: true,
fontSize: 14,
colorSuccess: '#55D187',
colorInfo: primary,
borderRadius: 2,
sizeStep: 4,
sizeUnit: 4,
colorWarning: '#EFBD47',
colorError: '#ED6F6F',
},
},
};
},
{ immediate: true }
);
setTimeout(() => {
appStore.getProjectConfig?.themeColor && changeTheme(appStore.getProjectConfig.themeColor);
}, 300);
// update-end--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x
</script> </script>
<style lang="less">
// update-begin--author:liaozhiyang---date:20230803---forQQYUN-5839windihtml2canvas
img {
display: inline-block;
}
// update-end--author:liaozhiyang---date:20230803---forQQYUN-5839windihtml2canvas
</style>

View File

@ -23,6 +23,13 @@ export const getMenuList = () => {
}); });
}; };
/**
* @description:
*/
export function getBackMenuAndPerms() {
return defHttp.get({ url: Api.GetMenuList });
}
/** /**
* vue3菜单 * vue3菜单
*/ */

View File

@ -85,7 +85,17 @@ export function getUserInfo() {
const userStore = useUserStoreWithOut(); const userStore = useUserStoreWithOut();
userStore.setToken(''); userStore.setToken('');
setAuthCache(TOKEN_KEY, null); setAuthCache(TOKEN_KEY, null);
router.push(PageEnum.BASE_LOGIN);
// update-begin-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
router.push({
path: PageEnum.BASE_LOGIN,
query: {
// 传入当前的路由,登录成功后跳转到当前路由
redirect: router.currentRoute.value.fullPath,
}
});
// update-end-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
} }
// update-end--author:zyf---date:20220425---for:【VUEN-76】捕获接口超时异常,跳转到登录界面 // update-end--author:zyf---date:20220425---for:【VUEN-76】捕获接口超时异常,跳转到登录界面
}); });
@ -116,6 +126,9 @@ export function getCaptcha(params) {
createErrorModal({ title: '错误提示', content: res.message || '未知问题' }); createErrorModal({ title: '错误提示', content: res.message || '未知问题' });
reject(); reject();
} }
}).catch((res)=>{
createErrorModal({ title: '错误提示', content: res.message || '未知问题' });
reject();
}); });
}); });
} }
@ -146,9 +159,15 @@ export const passwordChange = (params) => defHttp.get({ url: Api.passwordChange,
* @description: * @description:
*/ */
export function thirdLogin(params, mode: ErrorMessageMode = 'modal') { export function thirdLogin(params, mode: ErrorMessageMode = 'modal') {
//==========begin 第三方登录/auth2登录需要传递租户id===========
let tenantId = "0";
if(!params.tenantId){
tenantId = params.tenantId;
}
//==========end 第三方登录/auth2登录需要传递租户id===========
return defHttp.get<LoginResultModel>( return defHttp.get<LoginResultModel>(
{ {
url: `${Api.thirdLogin}/${params.token}/${params.thirdType}`, url: `${Api.thirdLogin}/${params.token}/${params.thirdType}/${tenantId}`,
}, },
{ {
errorMessageMode: mode, errorMessageMode: mode,

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -62,10 +62,13 @@
padding-left: 7px; padding-left: 7px;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
//
&.light { &.jeecg-layout-mix-sider-logo,&.jeecg-layout-menu-logo{
border-bottom: 1px solid @border-color-base; background:@sider-logo-bg-color;
} }
// &.light {
// border-bottom: 1px solid @border-color-base;
// }
&.collapsed-show-title { &.collapsed-show-title {
padding-left: 20px; padding-left: 20px;

View File

@ -178,7 +178,7 @@
&-input { &-input {
width: 100%; width: 100%;
height: 48px; height: 48px;
font-size: 1.5em; font-size: 1.3em;
color: #1c1e21; color: #1c1e21;
border-radius: 6px; border-radius: 6px;
@ -222,7 +222,7 @@
font-size: 14px; font-size: 14px;
color: @text-color-base; color: @text-color-base;
cursor: pointer; cursor: pointer;
background-color: @component-background; // background-color: @component-background;
border-radius: 4px; border-radius: 4px;
box-shadow: 0 1px 3px 0 #d4d9e1; box-shadow: 0 1px 3px 0 #d4d9e1;
align-items: center; align-items: center;

View File

@ -53,6 +53,10 @@
cursor: move; cursor: move;
user-select: none; user-select: none;
&.is-drawer {
cursor: default;
}
&-normal { &-normal {
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;

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

@ -15,7 +15,7 @@
import { computed } from 'vue'; import { computed } from 'vue';
import CodeMirrorEditor from './codemirror/CodeMirror.vue'; import CodeMirrorEditor from './codemirror/CodeMirror.vue';
import { isString } from '/@/utils/is'; import { isString } from '/@/utils/is';
const props = defineProps({ const props = defineProps({
value: { type: [Object, String] as PropType<Record<string, any> | string> }, value: { type: [Object, String] as PropType<Record<string, any> | string> },
mode: { type: String, default: MODE.JSON }, mode: { type: String, default: MODE.JSON },

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

@ -12,7 +12,7 @@
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import CountButton from './CountButton.vue'; import CountButton from './CountButton.vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useRuleFormItem } from '/@/hooks/component/useFormItem'; import { useRuleFormItem } from '/@/hooks/component/useFormItemSingle';
const props = { const props = {
value: { type: String }, value: { type: String },

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

@ -40,7 +40,7 @@
components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader }, components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader },
inheritAttrs: false, inheritAttrs: false,
props: basicProps, props: basicProps,
emits: ['visible-change', 'ok', 'close', 'register'], emits: ['visible-change', 'open-change', 'ok', 'close', 'register'],
setup(props, { emit }) { setup(props, { emit }) {
const visibleRef = ref(false); const visibleRef = ref(false);
const attrs = useAttrs(); const attrs = useAttrs();
@ -63,12 +63,14 @@
}); });
const getProps = computed((): DrawerProps => { const getProps = computed((): DrawerProps => {
// update-begin--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x
const opt = { const opt = {
placement: 'right', placement: 'right',
...unref(attrs), ...unref(attrs),
...unref(getMergeProps), ...unref(getMergeProps),
visible: unref(visibleRef), open: unref(visibleRef),
}; };
// update-end--author:liaozhiyang---date:20231218---forQQYUN-6366antd4.x
opt.title = undefined; opt.title = undefined;
let { isDetail, width, wrapClassName, getContainer } = opt; let { isDetail, width, wrapClassName, getContainer } = opt;
if (isDetail) { if (isDetail) {
@ -123,11 +125,20 @@
{ deep: true } { deep: true }
); );
watch(
() => props.open,
(newVal, oldVal) => {
if (newVal !== oldVal) visibleRef.value = newVal;
},
{ deep: true }
);
watch( watch(
() => visibleRef.value, () => visibleRef.value,
(visible) => { (visible) => {
nextTick(() => { nextTick(() => {
emit('visible-change', visible); emit('visible-change', visible);
emit('open-change', visible);
instance && drawerInstance.emitVisible?.(visible, instance.uid); instance && drawerInstance.emitVisible?.(visible, instance.uid);
}); });
} }
@ -152,6 +163,9 @@
if (Reflect.has(props, 'visible')) { if (Reflect.has(props, 'visible')) {
visibleRef.value = !!props.visible; visibleRef.value = !!props.visible;
} }
if (Reflect.has(props, 'open')) {
visibleRef.value = !!props.open;
}
} }
function handleOk() { function handleOk() {

View File

@ -1,5 +1,5 @@
<template> <template>
<BasicTitle v-if="!isDetail" :class="prefixCls"> <BasicTitle v-if="!isDetail" :class="[prefixCls, 'is-drawer']">
<slot name="title"></slot> <slot name="title"></slot>
{{ !$slots.title ? title : '' }} {{ !$slots.title ? title : '' }}
</BasicTitle> </BasicTitle>

View File

@ -31,6 +31,7 @@ export const basicProps = {
loadingText: { type: String }, loadingText: { type: String },
showDetailBack: { type: Boolean, default: true }, showDetailBack: { type: Boolean, default: true },
visible: { type: Boolean }, visible: { type: Boolean },
open: { type: Boolean },
loading: { type: Boolean }, loading: { type: Boolean },
maskClosable: { type: Boolean, default: true }, maskClosable: { type: Boolean, default: true },
getContainer: { getContainer: {

View File

@ -11,6 +11,7 @@ export interface ReturnMethods extends DrawerInstance {
openDrawer: <T = any>(visible?: boolean, data?: T, openOnSet?: boolean) => void; openDrawer: <T = any>(visible?: boolean, data?: T, openOnSet?: boolean) => void;
closeDrawer: () => void; closeDrawer: () => void;
getVisible?: ComputedRef<boolean>; getVisible?: ComputedRef<boolean>;
getOpen?: ComputedRef<boolean>;
} }
export type RegisterFn = (drawerInstance: DrawerInstance, uuid?: string) => void; export type RegisterFn = (drawerInstance: DrawerInstance, uuid?: string) => void;
@ -20,6 +21,7 @@ export interface ReturnInnerMethods extends DrawerInstance {
changeLoading: (loading: boolean) => void; changeLoading: (loading: boolean) => void;
changeOkLoading: (loading: boolean) => void; changeOkLoading: (loading: boolean) => void;
getVisible?: ComputedRef<boolean>; getVisible?: ComputedRef<boolean>;
getOpen?: ComputedRef<boolean>;
} }
export type UseDrawerReturnType = [RegisterFn, ReturnMethods]; export type UseDrawerReturnType = [RegisterFn, ReturnMethods];
@ -74,6 +76,7 @@ export interface DrawerProps extends DrawerFooterProps {
loading?: boolean; loading?: boolean;
showDetailBack?: boolean; showDetailBack?: boolean;
visible?: boolean; visible?: boolean;
open?: boolean;
/** /**
* Built-in ScrollContainer component configuration * Built-in ScrollContainer component configuration
* @type ScrollContainerOptions * @type ScrollContainerOptions

View File

@ -58,10 +58,16 @@ export function useDrawer(): UseDrawerReturnType {
return visibleData[~~unref(uid)]; return visibleData[~~unref(uid)];
}), }),
getOpen: computed((): boolean => {
return visibleData[~~unref(uid)];
}),
openDrawer: <T = any>(visible = true, data?: T, openOnSet = true): void => { openDrawer: <T = any>(visible = true, data?: T, openOnSet = true): void => {
// update-begin--author:liaozhiyang---date:20231218---for【QQYUN-6366】升级到antd4.x
getInstance()?.setDrawerProps({ getInstance()?.setDrawerProps({
visible: visible, open: visible,
}); });
// update-end--author:liaozhiyang---date:20231218---for【QQYUN-6366】升级到antd4.x
if (!data) return; if (!data) return;
if (openOnSet) { if (openOnSet) {
@ -75,7 +81,9 @@ export function useDrawer(): UseDrawerReturnType {
} }
}, },
closeDrawer: () => { closeDrawer: () => {
getInstance()?.setDrawerProps({ visible: false }); // update-begin--author:liaozhiyang---date:20231218---for【QQYUN-6366】升级到antd4.x
getInstance()?.setDrawerProps({ open: false });
// update-end--author:liaozhiyang---date:20231218---for【QQYUN-6366】升级到antd4.x
}, },
}; };
@ -133,9 +141,11 @@ export const useDrawerInner = (callbackFn?: Fn): UseDrawerInnerReturnType => {
getVisible: computed((): boolean => { getVisible: computed((): boolean => {
return visibleData[~~unref(uidRef)]; return visibleData[~~unref(uidRef)];
}), }),
getOpen: computed((): boolean => {
return visibleData[~~unref(uidRef)];
}),
closeDrawer: () => { closeDrawer: () => {
getInstance()?.setDrawerProps({ visible: false }); getInstance()?.setDrawerProps({ open: false });
}, },
setDrawerProps: (props: Partial<DrawerProps>) => { setDrawerProps: (props: Partial<DrawerProps>) => {

View File

@ -10,22 +10,28 @@
v-bind="getAttr(item.event)" v-bind="getAttr(item.event)"
@click="handleClickMenu(item)" @click="handleClickMenu(item)"
:disabled="item.disabled" :disabled="item.disabled"
:class="[{ 'is-pop-confirm': item.popConfirm }, (item.class ?? [])]" :class="[{ 'is-pop-confirm': item.popConfirm }, item.class ?? []]"
> >
<a-popconfirm v-if="popconfirm && item.popConfirm" v-bind="getPopConfirmAttrs(item.popConfirm)"> <!-- update-begin--author:liaozhiyang---date:20231110---forissues/839BasicTable表格的更多操作按钮禁用还能点击弹出气泡框 -->
<a-popconfirm :disabled="item.disabled" v-if="popconfirm && item.popConfirm" v-bind="getPopConfirmAttrs(item.popConfirm)">
<!-- update-end--author:liaozhiyang---date:20231110---forissues/839BasicTable表格的更多操作按钮禁用还能点击弹出气泡框 -->
<template #icon v-if="item.popConfirm.icon"> <template #icon v-if="item.popConfirm.icon">
<Icon v-if="item.iconColor" :icon="item.popConfirm.icon" :color="item.iconColor"/> <Icon v-if="item.iconColor" :icon="item.popConfirm.icon" :color="item.iconColor" />
<Icon v-else :icon="item.popConfirm.icon"/> <Icon v-else :icon="item.popConfirm.icon" />
</template> </template>
<div class="dropdown-event-area"> <div class="dropdown-event-area">
<Icon :icon="item.icon" v-if="item.icon && item.iconColor" :color="item.iconColor"/> <Icon :icon="item.icon" v-if="item.icon && item.iconColor" :color="item.iconColor" />
<Icon :icon="item.icon" v-else-if="item.icon"/> <Icon :icon="item.icon" v-else-if="item.icon" />
<span class="ml-1">{{ item.text }}</span> <span class="ml-1">{{ item.text }}</span>
</div> </div>
</a-popconfirm> </a-popconfirm>
<!-- 设置动态插槽 -->
<template v-else-if="item.slot">
<slot :name="item.slot" :label="item.text"></slot>
</template>
<template v-else> <template v-else>
<Icon :icon="item.icon" v-if="item.icon && item.iconColor" :color="item.iconColor"/> <Icon :icon="item.icon" v-if="item.icon && item.iconColor" :color="item.iconColor" />
<Icon :icon="item.icon" v-else-if="item.icon"/> <Icon :icon="item.icon" v-else-if="item.icon" />
<span class="ml-1">{{ item.text }}</span> <span class="ml-1">{{ item.text }}</span>
</template> </template>
</a-menu-item> </a-menu-item>
@ -37,7 +43,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, PropType } from 'vue'; import { computed, PropType, ref } from 'vue';
import type { DropMenu } from './typing'; import type { DropMenu } from './typing';
import { Dropdown, Menu, Popconfirm } from 'ant-design-vue'; import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
import { Icon } from '/@/components/Icon'; import { Icon } from '/@/components/Icon';

View File

@ -11,6 +11,7 @@
:allDefaultValues="defaultValueRef" :allDefaultValues="defaultValueRef"
:formModel="formModel" :formModel="formModel"
:setFormModel="setFormModel" :setFormModel="setFormModel"
:validateFields="validateFields"
> >
<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>
@ -51,6 +52,8 @@
import { useModalContext } from '/@/components/Modal'; import { useModalContext } from '/@/components/Modal';
import { basicProps } from './props'; import { basicProps } from './props';
import componentSetting from '/@/settings/componentSetting';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useDebounceFn } from '@vueuse/core'; import { useDebounceFn } from '@vueuse/core';
@ -88,6 +91,16 @@
mergeProps.labelCol = undefined; mergeProps.labelCol = undefined;
} }
//update-end-author:sunjianlei date:20220923 for: labelWidth使labelCollabelWidth //update-end-author:sunjianlei date:20220923 for: labelWidth使labelCollabelWidth
// update-begin--author:liaozhiyang---date:20231017---forQQYUN-6566BasicForm(inline)
if (mergeProps.layout === 'inline') {
if (mergeProps.labelCol === componentSetting.form.labelCol) {
mergeProps.labelCol = undefined;
}
if (mergeProps.wrapperCol === componentSetting.form.wrapperCol) {
mergeProps.wrapperCol = undefined;
}
}
// update-end--author:liaozhiyang---date:20231017---forQQYUN-6566BasicForm(inline)
return mergeProps; return mergeProps;
}); });
@ -252,10 +265,12 @@
const onFormSubmitWhenChange = useDebounceFn(handleSubmit, 300); const onFormSubmitWhenChange = useDebounceFn(handleSubmit, 300);
function setFormModel(key: string, value: any) { function setFormModel(key: string, value: any) {
formModel[key] = value; formModel[key] = value;
const { validateTrigger } = unref(getBindValue); // update-begin--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur'
if (!validateTrigger || validateTrigger === 'change') { // const { validateTrigger } = unref(getBindValue);
validateFields([key]).catch((_) => {}); // if (!validateTrigger || validateTrigger === 'change') {
} // validateFields([key]).catch((_) => {});
// }
// update-end--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur'
if(props.autoSearch === true){ if(props.autoSearch === true){
onFormSubmitWhenChange(); onFormSubmitWhenChange();
} }
@ -377,5 +392,12 @@
margin-bottom: 8px !important; margin-bottom: 8px !important;
} }
} }
// update-begin--author:liaozhiyang---date:20231017---forQQYUN-6566BasicForm(inline)
&.ant-form-inline {
& > .ant-row {
.ant-col { width:auto !important; }
}
}
// update-end--author:liaozhiyang---date:20231017---forQQYUN-6566BasicForm(inline)
} }
</style> </style>

View File

@ -44,6 +44,9 @@ 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';
@ -61,6 +64,7 @@ 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 RoleSelectInput from './jeecg/components/roleSelect/RoleSelectInput.vue';
const componentMap = new Map<ComponentType, Component>(); const componentMap = new Map<ComponentType, Component>();
@ -115,6 +119,9 @@ componentMap.set('JCodeEditor', JCodeEditor);
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);
@ -131,6 +138,9 @@ componentMap.set('JRangeNumber', JRangeNumber);
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);
export function add(compName: ComponentType, component: Component) { export function add(compName: ComponentType, component: Component) {
componentMap.set(compName, component); componentMap.set(compName, component);

View File

@ -1,5 +1,5 @@
<template> <template>
<Select @dropdownVisibleChange="handleFetch" v-bind="$attrs" @change="handleChange" :options="getOptions" v-model:value="state"> <Select @dropdownVisibleChange="handleFetch" v-bind="attrs_" @change="handleChange" :options="getOptions" v-model:value="state">
<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>
</template> </template>
@ -63,7 +63,30 @@
// Embedded in the form, just use the hook binding to perform form verification // Embedded in the form, just use the hook binding to perform form verification
const [state, setState] = useRuleFormItem(props, 'value', 'change', emitData); const [state, setState] = useRuleFormItem(props, 'value', 'change', emitData);
// update-begin--author:liaozhiyang---date:20230830---forQQYUN-6308
let vModalValue: any;
const attrs_ = computed(() => {
let obj: any = unref(attrs) || {};
if (obj && obj['onUpdate:value']) {
vModalValue = obj['onUpdate:value'];
delete obj['onUpdate:value'];
}
// update-begin--author:liaozhiyang---date:20231017---forissues/5467ApiSelect
if (obj['filterOption'] === undefined) {
// update-begin--author:liaozhiyang---date:20230904---forissues/5305
obj['filterOption'] = (inputValue, option) => {
if (typeof option['label'] === 'string') {
return option['label'].toLowerCase().indexOf(inputValue.toLowerCase()) != -1;
} else {
return true;
}
};
// update-end--author:liaozhiyang---date:20230904---forissues/5305
}
// update-end--author:liaozhiyang---date:20231017---forissues/5467ApiSelect
return obj;
});
// update-begin--author:liaozhiyang---date:20230830---forQQYUN-6308
const getOptions = computed(() => { const getOptions = computed(() => {
const { labelField, valueField, numberToString } = props; const { labelField, valueField, numberToString } = props;
return unref(options).reduce((prev, next: Recordable) => { return unref(options).reduce((prev, next: Recordable) => {
@ -90,6 +113,10 @@
}, },
{ deep: true } { deep: true }
); );
//
watchEffect(() => {
props.value && handleFetch();
});
async function fetch() { async function fetch() {
const api = props.api; const api = props.api;
@ -140,10 +167,11 @@
} }
function handleChange(_, ...args) { function handleChange(_, ...args) {
vModalValue && vModalValue(_);
emitData.value = args; emitData.value = args;
} }
return { state, attrs, getOptions, loading, t, handleFetch, handleChange }; return { state, attrs_, attrs, getOptions, loading, t, handleFetch, handleChange };
}, },
}); });
</script> </script>

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

@ -65,6 +65,7 @@
actionSpan: propTypes.number.def(6), actionSpan: propTypes.number.def(6),
isAdvanced: propTypes.bool, isAdvanced: propTypes.bool,
hideAdvanceBtn: propTypes.bool, hideAdvanceBtn: propTypes.bool,
layout: propTypes.oneOf(['horizontal', 'vertical', 'inline']).def('horizontal'),
}, },
emits: ['toggle-advanced'], emits: ['toggle-advanced'],
setup(props, { emit }) { setup(props, { emit }) {
@ -74,12 +75,18 @@
const { showAdvancedButton, actionSpan: span, actionColOptions } = props; const { showAdvancedButton, actionSpan: span, actionColOptions } = props;
const actionSpan = 24 - span; const actionSpan = 24 - span;
const advancedSpanObj = showAdvancedButton ? { span: actionSpan < 6 ? 24 : actionSpan } : {}; const advancedSpanObj = showAdvancedButton ? { span: actionSpan < 6 ? 24 : actionSpan } : {};
// update-begin--author:liaozhiyang---date:20240105---forQQYUN-6566BasicForm(inline)
const defaultSpan = props.layout == 'inline' ? {} : { span: showAdvancedButton ? 6 : 4 };
// update-end--author:liaozhiyang---date:20240105---forQQYUN-6566BasicForm(inline)
const actionColOpt: Partial<ColEx> = { const actionColOpt: Partial<ColEx> = {
style: { textAlign: 'right' }, style: { textAlign: 'right' },
span: showAdvancedButton ? 6 : 4, ...defaultSpan,
...advancedSpanObj, ...advancedSpanObj,
...actionColOptions, ...actionColOptions,
}; };
return actionColOpt; return actionColOpt;
}); });

View File

@ -1,4 +1,5 @@
<script lang="tsx"> <script lang="tsx">
import { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface';
import type { PropType, Ref } from 'vue'; import type { PropType, Ref } from 'vue';
import type { FormActionType, FormProps } from '../types/form'; import type { FormActionType, FormProps } from '../types/form';
import type { FormSchema } from '../types/form'; import type { FormSchema } from '../types/form';
@ -40,6 +41,10 @@
type: Function as PropType<(key: string, value: any) => void>, type: Function as PropType<(key: string, value: any) => void>,
default: null, default: null,
}, },
validateFields: {
type: Function as PropType<(nameList?: NamePath[] | undefined, options?: ValidateOptions) => Promise<any>>,
default: null,
},
tableAction: { tableAction: {
type: Object as PropType<TableActionType>, type: Object as PropType<TableActionType>,
}, },
@ -79,10 +84,9 @@
componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {}; componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
} }
if (schema.component === 'Divider') { if (schema.component === 'Divider') {
componentProps = Object.assign({ type: 'horizontal' }, componentProps, { //update-begin---author:wangshuai---date:2023-09-22---for:QQYUN-6603线---
orientation: 'left', componentProps = Object.assign({ type: 'horizontal',orientation:'left', plain: true, }, componentProps);
plain: true, //update-end---author:wangshuai---date:2023-09-22---for:QQYUN-6603线---
});
} }
return componentProps as Recordable; return componentProps as Recordable;
}); });
@ -179,9 +183,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;
@ -198,16 +205,37 @@
if (characterInx !== -1 && !rules[characterInx].validator) { if (characterInx !== -1 && !rules[characterInx].validator) {
rules[characterInx].message = rules[characterInx].message || t('component.form.maxTip', [rules[characterInx].max] as Recordable); rules[characterInx].message = rules[characterInx].message || t('component.form.maxTip', [rules[characterInx].max] as Recordable);
} }
// update-begin--author:liaozhiyang---date:20241226---forQQYUN-7495patternantd使InputNumber
rules.forEach((item) => {
if (typeof item.pattern === 'string') {
try {
const reg = new Function('item', `return ${item.pattern}`)(item);
if (Object.prototype.toString.call(reg) === '[object RegExp]') {
item.pattern = reg;
} else {
item.pattern = new RegExp(item.pattern);
}
} catch (error) {
item.pattern = new RegExp(item.pattern);
}
}
});
// update-end--author:liaozhiyang---date:20231226---forQQYUN-7495patternantd使InputNumber
return rules; return rules;
} }
function renderComponent() { function renderComponent() {
const { renderComponentContent, component, field, changeEvent = 'change', valueField } = props.schema; const { renderComponentContent, component, field, changeEvent = 'change', valueField, componentProps } = props.schema;
const isCheck = component && ['Switch', 'Checkbox'].includes(component); const isCheck = component && ['Switch', 'Checkbox'].includes(component);
// update-begin--author:liaozhiyang---date:20231013---forQQYUN-6679input
let isTrim = false;
if (component === 'Input' && componentProps && componentProps.trim) {
isTrim = true;
}
// update-end--author:liaozhiyang---date:20231013---forQQYUN-6679input
const eventKey = `on${upperFirst(changeEvent)}`; const eventKey = `on${upperFirst(changeEvent)}`;
// update-begin--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur'
const on = { const on = {
[eventKey]: (...args: Nullable<Recordable>[]) => { [eventKey]: (...args: Nullable<Recordable>[]) => {
const [e] = args; const [e] = args;
@ -215,16 +243,35 @@
propsData[eventKey](...args); propsData[eventKey](...args);
} }
const target = e ? e.target : null; const target = e ? e.target : null;
const value = target ? (isCheck ? target.checked : target.value) : e; // update-begin--author:liaozhiyang---date:20231013---forQQYUN-6679input
let value;
if (target) {
if (isCheck) {
value = target.checked;
} else {
value = isTrim ? target.value.trim() : target.value;
}
} else {
value = e;
}
// update-end--author:liaozhiyang---date:20231013---forQQYUN-6679input
props.setFormModel(field, value); props.setFormModel(field, value);
//props.validateFields([field], { triggerName: 'change' }).catch((_) => {});
}, },
// onBlur: () => {
// props.validateFields([field], { triggerName: 'blur' }).catch((_) => {});
// },
}; };
// update-end--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur'
const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>; const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>;
const { autoSetPlaceHolder, size } = props.formProps; const { autoSetPlaceHolder, size } = props.formProps;
const propsData: Recordable = { const propsData: Recordable = {
allowClear: true, allowClear: true,
getPopupContainer: (trigger: Element) => trigger.parentNode, getPopupContainer: (trigger: Element) => {
return trigger?.parentNode;
},
size, size,
...unref(getComponentsProps), ...unref(getComponentsProps),
disabled: unref(getDisable), disabled: unref(getDisable),
@ -347,10 +394,10 @@
// update-begin--author:liaozhiyang---date:20230803---forissues-641span // update-begin--author:liaozhiyang---date:20230803---forissues-641span
const { getIsMobile } = useAppInject(); const { getIsMobile } = useAppInject();
let realColProps; let realColProps;
if (colProps['span'] && !unref(getIsMobile)) {
['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].forEach((name) => delete baseColProps[name]);
}
realColProps = { ...baseColProps, ...colProps }; realColProps = { ...baseColProps, ...colProps };
if (colProps['span'] && !unref(getIsMobile)) {
['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].forEach((name) => delete realColProps[name]);
}
// update-end--author:liaozhiyang---date:20230803---forissues-641span // update-end--author:liaozhiyang---date:20230803---forissues-641span
const { isIfShow, isShow } = getShow(); const { isIfShow, isShow } = getShow();
const values = unref(getValues); const values = unref(getValues);

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)) {
@ -61,6 +67,18 @@ export function handleInputNumberValue(component?: ComponentType, val?: any) {
} }
return val; return val;
} }
/**
*liaozhiyang
*2023-12-26
*
*/
export function handleInputStringValue(component?: ComponentType, val?: any) {
if (!component) return val;
if (['InputNumber'].includes(component) && typeof val === 'string') {
return Number(val);
}
return val;
}
/** /**
* *

View File

@ -1,5 +1,5 @@
import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form'; import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form';
import type { NamePath } from 'ant-design-vue/lib/form/interface'; import type { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface';
import type { DynamicProps } from '/#/utils'; import type { DynamicProps } from '/#/utils';
import { handleRangeValue } from '../utils/formUtils'; import { handleRangeValue } from '../utils/formUtils';
import { ref, onUnmounted, unref, nextTick, watch } from 'vue'; import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
@ -10,7 +10,7 @@ import { add } from "/@/components/Form/src/componentMap";
//集成online专用控件 //集成online专用控件
import { OnlineSelectCascade, LinkTableCard, LinkTableSelect } from '@jeecg/online'; import { OnlineSelectCascade, LinkTableCard, LinkTableSelect } from '@jeecg/online';
export declare type ValidateFields = (nameList?: NamePath[]) => Promise<Recordable>; export declare type ValidateFields = (nameList?: NamePath[], options?: ValidateOptions) => Promise<Recordable>;
type Props = Partial<DynamicProps<FormProps>>; type Props = Partial<DynamicProps<FormProps>>;
@ -149,9 +149,9 @@ export function useForm(props?: Props): UseFormReturnType {
}); });
return values; return values;
}, },
validateFields: async (nameList?: NamePath[]): Promise<Recordable> => { validateFields: async (nameList?: NamePath[], options?: ValidateOptions): Promise<Recordable> => {
const form = await getForm(); const form = await getForm();
return form.validateFields(nameList); return form.validateFields(nameList, options);
}, },
}; };

View File

@ -1,10 +1,10 @@
import type { ComputedRef, Ref } from 'vue'; import type { ComputedRef, Ref } from 'vue';
import type { FormProps, FormSchema, FormActionType } from '../types/form'; import type { FormProps, FormSchema, FormActionType } from '../types/form';
import type { NamePath } from 'ant-design-vue/lib/form/interface'; import type { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface';
import { unref, toRaw } from 'vue'; import { unref, toRaw } from 'vue';
import { isArray, isFunction, isObject, isString } from '/@/utils/is'; import { isArray, isFunction, isObject, isString } from '/@/utils/is';
import { deepMerge, getValueType } from '/@/utils'; import { deepMerge, getValueType } from '/@/utils';
import { dateItemType, handleInputNumberValue } from '../helper'; import { dateItemType, handleInputNumberValue, handleInputStringValue } from '../helper';
import { dateUtil } from '/@/utils/dateUtil'; import { dateUtil } from '/@/utils/dateUtil';
import { cloneDeep, uniqBy } from 'lodash-es'; import { cloneDeep, uniqBy } from 'lodash-es';
import { error } from '/@/utils/log'; import { error } from '/@/utils/log';
@ -65,6 +65,9 @@ export function useFormEvents({
const hasKey = Reflect.has(values, key); const hasKey = Reflect.has(values, key);
value = handleInputNumberValue(schema?.component, value); value = handleInputNumberValue(schema?.component, value);
// update-begin--author:liaozhiyang---date:20231226---for【QQYUN-7535】popup回填字段inputNumber组件验证错误
value = handleInputStringValue(schema?.component, value);
// update-end--author:liaozhiyang---date:20231226---for【QQYUN-7535】popup回填字段inputNumber组件验证错误
// 0| '' is allow // 0| '' is allow
if (hasKey && fields.includes(key)) { if (hasKey && fields.includes(key)) {
// time type // time type
@ -207,8 +210,8 @@ export function useFormEvents({
}); });
} }
async function validateFields(nameList?: NamePath[] | undefined) { async function validateFields(nameList?: NamePath[] | undefined, options?: ValidateOptions) {
return unref(formElRef)?.validateFields(nameList); return unref(formElRef)?.validateFields(nameList, options);
} }
async function validate(nameList?: NamePath[] | undefined) { async function validate(nameList?: NamePath[] | undefined) {

View File

@ -15,7 +15,7 @@
}, },
inheritAttrs: false, inheritAttrs: false,
props: { props: {
value: propTypes.oneOfType([propTypes.object, propTypes.array]), value: propTypes.oneOfType([propTypes.object, propTypes.array, propTypes.string]),
// //
showArea: propTypes.bool.def(true), showArea: propTypes.bool.def(true),
// //

View File

@ -44,7 +44,7 @@
allowClear: propTypes.bool.def(false), allowClear: propTypes.bool.def(false),
getPopupContainer: { getPopupContainer: {
type: Function, type: Function,
default: (node) => node.parentNode, default: (node) => node?.parentNode,
}, },
}, },
emits: ['change', 'update:value','update:area','update:city','update:province'], emits: ['change', 'update:value','update:area','update:city','update:province'],
@ -152,11 +152,14 @@
<style lang="less" scoped> <style lang="less" scoped>
.area-select { .area-select {
width: 100%; width: 100%;
display: flex;
/* update-begin-author:taoyan date:2023-2-18 for: QQYUN-4292【online表单】高级查询 2.省市县样式问题 */
/* display: flex;*/
.ant-select { .ant-select {
width: 33.3%; width: calc(33.3% - 7px)
} }
/* update-end-author:taoyan date:2023-2-18 for: QQYUN-4292【online表单】高级查询 2.省市县样式问题 */
.ant-select:not(:first-child) { .ant-select:not(:first-child) {
margin-left: 10px; margin-left: 10px;

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

@ -1,5 +1,5 @@
<template> <template>
<div v-bind="boxBindProps"> <div ref="containerRef" v-bind="boxBindProps">
<!-- 全屏按钮 --> <!-- 全屏按钮 -->
<a-icon v-if="fullScreen" class="full-screen-icon" :type="fullScreenIcon" @click="onToggleFullScreen" /> <a-icon v-if="fullScreen" class="full-screen-icon" :type="fullScreenIcon" @click="onToggleFullScreen" />
<textarea ref="textarea" v-bind="getBindValue"></textarea> <textarea ref="textarea" v-bind="getBindValue"></textarea>
@ -45,6 +45,8 @@
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';
export default defineComponent({ export default defineComponent({
name: 'JCodeEditor', name: 'JCodeEditor',
@ -58,12 +60,15 @@
// //
fullScreen: propTypes.bool.def(false), fullScreen: propTypes.bool.def(false),
// z-index // z-index
zIndex: propTypes.any.def(999), zIndex: propTypes.any.def(1500),
theme: propTypes.string.def('idea'), theme: propTypes.string.def('idea'),
language: propTypes.string.def(''), language: propTypes.string.def(''),
//
keywords: propTypes.array.def([]),
}, },
emits: ['change', 'update:value'], emits: ['change', 'update:value'],
setup(props, { emit }) { setup(props, { emit }) {
const containerRef = ref(null);
const { prefixCls } = useDesign('code-editer'); const { prefixCls } = useDesign('code-editer');
const CodeMirror = window.CodeMirror || _CodeMirror; const CodeMirror = window.CodeMirror || _CodeMirror;
const emitData = ref<object>(); const emitData = ref<object>();
@ -89,6 +94,9 @@
// : // :
// //
styleActiveLine: true, styleActiveLine: true,
// update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode
mode: props.language,
// update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode
// //
extraKeys: { extraKeys: {
Tab: function autoFormat(editor) { Tab: function autoFormat(editor) {
@ -121,6 +129,10 @@
} }
return _props; return _props;
}); });
// update-begin--author:liaozhiyang---date:20230904---forQQYUN-5955online js
const { codeHintingMount, codeHintingRegistry } = useCodeHinting(CodeMirror, props.keywords, props.language);
codeHintingRegistry();
// update-end--author:liaozhiyang---date:20230904---forQQYUN-5955online js
/** /**
* 监听组件值 * 监听组件值
*/ */
@ -171,6 +183,9 @@
coder.on('change', onChange); coder.on('change', onChange);
// //
setValue(innerValue, false); setValue(innerValue, false);
// update-begin--author:liaozhiyang---date:20230904---forQQYUN-5955online js
codeHintingMount(coder);
// update-end--author:liaozhiyang---date:20230904---forQQYUN-5955online js
} }
// //
@ -205,7 +220,8 @@
} }
} }
//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
return { return {
state, state,
textarea, textarea,
@ -215,7 +231,8 @@
isFullScreen, isFullScreen,
fullScreenIcon, fullScreenIcon,
onToggleFullScreen, onToggleFullScreen,
refresh refresh,
containerRef,
}; };
}, },
}); });
@ -295,4 +312,9 @@
border: 1px solid #ddd; border: 1px solid #ddd;
} }
} }
.CodeMirror-hints.idea {
z-index: 1001;
max-width: 600px;
max-height: 300px;
}
</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,9 +75,10 @@
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,
}, },
// //
showChooseOption: propTypes.bool.def(true), showChooseOption: propTypes.bool.def(true),
@ -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;
@ -185,11 +193,15 @@
/** 用于搜索下拉框中的内容 */ /** 用于搜索下拉框中的内容 */
function handleFilterOption(input, option) { function handleFilterOption(input, option) {
// label // update-begin--author:liaozhiyang---date:20230914---forQQYUN-6514 Y
let labelIf = option.children()[0]?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0; if (typeof option.children === 'function') {
if (labelIf) { // label
return true; let labelIf = option.children()[0]?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
if (labelIf) {
return true;
}
} }
// update-end--author:liaozhiyang---date:20230914---forQQYUN-6514 Y
// value // value
return (option.value || '').toString().toLowerCase().indexOf(input.toLowerCase()) >= 0; return (option.value || '').toString().toLowerCase().indexOf(input.toLowerCase()) >= 0;
} }
@ -209,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

@ -11,7 +11,7 @@
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
const props = defineProps({ const props = defineProps({
value: propTypes.oneOfType([propTypes.string, propTypes.array]), value: propTypes.oneOfType([propTypes.string, propTypes.number, propTypes.array]),
length: propTypes.number.def(25), length: propTypes.number.def(25),
}); });
// //

View File

@ -25,19 +25,19 @@
</a-button> </a-button>
</div> </div>
</a-upload> </a-upload>
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel()"> <a-modal :open="previewVisible" :footer="null" @cancel="handleCancel()">
<img alt="example" style="width: 100%" :src="previewImage" /> <img alt="example" style="width: 100%" :src="previewImage" />
</a-modal> </a-modal>
</div> </div>
</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, nextTick } from 'vue';
import { LoadingOutlined, UploadOutlined } from '@ant-design/icons-vue'; import { LoadingOutlined, UploadOutlined } from '@ant-design/icons-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';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { getFileAccessHttpUrl, getRandom } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl, getHeaders, getRandom } from '/@/utils/common/compUtils';
import { uploadUrl } from '/@/api/common/api'; import { uploadUrl } from '/@/api/common/api';
import { getToken } from '/@/utils/auth'; import { getToken } from '/@/utils/auth';
@ -94,9 +94,7 @@
return path.substring(path.lastIndexOf('/') + 1); return path.substring(path.lastIndexOf('/') + 1);
}; };
//token //token
const headers = ref<object>({ const headers = getHeaders();
'X-Access-Token': getToken(),
});
// //
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
// //
@ -177,28 +175,36 @@
*/ */
function handleChange({ file, fileList, event }) { function handleChange({ file, fileList, event }) {
initTag.value = false; initTag.value = false;
uploadFileList.value = fileList; // update-begin--author:liaozhiyang---date:20231116---forissues/846
// uploadFileList.value = fileList;
if (file.status === 'error') { if (file.status === 'error') {
createMessage.error(`${file.name} 上传失败.`); createMessage.error(`${file.name} 上传失败.`);
} }
let fileUrls = []; let fileUrls = [];
// let noUploadingFileCount = 0;
if (file.status != 'uploading') { if (file.status != 'uploading') {
fileList.forEach((file) => { fileList.forEach((file) => {
if (file.status === 'done') { if (file.status === 'done') {
//update-begin---author:wangshuai ---date:20221121 for[issues/248]使,------------
initTag.value = true;
//update-end---author:wangshuai ---date:20221121 for[issues/248]使,------------
fileUrls.push(file.response.message); fileUrls.push(file.response.message);
} }
if (file.status != 'uploading') {
noUploadingFileCount++;
}
}); });
if (file.status === 'removed') { if (file.status === 'removed') {
handleDelete(file); handleDelete(file);
} }
if (noUploadingFileCount == fileList.length) {
state.value = fileUrls.join(',');
emit('update:value', fileUrls.join(','));
// update-begin---author:wangshuai ---date:20221121 for[issues/248]使,------------
nextTick(() => {
initTag.value = true;
});
// update-end---author:wangshuai ---date:20221121 for[issues/248]使,------------
}
} }
// emitData.value = fileUrls.join(','); // update-end--author:liaozhiyang---date:20231116---forissues/846
state.value = fileUrls.join(',');
emit('update:value', fileUrls.join(','));
} }
/** /**

View File

@ -2,14 +2,14 @@
<div> <div>
<BasicModal v-bind="$attrs" @register="register" title="导入EXCEL" :width="600" @cancel="handleClose" :confirmLoading="uploading" destroyOnClose> <BasicModal v-bind="$attrs" @register="register" title="导入EXCEL" :width="600" @cancel="handleClose" :confirmLoading="uploading" destroyOnClose>
<!--是否校验--> <!--是否校验-->
<div style="margin: 0 5px 1px" v-if="online"> <div style="margin: 0 5px 5px" v-if="online">
<span style="display: inline-block; height: 32px; line-height: 32px; vertical-align: middle">是否开启校验:</span> <span style="display: inline-block; height: 32px; line-height: 32px; vertical-align: middle">是否开启校验:</span>
<span style="margin-left: 6px"> <span style="margin-left: 6px">
<a-switch :checked="validateStatus == 1" @change="handleChangeValidateStatus" checked-children="" un-checked-children="" size="small" /> <a-switch :checked="validateStatus == 1" @change="handleChangeValidateStatus" checked-children="" un-checked-children="" />
</span> </span>
</div> </div>
<!--上传--> <!--上传-->
<a-upload name="file" accept=".xls,.xlsx" :multiple="true" :fileList="fileList" :remove="handleRemove" :beforeUpload="beforeUpload"> <a-upload name="file" accept=".xls,.xlsx" :multiple="true" :fileList="fileList" @remove="handleRemove" :beforeUpload="beforeUpload">
<a-button preIcon="ant-design:upload-outlined">选择导入文件</a-button> <a-button preIcon="ant-design:upload-outlined">选择导入文件</a-button>
</a-upload> </a-upload>
<!--页脚--> <!--页脚-->
@ -81,7 +81,10 @@
// //
function handleClose() { function handleClose() {
closeModal() && reset(); // update-begin--author:liaozhiyang---date:20231226---forQQYUN-7477
closeModal();
reset();
// update-end--author:liaozhiyang---date:20231226---forQQYUN-7477
} }
// //
@ -139,6 +142,8 @@
} else { } else {
createMessage.warning(res.message); createMessage.warning(res.message);
} }
}).catch(() => {
uploading.value = false;
}); });
} }

View File

@ -3,10 +3,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType, ref, watchEffect, unref, watch } from 'vue'; import { defineComponent, PropType, ref, watchEffect, unref, watch, computed } from 'vue';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { JInputTypeEnum } from '/@/enums/jeecgEnum.ts'; import { JInputTypeEnum } from '/@/enums/jeecgEnum.ts';
import { omit } from 'lodash-es';
export default defineComponent({ export default defineComponent({
name: 'JInput', name: 'JInput',
@ -22,8 +23,12 @@
const attrs = useAttrs(); const attrs = useAttrs();
// //
const showText = ref(''); const showText = ref('');
// update-begin--author:liaozhiyang---date:20231026---forissues/803JIput updateSchema
// //
const getBindValue = Object.assign({}, unref(props), unref(attrs)); const getBindValue = computed(() => {
return omit(Object.assign({}, unref(props), unref(attrs)), ['value']);
});
// update-end--author:liaozhiyang---date:20231026---forissues/803JIput updateSchema
// //
watch( watch(
() => props.type, () => props.type,

View File

@ -1,7 +1,7 @@
<template> <template>
<a-popover <a-popover
trigger="contextmenu" trigger="contextmenu"
v-model:visible="visible" v-model:open="visible"
:overlayClassName="`${prefixCls}-popover`" :overlayClassName="`${prefixCls}-popover`"
:getPopupContainer="getPopupContainer" :getPopupContainer="getPopupContainer"
:placement="position" :placement="position"
@ -80,7 +80,7 @@
// //
function getPopupContainer(node) { function getPopupContainer(node) {
if (!props.popContainer) { if (!props.popContainer) {
return node.parentNode; return node?.parentNode;
} else if (typeof props.popContainer === 'function') { } else if (typeof props.popContainer === 'function') {
return props.popContainer(node); return props.popContainer(node);
} else { } else {

View File

@ -57,7 +57,7 @@
default: () => [], default: () => [],
}, },
}, },
emits: ['update:value', 'register', 'change','focus' ], emits: ['update:value', 'register', 'popUpChange', 'focus'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
const { createMessage } = useMessage(); const { createMessage } = useMessage();
const attrs = useAttrs(); const attrs = useAttrs();
@ -115,7 +115,10 @@
//popup //popup
let values = {}; let values = {};
for (let item of fieldConfig) { for (let item of fieldConfig) {
let val = rows.map((row) => row[item.source]).join(','); let val = rows.map((row) => row[item.source]);
// update-begin--author:liaozhiyang---date:20230831---forQQYUN-7535numberjoinstring
val = val.length == 1 ? val[0] : val.join(',');
// update-begin--author:liaozhiyang---date:20230831---forQQYUN-7535numberjoinstring
item.target.split(',').forEach((target) => { item.target.split(',').forEach((target) => {
values[target] = val; values[target] = val;
}); });
@ -124,9 +127,11 @@
props.formElRef && props.formElRef.setFieldsValue(values); props.formElRef && props.formElRef.setFieldsValue(values);
// //
props.setFieldsValue && props.setFieldsValue(values); props.setFieldsValue && props.setFieldsValue(values);
// update-begin--author:liaozhiyang---date:20230831---forissues/5288popup
// update-begin--author:liaozhiyang---date:20230811---forissues/5213JPopupchange // update-begin--author:liaozhiyang---date:20230811---forissues/5213JPopupchange
emit('change', values); emit('popUpChange', values);
// update-end--author:liaozhiyang---date:20230811---forissues/5213JPopupchange // update-end--author:liaozhiyang---date:20230811---forissues/5213JPopupchange
// update-begin--author:liaozhiyang---date:20230831---forissues/5288popup
} }
return { return {

View File

@ -0,0 +1,217 @@
<!--popup组件-->
<template>
<div class="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>
<!--popup弹窗-->
<JPopupOnlReportModal
@register="regModal"
:code="code"
:multi="multi"
:sorter="sorter"
:groupId="''"
:param="param"
@ok="callBack"
:getContainer="getContainer"
/>
</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,
},
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() {
!props.disabled && openModal(true);
}
/**
* 监听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>
.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

@ -9,7 +9,7 @@
allowClear allowClear
:getPopupContainer="getParentContainer" :getPopupContainer="getParentContainer"
:placeholder="placeholder" :placeholder="placeholder"
:filterOption="false" :filterOption="isDictTable ? false : filterOption"
:notFoundContent="loading ? undefined : null" :notFoundContent="loading ? undefined : null"
@search="loadData" @search="loadData"
@change="handleAsyncChange" @change="handleAsyncChange"
@ -63,7 +63,7 @@
pageSize: propTypes.number.def(10), pageSize: propTypes.number.def(10),
getPopupContainer: { getPopupContainer: {
type: Function, type: Function,
default: (node) => node.parentNode, default: (node) => node?.parentNode,
}, },
//YSelect //YSelect
//update-begin-author:liusq date:2023-04-04 for:[issue/286] //update-begin-author:liusq date:2023-04-04 for:[issue/286]
@ -83,18 +83,37 @@
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
const options = ref<any[]>([]); const options = ref<any[]>([]);
const loading = ref(false); const loading = ref(false);
const attrs = useAttrs(); // update-begin--author:liaozhiyang---date:20231205---forissues/897JSearchSelectclass/style
const attrs = useAttrs({'excludeDefaultKeys': false});
// update-end--author:liaozhiyang---date:20231205---forissues/897JSearchSelectclass/style
const selectedValue = ref([]); const selectedValue = ref([]);
const selectedAsyncValue = ref([]); const selectedAsyncValue = ref([]);
const lastLoad = ref(0); const lastLoad = ref(0);
// valuetext // valuetext
const loadSelectText = ref(true); const loadSelectText = ref(true);
//
const isDictTable = computed(() => {
if (props.dict) {
return props.dict.split(',').length >= 2
}
return false;
})
/** /**
* 监听字典code * 监听字典code
*/ */
watchEffect(() => { watch(() => props.dict, () => {
props.dict && initDictData(); if (!props.dict) {
}); return
}
if (isDictTable.value) {
initDictTableData();
} else {
initDictCodeData();
}
}, {immediate: true});
/** /**
* 监听value * 监听value
*/ */
@ -116,7 +135,7 @@
watch( watch(
() => props.dictOptions, () => props.dictOptions,
(val) => { (val) => {
if (val && val.length > 0) { if (val && val.length >= 0) {
options.value = [...val]; options.value = [...val];
} }
}, },
@ -126,6 +145,9 @@
* 异步查询数据 * 异步查询数据
*/ */
async function loadData(value) { async function loadData(value) {
if (!isDictTable.value) {
return;
}
lastLoad.value += 1; lastLoad.value += 1;
const currentLoad = unref(lastLoad); const currentLoad = unref(lastLoad);
options.value = []; options.value = [];
@ -188,7 +210,7 @@
/** /**
* 初始化字典下拉数据 * 初始化字典下拉数据
*/ */
async function initDictData() { async function initDictTableData() {
let { dict, async, dictOptions, pageSize } = props; let { dict, async, dictOptions, pageSize } = props;
if (!async) { if (!async) {
// //
@ -231,6 +253,14 @@
} }
} }
} }
/**
* 查询数据字典
*/
async function initDictCodeData() {
options.value = await initDictOptions(props.dict);
}
/** /**
* 同步改变事件 * 同步改变事件
* */ * */
@ -286,7 +316,7 @@
if (typeof props.getPopupContainer === 'function') { if (typeof props.getPopupContainer === 'function') {
return props.getPopupContainer(node); return props.getPopupContainer(node);
} else { } else {
return node.parentNode; return node?.parentNode;
} }
} }
// update-end-author:taoyan date:20220407 for: getPopupContainer popContainer // update-end-author:taoyan date:20220407 for: getPopupContainer popContainer
@ -314,6 +344,7 @@
attrs, attrs,
options, options,
loading, loading,
isDictTable,
selectedValue, selectedValue,
selectedAsyncValue, selectedAsyncValue,
loadData: useDebounceFn(loadData, 800), loadData: useDebounceFn(loadData, 800),

View File

@ -2,7 +2,7 @@
<template> <template>
<div> <div>
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" @change="handleChange"/> <JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" @change="handleChange"/>
<DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" /> <DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :multiple="multiple" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">

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>
@ -68,6 +68,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 }) {
@ -118,7 +122,7 @@
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); return document.querySelector(props.popContainer);
} }
@ -135,7 +139,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 +166,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

@ -30,7 +30,7 @@
}, },
rowKey: { rowKey: {
type: String, type: String,
default: 'code', default: 'id',
}, },
params: { params: {
type: Object, type: Object,

View File

@ -2,7 +2,7 @@
<template> <template>
<div> <div>
<JSelectBiz @change="handleChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz> <JSelectBiz @change="handleChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<UserSelectModal :rowKey="rowKey" @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></UserSelectModal> <UserSelectModal :rowKey="rowKey" @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :excludeUserIdList="excludeUserIdList"></UserSelectModal>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -37,6 +37,13 @@
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
//id
excludeUserIdList:{
type: Array,
default: () => [],
}
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
}, },
emits: ['options-change', 'change', 'update:value'], emits: ['options-change', 'change', 'update:value'],
setup(props, { emit }) { setup(props, { emit }) {
@ -84,6 +91,17 @@
} }
}); });
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
const excludeUserIdList = ref<any>([]);
/**
* 需要监听一下excludeUserIdList否则modal获取不到
*/
watch(()=>props.excludeUserIdList,(data)=>{
excludeUserIdList.value = data;
},{ immediate: true })
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
/** /**
* 打卡弹出框 * 打卡弹出框
*/ */
@ -141,6 +159,7 @@
regModal, regModal,
setValue, setValue,
handleOpen, handleOpen,
excludeUserIdList,
handleChange, handleChange,
}; };
}, },

View File

@ -41,12 +41,14 @@
() => props.value, () => props.value,
(val) => { (val) => {
if (!props.query) { if (!props.query) {
if (!val) { // update-begin--author:liaozhiyang---date:20231226---forQQYUN-7473options使[0,1]
if (!val && !props.options.includes(val)) {
checked.value = false; checked.value = false;
emitValue(props.options[1]); emitValue(props.options[1]);
} else { } else {
checked.value = props.options[0] == val; checked.value = props.options[0] == val;
} }
// update-end--author:liaozhiyang---date:20231226---forQQYUN-7473options使[0,1]
} }
}, },
{ immediate: true } { immediate: true }

View File

@ -3,7 +3,7 @@
allowClear allowClear
labelInValue labelInValue
style="width: 100%" style="width: 100%"
:getPopupContainer="(node) => node.parentNode" :getPopupContainer="(node) => node?.parentNode"
:dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }" :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
:placeholder="placeholder" :placeholder="placeholder"
:loadData="asyncLoadTreeData" :loadData="asyncLoadTreeData"

View File

@ -17,7 +17,7 @@
<div class="ant-upload-text">{{ text }}</div> <div class="ant-upload-text">{{ text }}</div>
</div> </div>
</template> </template>
<a-button v-else-if="buttonVisible" :disabled="isMaxCount || disabled"> <a-button v-else-if="buttonVisible" :disabled="buttonDisabled">
<Icon icon="ant-design:upload-outlined" /> <Icon icon="ant-design:upload-outlined" />
<span>{{ text }}</span> <span>{{ text }}</span>
</a-button> </a-button>
@ -36,7 +36,7 @@
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 { UploadTypeEnum } from './upload.data'; import { UploadTypeEnum } from './upload.data';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl, getHeaders } from '/@/utils/common/compUtils';
import UploadItemActions from './components/UploadItemActions.vue'; import UploadItemActions from './components/UploadItemActions.vue';
const { createMessage, createConfirm } = useMessage(); const { createMessage, createConfirm } = useMessage();
@ -67,11 +67,11 @@
removeConfirm: propTypes.bool.def(false), removeConfirm: propTypes.bool.def(false),
beforeUpload: propTypes.func, beforeUpload: propTypes.func,
disabled: propTypes.bool.def(false), disabled: propTypes.bool.def(false),
//
replaceLastOne: propTypes.bool.def(false),
}); });
const headers = reactive({ const headers = getHeaders();
'X-Access-Token': getToken(),
});
const fileList = ref<any[]>([]); const fileList = ref<any[]>([]);
const uploadGoOn = ref<boolean>(true); const uploadGoOn = ref<boolean>(true);
// refs // refs
@ -80,6 +80,20 @@
const isMaxCount = computed(() => props.maxCount > 0 && fileList.value.length >= props.maxCount); const isMaxCount = computed(() => props.maxCount > 0 && fileList.value.length >= props.maxCount);
// //
const isImageMode = computed(() => props.fileType === UploadTypeEnum.image); const isImageMode = computed(() => props.fileType === UploadTypeEnum.image);
//
const buttonDisabled = computed(()=>{
if(props.disabled === true){
return true;
}
if(isMaxCount.value === true){
if(props.replaceLastOne === true){
return false
}else{
return true;
}
}
return false
});
// props attrs // props attrs
const bindProps = computed(() => { const bindProps = computed(() => {
//update-begin-author:liusq date:20220411 for: [issue/455]accept //update-begin-author:liusq date:20220411 for: [issue/455]accept
@ -112,7 +126,13 @@
parseArrayValue(val); parseArrayValue(val);
} }
} else { } else {
parsePathsValue(val); //update-begin---author:liusq ---date:20230914 for[issues/5327]UploadreturnUrlfalse'[object Object]' ------------
if (props.returnUrl) {
parsePathsValue(val);
} else {
val && parseArrayValue(JSON.parse(val));
}
//update-end---author:liusq ---date:20230914 for[issues/5327]UploadreturnUrlfalse'[object Object]' ------------
} }
}, },
{ immediate: true } { immediate: true }
@ -305,7 +325,9 @@
return; return;
} }
} }
emitValue(newFileList); //update-begin---author:liusq ---date:20230914 for[issues/5327]UploadreturnUrlfalse'[object Object]' ------------
emitValue(JSON.stringify(newFileList));
//update-end---author:liusq ---date:20230914 for[issues/5327]UploadreturnUrlfalse'[object Object]' ------------
} }
} }
} }

View File

@ -1,7 +1,7 @@
<!--部门选择框--> <!--部门选择框-->
<template> <template>
<div> <div>
<BasicModal v-bind="$attrs" @register="register" :title="modalTitle" width="500px" @ok="handleOk" destroyOnClose @visible-change="visibleChange"> <BasicModal v-bind="$attrs" @register="register" :title="modalTitle" width="500px" :maxHeight="maxHeight" @ok="handleOk" destroyOnClose @visible-change="visibleChange">
<BasicTree <BasicTree
ref="treeRef" ref="treeRef"
:treeData="treeData" :treeData="treeData"
@ -11,6 +11,7 @@
@check="onCheck" @check="onCheck"
:fieldNames="fieldNames" :fieldNames="fieldNames"
:checkedKeys="checkedKeys" :checkedKeys="checkedKeys"
:multiple="multiple"
:checkStrictly="getCheckStrictly" :checkStrictly="getCheckStrictly"
/> />
<!--树操作部分--> <!--树操作部分-->
@ -39,6 +40,7 @@
import { BasicTree, TreeActionType } from '/@/components/Tree'; import { BasicTree, TreeActionType } from '/@/components/Tree';
import { useTreeBiz } from '/@/components/Form/src/jeecg/hooks/useTreeBiz'; import { useTreeBiz } from '/@/components/Form/src/jeecg/hooks/useTreeBiz';
import {propTypes} from "/@/utils/propTypes"; import {propTypes} from "/@/utils/propTypes";
import { omit } from 'lodash-es';
export default defineComponent({ export default defineComponent({
name: 'DeptSelectModal', name: 'DeptSelectModal',
@ -53,6 +55,12 @@
type: String, type: String,
default: '部门选择', default: '部门选择',
}, },
// update-begin--author:liaozhiyang---date:20231220---forQQYUN-7678
maxHeight: {
type: Number,
default: 500,
},
// 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'],
@ -65,13 +73,14 @@
//update-begin-author:taoyan date:2022-10-28 for: //update-begin-author:taoyan date:2022-10-28 for:
let propValue = props.value === ''?[]:props.value; let propValue = props.value === ''?[]:props.value;
//update-begin-author:liusq date:2023-05-26 for: [issues/538]JSelectDept dynamicDisabled //update-begin-author:liusq date:2023-05-26 for: [issues/538]JSelectDept dynamicDisabled
const getBindValue = Object.assign({}, unref(props), unref(attrs), {value: propValue},{disabled: false}); let temp = Object.assign({}, unref(props), unref(attrs), {value: propValue},{disabled: false});
const getBindValue = omit(temp, 'multiple');
//update-end-author:liusq date:2023-05-26 for: [issues/538]JSelectDept dynamicDisabled //update-end-author:liusq date:2023-05-26 for: [issues/538]JSelectDept dynamicDisabled
//update-end-author:taoyan date:2022-10-28 for: //update-end-author:taoyan date:2022-10-28 for:
const queryUrl = getQueryUrl(); const queryUrl = getQueryUrl();
const [{ visibleChange, checkedKeys, getCheckStrictly, getSelectTreeData, onCheck, onLoadData, treeData, checkALL, expandAll, onSelect }] = const [{ visibleChange, checkedKeys, getCheckStrictly, getSelectTreeData, onCheck, onLoadData, treeData, checkALL, expandAll, onSelect }] =
useTreeBiz(treeRef, queryUrl, getBindValue); useTreeBiz(treeRef, queryUrl, getBindValue, props);
const searchInfo = ref(props.params); const searchInfo = ref(props.params);
const tree = ref([]); const tree = ref([]);
//treeNodekeytreeData //treeNodekeytreeData

View File

@ -151,10 +151,12 @@
watch( watch(
() => props.param, () => props.param,
() => { () => {
if (visible) { // update-begin--author:liaozhiyang---date:20231213---forissues/901JPopupparam
if (visible.value) {
dynamicParamHandler(); dynamicParamHandler();
loadData(); loadData();
} }
// update-end--author:liaozhiyang---date:20231213---forissues/901JPopupparam
} }
); );
/** /**
@ -202,6 +204,9 @@
closeModal(); closeModal();
checkedKeys.value = []; checkedKeys.value = [];
selectRows.value = []; selectRows.value = [];
// update-begin--author:liaozhiyang---date:20230908---forissues/742
tableRef.value.clearSelectedRowKeys();
// update-end--author:liaozhiyang---date:20230908---forissues/742
} }
/** /**
@ -282,7 +287,7 @@
white-space: nowrap; white-space: nowrap;
} }
} }
:deep .jeecg-basic-table .ant-table-wrapper .ant-table-title { :deep(.jeecg-basic-table .ant-table-wrapper .ant-table-title){
min-height: 0; min-height: 0;
} }
</style> </style>

View File

@ -5,7 +5,7 @@
v-bind="$attrs" v-bind="$attrs"
@register="register" @register="register"
:title="modalTitle" :title="modalTitle"
width="900px" width="1100px"
wrapClassName="j-user-select-modal" wrapClassName="j-user-select-modal"
@ok="handleOk" @ok="handleOk"
destroyOnClose destroyOnClose
@ -78,7 +78,8 @@
canResize: false, canResize: false,
bordered: true, bordered: true,
size: 'small', size: 'small',
rowKey: 'code', //rowKey,
rowKey: props.rowKey,
}; };
const getBindValue = Object.assign({}, unref(props), unref(attrs), config); const getBindValue = Object.assign({}, unref(props), unref(attrs), config);
const [{ rowSelection, visibleChange, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows }] = useSelectBiz( const [{ rowSelection, visibleChange, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows }] = useSelectBiz(
@ -89,7 +90,7 @@
//form //form
const formConfig = { const formConfig = {
labelCol: { labelCol: {
span: 8, span: 4,
}, },
baseColProps: { baseColProps: {
xs: 24, xs: 24,
@ -99,6 +100,16 @@
xl: 10, xl: 10,
xxl: 10, xxl: 10,
}, },
//update-begin-author:liusq date:2023-10-30 for: [issues/5514]
actionColOptions: {
xs: 24,
sm: 8,
md: 8,
lg: 8,
xl: 8,
xxl: 8,
},
//update-end-author:liusq date:2023-10-30 for: [issues/5514]
schemas: [ schemas: [
{ {
label: '职务名称', label: '职务名称',
@ -176,6 +187,7 @@
selectedTable, selectedTable,
selectRows, selectRows,
handleDeleteSelected, handleDeleteSelected,
searchInfo,
}; };
}, },
}); });

View File

@ -67,11 +67,21 @@
xl: 14, xl: 14,
xxl: 14, xxl: 14,
}, },
//update-begin-author:liusq date:2023-10-30 for: [issues/5514]
actionColOptions: {
xs: 24,
sm: 8,
md: 8,
lg: 8,
xl: 8,
xxl: 8,
},
//update-end-author:liusq date:2023-10-30 for: [issues/5514]
schemas: [ schemas: [
{ {
label: '角色名称', label: '角色名称',
field: 'roleName', field: 'roleName',
component: 'JInput', component: 'Input',
}, },
], ],
}; };

View File

@ -110,6 +110,16 @@
xl: 6, xl: 6,
xxl: 10, xxl: 10,
}, },
//update-begin-author:liusq date:2023-10-30 for: [issues/5514]
actionColOptions: {
xs: 24,
sm: 12,
md: 12,
lg: 12,
xl: 8,
xxl: 8,
},
//update-end-author:liusq date:2023-10-30 for: [issues/5514]
schemas: [ schemas: [
{ {
label: '账号', label: '账号',

View File

@ -5,7 +5,7 @@
v-bind="$attrs" v-bind="$attrs"
@register="register" @register="register"
:title="modalTitle" :title="modalTitle"
width="900px" :width="showSelected ? '1200px' : '900px'"
wrapClassName="j-user-select-modal" wrapClassName="j-user-select-modal"
@ok="handleOk" @ok="handleOk"
destroyOnClose destroyOnClose
@ -24,6 +24,7 @@
:searchInfo="searchInfo" :searchInfo="searchInfo"
:rowSelection="rowSelection" :rowSelection="rowSelection"
:indexColumnProps="indexColumnProps" :indexColumnProps="indexColumnProps"
:afterFetch="afterFetch"
> >
<!-- update-begin-author:taoyan date:2022-5-25 for: VUEN-1112一对多 用户选择 未显示选择条数及清空 --> <!-- update-begin-author:taoyan date:2022-5-25 for: VUEN-1112一对多 用户选择 未显示选择条数及清空 -->
<template #tableTitle></template> <template #tableTitle></template>
@ -48,7 +49,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, unref, ref } from 'vue'; import { defineComponent, unref, ref, watch } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { getUserList } from '/@/api/common/api'; import { getUserList } from '/@/api/common/api';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
@ -72,6 +73,13 @@
type: String, type: String,
default: '选择用户', default: '选择用户',
}, },
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
//id
excludeUserIdList: {
type: Array,
default: [],
},
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
}, },
emits: ['register', 'getSelectResult'], emits: ['register', 'getSelectResult'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
@ -107,6 +115,15 @@
getBindValue getBindValue
); );
const searchInfo = ref(props.params); const searchInfo = ref(props.params);
// update-begin--author:liaozhiyang---date:20230811---forissues/657
watch(rowSelection.selectedRowKeys, (newVal) => {
//update-begin---author:wangshuai ---date: 20230829 fornull------------
if(tableRef.value){
tableRef.value.setSelectedRowKeys(newVal);
}
//update-end---author:wangshuai ---date: 20230829 fornull------------
});
// update-end--author:liaozhiyang---date:20230811---forissues/657
//form //form
const formConfig = { const formConfig = {
baseColProps: { baseColProps: {
@ -209,6 +226,29 @@
closeModal(); closeModal();
}); });
} }
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
/**
* 用户返回结果逻辑查询
*/
function afterFetch(record) {
let excludeList = props.excludeUserIdList;
if(!excludeList){
return record;
}
let arr:any[] = [];
//id
if(excludeList.length>0 && record && record.length>0){
for(let item of record){
if(excludeList.indexOf(item.id)<0){
arr.push({...item})
}
}
return arr;
}
return record;
}
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
return { return {
//config, //config,
@ -227,6 +267,7 @@
handleDeleteSelected, handleDeleteSelected,
tableScroll, tableScroll,
tableRef, tableRef,
afterFetch,
}; };
}, },
}); });

View File

@ -0,0 +1,232 @@
<template>
<div>
<div @click="showModal" :class="disabled ? 'select-input disabled-select' : 'select-input'">
<template v-if="selectedList.length > 0">
<template v-for="(item, index) in selectedList">
<SelectedUserItem v-if="index < maxCount" :info="item" @unSelect="unSelect" query />
</template>
</template>
<span v-else style="height: 30px; line-height: 30px; display: inline-block; margin-left: 7px; color: #bfbfbf">请选择</span>
<div v-if="ellipsisInfo.status" class="user-selected-item">
<div class="user-select-ellipsis">
<span style="color: red">+{{ ellipsisInfo.count }}...</span>
</div>
</div>
</div>
<RoleSelectModal :appId="currentAppId" :multi="multi" :getContainer="getContainer" title="选择组织角色" @register="registerRoleModal" @selected="onSelected" />
</div>
</template>
<script lang="ts">
import { useModal } from '/@/components/Modal';
import { defHttp } from '/@/utils/http/axios';
import { computed, ref, watch, watchEffect, defineComponent } from 'vue';
import RoleSelectModal from './RoleSelectModal.vue';
import SelectedUserItem from '../userSelect/SelectedUserItem.vue';
import { Form } from 'ant-design-vue';
import { useUserStore } from '/@/store/modules/user';
const maxCount = 2;
export default defineComponent({
name: 'RoleSelectInput',
components: {
RoleSelectModal,
SelectedUserItem,
},
props: {
disabled: {
type: Boolean,
default: false,
},
store: {
type: String,
default: 'id',
},
value: {
type: String,
default: '',
},
multi: {
type: Boolean,
default: false,
},
getContainer: {
type: Function,
default: null,
},
appId: {
type: String,
default: '',
},
},
emits: ['update:value', 'change'],
setup(props, { emit }) {
const formItemContext = Form.useInjectFormItemContext();
const selectedList = ref<any[]>([]);
const loading = ref(true);
const [registerRoleModal, { openModal: openRoleModal, closeModal: closeRoleModal }] = useModal();
function showModal(e) {
e.preventDefault();
e.stopPropagation();
let list = selectedList.value.map((item) => item.id);
openRoleModal(true, {
list,
});
}
const ellipsisInfo = computed(() => {
let max = maxCount;
let len = selectedList.value.length;
if (len > max) {
return { status: true, count: len - max };
} else {
return { status: false };
}
});
function unSelect(id) {
console.log('unSelectUser', id);
loading.value = false;
let arr = selectedList.value;
let index = -1;
for (let i = 0; i < arr.length; i++) {
if (arr[i].id == id) {
index = i;
break;
}
}
if (index >= 0) {
arr.splice(index, 1);
selectedList.value = arr;
onSelectedChange();
}
}
function onSelectedChange() {
let temp: any[] = [];
let arr = selectedList.value;
if (arr && arr.length > 0) {
temp = arr.map((k) => {
return k[props.store];
});
}
let str = temp.join(',');
emit('update:value', str);
emit('change', str);
formItemContext.onFieldChange();
console.log('选中数据', str);
}
function onSelected(_v, values) {
console.log('角色选择完毕:', values);
loading.value = false;
if (values && values.length > 0) {
selectedList.value = values;
} else {
selectedList.value = [];
}
onSelectedChange();
closeRoleModal();
}
//
const currentAppId = ref('');
const userStore = useUserStore();
watchEffect(() => {
let tenantId = userStore.getTenant;
let appId = props.appId;
if (appId) {
currentAppId.value = appId;
} else {
currentAppId.value = new Date().getTime() + '-' + tenantId;
}
});
watch(
() => props.value,
async (val) => {
if (val) {
if (loading.value === true) {
await getRoleList(val);
}
} else {
selectedList.value = [];
}
loading.value = true;
},
{ immediate: true }
);
/**
* 获取角色列表
* @param ids
*/
async function getRoleList(ids) {
const url = '/sys/role/listByTenant';
let params = {
[props.store]: ids,
pageSize: 200
};
// roleCode
if (props.store === 'code') {
params.roleCode = ids;
}
selectedList.value = [];
const data = await defHttp.get({ url, params }, { isTransformResponse: false });
console.log('getRoleList>>', data);
if (data.success) {
const { records } = data.result;
let arr: any[] = [];
if (records && records.length > 0) {
for (let item of records) {
arr.push({
id: item.id,
name: item.name || item.roleName,
code: item.roleCode,
checked: true,
selectType: 'sys_role',
});
}
}
selectedList.value = arr;
} else {
console.error(data.message);
}
}
return {
selectedList,
ellipsisInfo,
maxCount,
registerRoleModal,
closeRoleModal,
showModal,
onSelected,
unSelect,
currentAppId,
};
},
});
</script>
<style scoped lang="less">
.select-input {
padding: 0 5px;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 3px;
box-sizing: border-box;
display: flex;
color: #9e9e9e;
font-size: 14px;
flex-wrap: nowrap;
min-height: 32px;
overflow-x: hidden;
&.disabled-select {
cursor: not-allowed;
background-color: #f5f5f5 !important;
}
}
</style>

View File

@ -99,19 +99,25 @@
// //
const [register] = useModalInner(() => { const [register] = useModalInner((data) => {
let list = dataList.value; let list = dataList.value;
if(!list || list.length ==0 ){ if(!list || list.length ==0 ){
} }else{
for(let item of list){ let selectedIdList = data.list || [];
item.checked = false for(let item of list){
if(selectedIdList.indexOf(item.id)>=0){
item.checked = true;
}else{
item.checked = false;
}
}
} }
}); });
// //
function handleOk() { function handleOk() {
let arr = toRaw(selectedIdList.value); let arr = toRaw(selectedIdList.value);
emit('selected', arr); emit('selected', arr, toRaw(selectedList.value));
} }
const dataList = ref<any[]>([]); const dataList = ref<any[]>([]);
@ -161,6 +167,7 @@
arr.push({ arr.push({
id: item.id, id: item.id,
name: item.name || item.roleName, name: item.name || item.roleName,
code: item.roleCode,
selectType: props.type, selectType: props.type,
checked: false checked: false
}) })
@ -177,6 +184,13 @@
function onSelect(e, item) { function onSelect(e, item) {
prevent(e); prevent(e);
console.log('onselect'); console.log('onselect');
// false
if(props.multi === false){
let list = dataList.value;
for(let item of list){
item.checked = false;
}
}
item.checked = !item.checked; item.checked = !item.checked;
} }

View File

@ -14,6 +14,12 @@
<span style="width: 24px; height: 24px; line-height: 20px; margin-right: 3px; display: inline-block"> <span style="width: 24px; height: 24px; line-height: 20px; margin-right: 3px; display: inline-block">
<a-avatar v-if="info.avatar" :src="getFileAccessHttpUrl(info.avatar)" :size="24"></a-avatar> <a-avatar v-if="info.avatar" :src="getFileAccessHttpUrl(info.avatar)" :size="24"></a-avatar>
<a-avatar v-else-if="info.avatarIcon" class="ant-btn-primary" :size="24" >
<template #icon>
<Icon :icon=" 'ant-design:'+info.avatarIcon " style="font-size: 16px;margin-top: 4px"/>
</template>
</a-avatar>
<a-avatar v-else-if="info.selectType == 'sys_role'" :size="24" style="background-color: rgb(255, 173, 0);"> <a-avatar v-else-if="info.selectType == 'sys_role'" :size="24" style="background-color: rgb(255, 173, 0);">
<template #icon> <template #icon>
<team-outlined style="font-size: 16px"/> <team-outlined style="font-size: 16px"/>

View File

@ -3,11 +3,17 @@
<template #renderItem="{ item }"> <template #renderItem="{ item }">
<a-list-item style="padding: 3px 0"> <a-list-item style="padding: 3px 0">
<div class="user-select-user-info" @click="(e) => onClickUser(e, item)"> <div class="user-select-user-info" @click="(e) => onClickUser(e, item)">
<div> <div style="margin-left: 10px">
<a-checkbox v-model:checked="checkStatus[item.id]" /> <a-checkbox v-model:checked="checkStatus[item.id]" v-if="multi" />
<a-radio v-model:checked="checkStatus[item.id]" v-else />
</div> </div>
<div> <div>
<a-avatar v-if="item.avatar" :src="getFileAccessHttpUrl(item.avatar)"></a-avatar> <a-avatar v-if="item.avatar" :src="getFileAccessHttpUrl(item.avatar)"></a-avatar>
<a-avatar v-else-if="item.avatarIcon" class="ant-btn-primary">
<template #icon>
<Icon :icon=" 'ant-design:'+item.avatarIcon " style="margin-top: 4px;font-size: 24px;"/>
</template>
</a-avatar>
<a-avatar v-else> <a-avatar v-else>
<template #icon><UserOutlined /></template> <template #icon><UserOutlined /></template>
</a-avatar> </a-avatar>
@ -15,9 +21,10 @@
<div :style="nameStyle"> <div :style="nameStyle">
{{ item.realname }} {{ item.realname }}
</div> </div>
<div :style="departStyle"> <div :style="departStyle" class="ellipsis" :title="item.orgCodeTxt">
{{ item.orgCodeTxt }} {{ item.orgCodeTxt }}
</div> </div>
<div style="width: 1px"></div>
</div> </div>
</a-list-item> </a-list-item>
</template> </template>
@ -32,6 +39,10 @@
export default { export default {
name: 'UserList', name: 'UserList',
props: { props: {
multi: {
type: Boolean,
default: false,
},
dataList: { dataList: {
type: Array, type: Array,
default: () => [], default: () => [],
@ -126,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;
@ -139,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;
}); });
@ -166,10 +178,16 @@
<style lang="less"> <style lang="less">
.user-select-user-info { .user-select-user-info {
display: flex; display: flex;
width: 100%;
> div { > div {
height: 36px; height: 36px;
line-height: 36px; line-height: 36px;
margin-right: 10px; margin-right: 10px;
} }
.ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
} }
</style> </style>

View File

@ -12,12 +12,15 @@
v-model:expandedKeys="expandedKeys" v-model:expandedKeys="expandedKeys"
@select="onSelect" @select="onSelect"
> >
<template #title="{ title, key }">
<FolderFilled style="color: #9e9e9e"/><span style="margin-left: 5px">{{ title }}</span>
</template>
</a-tree> </a-tree>
</div> </div>
</a-col> </a-col>
<a-col :span="12" style="padding-left: 10px"> <a-col :span="12" style="padding-left: 10px">
<div :style="containerStyle"> <div :style="containerStyle">
<user-list :excludeUserIdList="excludeUserIdList" :dataList="userDataList" :selectedIdList="selectedIdList" @selected="onSelectUser" @unSelect="unSelectUser" /> <user-list :multi="multi" :excludeUserIdList="excludeUserIdList" :dataList="userDataList" :selectedIdList="selectedIdList" @selected="onSelectUser" @unSelect="unSelectUser" />
</div> </div>
</a-col> </a-col>
</a-row> </a-row>
@ -27,11 +30,13 @@
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import UserList from './UserList.vue'; import UserList from './UserList.vue';
import { FolderFilled } from '@ant-design/icons-vue';
export default { export default {
name: 'DepartUserList', name: 'DepartUserList',
components: { components: {
UserList, UserList,
FolderFilled
}, },
props: { props: {
searchText: { searchText: {
@ -45,6 +50,10 @@
excludeUserIdList:{ excludeUserIdList:{
type: Array, type: Array,
default: () => [], default: () => [],
},
multi: {
type: Boolean,
default: false,
} }
}, },
emits: ['loaded', 'selected', 'unSelect'], emits: ['loaded', 'selected', 'unSelect'],
@ -132,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;
@ -140,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

@ -2,12 +2,16 @@
<a-row> <a-row>
<a-col :span="12"> <a-col :span="12">
<div :style="containerStyle"> <div :style="containerStyle">
<a-tree v-if="treeData.length > 0" showIcon :treeData="treeData" :selectedKeys="selectedKeys" @select="onSelect"> </a-tree> <a-tree v-if="treeData.length > 0" showIcon :treeData="treeData" :selectedKeys="selectedKeys" @select="onSelect">
<template #title="{ title, key }">
<UserOutlined style="color: #9e9e9e"/><span style="margin-left: 5px">{{ title }}</span>
</template>
</a-tree>
</div> </div>
</a-col> </a-col>
<a-col :span="12" style="padding-left: 10px"> <a-col :span="12" style="padding-left: 10px">
<div :style="containerStyle"> <div :style="containerStyle">
<user-list :excludeUserIdList="excludeUserIdList" :dataList="userDataList" :selectedIdList="selectedIdList" @selected="onSelectUser" @unSelect="unSelectUser" /> <user-list :multi="multi" :excludeUserIdList="excludeUserIdList" :dataList="userDataList" :selectedIdList="selectedIdList" @selected="onSelectUser" @unSelect="unSelectUser" />
</div> </div>
</a-col> </a-col>
</a-row> </a-row>
@ -17,11 +21,13 @@
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import UserList from './UserList.vue'; import UserList from './UserList.vue';
import { UserOutlined } from '@ant-design/icons-vue';
export default { export default {
name: 'RoleUserList', name: 'RoleUserList',
components: { components: {
UserList, UserList,
UserOutlined
}, },
props: { props: {
searchText: { searchText: {
@ -35,6 +41,10 @@
excludeUserIdList:{ excludeUserIdList:{
type: Array, type: Array,
default: () => [], default: () => [],
},
multi: {
type: Boolean,
default: false,
} }
}, },
emits: ['selected', 'unSelect'], emits: ['selected', 'unSelect'],
@ -80,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;
@ -88,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

@ -35,7 +35,7 @@
<a-tabs v-model:activeKey="myActiveKey" :centered="true" @change="onChangeTab"> <a-tabs v-model:activeKey="myActiveKey" :centered="true" @change="onChangeTab">
<!-- 所有用户 --> <!-- 所有用户 -->
<a-tab-pane key="1" tab="全部" forceRender> <a-tab-pane key="1" tab="全部" forceRender>
<user-list :excludeUserIdList="excludeUserIdList" :dataList="userDataList" :selectedIdList="selectedIdList" depart @selected="onSelectUser" @unSelect="unSelectUser" /> <user-list :multi="multi" :excludeUserIdList="excludeUserIdList" :dataList="userDataList" :selectedIdList="selectedIdList" depart @selected="onSelectUser" @unSelect="unSelectUser" />
</a-tab-pane> </a-tab-pane>
<!-- 部门用户 --> <!-- 部门用户 -->
@ -92,8 +92,10 @@
const APagination = Pagination; const APagination = Pagination;
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { computed, ref, toRaw } from 'vue'; import {computed, ref, toRaw, unref} from 'vue';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
import { mySelfData } from './useUserSelect'
export default { export default {
name: 'UserSelectModal', name: 'UserSelectModal',
components: { components: {
@ -120,6 +122,11 @@
type: Boolean, type: Boolean,
default: false, default: false,
}, },
//
inSuperQuery:{
type: Boolean,
default: false,
}
}, },
emits: ['selected', 'register'], emits: ['selected', 'register'],
setup(props, { emit }) { setup(props, { emit }) {
@ -154,6 +161,8 @@
if (props.izExcludeMy) { if (props.izExcludeMy) {
excludeUserIdList.value.push(userStore.getUserInfo.id); excludeUserIdList.value.push(userStore.getUserInfo.id);
} }
//
loadUserList();
}); });
// //
@ -213,16 +222,31 @@
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) {
const { records, total } = data.result; let { records, total } = data.result;
totalRecord.value = total; totalRecord.value = total;
initCurrentUserData(records);
userDataList.value = records; userDataList.value = records;
} else { } else {
console.error(data.message); console.error(data.message);
} }
console.log('loadUserList', data); console.log('loadUserList', data);
} }
//
function initCurrentUserData(records) {
if(pageNo.value==1 && props.inSuperQuery === true){
records.unshift({...mySelfData})
}
}
/*--------------加载数据---------------*/ /*--------------加载数据---------------*/
/*--------------选中/取消选中---------------*/ /*--------------选中/取消选中---------------*/

View File

@ -19,7 +19,7 @@
<a-button v-if="showAddButton" shape="circle" @click="onShowModal"><PlusOutlined /></a-button> <a-button v-if="showAddButton" shape="circle" @click="onShowModal"><PlusOutlined /></a-button>
</div> </div>
<user-select-modal :multi="multi" :getContainer="getContainer" @register="registerModal" @selected="onSelected" :izExcludeMy="izExcludeMy"></user-select-modal> <user-select-modal :inSuperQuery="inSuperQuery" :multi="multi" :getContainer="getContainer" @register="registerModal" @selected="onSelected" :izExcludeMy="izExcludeMy"></user-select-modal>
</div> </div>
</template> </template>
@ -31,6 +31,7 @@
import UserSelectModal from './UserSelectModal.vue'; import UserSelectModal from './UserSelectModal.vue';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import SelectedUserItem from './SelectedUserItem.vue'; import SelectedUserItem from './SelectedUserItem.vue';
import { mySelfExpress, mySelfData } from './useUserSelect'
export default defineComponent({ export default defineComponent({
name: 'UserSelect', name: 'UserSelect',
@ -74,6 +75,11 @@
izExcludeMy:{ izExcludeMy:{
type: Boolean, type: Boolean,
default: false, default: false,
},
//
inSuperQuery:{
type: Boolean,
default: false,
} }
}, },
emits: ['update:value', 'change'], emits: ['update:value', 'change'],
@ -150,19 +156,41 @@
); );
async function getUserList(ids) { async function getUserList(ids) {
const url = '/sys/user/list'; let hasUserExpress = false;
let params = { let paramIds = ids;
[props.store]: ids, let idList = [];
};
selectedUserList.value = []; selectedUserList.value = [];
const data = await defHttp.get({ url, params }, { isTransformResponse: false }); if(ids){
if (data.success) { // update-begin-author:sunjianlei date:20230330 for:
const { records } = data.result; let tempArray = ids.split(',').map(s => s.trim()).filter(s => s != '');
selectedUserList.value = records; if (tempArray.includes(mySelfExpress)) {
} else { hasUserExpress = true;
console.error(data.message); idList = tempArray.filter(item => item != mySelfExpress);
} else {
idList = tempArray;
}
// update-end-author:sunjianlei date:20230330 for:
}
if(idList.length>0){
paramIds = idList.join(',')
const url = '/sys/user/list';
let params = {
[props.store]: paramIds,
};
const data = await defHttp.get({ url, params }, { isTransformResponse: false });
console.log('getUserList', data);
if (data.success) {
const { records } = data.result;
selectedUserList.value = records;
} else {
console.error(data.message);
}
}
if(hasUserExpress){
let temp = selectedUserList.value;
temp.push({...mySelfData})
} }
console.log('getUserList', data);
} }
const showAddButton = computed(() => { const showAddButton = computed(() => {

View File

@ -0,0 +1,11 @@
/**
*
*/
export const mySelfExpress = '#{sys_user_code}';
/**
*
*/
export const mySelfData = {
id: mySelfExpress, username: mySelfExpress, realname: '当前用户', avatarIcon: 'idcard-outlined', avatarColor: 'rgb(75 176 79)'
}

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