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_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

View File

@ -4,17 +4,14 @@ VITE_USE_MOCK = true
# 发布路径
VITE_PUBLIC_PATH = /
# 跨域代理,您可以配置多个 ,请注意,没有换行符
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=

View File

@ -4,9 +4,6 @@ VITE_USE_MOCK = true
# 发布路径
VITE_PUBLIC_PATH = /
# 控制台不输出
VITE_DROP_CONSOLE = true
# 是否启用gzip或brotli压缩
# 选项值: gzip | brotli | none
# 如果需要多个可以使用“,”分隔
@ -16,19 +13,10 @@ VITE_BUILD_COMPRESS = 'gzip'
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_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
.idea
.svn
# .vscode
*.suo
*.ntvs*
@ -29,6 +30,7 @@ pnpm-debug.log*
*.sln
*.sw?
/os_del.cmd
os_del.cmd
/.vscode/
/.history/
/svn clear.bat

View File

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

View File

@ -1,18 +1,18 @@
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)
[![](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/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 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版本。
> 强大的代码生成器让前后端代码一键生成! JeecgBoot引领低代码开发模式(OnlineCoding-> 代码生成-> 手工MERGE) 帮助解决Java项目70%的重复工作,让开发更多关注业务。既能快速提高效率,节省成本,同时又不失灵活性
@ -31,10 +31,10 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue3、TypeScript 等新技术
##### 项目说明
| 项目名 | 说明 |
|--------------------|------------------------|
| `jeecgboot-vue3` | Vue3版前端代码 |
| `jeecg-boot` | SpringBoot后台项目支持微服务 |
| 项目名 | 说明 |
|--------------------|-----------------------------------------|
| `jeecgboot-vue3` | 前端源码Vue3版下载 |
| `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)
- 官方网站: [http://www.jeecg.com](http://www.jeecg.com)
- 官方文档:[https://help.jeecg.com](https://help.jeecg.com)
- 官方网站: [https://www.jeecg.com](https://www.jeecg.com)
- 快速入门:[快速入门](http://jeecg.com/doc/quickstart) | [常见问题](http://help.jeecg.com/qa.html) | [视频教程](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://help.jeecg.com/vue3/codegen/online.html)
- QQ交流群⑦791696430、683903138
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [Vue2演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)
- QQ交流群⑧825232878、⑦791696430(满)、683903138(满)
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)| [敲敲云零代码](https://www.qiaoqiaoyun.com)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取

View File

@ -1,11 +1,21 @@
import { generateAntColors, primaryColor } from '../config/themeConfig';
import { getThemeVariables } from 'ant-design-vue/dist/theme';
import { primaryColor } from '../config/themeConfig';
// import { getThemeVariables } from 'ant-design-vue/dist/theme';
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
*/
export function generateModifyVars(dark = false) {
export function generateModifyVars() {
const palettes = generateAntColors(primaryColor);
const primary = palettes[5];
@ -15,12 +25,14 @@ export function generateModifyVars(dark = false) {
primaryColorObj[`primary-${index + 1}`] = palettes[index];
}
const modifyVars = getThemeVariables({ dark });
const mapToken = defaultAlgorithm(defaultSeed);
const v3Token = convertLegacyToken(mapToken);
return {
...modifyVars,
...v3Token,
// ...modifyVars,
// Used for global import to avoid the need to import each style file separately
// 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,
...primaryColorObj,
'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 fs, { writeFileSync } from 'fs-extra';

View File

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

View File

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

View File

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

View File

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

View File

@ -57,7 +57,7 @@ export function configThemePlugin(isBuild: boolean): PluginOption[] {
vite_theme_plugin,
antdDarkThemePlugin({
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(), 'src/design/index.less'),
],

View File

@ -166,5 +166,16 @@
</div>
</div>
<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>
</html>

View File

@ -6,10 +6,19 @@ const demoList = (keyword, count = 20) => {
list: [] as any[],
};
for (let index = 0; index < count; index++) {
result.list.push({
name: `${keyword ?? ''}选项${index}`,
id: `${index}`,
});
//根据搜索关键词做一下匹配
let name = `选项${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;
};
@ -21,7 +30,7 @@ export default [
method: 'get',
response: ({ query }) => {
const { keyword,count} = query;
console.log(keyword);
console.log("查询条件:", keyword);
return resultSuccess(demoList(keyword,count));
},
},

View File

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

View File

@ -1,185 +1,159 @@
{
"name": "jeecgboot-vue3",
"version": "3.5.3",
"version": "3.6.3",
"author": {
"name": "jeecg",
"name": "北京国炬信息技术有限公司",
"email": "jeecgos@163.com",
"url": "https://github.com/jeecgboot/jeecgboot-vue3"
},
"scripts": {
"bootstrap": "pnpm install",
"serve": "npm run dev",
"dev": "vite",
"pinstall": "pnpm install",
"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:no-cache": "pnpm clean:cache && npm run build",
"report": "cross-env REPORT=true npm run build",
"type:check": "vue-tsc --noEmit --skipLibCheck",
"build:report": "pnpm clean:cache && cross-env REPORT=true npm run build",
"preview": "npm run build && vite preview",
"preview:dist": "vite preview",
"log": "conventional-changelog -p angular -i CHANGELOG.md -s",
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
"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"
"reinstall": "rimraf pnpm-lock.yaml && rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run install",
"clean:lib": "rimraf node_modules",
"gen:icon": "esno ./build/generate/icon/index.ts",
"batch:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"upgrade:log": "conventional-changelog -p angular -i CHANGELOG.md -s",
"husky:install": "husky install"
},
"dependencies": {
"@jeecg/online": "3.5.3-beta3",
"@qiaoqiaoyun/drag-free": "^1.0.52",
"@iconify/iconify": "^2.2.1",
"@ant-design/colors": "^6.0.0",
"@ant-design/icons-vue": "^6.1.0",
"@logicflow/core": "^1.1.13",
"@logicflow/extension": "^1.1.13",
"@vue/shared": "^3.2.33",
"@vue/runtime-core": "^3.2.33",
"@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",
"@jeecg/online": "3.6.2-beta",
"@iconify/iconify": "^3.1.1",
"@ant-design/colors": "^7.0.2",
"@ant-design/icons-vue": "^7.0.1",
"@vue/shared": "^3.3.4",
"@vueuse/core": "^10.7.1",
"@zxcvbn-ts/core": "^3.0.4",
"ant-design-vue": "^4.1.2",
"axios": "^1.6.4",
"china-area-data": "^5.0.1",
"clipboard": "^2.0.8",
"clipboard": "^2.0.11",
"codemirror": "^5.65.3",
"cron-parser": "^3.5.0",
"cropperjs": "^1.5.12",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.1",
"dom-align": "^1.12.2",
"echarts": "^5.3.2",
"emoji-mart-vue-fast": "^11.1.1",
"cron-parser": "^4.9.0",
"cropperjs": "^1.6.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"dom-align": "^1.12.4",
"echarts": "^5.4.3",
"emoji-mart-vue-fast": "^15.0.0",
"enquire.js": "^2.1.6",
"intro.js": "^5.1.0",
"intro.js": "^7.2.0",
"lodash-es": "^4.17.21",
"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",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"path-to-regexp": "^6.2.0",
"pinia": "2.0.12",
"path-to-regexp": "^6.2.1",
"pinia": "2.1.7",
"print-js": "^1.6.0",
"pinyin-pro": "^3.11.0",
"qs": "^6.10.3",
"qrcode": "^1.5.0",
"qrcodejs2": "0.0.2",
"qs": "^6.11.2",
"qrcode": "^1.5.3",
"resize-observer-polyfill": "^1.5.1",
"showdown": "^2.1.0",
"sortablejs": "^1.15.0",
"sortablejs": "^1.15.1",
"tinymce": "^5.10.3",
"vditor": "^3.8.13",
"vue": "^3.2.47",
"vue-cropper": "^0.5.6",
"vditor": "^3.9.8",
"vue": "^3.4.15",
"vue-cropper": "^0.6.4",
"vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.1.9",
"vue-i18n": "^9.8.0",
"vue-infinite-scroll": "^2.0.2",
"vue-print-nb-jeecg": "^1.0.12",
"vue-router": "^4.0.14",
"vue-types": "^4.1.1",
"vue-router": "^4.2.5",
"vue-types": "^5.1.1",
"vuedraggable": "^4.1.0",
"vxe-table": "4.1.0",
"vxe-table-plugin-antd": "3.0.5",
"xe-utils": "^3.3.1",
"vue-json-pretty": "^2.0.6",
"xss": "^1.0.13"
"vxe-table": "4.5.17",
"vxe-table-plugin-antd": "3.1.0",
"xe-utils": "3.5.14",
"xss": "^1.0.14"
},
"devDependencies": {
"@commitlint/cli": "^16.2.3",
"@commitlint/config-conventional": "^16.2.1",
"@iconify/json": "^2.1.30",
"@purge-icons/generated": "^0.8.1",
"@types/codemirror": "^5.60.5",
"@types/crypto-js": "^4.1.1",
"@types/fs-extra": "^9.0.13",
"@types/inquirer": "^8.2.1",
"@types/intro.js": "^3.0.2",
"@types/jest": "^27.0.2",
"@types/lodash-es": "^4.17.6",
"@types/mockjs": "^1.0.6",
"@types/node": "^17.0.25",
"@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.4.2",
"@types/qs": "^6.9.7",
"@types/pinyin": "^2.10.0",
"@types/showdown": "^1.9.4",
"@types/sortablejs": "^1.10.7",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"@vitejs/plugin-legacy": "^2.0.0",
"@vitejs/plugin-vue": "^3.0.1",
"@vitejs/plugin-vue-jsx": "^1.3.10",
"@vue/compiler-sfc": "^3.2.33",
"@vue/test-utils": "^2.0.0-rc.21",
"autoprefixer": "^10.4.4",
"commitizen": "^4.2.4",
"conventional-changelog-cli": "^2.2.2",
"@commitlint/cli": "^18.4.3",
"@commitlint/config-conventional": "^18.4.3",
"@iconify/json": "^2.2.164",
"@purge-icons/generated": "^0.10.0",
"@types/codemirror": "^5.60.15",
"@types/crypto-js": "^4.2.1",
"@types/fs-extra": "^11.0.4",
"@types/inquirer": "^9.0.7",
"@types/intro.js": "^5.1.5",
"@types/jest": "^29.5.11",
"@types/lodash-es": "^4.17.12",
"@types/mockjs": "^1.0.10",
"@types/node": "^20.10.6",
"@types/nprogress": "^0.2.3",
"@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.11",
"@types/showdown": "^2.0.6",
"@types/sortablejs": "^1.15.7",
"@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.17.0",
"@vitejs/plugin-vue": "^4.3.3",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "^3.4.4",
"@vue/test-utils": "^2.4.3",
"autoprefixer": "^10.4.16",
"commitizen": "^4.3.0",
"conventional-changelog-cli": "^4.1.0",
"cross-env": "^7.0.3",
"cz-git": "^1.3.9",
"czg": "^1.3.9",
"dotenv": "^16.0.0",
"eslint": "^8.22.0",
"eslint-config-prettier": "^8.6.0",
"eslint-define-config": "^1.14.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.9.0",
"esno": "^0.14.1",
"fs-extra": "^10.1.0",
"http-server": "^14.0.0",
"husky": "^7.0.4",
"inquirer": "^8.2.2",
"is-ci": "^3.0.0",
"jest": "^27.3.1",
"less": "^4.1.2",
"lint-staged": "12.3.7",
"cz-git": "^1.8.0",
"czg": "^1.8.0",
"dotenv": "^16.3.1",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-define-config": "^2.1.0",
"eslint-plugin-jest": "^27.6.1",
"eslint-plugin-prettier": "^5.1.2",
"eslint-plugin-vue": "^9.19.2",
"esno": "^4.0.0",
"fs-extra": "^11.2.0",
"http-server": "^14.1.1",
"husky": "^8.0.3",
"inquirer": "^9.2.12",
"is-ci": "^3.0.1",
"jest": "^29.7.0",
"less": "^4.2.0",
"lint-staged": "15.2.0",
"npm-run-all": "^4.1.5",
"picocolors": "^1.0.0",
"postcss": "^8.4.12",
"postcss-html": "^1.4.1",
"postcss": "^8.4.32",
"postcss-html": "^1.5.0",
"postcss-less": "^6.0.0",
"prettier": "^2.6.2",
"pretty-quick": "^3.1.1",
"rimraf": "^3.0.2",
"rollup": "^2.70.2",
"rollup-plugin-visualizer": "^5.6.0",
"stylelint": "^14.7.1",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-recommended": "^7.0.0",
"stylelint-config-recommended-vue": "^1.4.0",
"stylelint-config-standard": "^25.0.0",
"stylelint-order": "^5.0.0",
"ts-jest": "^27.0.7",
"ts-node": "^10.7.0",
"typescript": "^4.6.3",
"vite": "^3.2.3",
"prettier": "^3.1.1",
"pretty-quick": "^3.1.3",
"rimraf": "^5.0.5",
"rollup": "^4.9.2",
"rollup-plugin-visualizer": "^5.12.0",
"stylelint": "^16.1.0",
"stylelint-config-prettier": "^9.0.5",
"stylelint-config-recommended": "^14.0.0",
"stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard": "^36.0.0",
"stylelint-order": "^6.0.4",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"typescript": "^4.9.5",
"vite": "^4.4.9",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.0",
"vite-plugin-imagemin": "^0.6.1",
"vite-plugin-mkcert": "^1.10.1",
"vite-plugin-html": "^3.2.1",
"vite-plugin-mkcert": "^1.17.1",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-optimize-persist": "^0.1.2",
"vite-plugin-package-config": "^0.1.1",
"vite-plugin-purge-icons": "^0.8.2",
"vite-plugin-pwa": "^0.12.3",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-purge-icons": "^0.10.0",
"vite-plugin-svg-icons": "^2.0.1",
"@rys-fe/vite-plugin-theme": "^0.8.6",
"vite-plugin-vue-setup-extend-plus": "^0.1.0",
"vite-plugin-windicss": "^1.8.7",
"vue-eslint-parser": "^8.3.0",
"vue-tsc": "^0.33.9"
},
"resolutions": {
"bin-wrapper": "npm:bin-wrapper-china",
"rollup": "^2.72.0"
"unocss": "^0.58.3",
"vue-eslint-parser": "^9.3.2",
"vue-tsc": "^1.8.27"
},
"repository": {
"type": "git",
@ -189,69 +163,13 @@
"bugs": {
"url": "https://github.com/jeecgboot/jeecgboot-vue3/issues"
},
"homepage": "https://github.com/jeecgboot/jeecgboot-vue3",
"homepage": "https://www.jeecg.com",
"engines": {
"node": "^12 || >=14"
},
"vite": {
"optimizeDeps": {
"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/plugins/advlist",
"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>
<ConfigProvider :locale="getAntdLocale">
<ConfigProvider :theme="appTheme" :locale="getAntdLocale">
<AppProvider>
<RouterView />
</AppProvider>
@ -7,15 +7,73 @@
</template>
<script lang="ts" setup>
import { watch, ref } from 'vue';
import { theme } from 'ant-design-vue';
import { ConfigProvider } from 'ant-design-vue';
import { AppProvider } from '/@/components/Application';
import { useTitle } from '/@/hooks/web/useTitle';
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';
// support Multi-language
const { getAntdLocale } = useLocale();
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>
<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菜单
*/

View File

@ -85,7 +85,17 @@ export function getUserInfo() {
const userStore = useUserStoreWithOut();
userStore.setToken('');
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】捕获接口超时异常,跳转到登录界面
});
@ -116,6 +126,9 @@ export function getCaptcha(params) {
createErrorModal({ title: '错误提示', content: res.message || '未知问题' });
reject();
}
}).catch((res)=>{
createErrorModal({ title: '错误提示', content: res.message || '未知问题' });
reject();
});
});
}
@ -146,9 +159,15 @@ export const passwordChange = (params) => defHttp.get({ url: Api.passwordChange,
* @description:
*/
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>(
{
url: `${Api.thirdLogin}/${params.token}/${params.thirdType}`,
url: `${Api.thirdLogin}/${params.token}/${params.thirdType}/${tenantId}`,
},
{
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;
cursor: pointer;
transition: all 0.2s ease;
&.light {
border-bottom: 1px solid @border-color-base;
//
&.jeecg-layout-mix-sider-logo,&.jeecg-layout-menu-logo{
background:@sider-logo-bg-color;
}
// &.light {
// border-bottom: 1px solid @border-color-base;
// }
&.collapsed-show-title {
padding-left: 20px;

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@
import { computed } from 'vue';
import CodeMirrorEditor from './codemirror/CodeMirror.vue';
import { isString } from '/@/utils/is';
const props = defineProps({
value: { type: [Object, String] as PropType<Record<string, any> | string> },
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 CountButton from './CountButton.vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useRuleFormItem } from '/@/hooks/component/useFormItemSingle';
const props = {
value: { type: String },

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,22 +10,28 @@
v-bind="getAttr(item.event)"
@click="handleClickMenu(item)"
: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">
<Icon v-if="item.iconColor" :icon="item.popConfirm.icon" :color="item.iconColor"/>
<Icon v-else :icon="item.popConfirm.icon"/>
<Icon v-if="item.iconColor" :icon="item.popConfirm.icon" :color="item.iconColor" />
<Icon v-else :icon="item.popConfirm.icon" />
</template>
<div class="dropdown-event-area">
<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-if="item.icon && item.iconColor" :color="item.iconColor" />
<Icon :icon="item.icon" v-else-if="item.icon" />
<span class="ml-1">{{ item.text }}</span>
</div>
</a-popconfirm>
<!-- 设置动态插槽 -->
<template v-else-if="item.slot">
<slot :name="item.slot" :label="item.text"></slot>
</template>
<template v-else>
<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-if="item.icon && item.iconColor" :color="item.iconColor" />
<Icon :icon="item.icon" v-else-if="item.icon" />
<span class="ml-1">{{ item.text }}</span>
</template>
</a-menu-item>
@ -37,7 +43,7 @@
</template>
<script lang="ts" setup>
import { computed, PropType } from 'vue';
import { computed, PropType, ref } from 'vue';
import type { DropMenu } from './typing';
import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
import { Icon } from '/@/components/Icon';

View File

@ -11,6 +11,7 @@
:allDefaultValues="defaultValueRef"
:formModel="formModel"
:setFormModel="setFormModel"
:validateFields="validateFields"
>
<template #[item]="data" v-for="item in Object.keys($slots)">
<slot :name="item" v-bind="data || {}"></slot>
@ -51,6 +52,8 @@
import { useModalContext } from '/@/components/Modal';
import { basicProps } from './props';
import componentSetting from '/@/settings/componentSetting';
import { useDesign } from '/@/hooks/web/useDesign';
import dayjs from 'dayjs';
import { useDebounceFn } from '@vueuse/core';
@ -88,6 +91,16 @@
mergeProps.labelCol = undefined;
}
//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;
});
@ -252,10 +265,12 @@
const onFormSubmitWhenChange = useDebounceFn(handleSubmit, 300);
function setFormModel(key: string, value: any) {
formModel[key] = value;
const { validateTrigger } = unref(getBindValue);
if (!validateTrigger || validateTrigger === 'change') {
validateFields([key]).catch((_) => {});
}
// update-begin--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur'
// const { validateTrigger } = unref(getBindValue);
// if (!validateTrigger || validateTrigger === 'change') {
// validateFields([key]).catch((_) => {});
// }
// update-end--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur'
if(props.autoSearch === true){
onFormSubmitWhenChange();
}
@ -377,5 +392,12 @@
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>

View File

@ -44,6 +44,9 @@ import JCodeEditor from './jeecg/components/JCodeEditor.vue';
import JCategorySelect from './jeecg/components/JCategorySelect.vue';
import JSelectMultiple from './jeecg/components/JSelectMultiple.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 JTreeDict from './jeecg/components/JTreeDict.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 JRangeDate from './jeecg/components/JRangeDate.vue'
import JRangeTime from './jeecg/components/JRangeTime.vue'
import RoleSelectInput from './jeecg/components/roleSelect/RoleSelectInput.vue';
const componentMap = new Map<ComponentType, Component>();
@ -115,6 +119,9 @@ componentMap.set('JCodeEditor', JCodeEditor);
componentMap.set('JCategorySelect', JCategorySelect);
componentMap.set('JSelectMultiple', JSelectMultiple);
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('JTreeDict', JTreeDict);
componentMap.set('JInputPop', JInputPop);
@ -131,6 +138,9 @@ componentMap.set('JRangeNumber', JRangeNumber);
componentMap.set('UserSelect', UserSelect);
componentMap.set('RangeDate', JRangeDate);
componentMap.set('RangeTime', JRangeTime);
componentMap.set('RoleSelect', RoleSelectInput);
export function add(compName: ComponentType, component: Component) {
componentMap.set(compName, component);

View File

@ -1,5 +1,5 @@
<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)">
<slot :name="item" v-bind="data || {}"></slot>
</template>
@ -63,7 +63,30 @@
// Embedded in the form, just use the hook binding to perform form verification
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 { labelField, valueField, numberToString } = props;
return unref(options).reduce((prev, next: Recordable) => {
@ -90,6 +113,10 @@
},
{ deep: true }
);
//
watchEffect(() => {
props.value && handleFetch();
});
async function fetch() {
const api = props.api;
@ -140,10 +167,11 @@
}
function handleChange(_, ...args) {
vModalValue && vModalValue(_);
emitData.value = args;
}
return { state, attrs, getOptions, loading, t, handleFetch, handleChange };
return { state, attrs_, attrs, getOptions, loading, t, handleFetch, handleChange };
},
});
</script>

View File

@ -44,7 +44,9 @@
watch(
() => 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 }
);

View File

@ -65,6 +65,7 @@
actionSpan: propTypes.number.def(6),
isAdvanced: propTypes.bool,
hideAdvanceBtn: propTypes.bool,
layout: propTypes.oneOf(['horizontal', 'vertical', 'inline']).def('horizontal'),
},
emits: ['toggle-advanced'],
setup(props, { emit }) {
@ -74,12 +75,18 @@
const { showAdvancedButton, actionSpan: span, actionColOptions } = props;
const actionSpan = 24 - span;
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> = {
style: { textAlign: 'right' },
span: showAdvancedButton ? 6 : 4,
...defaultSpan,
...advancedSpanObj,
...actionColOptions,
};
return actionColOpt;
});

View File

@ -1,4 +1,5 @@
<script lang="tsx">
import { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface';
import type { PropType, Ref } from 'vue';
import type { FormActionType, FormProps } from '../types/form';
import type { FormSchema } from '../types/form';
@ -40,6 +41,10 @@
type: Function as PropType<(key: string, value: any) => void>,
default: null,
},
validateFields: {
type: Function as PropType<(nameList?: NamePath[] | undefined, options?: ValidateOptions) => Promise<any>>,
default: null,
},
tableAction: {
type: Object as PropType<TableActionType>,
},
@ -79,10 +84,9 @@
componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
}
if (schema.component === 'Divider') {
componentProps = Object.assign({ type: 'horizontal' }, componentProps, {
orientation: 'left',
plain: true,
});
//update-begin---author:wangshuai---date:2023-09-22---for:QQYUN-6603线---
componentProps = Object.assign({ type: 'horizontal',orientation:'left', plain: true, }, componentProps);
//update-end---author:wangshuai---date:2023-09-22---for:QQYUN-6603线---
}
return componentProps as Recordable;
});
@ -179,9 +183,12 @@
rule.required = false;
}
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';
}
}*/
//update-end---author:wangshuai---date:2024-02-01---for:QQYUN-8176,,ApiSelect,,使,---
rule.message = rule.message || defaultMsg;
@ -198,16 +205,37 @@
if (characterInx !== -1 && !rules[characterInx].validator) {
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;
}
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);
// 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)}`;
// update-begin--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur'
const on = {
[eventKey]: (...args: Nullable<Recordable>[]) => {
const [e] = args;
@ -215,16 +243,35 @@
propsData[eventKey](...args);
}
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.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 { autoSetPlaceHolder, size } = props.formProps;
const propsData: Recordable = {
allowClear: true,
getPopupContainer: (trigger: Element) => trigger.parentNode,
getPopupContainer: (trigger: Element) => {
return trigger?.parentNode;
},
size,
...unref(getComponentsProps),
disabled: unref(getDisable),
@ -347,10 +394,10 @@
// update-begin--author:liaozhiyang---date:20230803---forissues-641span
const { getIsMobile } = useAppInject();
let realColProps;
if (colProps['span'] && !unref(getIsMobile)) {
['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].forEach((name) => delete baseColProps[name]);
}
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
const { isIfShow, isShow } = getShow();
const values = unref(getValues);

View File

@ -36,6 +36,12 @@ function genType() {
}
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)) {
rule.type = valueFormat ? 'string' : 'object';
} else if (['RangePicker', 'Upload', 'CheckboxGroup', 'TimePicker'].includes(component)) {
@ -61,6 +67,18 @@ export function handleInputNumberValue(component?: ComponentType, val?: any) {
}
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 { 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 { handleRangeValue } from '../utils/formUtils';
import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
@ -10,7 +10,7 @@ import { add } from "/@/components/Form/src/componentMap";
//集成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>>;
@ -149,9 +149,9 @@ export function useForm(props?: Props): UseFormReturnType {
});
return values;
},
validateFields: async (nameList?: NamePath[]): Promise<Recordable> => {
validateFields: async (nameList?: NamePath[], options?: ValidateOptions): Promise<Recordable> => {
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 { 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 { isArray, isFunction, isObject, isString } from '/@/utils/is';
import { deepMerge, getValueType } from '/@/utils';
import { dateItemType, handleInputNumberValue } from '../helper';
import { dateItemType, handleInputNumberValue, handleInputStringValue } from '../helper';
import { dateUtil } from '/@/utils/dateUtil';
import { cloneDeep, uniqBy } from 'lodash-es';
import { error } from '/@/utils/log';
@ -65,6 +65,9 @@ export function useFormEvents({
const hasKey = Reflect.has(values, key);
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
if (hasKey && fields.includes(key)) {
// time type
@ -207,8 +210,8 @@ export function useFormEvents({
});
}
async function validateFields(nameList?: NamePath[] | undefined) {
return unref(formElRef)?.validateFields(nameList);
async function validateFields(nameList?: NamePath[] | undefined, options?: ValidateOptions) {
return unref(formElRef)?.validateFields(nameList, options);
}
async function validate(nameList?: NamePath[] | undefined) {

View File

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

View File

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

View File

@ -1,5 +1,9 @@
<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>
<script lang="ts">
@ -13,6 +17,7 @@
props: {
value:propTypes.oneOfType([propTypes.string, propTypes.number]),
dictCode: propTypes.string,
useDicColor: propTypes.bool.def(false),
options: {
type: Array,
default: () => [],
@ -69,6 +74,7 @@
prev.push({
label: next['text'],
value: value,
color: next['color'],
});
}
return prev;
@ -84,8 +90,30 @@
emit('update:value', $event.join(','));
emit('change', $event.join(','));
}
return { checkboxArray, checkOptions, attrs, handleChange };
const getDicColor = (value) => {
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>
<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>
<div v-bind="boxBindProps">
<div ref="containerRef" v-bind="boxBindProps">
<!-- 全屏按钮 -->
<a-icon v-if="fullScreen" class="full-screen-icon" :type="fullScreenIcon" @click="onToggleFullScreen" />
<textarea ref="textarea" v-bind="getBindValue"></textarea>
@ -45,6 +45,8 @@
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useDesign } from '/@/hooks/web/useDesign';
import { isJsonObjectString } from '/@/utils/is.ts';
//
import { useCodeHinting } from '../hooks/useCodeHinting';
export default defineComponent({
name: 'JCodeEditor',
@ -58,12 +60,15 @@
//
fullScreen: propTypes.bool.def(false),
// z-index
zIndex: propTypes.any.def(999),
zIndex: propTypes.any.def(1500),
theme: propTypes.string.def('idea'),
language: propTypes.string.def(''),
//
keywords: propTypes.array.def([]),
},
emits: ['change', 'update:value'],
setup(props, { emit }) {
const containerRef = ref(null);
const { prefixCls } = useDesign('code-editer');
const CodeMirror = window.CodeMirror || _CodeMirror;
const emitData = ref<object>();
@ -89,6 +94,9 @@
// :
//
styleActiveLine: true,
// update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode
mode: props.language,
// update-begin--author:liaozhiyang---date:20231201---forissues/869JCodeEditormode
//
extraKeys: {
Tab: function autoFormat(editor) {
@ -121,6 +129,10 @@
}
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);
//
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
return {
state,
textarea,
@ -215,7 +231,8 @@
isFullScreen,
fullScreenIcon,
onToggleFullScreen,
refresh
refresh,
containerRef,
};
},
});
@ -295,4 +312,9 @@
border: 1px solid #ddd;
}
}
.CodeMirror-hints.idea {
z-index: 1001;
max-width: 600px;
max-height: 300px;
}
</style>

View File

@ -2,7 +2,9 @@
<a-radio-group v-if="compType === CompTypeEnum.Radio" v-bind="attrs" v-model:value="state" @change="handleChangeRadio">
<template v-for="item in dictOptions" :key="`${item.value}`">
<a-radio :value="item.value">
{{ item.label }}
<span :class="[useDicColor && item.color ? 'colorText' : '']" :style="{ backgroundColor: `${useDicColor && item.color}` }">
{{ item.label }}
</span>
</a-radio>
</template>
</a-radio-group>
@ -41,7 +43,11 @@
<a-select-option v-if="showChooseOption" :value="null">请选择</a-select-option>
<template v-for="item in dictOptions" :key="`${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 }}
</span>
</a-select-option>
@ -69,9 +75,10 @@
type: propTypes.string,
placeholder: propTypes.string,
stringToNumber: propTypes.bool,
useDicColor: propTypes.bool.def(false),
getPopupContainer: {
type: Function,
default: (node) => node.parentNode,
default: (node) => node?.parentNode,
},
//
showChooseOption: propTypes.bool.def(true),
@ -139,7 +146,8 @@
prev.push({
label: next['text'] || next['label'],
value: stringToNumber ? +value : value,
...omit(next, ['text', 'value']),
color: next['color'],
...omit(next, ['text', 'value', 'color']),
});
}
return prev;
@ -185,11 +193,15 @@
/** 用于搜索下拉框中的内容 */
function handleFilterOption(input, option) {
// label
let labelIf = option.children()[0]?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0;
if (labelIf) {
return true;
// update-begin--author:liaozhiyang---date:20230914---forQQYUN-6514 Y
if (typeof option.children === 'function') {
// label
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
return (option.value || '').toString().toLowerCase().indexOf(input.toLowerCase()) >= 0;
}
@ -209,3 +221,17 @@
},
});
</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';
const props = defineProps({
value: propTypes.oneOfType([propTypes.string, propTypes.array]),
value: propTypes.oneOfType([propTypes.string, propTypes.number, propTypes.array]),
length: propTypes.number.def(25),
});
//

View File

@ -25,19 +25,19 @@
</a-button>
</div>
</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" />
</a-modal>
</div>
</template>
<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 { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs';
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 { getToken } from '/@/utils/auth';
@ -94,9 +94,7 @@
return path.substring(path.lastIndexOf('/') + 1);
};
//token
const headers = ref<object>({
'X-Access-Token': getToken(),
});
const headers = getHeaders();
//
const loading = ref<boolean>(false);
//
@ -177,28 +175,36 @@
*/
function handleChange({ file, fileList, event }) {
initTag.value = false;
uploadFileList.value = fileList;
// update-begin--author:liaozhiyang---date:20231116---forissues/846
// uploadFileList.value = fileList;
if (file.status === 'error') {
createMessage.error(`${file.name} 上传失败.`);
}
let fileUrls = [];
//
let noUploadingFileCount = 0;
if (file.status != 'uploading') {
fileList.forEach((file) => {
if (file.status === 'done') {
//update-begin---author:wangshuai ---date:20221121 for[issues/248]使,------------
initTag.value = true;
//update-end---author:wangshuai ---date:20221121 for[issues/248]使,------------
fileUrls.push(file.response.message);
}
if (file.status != 'uploading') {
noUploadingFileCount++;
}
});
if (file.status === 'removed') {
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(',');
state.value = fileUrls.join(',');
emit('update:value', fileUrls.join(','));
// update-end--author:liaozhiyang---date:20231116---forissues/846
}
/**

View File

@ -2,14 +2,14 @@
<div>
<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="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>
</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-upload>
<!--页脚-->
@ -81,7 +81,10 @@
//
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 {
createMessage.warning(res.message);
}
}).catch(() => {
uploading.value = false;
});
}

View File

@ -3,10 +3,11 @@
</template>
<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 { propTypes } from '/@/utils/propTypes';
import { JInputTypeEnum } from '/@/enums/jeecgEnum.ts';
import { omit } from 'lodash-es';
export default defineComponent({
name: 'JInput',
@ -22,8 +23,12 @@
const attrs = useAttrs();
//
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(
() => props.type,

View File

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

View File

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

View File

@ -2,7 +2,7 @@
<template>
<div>
<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>
</template>
<script lang="ts">

View File

@ -11,7 +11,7 @@
:getPopupContainer="getParentContainer"
>
<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>
</template>
@ -68,6 +68,10 @@
type: Boolean,
default: false,
},
useDicColor: {
type: Boolean,
default: false,
},
},
emits: ['options-change', 'change', 'input', 'update:value'],
setup(props, { emit, refs }) {
@ -118,7 +122,7 @@
function getParentContainer(node) {
if (!props.popContainer) {
return node.parentNode;
return node?.parentNode;
} else {
return document.querySelector(props.popContainer);
}
@ -135,7 +139,7 @@
//update-end-author:taoyan date:2022-6-21 for:
getDictItems(temp).then((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);
} else {
console.error('getDictItems error: : ', res);
@ -162,3 +166,15 @@
},
});
</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: {
type: String,
default: 'code',
default: 'id',
},
params: {
type: Object,

View File

@ -2,7 +2,7 @@
<template>
<div>
<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>
</template>
<script lang="ts">
@ -37,6 +37,13 @@
type: Object,
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'],
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,
setValue,
handleOpen,
excludeUserIdList,
handleChange,
};
},

View File

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

View File

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

View File

@ -17,7 +17,7 @@
<div class="ant-upload-text">{{ text }}</div>
</div>
</template>
<a-button v-else-if="buttonVisible" :disabled="isMaxCount || disabled">
<a-button v-else-if="buttonVisible" :disabled="buttonDisabled">
<Icon icon="ant-design:upload-outlined" />
<span>{{ text }}</span>
</a-button>
@ -36,7 +36,7 @@
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useDesign } from '/@/hooks/web/useDesign';
import { UploadTypeEnum } from './upload.data';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { getFileAccessHttpUrl, getHeaders } from '/@/utils/common/compUtils';
import UploadItemActions from './components/UploadItemActions.vue';
const { createMessage, createConfirm } = useMessage();
@ -67,11 +67,11 @@
removeConfirm: propTypes.bool.def(false),
beforeUpload: propTypes.func,
disabled: propTypes.bool.def(false),
//
replaceLastOne: propTypes.bool.def(false),
});
const headers = reactive({
'X-Access-Token': getToken(),
});
const headers = getHeaders();
const fileList = ref<any[]>([]);
const uploadGoOn = ref<boolean>(true);
// refs
@ -80,6 +80,20 @@
const isMaxCount = computed(() => props.maxCount > 0 && fileList.value.length >= props.maxCount);
//
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
const bindProps = computed(() => {
//update-begin-author:liusq date:20220411 for: [issue/455]accept
@ -112,7 +126,13 @@
parseArrayValue(val);
}
} 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 }
@ -305,7 +325,9 @@
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>
<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
ref="treeRef"
:treeData="treeData"
@ -11,6 +11,7 @@
@check="onCheck"
:fieldNames="fieldNames"
:checkedKeys="checkedKeys"
:multiple="multiple"
:checkStrictly="getCheckStrictly"
/>
<!--树操作部分-->
@ -39,6 +40,7 @@
import { BasicTree, TreeActionType } from '/@/components/Tree';
import { useTreeBiz } from '/@/components/Form/src/jeecg/hooks/useTreeBiz';
import {propTypes} from "/@/utils/propTypes";
import { omit } from 'lodash-es';
export default defineComponent({
name: 'DeptSelectModal',
@ -53,6 +55,12 @@
type: String,
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])
},
emits: ['register', 'getSelectResult'],
@ -65,13 +73,14 @@
//update-begin-author:taoyan date:2022-10-28 for:
let propValue = props.value === ''?[]:props.value;
//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:taoyan date:2022-10-28 for:
const queryUrl = getQueryUrl();
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 tree = ref([]);
//treeNodekeytreeData

View File

@ -151,10 +151,12 @@
watch(
() => props.param,
() => {
if (visible) {
// update-begin--author:liaozhiyang---date:20231213---forissues/901JPopupparam
if (visible.value) {
dynamicParamHandler();
loadData();
}
// update-end--author:liaozhiyang---date:20231213---forissues/901JPopupparam
}
);
/**
@ -202,6 +204,9 @@
closeModal();
checkedKeys.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;
}
}
:deep .jeecg-basic-table .ant-table-wrapper .ant-table-title {
:deep(.jeecg-basic-table .ant-table-wrapper .ant-table-title){
min-height: 0;
}
</style>

View File

@ -5,7 +5,7 @@
v-bind="$attrs"
@register="register"
:title="modalTitle"
width="900px"
width="1100px"
wrapClassName="j-user-select-modal"
@ok="handleOk"
destroyOnClose
@ -78,7 +78,8 @@
canResize: false,
bordered: true,
size: 'small',
rowKey: 'code',
//rowKey,
rowKey: props.rowKey,
};
const getBindValue = Object.assign({}, unref(props), unref(attrs), config);
const [{ rowSelection, visibleChange, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows }] = useSelectBiz(
@ -89,7 +90,7 @@
//form
const formConfig = {
labelCol: {
span: 8,
span: 4,
},
baseColProps: {
xs: 24,
@ -99,6 +100,16 @@
xl: 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: [
{
label: '职务名称',
@ -176,6 +187,7 @@
selectedTable,
selectRows,
handleDeleteSelected,
searchInfo,
};
},
});

View File

@ -67,11 +67,21 @@
xl: 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: [
{
label: '角色名称',
field: 'roleName',
component: 'JInput',
component: 'Input',
},
],
};

View File

@ -110,6 +110,16 @@
xl: 6,
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: [
{
label: '账号',

View File

@ -5,7 +5,7 @@
v-bind="$attrs"
@register="register"
:title="modalTitle"
width="900px"
:width="showSelected ? '1200px' : '900px'"
wrapClassName="j-user-select-modal"
@ok="handleOk"
destroyOnClose
@ -24,6 +24,7 @@
:searchInfo="searchInfo"
:rowSelection="rowSelection"
:indexColumnProps="indexColumnProps"
:afterFetch="afterFetch"
>
<!-- update-begin-author:taoyan date:2022-5-25 for: VUEN-1112一对多 用户选择 未显示选择条数及清空 -->
<template #tableTitle></template>
@ -48,7 +49,7 @@
</div>
</template>
<script lang="ts">
import { defineComponent, unref, ref } from 'vue';
import { defineComponent, unref, ref, watch } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { getUserList } from '/@/api/common/api';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
@ -72,6 +73,13 @@
type: String,
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'],
setup(props, { emit, refs }) {
@ -107,6 +115,15 @@
getBindValue
);
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
const formConfig = {
baseColProps: {
@ -209,6 +226,29 @@
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 {
//config,
@ -227,6 +267,7 @@
handleDeleteSelected,
tableScroll,
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;
if(!list || list.length ==0 ){
}
for(let item of list){
item.checked = false
}else{
let selectedIdList = data.list || [];
for(let item of list){
if(selectedIdList.indexOf(item.id)>=0){
item.checked = true;
}else{
item.checked = false;
}
}
}
});
//
function handleOk() {
let arr = toRaw(selectedIdList.value);
emit('selected', arr);
emit('selected', arr, toRaw(selectedList.value));
}
const dataList = ref<any[]>([]);
@ -161,6 +167,7 @@
arr.push({
id: item.id,
name: item.name || item.roleName,
code: item.roleCode,
selectType: props.type,
checked: false
})
@ -177,6 +184,13 @@
function onSelect(e, item) {
prevent(e);
console.log('onselect');
// false
if(props.multi === false){
let list = dataList.value;
for(let item of list){
item.checked = false;
}
}
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">
<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);">
<template #icon>
<team-outlined style="font-size: 16px"/>

View File

@ -3,11 +3,17 @@
<template #renderItem="{ item }">
<a-list-item style="padding: 3px 0">
<div class="user-select-user-info" @click="(e) => onClickUser(e, item)">
<div>
<a-checkbox v-model:checked="checkStatus[item.id]" />
<div style="margin-left: 10px">
<a-checkbox v-model:checked="checkStatus[item.id]" v-if="multi" />
<a-radio v-model:checked="checkStatus[item.id]" v-else />
</div>
<div>
<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>
<template #icon><UserOutlined /></template>
</a-avatar>
@ -15,9 +21,10 @@
<div :style="nameStyle">
{{ item.realname }}
</div>
<div :style="departStyle">
<div :style="departStyle" class="ellipsis" :title="item.orgCodeTxt">
{{ item.orgCodeTxt }}
</div>
<div style="width: 1px"></div>
</div>
</a-list-item>
</template>
@ -32,6 +39,10 @@
export default {
name: 'UserList',
props: {
multi: {
type: Boolean,
default: false,
},
dataList: {
type: Array,
default: () => [],
@ -126,8 +137,8 @@
e.preventDefault();
e.stopPropagation();
}
function records2DataList() {
//update-begin---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
/* function records2DataList() {
let arr:any[] = [];
let excludeList = props.excludeUserIdList;
let records = props.dataList;
@ -139,13 +150,14 @@
}
}
return arr;
}
}*/
const showDataList = computed(()=>{
let excludeList = props.excludeUserIdList;
/* let excludeList = props.excludeUserIdList;
if(excludeList && excludeList.length>0){
return records2DataList();
}
}*/
//update-end---author:wangshuai---date:2024-02-02---for:QQYUN-8239 2---
return props.dataList;
});
@ -166,10 +178,16 @@
<style lang="less">
.user-select-user-info {
display: flex;
width: 100%;
> div {
height: 36px;
line-height: 36px;
margin-right: 10px;
}
.ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
</style>

View File

@ -12,12 +12,15 @@
v-model:expandedKeys="expandedKeys"
@select="onSelect"
>
<template #title="{ title, key }">
<FolderFilled style="color: #9e9e9e"/><span style="margin-left: 5px">{{ title }}</span>
</template>
</a-tree>
</div>
</a-col>
<a-col :span="12" style="padding-left: 10px">
<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>
</a-col>
</a-row>
@ -27,11 +30,13 @@
import { defHttp } from '/@/utils/http/axios';
import { computed, ref, watch } from 'vue';
import UserList from './UserList.vue';
import { FolderFilled } from '@ant-design/icons-vue';
export default {
name: 'DepartUserList',
components: {
UserList,
FolderFilled
},
props: {
searchText: {
@ -45,6 +50,10 @@
excludeUserIdList:{
type: Array,
default: () => [],
},
multi: {
type: Boolean,
default: false,
}
},
emits: ['loaded', 'selected', 'unSelect'],
@ -132,7 +141,7 @@
const url = '/sys/user/selectUserList';
let params = {
pageNo: 1,
pageSize: 10,
pageSize: 99,
};
if (props.searchText) {
params['keyword'] = props.searchText;
@ -140,6 +149,11 @@
if (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 });
if (data.success) {
const { records } = data.result;

View File

@ -2,12 +2,16 @@
<a-row>
<a-col :span="12">
<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>
</a-col>
<a-col :span="12" style="padding-left: 10px">
<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>
</a-col>
</a-row>
@ -17,11 +21,13 @@
import { computed, ref, watch } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import UserList from './UserList.vue';
import { UserOutlined } from '@ant-design/icons-vue';
export default {
name: 'RoleUserList',
components: {
UserList,
UserOutlined
},
props: {
searchText: {
@ -35,6 +41,10 @@
excludeUserIdList:{
type: Array,
default: () => [],
},
multi: {
type: Boolean,
default: false,
}
},
emits: ['selected', 'unSelect'],
@ -80,7 +90,7 @@
const url = '/sys/user/selectUserList';
let params = {
pageNo: 1,
pageSize: 10,
pageSize: 99,
};
if (props.searchText) {
params['keyword'] = props.searchText;
@ -88,6 +98,11 @@
if (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 });
if (data.success) {
const { records } = data.result;

View File

@ -35,7 +35,7 @@
<a-tabs v-model:activeKey="myActiveKey" :centered="true" @change="onChangeTab">
<!-- 所有用户 -->
<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>
<!-- 部门用户 -->
@ -92,8 +92,10 @@
const APagination = Pagination;
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 { mySelfData } from './useUserSelect'
export default {
name: 'UserSelectModal',
components: {
@ -120,6 +122,11 @@
type: Boolean,
default: false,
},
//
inSuperQuery:{
type: Boolean,
default: false,
}
},
emits: ['selected', 'register'],
setup(props, { emit }) {
@ -154,6 +161,8 @@
if (props.izExcludeMy) {
excludeUserIdList.value.push(userStore.getUserInfo.id);
}
//
loadUserList();
});
//
@ -213,16 +222,31 @@
if (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 });
if (data.success) {
const { records, total } = data.result;
let { records, total } = data.result;
totalRecord.value = total;
initCurrentUserData(records);
userDataList.value = records;
} else {
console.error(data.message);
}
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>
</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>
</template>
@ -31,6 +31,7 @@
import UserSelectModal from './UserSelectModal.vue';
import { defHttp } from '/@/utils/http/axios';
import SelectedUserItem from './SelectedUserItem.vue';
import { mySelfExpress, mySelfData } from './useUserSelect'
export default defineComponent({
name: 'UserSelect',
@ -74,6 +75,11 @@
izExcludeMy:{
type: Boolean,
default: false,
},
//
inSuperQuery:{
type: Boolean,
default: false,
}
},
emits: ['update:value', 'change'],
@ -150,19 +156,41 @@
);
async function getUserList(ids) {
const url = '/sys/user/list';
let params = {
[props.store]: ids,
};
let hasUserExpress = false;
let paramIds = ids;
let idList = [];
selectedUserList.value = [];
const data = await defHttp.get({ url, params }, { isTransformResponse: false });
if (data.success) {
const { records } = data.result;
selectedUserList.value = records;
} else {
console.error(data.message);
if(ids){
// update-begin-author:sunjianlei date:20230330 for:
let tempArray = ids.split(',').map(s => s.trim()).filter(s => s != '');
if (tempArray.includes(mySelfExpress)) {
hasUserExpress = true;
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(() => {

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