mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-01-02 02:25:27 +08:00
【3.7.3 版本合并升级】
Merge remote-tracking branch 'origin/springboot3' into springboot3_sas # Conflicts: # jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java # jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java # jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java # jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantPackServiceImpl.java # jeecgboot-vue3/package.json
This commit is contained in:
@ -19,3 +19,9 @@ VITE_GLOB_API_URL_PREFIX=
|
||||
|
||||
#微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
|
||||
VITE_APP_SUB_jeecg-app-1 = '//localhost:8092'
|
||||
|
||||
|
||||
# 填写后将作为乾坤子应用启动,主应用注册时AppName需保持一致(放开 VITE_GLOB_QIANKUN_MICRO_APP_NAME 参数表示jeecg-vue3将以乾坤子应用模式启动)
|
||||
#VITE_GLOB_QIANKUN_MICRO_APP_NAME=jeecg-vue3
|
||||
# 作为乾坤子应用启动时必填,需与qiankun主应用注册子应用时填写的 entry 保持一致
|
||||
#VITE_GLOB_QIANKUN_MICRO_APP_ENTRY=//localhost:3001/jeecg-vue3
|
||||
|
||||
@ -20,3 +20,9 @@ VITE_GLOB_DOMAIN_URL=http://jeecg-boot-system:8080/jeecg-boot
|
||||
|
||||
# 接口父路径前缀
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
|
||||
|
||||
# 填写后将作为乾坤子应用启动,主应用注册时AppName需保持一致(放开 VITE_GLOB_QIANKUN_MICRO_APP_NAME 参数表示jeecg-vue3将以乾坤子应用模式启动)
|
||||
#VITE_GLOB_QIANKUN_MICRO_APP_NAME=jeecg-vue3
|
||||
# 作为乾坤子应用启动时必填,需与qiankun主应用注册子应用时填写的 entry 保持一致
|
||||
#VITE_GLOB_QIANKUN_MICRO_APP_ENTRY=//qiankun.boot3.jeecg.com/jeecg-vue3
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
JeecgBoot 企业级低代码开发平台
|
||||
===============
|
||||
当前最新版本: 3.7.1(发布时间:2024-09-12)
|
||||
当前最新版本: 3.7.3(发布时间:2025-02-10)
|
||||
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
|
||||
[](http://jeecg.com/aboutusIndex)
|
||||
[](https://github.com
|
||||
[](https://github.com
|
||||
/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
@ -27,7 +27,7 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue4、TypeScript 等新技术
|
||||
|
||||
- 官方文档:[https://help.jeecg.com](https://help.jeecg.com)
|
||||
- 快速入门:[快速入门](http://jeecg.com/doc/quickstart) | [常见问题](http://help.jeecg.com/qa.html)
|
||||
- QQ交流群:⑨808791225、其他满
|
||||
- QQ交流群:⑩716488839、⑨808791225、其他满
|
||||
- 在线演示 : [系统演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)
|
||||
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import { createHtmlPlugin } from 'vite-plugin-html';
|
||||
import pkg from '../../../package.json';
|
||||
import { GLOB_CONFIG_FILE_NAME } from '../../constant';
|
||||
|
||||
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
||||
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean, isQiankunMicro: boolean) {
|
||||
const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;
|
||||
|
||||
const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`;
|
||||
@ -16,12 +16,17 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
||||
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
|
||||
};
|
||||
|
||||
// 【JEECG作为乾坤子应用】补充静态资源前缀
|
||||
const {VITE_GLOB_QIANKUN_MICRO_APP_ENTRY} = env;
|
||||
const basePublicPath = isQiankunMicro ? VITE_GLOB_QIANKUN_MICRO_APP_ENTRY : '';
|
||||
|
||||
const htmlPlugin: PluginOption[] = createHtmlPlugin({
|
||||
minify: isBuild,
|
||||
inject: {
|
||||
// 修改模板html的标题
|
||||
data: {
|
||||
title: VITE_GLOB_APP_TITLE,
|
||||
basePublicPath: basePublicPath,
|
||||
},
|
||||
// 将app.config.js文件注入到模板html中
|
||||
tags: isBuild
|
||||
|
||||
@ -15,11 +15,18 @@ import { configCompressPlugin } from './compress';
|
||||
import { configVisualizerConfig } from './visualizer';
|
||||
import { configThemePlugin } from './theme';
|
||||
import { configSvgIconsPlugin } from './svgSprite';
|
||||
import { configQiankunMicroPlugin } from './qiankunMicro';
|
||||
// //预编译加载插件(不支持vite3作废)
|
||||
// import OptimizationPersist from 'vite-plugin-optimize-persist';
|
||||
// import PkgConfig from 'vite-plugin-package-config';
|
||||
|
||||
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||
/**
|
||||
*
|
||||
* @param viteEnv
|
||||
* @param isBuild
|
||||
* @param isQiankunMicro 是否【JEECG作为乾坤子应用】
|
||||
*/
|
||||
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean, isQiankunMicro: boolean) {
|
||||
const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv;
|
||||
|
||||
const vitePlugins: (PluginOption | PluginOption[])[] = [
|
||||
@ -38,7 +45,7 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||
vitePlugins.push(UnoCSS({ presets: [presetUno(), presetTypography()] }));
|
||||
|
||||
// vite-plugin-html
|
||||
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild));
|
||||
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild, isQiankunMicro));
|
||||
|
||||
// vite-plugin-svg-icons
|
||||
vitePlugins.push(configSvgIconsPlugin(isBuild));
|
||||
@ -55,6 +62,12 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||
// vite-plugin-theme
|
||||
vitePlugins.push(configThemePlugin(isBuild));
|
||||
|
||||
// 【JEECG作为乾坤子应用】注册乾坤子应用模式插件
|
||||
if (isQiankunMicro) {
|
||||
// vite-plugin-qiankun
|
||||
vitePlugins.push(...configQiankunMicroPlugin(viteEnv))
|
||||
}
|
||||
|
||||
// The following plugins only work in the production environment
|
||||
if (isBuild) {
|
||||
|
||||
|
||||
16
jeecgboot-vue3/build/vite/plugin/qiankunMicro.ts
Normal file
16
jeecgboot-vue3/build/vite/plugin/qiankunMicro.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import qiankun from 'vite-plugin-qiankun';
|
||||
|
||||
/**
|
||||
* 【JEECG作为乾坤子应用】Vite适配乾坤以子应用模式运行
|
||||
* @param env
|
||||
*/
|
||||
export function configQiankunMicroPlugin(env: ViteEnv) {
|
||||
const {VITE_GLOB_QIANKUN_MICRO_APP_NAME} = env
|
||||
|
||||
return [
|
||||
qiankun(VITE_GLOB_QIANKUN_MICRO_APP_NAME!, {
|
||||
useDevMode: true,
|
||||
})
|
||||
]
|
||||
|
||||
}
|
||||
@ -10,7 +10,7 @@
|
||||
/>
|
||||
|
||||
<title><%= title %></title>
|
||||
<link rel="icon" href="/logo.png" />
|
||||
<link rel="icon" href="<%= basePublicPath %>/logo.png" />
|
||||
<!-- 全局配置 -->
|
||||
<script>
|
||||
window._CONFIG = {};
|
||||
@ -157,7 +157,7 @@
|
||||
</style>
|
||||
<div class="app-loading">
|
||||
<div class="app-loading-wrap">
|
||||
<img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
|
||||
<img src="<%= basePublicPath %>/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
|
||||
<div class="app-loading-dots">
|
||||
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
|
||||
</div>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "jeecgboot-vue3",
|
||||
"version": "3.7.1",
|
||||
"version": "3.7.3",
|
||||
"author": {
|
||||
"name": "北京国炬信息技术有限公司",
|
||||
"email": "jeecgos@163.com",
|
||||
"url": "https://github.com/jeecgboot/jeecgboot-vue3"
|
||||
"url": "https://www.jeecg.com"
|
||||
},
|
||||
"scripts": {
|
||||
"pinstall": "pnpm install",
|
||||
@ -23,149 +23,152 @@
|
||||
"dependencies": {
|
||||
"@jeecg/online": "3.7.1-RC",
|
||||
"@iconify/iconify": "^3.1.1",
|
||||
"@ant-design/colors": "^7.0.2",
|
||||
"@ant-design/colors": "^7.2.0",
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@vue/shared": "^3.4.19",
|
||||
"@vueuse/core": "^10.8.0",
|
||||
"@vue/shared": "^3.5.13",
|
||||
"@vueuse/core": "^10.11.1",
|
||||
"@tinymce/tinymce-vue": "4.0.7",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"ant-design-vue": "^4.1.2",
|
||||
"axios": "^1.6.7",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"axios": "^1.7.9",
|
||||
"china-area-data": "^5.0.1",
|
||||
"@vant/area-data": "^1.5.1",
|
||||
"@vant/area-data": "^1.5.2",
|
||||
"clipboard": "^2.0.11",
|
||||
"codemirror": "^5.65.3",
|
||||
"codemirror": "^5.65.18",
|
||||
"cron-parser": "^4.9.0",
|
||||
"cropperjs": "^1.6.1",
|
||||
"cropperjs": "^1.6.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"dayjs": "^1.11.13",
|
||||
"dom-align": "^1.12.4",
|
||||
"echarts": "^5.4.3",
|
||||
"emoji-mart-vue-fast": "^15.0.1",
|
||||
"echarts": "^5.6.0",
|
||||
"emoji-mart-vue-fast": "^15.0.3",
|
||||
"enquire.js": "^2.1.6",
|
||||
"intro.js": "^7.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lodash.get": "^4.4.2",
|
||||
"markdown-it": "^14.0.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
"event-source-polyfill": "^1.0.31",
|
||||
"highlight.js": "^11.9.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
"@traptitech/markdown-it-katex": "^3.6.0",
|
||||
"md5": "^2.3.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.2.1",
|
||||
"path-to-regexp": "^6.3.0",
|
||||
"pinia": "2.1.7",
|
||||
"print-js": "^1.6.0",
|
||||
"qs": "^6.11.2",
|
||||
"qrcode": "^1.5.3",
|
||||
"qrcode": "^1.5.4",
|
||||
"qs": "^6.13.1",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"showdown": "^2.1.0",
|
||||
"sortablejs": "^1.15.2",
|
||||
"sortablejs": "^1.15.6",
|
||||
"tinymce": "6.6.2",
|
||||
"vditor": "^3.9.9",
|
||||
"vue": "^3.4.19",
|
||||
"vue-cropper": "^0.6.4",
|
||||
"vditor": "^3.10.8",
|
||||
"vue": "^3.5.13",
|
||||
"vue-cropper": "^0.6.5",
|
||||
"vue-cropperjs": "^5.0.0",
|
||||
"vue-i18n": "^9.9.1",
|
||||
"vue-i18n": "^9.14.2",
|
||||
"vue-infinite-scroll": "^2.0.2",
|
||||
"vue-print-nb-jeecg": "^1.0.12",
|
||||
"vue-router": "4.3.0",
|
||||
"vue-types": "^5.1.1",
|
||||
"vue-router": "^4.5.0",
|
||||
"vue-types": "^5.1.3",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vxe-table": "4.6.17",
|
||||
"vxe-table-plugin-antd": "4.0.7",
|
||||
"xe-utils": "3.5.26",
|
||||
"xss": "^1.0.14"
|
||||
"xss": "^1.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^18.6.1",
|
||||
"@commitlint/config-conventional": "^18.6.2",
|
||||
"@iconify/json": "^2.2.185",
|
||||
"@commitlint/config-conventional": "^18.6.3",
|
||||
"@iconify/json": "^2.2.292",
|
||||
"@purge-icons/generated": "^0.10.0",
|
||||
"@types/codemirror": "^5.60.15",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/inquirer": "^9.0.7",
|
||||
"@types/intro.js": "^5.1.5",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/mockjs": "^1.0.10",
|
||||
"@types/node": "^20.11.19",
|
||||
"@types/node": "^20.17.12",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@types/qs": "^6.9.11",
|
||||
"@types/qs": "^6.9.17",
|
||||
"@types/showdown": "^2.0.6",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@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.4",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"commitizen": "^4.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"@vue/compiler-sfc": "^3.5.13",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"commitizen": "^4.3.1",
|
||||
"conventional-changelog-cli": "^4.1.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"cz-git": "^1.8.0",
|
||||
"czg": "^1.8.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^8.56.0",
|
||||
"cz-git": "^1.11.0",
|
||||
"czg": "^1.11.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-define-config": "^2.1.0",
|
||||
"eslint-plugin-jest": "^27.9.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-vue": "^9.21.1",
|
||||
"esno": "^4.0.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-vue": "^9.32.0",
|
||||
"esno": "^4.8.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"http-server": "^14.1.1",
|
||||
"husky": "^8.0.3",
|
||||
"inquirer": "^9.2.15",
|
||||
"inquirer": "^9.3.7",
|
||||
"is-ci": "^3.0.1",
|
||||
"jest": "^29.7.0",
|
||||
"less": "^4.2.0",
|
||||
"less": "^4.2.1",
|
||||
"lint-staged": "15.2.2",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss": "^8.4.35",
|
||||
"postcss-html": "^1.6.0",
|
||||
"picocolors": "^1.1.1",
|
||||
"postcss": "^8.4.49",
|
||||
"postcss-html": "^1.7.0",
|
||||
"postcss-less": "^6.0.0",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier": "^3.4.2",
|
||||
"pretty-quick": "^4.0.0",
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup": "^4.12.0",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"stylelint": "^16.2.1",
|
||||
"rimraf": "^5.0.10",
|
||||
"rollup": "^4.30.0",
|
||||
"rollup-plugin-visualizer": "^5.13.1",
|
||||
"stylelint": "^16.12.0",
|
||||
"stylelint-config-prettier": "^9.0.5",
|
||||
"stylelint-config-recommended": "^14.0.0",
|
||||
"stylelint-config-recommended": "^14.0.1",
|
||||
"stylelint-config-recommended-vue": "^1.5.0",
|
||||
"stylelint-config-standard": "^36.0.0",
|
||||
"stylelint-config-standard": "^36.0.1",
|
||||
"stylelint-order": "^6.0.4",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-jest": "^29.2.5",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^4.9.5",
|
||||
"vite": "^5.2.11",
|
||||
"vite": "^6.0.7",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
"vite-plugin-mkcert": "^1.17.3",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-mkcert": "^1.17.6",
|
||||
"vite-plugin-mock": "^2.9.8",
|
||||
"vite-plugin-optimize-persist": "^0.1.2",
|
||||
"vite-plugin-package-config": "^0.1.1",
|
||||
"vite-plugin-purge-icons": "^0.10.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-qiankun": "^1.0.15",
|
||||
"@rys-fe/vite-plugin-theme": "^0.8.6",
|
||||
"vite-plugin-vue-setup-extend-plus": "^0.1.0",
|
||||
"unocss": "^0.58.5",
|
||||
"vue-eslint-parser": "^9.4.2",
|
||||
"vue-tsc": "^1.8.27"
|
||||
"unocss": "^0.58.9",
|
||||
"vue-eslint-parser": "^9.4.3",
|
||||
"vue-tsc": "^1.8.27",
|
||||
"dingtalk-jsapi": "^3.0.42",
|
||||
"big.js": "^6.2.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/jeecgboot/jeecgboot-vue3.git"
|
||||
"url": "git+https://github.com/jeecgboot/JeecgBoot.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jeecgboot/jeecgboot-vue3/issues"
|
||||
"url": "https://github.com/jeecgboot/JeecgBoot/issues"
|
||||
},
|
||||
"homepage": "https://www.jeecg.com",
|
||||
"engines": {
|
||||
|
||||
21618
jeecgboot-vue3/pnpm-lock.yaml
generated
21618
jeecgboot-vue3/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -36,6 +36,7 @@
|
||||
|
||||
const props = defineProps({
|
||||
title: { type: String, default: '' },
|
||||
defaultExpan: { type: Boolean, default: true },
|
||||
loading: { type: Boolean },
|
||||
/**
|
||||
* Can it be expanded
|
||||
@ -58,8 +59,9 @@
|
||||
*/
|
||||
lazyTime: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const show = ref(true);
|
||||
// update-begin-author:liaozhiyang---date:2024-11-11--for:【issues/7402】CollapseContainer组件增加默认不展开属性
|
||||
const show = ref(props.defaultExpan);
|
||||
// update-begin-author:liaozhiyang---date:2024-11-11--for:【issues/7402】CollapseContainer组件增加默认不展开属性
|
||||
|
||||
const { prefixCls } = useDesign('collapse-container');
|
||||
|
||||
|
||||
@ -84,11 +84,14 @@ export default function ({ advanceState, emit, getProps, getSchema, formModel, d
|
||||
advanceState.isAdvanced = true;
|
||||
} else */
|
||||
// update-end--author:sunjianlei---date:20211108---for: 注释掉该逻辑,使小于等于2行时,也显示展开收起按钮
|
||||
if (itemColSum > BASIC_COL_LEN * 2 && itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3)) {
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
/*if (itemColSum > BASIC_COL_LEN * 2 && itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3)) {
|
||||
advanceState.hideAdvanceBtn = false;
|
||||
|
||||
// 默认超过 3 行折叠
|
||||
} else if (!advanceState.isLoad) {
|
||||
} else*/
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
if (!advanceState.isLoad) {
|
||||
advanceState.isLoad = true;
|
||||
advanceState.isAdvanced = !advanceState.isAdvanced;
|
||||
// update-begin--author:sunjianlei---date:20211108---for: 如果总列数大于 autoAdvancedCol,就默认折叠
|
||||
|
||||
@ -79,13 +79,8 @@
|
||||
function transform(arr) {
|
||||
let result: any = [];
|
||||
if (props.saveCode === 'region') {
|
||||
// 81 香港、82 澳门
|
||||
const regionCode = arr[0];
|
||||
if (['82', '81'].includes(regionCode.substring(0, 2))) {
|
||||
result = [`${regionCode.substring(0, 2)}0000`, regionCode];
|
||||
} else {
|
||||
result = [`${regionCode.substring(0, 2)}0000`, `${regionCode.substring(0, 2)}${regionCode.substring(2, 4)}00`, regionCode];
|
||||
}
|
||||
result = [`${regionCode.substring(0, 2)}0000`, `${regionCode.substring(0, 2)}${regionCode.substring(2, 4)}00`, regionCode];
|
||||
} else if (props.saveCode === 'city') {
|
||||
const cityCode = arr[0];
|
||||
result = [`${cityCode.substring(0, 2)}0000`, cityCode];
|
||||
|
||||
@ -26,72 +26,74 @@
|
||||
</a-tabs>
|
||||
<a-divider />
|
||||
<!-- 执行时间预览 -->
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="18" style="margin-top: 22px">
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.second" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'second'">秒</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.minute" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'minute'">分</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.hour" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'hour'">时</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.day" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'day'">日</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.month" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'month'">月</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.week" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'week'">周</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-input v-model:value="inputValues.year" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'year'">年</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="16">
|
||||
<a-input v-model:value="inputValues.cron" @blur="onInputCronBlur">
|
||||
<template #addonBefore>
|
||||
<a-tooltip title="Cron表达式">式</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div>近十次执行时间(不含年)</div>
|
||||
<a-textarea type="textarea" :value="preTimeList" :rows="5" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<div style="overflow: hidden">
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="18" style="margin-top: 22px">
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.second" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'second'">秒</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.minute" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'minute'">分</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.hour" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'hour'">时</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.day" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'day'">日</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.month" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'month'">月</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.week" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'week'">周</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-input v-model:value="inputValues.year" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'year'">年</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="16">
|
||||
<a-input v-model:value="inputValues.cron" @blur="onInputCronBlur">
|
||||
<template #addonBefore>
|
||||
<a-tooltip title="Cron表达式">式</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div>近十次执行时间(不含年)</div>
|
||||
<a-textarea type="textarea" :value="preTimeList" :rows="5" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" title="Cron表达式" width="800px" @ok="onOk">
|
||||
<BasicModal @register="registerModal" title="Cron表达式" width="1000px" @ok="onOk">
|
||||
<EasyCron v-bind="attrs" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
@ -13,9 +13,9 @@
|
||||
</span>
|
||||
</template>
|
||||
<template #content>
|
||||
<a-textarea ref="textareaRef" :value="innerValue" :disabled="disabled" :style="textareaStyle" v-bind="attrs" @input="onInputChange" />
|
||||
<a-textarea ref="textareaRef" :value="innerValue" :disabled="disabled" :style="textareaStyle" v-bind="attrs" @input="onInputChange" @blur="onInputBlur" />
|
||||
</template>
|
||||
<a-input :class="`${prefixCls}-input`" :value="innerValue" :disabled="disabled" v-bind="attrs" @change="onInputChange">
|
||||
<a-input :class="`${prefixCls}-input`" :value="innerValue" :disabled="disabled" v-bind="attrs" @change="onInputChange" @blur="onInputBlur">
|
||||
<template #suffix>
|
||||
<Icon icon="ant-design:fullscreen-outlined" @click.stop="onShowPopup" />
|
||||
</template>
|
||||
@ -44,7 +44,7 @@
|
||||
popContainer: propTypes.oneOfType([propTypes.string, propTypes.func]).def(''),
|
||||
});
|
||||
const attrs = useAttrs();
|
||||
const emit = defineEmits(['change', 'update:value']);
|
||||
const emit = defineEmits(['change', 'update:value', 'blur']);
|
||||
|
||||
const visible = ref<boolean>(false);
|
||||
const innerValue = ref<string>('');
|
||||
@ -92,6 +92,10 @@
|
||||
emit('change', value);
|
||||
emit('update:value', value);
|
||||
}
|
||||
|
||||
const onInputBlur = (event) => {
|
||||
emit('blur', event);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
@ -395,7 +395,14 @@
|
||||
// update-end--author:liaozhiyang---date:20240809---for:【TV360X-2062】下拉搜索选择第二页数据后,第一次点击时(得到焦点)滚动条没复原到初始位置且数据会加载第二页数据(应该只加载第一页数据)
|
||||
initDictTableData();
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20240709---for:【issues/6681】异步查询不生效
|
||||
// update-begin--author:liaozhiyang---date:20240919---for:【TV360X-2348】得到焦点时options选项显示第一页内容(解决新增时显示非第一页内容)
|
||||
if (Array.isArray(selectedAsyncValue.value) && selectedAsyncValue.value.length === 0 && isDictTable.value && props.async) {
|
||||
if (pageNo > 2) {
|
||||
options.value = [];
|
||||
initDictTableData();
|
||||
}
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20240919---for:【TV360X-2348】得到焦点时options选项显示第一页内容(解决新增时显示非第一页内容)
|
||||
attrs.onFocus?.();
|
||||
};
|
||||
// update-end--author:liaozhiyang---date:20240523---for:【TV360X-26】下拉搜索控件选中选项后再次点击下拉应该显示初始的下拉选项,而不是只展示选中结果
|
||||
|
||||
@ -31,11 +31,11 @@
|
||||
import { defineComponent, unref, ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicTree } from '/@/components/Tree/index';
|
||||
import { queryTreeList, getTableList } from '/@/api/common/api';
|
||||
import { queryTreeList, getTableList as getTableListOrigin } from '/@/api/common/api';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
import { useSelectBiz } from '/@/components/Form/src/jeecg/hooks/useSelectBiz';
|
||||
import { useAttrs } from '/@/hooks/core/useAttrs';
|
||||
import { queryDepartTreeSync } from '/@/views/system/depart/depart.api';
|
||||
import { queryDepartTreeSync as queryDepartTreeSyncOrigin } from '/@/views/system/depart/depart.api';
|
||||
import { selectProps } from '/@/components/Form/src/jeecg/props/props';
|
||||
export default defineComponent({
|
||||
name: 'UserSelectByDepModal',
|
||||
@ -132,6 +132,31 @@
|
||||
};
|
||||
const getBindValue = Object.assign({}, unref(props), unref(attrs), tableProps);
|
||||
const [{ rowSelection, visibleChange, indexColumnProps, getSelectResult, reset }] = useSelectBiz(getTableList, getBindValue);
|
||||
|
||||
function getTableList(params) {
|
||||
params = parseParams(params);
|
||||
return getTableListOrigin({...params});
|
||||
}
|
||||
|
||||
function queryDepartTreeSync(params) {
|
||||
params = parseParams(params);
|
||||
return queryDepartTreeSyncOrigin({...params});
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析参数
|
||||
* @param params
|
||||
*/
|
||||
function parseParams(params) {
|
||||
if (props?.params) {
|
||||
return {
|
||||
...params,
|
||||
...props.params,
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载树形数据
|
||||
*/
|
||||
|
||||
@ -31,7 +31,9 @@ export function useSelectBiz(getList, props, emit?) {
|
||||
if (selectValues['change'] == false && !isEmpty(selectValues['value'])) {
|
||||
//update-end-author:liusq---date:2023-10-19--for: [issues/788]判断有设置数值才去加载
|
||||
//update-begin---author:wangshuai ---date:20220412 for:[VUEN-672]发文草稿箱编辑时拟稿人显示用户名------------
|
||||
let params = { isMultiTranslate: 'true' };
|
||||
// update-begin-author:liaozhiyang---date:2024-11-11--for:【issues/7405】部门选择用户同时全部选择两页用户,回显到父页面。第二页用户显示的不是真是姓名
|
||||
let params = { isMultiTranslate: 'true', pageSize: selectValues.value?.length };
|
||||
// update-end-author:liaozhiyang---date:2024-10-11--for:【issues/7405】部门选择用户同时全部选择两页用户,回显到父页面。第二页用户显示的不是真是姓名
|
||||
params[props.rowKey] = selectValues['value'].join(',');
|
||||
//update-end---author:wangshuai ---date:20220412 for:[VUEN-672]发文草稿箱编辑时拟稿人显示用户名--------------
|
||||
loadingEcho.value = isFirstLoadEcho;
|
||||
|
||||
@ -67,8 +67,10 @@ export const basicProps = {
|
||||
rulesMessageJoinLabel: propTypes.bool.def(true),
|
||||
// 【jeecg】超过3列自动折叠
|
||||
autoAdvancedCol: propTypes.number.def(3),
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
// 超过3行自动折叠
|
||||
autoAdvancedLine: propTypes.number.def(3),
|
||||
// autoAdvancedLine: propTypes.number.def(3),
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
// 不受折叠影响的行数
|
||||
alwaysShowLines: propTypes.number.def(1),
|
||||
|
||||
|
||||
@ -99,7 +99,9 @@ export interface FormProps {
|
||||
// 【jeecg】如果 showAdvancedButton 为 true,超过指定列数默认折叠,默认为3
|
||||
autoAdvancedCol?: number;
|
||||
// 如果 showAdvancedButton 为 true,超过指定行数行默认折叠
|
||||
autoAdvancedLine?: number;
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
// autoAdvancedLine?: number;
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
// 折叠时始终保持显示的行数
|
||||
alwaysShowLines?: number;
|
||||
// Whether to show the operation button
|
||||
|
||||
@ -101,11 +101,6 @@ const jeecgAreaData = new Area();
|
||||
// 根据code找文本
|
||||
const getAreaTextByCode = function (code) {
|
||||
let index = 3;
|
||||
// update-begin--author:liaozhiyang---date:20240617---for:【TV360X-1210】online列表香港、澳门没翻译(香港、澳门只有两级其它省份是三级)
|
||||
if (code && ['82', '81'].includes(code.substring(0, 2))) {
|
||||
index = 2;
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20240617---for:【TV360X-1210】online列表香港、澳门没翻译(香港、澳门只有两级其它省份是三级)
|
||||
//update-begin-author:liusq---date:20220531--for: 判断code是否是多code逗号分割的字符串,是的话,获取最后一位的code ---
|
||||
if (code && code.includes(',')) {
|
||||
index = code.split(",").length;
|
||||
|
||||
@ -36,8 +36,10 @@ export function handleRangeTimeValue(props, values) {
|
||||
timeValue = timeValue.split(',');
|
||||
}
|
||||
const [startTime, endTime]: string[] = timeValue;
|
||||
values[startTimeKey] = dateUtil(startTime).format(format);
|
||||
values[endTimeKey] = dateUtil(endTime).format(format);
|
||||
//update-begin---author:wangshuai---date:2024-10-08---for:【issues/7216】当RangePicker组件值允许开始/结束为空时,表单的fieldMapToTime处理异常---
|
||||
startTime && (values[startTimeKey] = dateUtil(startTime).format(format));
|
||||
endTime && (values[endTimeKey] = dateUtil(endTime).format(format));
|
||||
//update-end---author:wangshuai---date:2024-10-08---for:【issues/7216】当RangePicker组件值允许开始/结束为空时,表单的fieldMapToTime处理异常---
|
||||
Reflect.deleteProperty(values, field);
|
||||
}
|
||||
return values;
|
||||
|
||||
@ -1,10 +1,23 @@
|
||||
<template>
|
||||
<a-input :disabled="disabled" :style="{ width }" readOnly :placeholder="t('component.icon.placeholder')" :class="prefixCls" v-model:value="currentSelect">
|
||||
<a-input
|
||||
:class="prefixCls"
|
||||
:value="currentSelect"
|
||||
readOnly
|
||||
:disabled="disabled"
|
||||
:placeholder="t('component.icon.placeholder')"
|
||||
:style="{ width }"
|
||||
@click="currentSelectClick"
|
||||
>
|
||||
<template #addonAfter>
|
||||
<span class="cursor-pointer px-2 py-1 flex items-center" v-if="isSvgMode && currentSelect">
|
||||
<SvgIcon :name="currentSelect" @click="currentSelectClick"/>
|
||||
</span>
|
||||
<Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else @click="currentSelectClick"/>
|
||||
<Icon v-else :icon="currentSelect || 'ion:apps-outline'" :class="['px-2 py-1', {
|
||||
'cursor-pointer': !disabled,
|
||||
'cursor-not-allowed': disabled,
|
||||
}]"
|
||||
@click="currentSelectClick"
|
||||
/>
|
||||
</template>
|
||||
</a-input>
|
||||
<a-modal :bodyStyle="{ padding: '24px'}" v-bind="$attrs" v-model:open="iconOpen" :keyboard="false" :width="800" @ok="handleOk" :ok-text="t('common.okText')" :cancel-text="t('common.cancelText')">
|
||||
@ -84,7 +97,7 @@
|
||||
width: propTypes.string.def('100%'),
|
||||
copy: propTypes.bool.def(false),
|
||||
mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
|
||||
disabled: propTypes.bool.def(true),
|
||||
disabled: propTypes.bool.def(false),
|
||||
clearSelect: propTypes.bool.def(false),
|
||||
iconPrefixSave: propTypes.bool.def(true),
|
||||
});
|
||||
@ -149,6 +162,9 @@
|
||||
* 图标点击重置页数
|
||||
*/
|
||||
function currentSelectClick() {
|
||||
if (props.disabled) {
|
||||
return
|
||||
}
|
||||
iconOpen.value = true;
|
||||
setTimeout(()=>{
|
||||
iconListRef.value.currentSelectClick();
|
||||
@ -185,6 +201,12 @@
|
||||
@prefix-cls: ~'@{namespace}-icon-picker';
|
||||
|
||||
.@{prefix-cls} {
|
||||
|
||||
// 输入框手势图标
|
||||
.ant-input:not([disabled]) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ant-input-group-addon {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
components: { JSelectUser },
|
||||
props: useJVxeCompProps(),
|
||||
setup(props: JVxeComponent.Props) {
|
||||
const { innerValue, cellProps, handleChangeCommon, useCellDesign } = useJVxeComponent(props);
|
||||
const { innerValue, cellProps, handleChangeCommon, useCellDesign, originColumn } = useJVxeComponent(props);
|
||||
const { prefixCls } = useCellDesign('user-select');
|
||||
|
||||
const selectedValue = computed(() => {
|
||||
@ -49,7 +49,9 @@
|
||||
// 不允许搜索
|
||||
showSearch: false,
|
||||
// 设置最大的显示个数
|
||||
maxTagCount: 1,
|
||||
// update-begin--author:liaozhiyang---date:20250106---for:【issues/7661】vxetable用户组件maxTagCount通过业务传递
|
||||
maxTagCount: originColumn.value.maxTagCount ?? 1,
|
||||
// update-end--author:liaozhiyang---date:20250106---for:【issues/7661】vxetable用户组件maxTagCount通过业务传递
|
||||
// 显示提示重写,去掉省略号
|
||||
maxTagPlaceholder: ({ length }) => '+' + length,
|
||||
// -update-begin--author:liaozhiyang---date:20240617---for:【TV360X-1002】详情页面行编辑用户组件和部门组件显示方式优化
|
||||
|
||||
@ -123,6 +123,13 @@
|
||||
window.open(key);
|
||||
return;
|
||||
}
|
||||
// update-begin--author:liaozhiyang---date:20250114---for:【issues/7706】顶部栏导航内部路由也可以支持采用新浏览器tab打开
|
||||
const findItem = getMatchingMenu(props.items, key);
|
||||
if (findItem?.internalOrExternal == true) {
|
||||
window.open(location.origin + key);
|
||||
return;
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20250114---for:【issues/7706】顶部栏导航内部路由也可以支持采用新浏览器tab打开
|
||||
// update-end--author:liaozhiyang---date:20240402---for:【QQYUN-8773】配置外部网址在顶部菜单模式和搜索打不开
|
||||
if (beforeClickFn && isFunction(beforeClickFn)) {
|
||||
const flag = await beforeClickFn(key);
|
||||
@ -218,6 +225,25 @@
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 2025-01-14
|
||||
* liaozhiyang
|
||||
* 获取菜单中匹配的path所在的项
|
||||
*/
|
||||
const getMatchingMenu = (menus, path) => {
|
||||
for (let i = 0, len = menus.length; i < len; i++) {
|
||||
const item = menus[i];
|
||||
if (item.path === path && !item.redirect && !item.paramPath) {
|
||||
return item;
|
||||
} else if (item.children?.length) {
|
||||
const result = getMatchingMenu(item.children, path);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
return {
|
||||
handleMenuClick,
|
||||
|
||||
@ -112,7 +112,10 @@
|
||||
|
||||
//整合warpClassName
|
||||
const getWrapClassName = computed(() => {
|
||||
const clsName = toRef(getMergeProps.value, 'wrapClassName').value || '';
|
||||
let clsName = toRef(getMergeProps.value, 'wrapClassName').value || '';
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
clsName = `${clsName} jeecg-modal-code-generate`;
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
return unref(fullScreenRef) ? `jeecg-full-screen-modal-code-generate ${clsName} ` : unref(clsName);
|
||||
});
|
||||
|
||||
@ -324,4 +327,13 @@
|
||||
}
|
||||
}
|
||||
/*end 全屏弹窗modal样式*/
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
.jeecg-modal-code-generate {
|
||||
.ant-modal {
|
||||
.ant-modal-close {
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
</style>
|
||||
|
||||
@ -120,7 +120,9 @@
|
||||
display: flex;
|
||||
height: 95%;
|
||||
align-items: center;
|
||||
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
margin-top: -2px;
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
> span {
|
||||
margin-left: 48px;
|
||||
font-size: 16px;
|
||||
|
||||
@ -19,6 +19,11 @@
|
||||
.@{namespace}-basic-title {
|
||||
cursor: default !important;
|
||||
}
|
||||
// update-begin--author:liaozhiyang---date:20241225---for:【issues/7601】ant-design-vue@4.2.6后弹窗全屏底部有空隙
|
||||
& > div:has( > .ant-modal-content) {
|
||||
height: 100%;
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20241225---for:【issues/7601】ant-design-vue@4.2.6后弹窗全屏底部有空隙
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,10 +81,12 @@
|
||||
}
|
||||
|
||||
.ant-modal-close-x {
|
||||
display: inline-block;
|
||||
width: 96px;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
// display: inline-block;
|
||||
// width: 96px;
|
||||
// height: 56px;
|
||||
// line-height: 56px;
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
}
|
||||
|
||||
.ant-modal-confirm-body {
|
||||
|
||||
@ -48,6 +48,11 @@
|
||||
const renderValue = String(value);
|
||||
const wrapEl = unref(wrapRef);
|
||||
|
||||
// 无值不生成
|
||||
if (renderValue == null || renderValue === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wrapEl) return;
|
||||
|
||||
if (tag === 'canvas') {
|
||||
|
||||
@ -222,7 +222,7 @@
|
||||
// update-end--author:sunjianlei---date:220230630---for:【QQYUN-5571】自封装选择列,解决数据行选择卡顿问题
|
||||
);
|
||||
|
||||
const { getScrollRef, redoHeight } = useTableScroll(getProps, tableElRef, getColumnsRef, getRowSelectionRef, getDataSourceRef);
|
||||
const { getScrollRef, redoHeight } = useTableScroll(getProps, tableElRef, getColumnsRef, getRowSelectionRef, getDataSourceRef, slots);
|
||||
|
||||
const { customRow } = useCustomRow(getProps, {
|
||||
setSelectedRowKeys,
|
||||
@ -406,7 +406,9 @@
|
||||
getProps.value.defaultExpandAllRows && expandAll();
|
||||
})
|
||||
// update-end--author:sunjianlei---date:20231226---for:【issues/945】BasicTable组件设置默认展开不生效
|
||||
expose(tableAction);
|
||||
// update-begin--author:liaozhiyang---date:20241225---for:【issues/7588】选择后自动刷新表格
|
||||
expose({ ...tableAction, handleSearchInfoChange });
|
||||
// update-end--author:liaozhiyang---date:20241225---for:【issues/7588】选择后自动刷新表格
|
||||
|
||||
emit('register', tableAction, formActions);
|
||||
|
||||
@ -605,7 +607,12 @@
|
||||
.ant-table > .ant-table-footer {
|
||||
padding: 12px 0 0;
|
||||
}
|
||||
|
||||
.ant-table > .ant-table-footer {
|
||||
// update-begin--author:liaozhiyang---date:20241111---for:【issues/7413】合计行有点对不齐
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
// update-end--author:liaozhiyang---date:20241111---for:【issues/7413】合计行有点对不齐
|
||||
}
|
||||
.ant-table.ant-table-bordered > .ant-table-footer {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
<template>
|
||||
<Table
|
||||
v-if="summaryFunc || summaryData"
|
||||
:showHeader="false"
|
||||
:bordered="bordered"
|
||||
:pagination="false"
|
||||
:dataSource="getDataSource"
|
||||
:rowKey="(r) => r[rowKey]"
|
||||
:columns="getColumns"
|
||||
tableLayout="fixed"
|
||||
:scroll="scroll"
|
||||
/>
|
||||
<div ref="tableFooter">
|
||||
<Table
|
||||
v-if="summaryFunc || summaryData"
|
||||
:showHeader="false"
|
||||
:bordered="bordered"
|
||||
:pagination="false"
|
||||
:dataSource="getDataSource"
|
||||
:rowKey="(r) => r[rowKey]"
|
||||
:columns="getColumns"
|
||||
tableLayout="fixed"
|
||||
:scroll="scroll"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
import { defineComponent, unref, computed, toRaw } from 'vue';
|
||||
import { defineComponent, unref, computed, toRaw, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { Table } from 'ant-design-vue';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { isFunction } from '/@/utils/is';
|
||||
@ -47,7 +49,7 @@
|
||||
},
|
||||
setup(props) {
|
||||
const table = useTableContext();
|
||||
|
||||
const tableFooter = ref<any>(null);
|
||||
const getDataSource = computed((): Recordable[] => {
|
||||
const { summaryFunc, summaryData } = props;
|
||||
if (summaryData?.length) {
|
||||
@ -119,7 +121,24 @@
|
||||
}
|
||||
return columns;
|
||||
});
|
||||
return { getColumns, getDataSource };
|
||||
// update-begin--author:liaozhiyang---date:20250218---for:【issues/7773】合计没有跟着左右滚动条滚动
|
||||
let mainTableBody, footerTable;
|
||||
const handleSroll = () => {
|
||||
const scrollLeft = mainTableBody.scrollLeft;
|
||||
footerTable.scrollLeft = scrollLeft;
|
||||
};
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
mainTableBody = tableFooter.value?.parentNode?.parentNode?.querySelector('.ant-table-body');
|
||||
footerTable = tableFooter.value?.querySelector('.ant-table-body');
|
||||
mainTableBody?.addEventListener('scroll', handleSroll, false);
|
||||
}, 1e3);
|
||||
});
|
||||
onUnmounted(() => {
|
||||
mainTableBody?.addEventListener('scroll', handleSroll);
|
||||
});
|
||||
// update-end--author:liaozhiyang---date:20250218---for:【issues/7773】合计没有跟着左右滚动条滚动
|
||||
return { getColumns, getDataSource, tableFooter };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -371,7 +371,9 @@
|
||||
|
||||
if (props.column.dataIndex) {
|
||||
if (!props.record.editValueRefs) props.record.editValueRefs = {};
|
||||
props.record.editValueRefs[props.column.dataIndex] = currentValueRef;
|
||||
// update-begin--author:liaozhiyang---date:20250206---for:【issues/7709】当dataSource是响应式时,单元格编辑输入会自动关闭
|
||||
props.record.editValueRefs[props.column.dataIndex] = unref(currentValueRef);
|
||||
// update-end--author:liaozhiyang---date:20250206---for:【issues/7709】当dataSource是响应式时,单元格编辑输入会自动关闭
|
||||
}
|
||||
/* eslint-disable */
|
||||
props.record.onCancelEdit = () => {
|
||||
|
||||
@ -73,6 +73,8 @@ export type EditRecordRow<T = Recordable> = Partial<
|
||||
submitCbs: Cbs[];
|
||||
cancelCbs: Cbs[];
|
||||
validCbs: Cbs[];
|
||||
editValueRefs: Recordable<Ref>;
|
||||
// update-begin--author:liaozhiyang---date:20250206---for:【issues/7709】当dataSource是响应式时,单元格编辑输入会自动关闭
|
||||
editValueRefs: Recordable;
|
||||
// update-end--author:liaozhiyang---date:20250206---for:【issues/7709】当dataSource是响应式时,单元格编辑输入会自动关闭
|
||||
} & T
|
||||
>;
|
||||
|
||||
@ -161,11 +161,8 @@ export function useColumns(
|
||||
const viewColumns = sortFixedColumn(unref(getColumnsRef));
|
||||
|
||||
const columns = cloneDeep(viewColumns);
|
||||
const result = columns
|
||||
.filter((column) => {
|
||||
return hasPermission(column.auth) && isIfShow(column);
|
||||
})
|
||||
.map((column) => {
|
||||
const formatEditColumn = (columns) => {
|
||||
return columns.map((column) => {
|
||||
// update-begin--author:liaozhiyang---date:20230718---for: 【issues-179】antd3 一些警告以及报错(针对表格)
|
||||
if(column.slots?.customRender) {
|
||||
// slots的备份,兼容老的写法,转成新写法避免控制台警告
|
||||
@ -198,8 +195,17 @@ export function useColumns(
|
||||
if ((edit || editRow) && !isDefaultAction) {
|
||||
column.customRender = renderEditCell(column);
|
||||
}
|
||||
// update-begin--author:liaozhiyang---date:20241021---for:【pull/7333】修复分组表头可编辑表格失效问题
|
||||
if (column.children?.length) {
|
||||
formatEditColumn(column.children.filter((item) => hasPermission(column.auth) && isIfShow(column)));
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20241021---for:【pull/7333】修复分组表头可编辑表格失效问题
|
||||
return reactive(column);
|
||||
});
|
||||
};
|
||||
// update-begin--author:liaozhiyang---date:20241021---for:【pull/7333】修复分组表头可编辑表格失效问题
|
||||
const result = formatEditColumn(columns.filter((item) => hasPermission(item.auth) && isIfShow(item)));
|
||||
// update-end--author:liaozhiyang---date:20241021---for:【pull/7333】修复分组表头可编辑表格失效问题
|
||||
// update-begin--author:liaozhiyang---date:20230919---for:【QQYUN-6387】展开写法(去掉报错)
|
||||
if (propsRef.value.expandedRowKeys && !propsRef.value.isTreeTable) {
|
||||
let index = 0;
|
||||
|
||||
@ -185,6 +185,10 @@ export function useCustomSelection(
|
||||
let bodyResizeObserver: Nullable<ResizeObserver> = null;
|
||||
// 获取首行行高
|
||||
watchEffect(() => {
|
||||
// update-begin--author:liaozhiyang---date:20241111---for:【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常
|
||||
// 这种写法是为了监听到 size 的变化
|
||||
propsRef.value.size && void 0;
|
||||
// update-end--author:liaozhiyang---date:20241111---for:【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常
|
||||
if (bodyEl.value) {
|
||||
// 监听div高度变化
|
||||
bodyResizeObserver = new ResizeObserver((entries) => {
|
||||
@ -194,17 +198,11 @@ export function useCustomSelection(
|
||||
bodyHeight.value = Math.ceil(height);
|
||||
}
|
||||
}
|
||||
updateRowHeight();
|
||||
});
|
||||
bodyResizeObserver.observe(bodyEl.value);
|
||||
const el = bodyEl.value?.querySelector('tbody.ant-table-tbody tr.ant-table-row') as HTMLDivElement;
|
||||
if (el) {
|
||||
rowHeight.value = el.offsetHeight;
|
||||
return;
|
||||
}
|
||||
}
|
||||
rowHeight.value = 50;
|
||||
// 这种写法是为了监听到 size 的变化
|
||||
propsRef.value.size && void 0;
|
||||
});
|
||||
|
||||
onMountedOrActivated(async () => {
|
||||
@ -220,6 +218,16 @@ export function useCustomSelection(
|
||||
}
|
||||
});
|
||||
|
||||
// 更新首行行高
|
||||
function updateRowHeight() {
|
||||
const el = bodyEl.value?.querySelector('tbody.ant-table-tbody tr.ant-table-row') as HTMLDivElement;
|
||||
if (el) {
|
||||
// update-begin--author:liaozhiyang---date:20241111---for:【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常
|
||||
nextTick(() => rowHeight.value = el.offsetHeight);
|
||||
// update-end--author:liaozhiyang---date:20241111---for:【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常
|
||||
}
|
||||
}
|
||||
|
||||
// 选择全部
|
||||
function onSelectAll(checked: boolean, flag = 'currentPage') {
|
||||
// update-begin--author:liaozhiyang---date:20231122---for:【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件
|
||||
|
||||
@ -38,24 +38,34 @@ export function useTableFooter(
|
||||
});
|
||||
|
||||
function handleSummary() {
|
||||
const { showSummary } = unref(propsRef);
|
||||
const { showSummary, canResize } = unref(propsRef);
|
||||
if (!showSummary || unref(getIsEmptyData)) return;
|
||||
|
||||
nextTick(() => {
|
||||
const tableEl = unref(tableElRef);
|
||||
if (!tableEl) return;
|
||||
const bodyDom = tableEl.$el.querySelector('.ant-table-content');
|
||||
useEventListener({
|
||||
el: bodyDom,
|
||||
name: 'scroll',
|
||||
listener: () => {
|
||||
const footerBodyDom = tableEl.$el.querySelector('.ant-table-footer .ant-table-content') as HTMLDivElement;
|
||||
if (!footerBodyDom || !bodyDom) return;
|
||||
footerBodyDom.scrollLeft = bodyDom.scrollLeft;
|
||||
},
|
||||
wait: 0,
|
||||
options: true,
|
||||
});
|
||||
let bodyDom;
|
||||
// update-begin--author:liaozhiyang---date:20241111---for:【issues/7422】BasicTable列表canResize属性为true时合计行不能横向滚动
|
||||
if (canResize) {
|
||||
setTimeout(() => {
|
||||
bodyDom = tableEl.$el.querySelector('.ant-table-body');
|
||||
}, 0);
|
||||
} else {
|
||||
bodyDom = tableEl.$el.querySelector('.ant-table-content');
|
||||
}
|
||||
setTimeout(() => {
|
||||
useEventListener({
|
||||
el: bodyDom,
|
||||
name: 'scroll',
|
||||
listener: () => {
|
||||
const footerBodyDom = tableEl.$el.querySelector('.ant-table-footer .ant-table-content') as HTMLDivElement;
|
||||
if (!footerBodyDom || !bodyDom) return;
|
||||
footerBodyDom.scrollLeft = bodyDom.scrollLeft;
|
||||
},
|
||||
wait: 0,
|
||||
options: true,
|
||||
});
|
||||
}, 0);
|
||||
// update-end--author:liaozhiyang---date:20241111---for:【issues/7422】BasicTable列表canResize属性为true时合计行不能横向滚动
|
||||
});
|
||||
}
|
||||
return { getFooterProps };
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/table';
|
||||
import type { Ref, ComputedRef } from 'vue';
|
||||
import type { Ref, ComputedRef, Slots } from 'vue';
|
||||
import { computed, unref, ref, nextTick, watch } from 'vue';
|
||||
import { getViewportOffset } from '/@/utils/domUtils';
|
||||
import { isBoolean } from '/@/utils/is';
|
||||
@ -14,7 +14,8 @@ export function useTableScroll(
|
||||
tableElRef: Ref<ComponentRef>,
|
||||
columnsRef: ComputedRef<BasicColumn[]>,
|
||||
rowSelectionRef: ComputedRef<TableRowSelection<any> | null>,
|
||||
getDataSourceRef: ComputedRef<Recordable[]>
|
||||
getDataSourceRef: ComputedRef<Recordable[]>,
|
||||
slots: Slots
|
||||
) {
|
||||
const tableHeightRef: Ref<Nullable<number>> = ref(null);
|
||||
|
||||
@ -175,7 +176,11 @@ export function useTableScroll(
|
||||
if (len !== 0) {
|
||||
width += len * NORMAL_WIDTH;
|
||||
}
|
||||
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
if (slots.expandedRowRender) {
|
||||
width += propsRef.value.expandColumnWidth;
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
const table = unref(tableElRef);
|
||||
const tableWidth = table?.$el?.offsetWidth ?? 0;
|
||||
return tableWidth > width ? '100%' : width;
|
||||
|
||||
@ -108,6 +108,9 @@ export const basicProps = {
|
||||
},
|
||||
minHeight: propTypes.number,
|
||||
maxHeight: propTypes.number,
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
expandColumnWidth: propTypes.number.def(48),
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
// 统一设置列最大宽度
|
||||
maxColumnWidth: propTypes.number,
|
||||
dataSource: {
|
||||
|
||||
@ -199,7 +199,7 @@ export interface BasicTableProps<T = any> {
|
||||
// 是否显示操作列
|
||||
showActionColumn?: boolean;
|
||||
// 操作列配置
|
||||
actionColumn?: BasicColumn;
|
||||
actionColumn?: Partial<BasicColumn>;
|
||||
// 文本超过宽度是否显示。。。
|
||||
ellipsis?: boolean;
|
||||
// 是否可以自适应高度
|
||||
@ -220,6 +220,10 @@ export interface BasicTableProps<T = any> {
|
||||
maxHeight?: number;
|
||||
// 是否显示边框
|
||||
bordered?: boolean;
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
// 展开列宽度
|
||||
expandColumnWidth: number;
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
// 分页配置
|
||||
pagination?: PaginationProps | boolean;
|
||||
// loading加载
|
||||
|
||||
@ -29,5 +29,5 @@ export interface PopConfirm {
|
||||
icon?: string;
|
||||
placement?: string;
|
||||
overlayClassName?: string;
|
||||
getPopupContainer: Fn;
|
||||
getPopupContainer?: Fn;
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
<ImgUpload
|
||||
:fullscreen="fullscreen"
|
||||
@uploading="handleImageUploading"
|
||||
@loading="handleLoading"
|
||||
@done="handleDone"
|
||||
v-show="editorRef"
|
||||
:disabled="disabled"
|
||||
@ -13,6 +14,7 @@
|
||||
<!-- update-end--author:liaozhiyang---date:20240517---for:【TV360X-35】富文本,图片上传遮挡其他按钮 -->
|
||||
<Editor :id="tinymceId" ref="elRef" :disabled="disabled" :init="initOptions" :style="{ visibility: 'hidden' }" v-if="!initOptions.inline"></Editor>
|
||||
<slot v-else></slot>
|
||||
<ProcessMask ref="processMaskRef" :show="showUploadMask"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -33,6 +35,7 @@
|
||||
import 'tinymce/plugins/image';
|
||||
import { defineComponent, computed, nextTick, ref, unref, watch, onDeactivated, onBeforeUnmount, onMounted } from 'vue';
|
||||
import ImgUpload from './ImgUpload.vue';
|
||||
import ProcessMask from './ProcessMask.vue';
|
||||
import {simpleToolbar, menubar, simplePlugins} from './tinymce';
|
||||
import { buildShortUUID } from '/@/utils/uuid';
|
||||
import { bindHandlers } from './helper';
|
||||
@ -82,6 +85,10 @@
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showUploadMask: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//是否聚焦
|
||||
autoFocus:{
|
||||
type: Boolean,
|
||||
@ -91,9 +98,9 @@
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Tinymce',
|
||||
components: { ImgUpload,Editor },
|
||||
components: { ImgUpload,Editor,ProcessMask },
|
||||
inheritAttrs: false,
|
||||
props: tinymceProps,
|
||||
props: tinymceProps as any,
|
||||
emits: ['change', 'update:modelValue', 'inited', 'init-error'],
|
||||
setup(props, { emit, attrs }) {
|
||||
console.log("---Tinymce---初始化---")
|
||||
@ -103,6 +110,7 @@
|
||||
const tinymceId = ref<string>(buildShortUUID('tiny-vue'));
|
||||
const elRef = ref<Nullable<HTMLElement>>(null);
|
||||
const editorRootRef = ref<Nullable<HTMLElement>>(null);
|
||||
const processMaskRef = ref<any>(null);
|
||||
const imgUploadShow = ref(false);
|
||||
const targetElem = ref<null | HTMLDivElement>(null);
|
||||
|
||||
@ -325,6 +333,20 @@
|
||||
setValue(editor, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传进度计算
|
||||
* @param file
|
||||
* @param fileList
|
||||
*/
|
||||
function handleLoading(fileLength,showMask){
|
||||
if(fileLength && fileLength > 0){
|
||||
setTimeout(() => {
|
||||
props?.showUploadMask && processMaskRef.value.calcProcess(fileLength)
|
||||
},100)
|
||||
}else{
|
||||
props?.showUploadMask && (processMaskRef.value.showMask = showMask);
|
||||
}
|
||||
}
|
||||
function getUploadingImgName(name: string) {
|
||||
return `[uploading:${name}]`;
|
||||
}
|
||||
@ -397,6 +419,9 @@
|
||||
editorRootRef,
|
||||
imgUploadShow,
|
||||
targetElem,
|
||||
|
||||
handleLoading,
|
||||
processMaskRef
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -428,6 +453,7 @@
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20240527---for:【TV360X-329】富文本禁用状态下工具栏划过边框丢失
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
.@{prefix-cls} {
|
||||
.tox .tox-edit-area__iframe {background-color: #141414;}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
:showUploadList="false"
|
||||
:data="getBizData()"
|
||||
:headers="getheader()"
|
||||
:before-upload="beforeUpload"
|
||||
accept=".jpg,.jpeg,.gif,.png,.webp"
|
||||
>
|
||||
<a-button type="primary" v-bind="{ ...getButtonProps }">
|
||||
@ -37,10 +38,8 @@
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['uploading', 'done', 'error'],
|
||||
emits: ['uploading', 'done', 'error', 'loading'],
|
||||
setup(props, { emit }) {
|
||||
let uploading = false;
|
||||
|
||||
//update-begin-author:taoyan date:2022-5-13 for: 富文本上传图片不支持
|
||||
function getheader() {
|
||||
return getHeaders();
|
||||
@ -67,33 +66,37 @@
|
||||
};
|
||||
});
|
||||
|
||||
let uploadLength = 0;
|
||||
function handleChange({ file, fileList }) {
|
||||
if (file.status === 'error') {
|
||||
emit('error');
|
||||
uploading = false;
|
||||
// 过滤掉已经存在的文件
|
||||
fileList = fileList.filter((file) => {
|
||||
const existFile = uploadFileList.value.find(({ uid }) => uid === file.uid);
|
||||
return existFile ? false : true;
|
||||
});
|
||||
uploadLength == 0 && (uploadLength = fileList.length);
|
||||
if (file.status != 'uploading') {
|
||||
emit('loading', uploadLength, true);
|
||||
}
|
||||
let files = [] as any;
|
||||
let noUploadingFileCount = 0;
|
||||
// 处理上传好的文件
|
||||
if (file.status != 'uploading') {
|
||||
fileList.forEach((file) => {
|
||||
if (file.status === 'done' && file.response.success) {
|
||||
files.push(file);
|
||||
const name = file?.name;
|
||||
let realUrl = getFileAccessHttpUrl(file.response.message);
|
||||
uploadFileList.value.push(file);
|
||||
emit('done', name, realUrl);
|
||||
}
|
||||
if (file.status != 'uploading') {
|
||||
noUploadingFileCount++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (noUploadingFileCount == fileList.length) {
|
||||
fileList.forEach((file) => {
|
||||
const name = file?.name;
|
||||
let realUrl = getFileAccessHttpUrl(file.response.message);
|
||||
emit('done', name, realUrl);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//上传之前
|
||||
function beforeUpload() {
|
||||
uploadLength = 0;
|
||||
emit('loading', null, true);
|
||||
setTimeout(() => {
|
||||
emit('loading', null, false);
|
||||
}, 10000);
|
||||
}
|
||||
return {
|
||||
prefixCls,
|
||||
handleChange,
|
||||
@ -102,7 +105,8 @@
|
||||
getBizData,
|
||||
t,
|
||||
getButtonProps,
|
||||
uploadFileList
|
||||
uploadFileList,
|
||||
beforeUpload,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
110
jeecgboot-vue3/src/components/Tinymce/src/ProcessMask.vue
Normal file
110
jeecgboot-vue3/src/components/Tinymce/src/ProcessMask.vue
Normal file
@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div :class="[prefixCls]" v-if="showMask && show">
|
||||
<div class="progress-bar-rear">
|
||||
<div class="progress-bar-front" :style="{ width: progressBarWidth }"></div>
|
||||
</div>
|
||||
<div class="value">{{ percentage }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import {useDesign} from "@/hooks/web/useDesign";
|
||||
|
||||
const props = defineProps({
|
||||
backColor: {
|
||||
type: [String],
|
||||
default: 'white',
|
||||
},
|
||||
processColor: {
|
||||
type: String,
|
||||
default: '#018FFB',
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const { prefixCls } = useDesign('tinymce-process-mask');
|
||||
|
||||
//显示遮罩
|
||||
const showMask = ref(false);
|
||||
//进度值占比
|
||||
const progressValue = ref<any>(0);
|
||||
//当前数量
|
||||
const currentNum = ref(0);
|
||||
// 计算进度条宽度的计算属性
|
||||
const progressBarWidth = computed(() => {
|
||||
return progressValue.value > 0 ? `${progressValue.value}px` : '0px';
|
||||
});
|
||||
// 计算进度条百分比
|
||||
const percentage = computed(() => {
|
||||
return `${progressValue.value}%`;
|
||||
});
|
||||
// 进度色
|
||||
const frontColor = computed(() => {
|
||||
return props.processColor;
|
||||
});
|
||||
// 后置背景色
|
||||
const rearColor = computed(() => {
|
||||
return props.backColor;
|
||||
});
|
||||
function calcProcess(totalNum) {
|
||||
!showMask.value && (showMask.value = true);
|
||||
currentNum.value += 1;
|
||||
progressValue.value = ((currentNum.value / totalNum) * 100).toFixed(2);
|
||||
console.log('currentNum.value', currentNum.value);
|
||||
console.log('totalNum.value', totalNum);
|
||||
if (currentNum.value == totalNum) {
|
||||
showMask.value = false;
|
||||
currentNum.value = 0;
|
||||
progressValue.value = 0;
|
||||
}
|
||||
}
|
||||
defineExpose({
|
||||
calcProcess,
|
||||
showMask,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
//noinspection LessUnresolvedVariable
|
||||
@prefix-cls: ~'@{namespace}-tinymce-process-mask';
|
||||
|
||||
.@{prefix-cls} {
|
||||
|
||||
& {
|
||||
position: absolute; /* 或者使用固定定位等其他方式 */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5); /* 半透明遮罩 */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.progress-bar-rear {
|
||||
width: 100px; /* 进度条宽度 */
|
||||
height: 10px; /* 进度条高度 */
|
||||
background-color: v-bind(rearColor); /* 进度条颜色 */
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.progress-bar-front {
|
||||
height: 10px; /* 进度条高度 */
|
||||
background-color: v-bind(frontColor); /* 进度条颜色 */
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #fff;
|
||||
margin-left: 5px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@ -153,6 +153,7 @@
|
||||
import presetQuestion from './presetQuestion.vue';
|
||||
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { message, Modal, Tabs } from 'ant-design-vue';
|
||||
import { isObject, isString } from '/@/utils/is';
|
||||
import '../style/github-markdown.less';
|
||||
import '../style/highlight.less';
|
||||
import '../style/style.less';
|
||||
@ -250,40 +251,46 @@
|
||||
// 当从事件源接收到数据时触发
|
||||
evtSource.onmessage = function (e) {
|
||||
const data = e.data;
|
||||
// console.log(e);
|
||||
if (data === '[DONE]') {
|
||||
updateChatSome(uuid, props.chatData.length - 1, { loading: false });
|
||||
scrollToBottom();
|
||||
handleStop();
|
||||
evtSource.close(); // 关闭连接
|
||||
} else {
|
||||
try {
|
||||
const _data = JSON.parse(data);
|
||||
const content = _data.content;
|
||||
if (content != undefined) {
|
||||
lastText += content;
|
||||
updateChat(uuid.value, props.chatData.length - 1, {
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: lastText,
|
||||
inversion: false,
|
||||
error: false,
|
||||
loading: true,
|
||||
conversationOptions: e.lastEventId == '[ERR]' ? null : { conversationId: data.conversationId, parentMessageId: e.lastEventId },
|
||||
requestOptions: { prompt: message, options: { ...options } },
|
||||
});
|
||||
scrollToBottom();
|
||||
} else {
|
||||
updateChatSome(uuid.value, props.chatData.length - 1, { loading: false });
|
||||
scrollToBottom();
|
||||
handleStop();
|
||||
}
|
||||
} catch (error) {
|
||||
updateChatSome(uuid.value, props.chatData.length - 1, { loading: false });
|
||||
let delay = 0;
|
||||
setTimeout(() => {
|
||||
if (data === '[DONE]') {
|
||||
updateChatSome(uuid, props.chatData.length - 1, { loading: false });
|
||||
scrollToBottom();
|
||||
handleStop();
|
||||
evtSource.close(); // 关闭连接
|
||||
} else {
|
||||
try {
|
||||
const _data = JSON.parse(data);
|
||||
const content = _data.content;
|
||||
if (content != undefined) {
|
||||
lastText += content;
|
||||
updateChat(uuid.value, props.chatData.length - 1, {
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: lastText,
|
||||
inversion: false,
|
||||
error: false,
|
||||
loading: true,
|
||||
conversationOptions: e.lastEventId == '[ERR]' ? null : { conversationId: data.conversationId, parentMessageId: e.lastEventId },
|
||||
requestOptions: { prompt: message, options: { ...options } },
|
||||
});
|
||||
scrollToBottom();
|
||||
} else {
|
||||
// updateChatSome(uuid.value, props.chatData.length - 1, { loading: false });
|
||||
// scrollToBottom();
|
||||
// handleStop();
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log('ai 聊天:::', error);
|
||||
if (isObject(error) && isString(error.message) && error.message.endsWith('is not valid JSON')) {
|
||||
return;
|
||||
}
|
||||
updateChatSome(uuid.value, props.chatData.length - 1, { loading: false });
|
||||
scrollToBottom();
|
||||
handleStop();
|
||||
evtSource.close(); // 关闭连接
|
||||
}
|
||||
}
|
||||
}
|
||||
}, delay);
|
||||
};
|
||||
// 与事件源的连接无法打开时触发
|
||||
evtSource.onerror = function (e) {
|
||||
@ -347,6 +354,7 @@
|
||||
};
|
||||
// 停止响应
|
||||
const handleStop = () => {
|
||||
console.log('ai 聊天:::---停止响应');
|
||||
if (loading.value) {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
@ -94,4 +94,15 @@ export function definedComponent() {
|
||||
// addComponent(JVxeTypes.userSelect, JVxeUserSelectCell)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空注册的组件
|
||||
*/
|
||||
export function clearComponent() {
|
||||
componentMap.clear();
|
||||
|
||||
// update-begin--author:liaozhiyang---date:20231208---for:【issues/860】生成的一对多代码,热更新之后点击新增卡死[暂时先解决]
|
||||
import.meta.env.DEV && (window[JVxeComponents] = componentMap);
|
||||
// update-end--author:liaozhiyang---date:20231208---for:【issues/860】生成的一对多代码,热更新之后点击新增卡死[暂时先解决]
|
||||
}
|
||||
|
||||
export { componentMap };
|
||||
|
||||
@ -5,15 +5,17 @@
|
||||
<template #buttons>
|
||||
<div :class="`${prefixCls}-button div`" :size="btnSize">
|
||||
<slot v-if="showPrefix" name="toolbarPrefix" :size="btnSize" />
|
||||
<a-button v-if="showAdd" type="primary" preIcon="ant-design:plus-outlined" :disabled="disabled" :loading="deleting" @click="trigger('add')">
|
||||
<span>新增</span>
|
||||
<a-button v-if="addBtnCfg.enabled && showAdd" type="primary" :preIcon="addBtnCfg.buttonIcon" :disabled="disabled" :loading="deleting" @click="trigger('add')">
|
||||
<span>{{ addBtnCfg.buttonName }}</span>
|
||||
</a-button>
|
||||
<a-button v-if="showSave" preIcon="ant-design:save-outlined" :disabled="disabled" @click="trigger('save')">
|
||||
<span>保存</span>
|
||||
</a-button>
|
||||
<template v-if="deleting || selectedRowIds.length > 0">
|
||||
<Popconfirm v-if="showRemove" :title="`确定要删除这 ${selectedRowIds.length} 项吗?`" :disabled="deleting" @confirm="onRemove">
|
||||
<a-button preIcon="ant-design:minus-outlined" :disabled="disabled" :loading="deleting">删除</a-button>
|
||||
<Popconfirm v-if="removeBtnCfg.enabled && showRemove" :title="`确定要删除这 ${selectedRowIds.length} 项吗?`" :disabled="deleting" @confirm="onRemove">
|
||||
<a-button :preIcon="removeBtnCfg.buttonIcon" :disabled="disabled" :loading="deleting">
|
||||
<span>{{ removeBtnCfg.buttonName }}</span>
|
||||
</a-button>
|
||||
</Popconfirm>
|
||||
<template v-if="showClearSelection">
|
||||
<a-button preIcon="ant-design:delete-outlined" @click="trigger('clearSelection')">清空选择</a-button>
|
||||
@ -46,6 +48,16 @@
|
||||
disabledRows: propTypes.object,
|
||||
hasBtnAuth: propTypes.func,
|
||||
selectedRowIds: propTypes.array.def(() => []),
|
||||
addBtnCfg: propTypes.object.def(() => ({
|
||||
enabled: true,
|
||||
buttonIcon: 'ant-design:plus-outlined',
|
||||
buttonName: '新增',
|
||||
})),
|
||||
removeBtnCfg: propTypes.object.def(() => ({
|
||||
enabled: true,
|
||||
buttonIcon: 'ant-design:minus-outlined',
|
||||
buttonName: '删除',
|
||||
})),
|
||||
});
|
||||
const emit = defineEmits(['save', 'add', 'remove', 'clearSelection', 'register']);
|
||||
const xToolbarRef = ref({} as VxeToolbarInstance);
|
||||
|
||||
@ -10,8 +10,10 @@
|
||||
<a-menu>
|
||||
<a-menu-item key="0" :disabled="disabledMoveUp" @click="handleRowMoveUp">向上移</a-menu-item>
|
||||
<a-menu-item key="1" :disabled="disabledMoveDown" @click="handleRowMoveDown">向下移</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="3" @click="handleRowInsertDown">插入一行</a-menu-item>
|
||||
<template v-if="allowInsertRow">
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="3" @click="handleRowInsertDown">插入一行</a-menu-item>
|
||||
</template>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
@ -48,6 +50,9 @@
|
||||
const disabledMoveUp = computed(() => rowIndex.value === 0);
|
||||
const disabledMoveDown = computed(() => rowIndex.value === fullDataLength.value - 1);
|
||||
|
||||
// 是否允许插入行
|
||||
const allowInsertRow = computed(() => originColumn.value.insertRow);
|
||||
|
||||
/** 向上移 */
|
||||
function handleRowMoveUp() {
|
||||
if (!disabledMoveUp.value) {
|
||||
@ -79,7 +84,8 @@
|
||||
handleRowMoveUp,
|
||||
handleRowMoveDown,
|
||||
handleRowInsertDown,
|
||||
isAllowDrag
|
||||
isAllowDrag,
|
||||
allowInsertRow,
|
||||
};
|
||||
},
|
||||
// 【组件增强】注释详见:JVxeComponent.Enhanced
|
||||
|
||||
@ -30,7 +30,8 @@ export function useColumns(props: JVxeTableProps, data: JVxeDataProps, methods:
|
||||
// handle 方法参数
|
||||
const args: HandleArgs = { props, slots, data, methods, columns };
|
||||
let seqColumn, selectionColumn, expandColumn, dragSortColumn;
|
||||
props.columns.forEach((column: JVxeColumn) => {
|
||||
|
||||
const handleColumn = (column: JVxeColumn, container: JVxeColumn[]) => {
|
||||
// 排除未授权的列 1 = 显示/隐藏; 2 = 禁用
|
||||
let auth = methods.getColAuth(column.key);
|
||||
if (auth?.type == '1' && !auth.isAuth) {
|
||||
@ -47,6 +48,15 @@ export function useColumns(props: JVxeTableProps, data: JVxeDataProps, methods:
|
||||
if (col.type === JVxeTypes.hidden) {
|
||||
return handleInnerColumn(args, col, handleHiddenColumn);
|
||||
}
|
||||
// 处理子级列
|
||||
// 判断是否是分组列,如果当前是父级,则无需处理 render
|
||||
if (Array.isArray(col.children) && col.children.length > 0) {
|
||||
const children: JVxeColumn[] = [];
|
||||
col.children.forEach((child: JVxeColumn) => handleColumn(child, children));
|
||||
col.children = children;
|
||||
container.push(col);
|
||||
return;
|
||||
}
|
||||
// 组件未注册,自动设置为 normal
|
||||
if (!isRegistered(col.type)) {
|
||||
col.type = JVxeTypes.normal;
|
||||
@ -72,21 +82,25 @@ export function useColumns(props: JVxeTableProps, data: JVxeDataProps, methods:
|
||||
};
|
||||
if (col.type === JVxeTypes.rowNumber) {
|
||||
seqColumn = col;
|
||||
columns.push(col);
|
||||
container.push(col);
|
||||
} else if (col.type === JVxeTypes.rowRadio || col.type === JVxeTypes.rowCheckbox) {
|
||||
selectionColumn = col;
|
||||
columns.push(col);
|
||||
container.push(col);
|
||||
} else if (col.type === JVxeTypes.rowExpand) {
|
||||
expandColumn = col;
|
||||
columns.push(col);
|
||||
container.push(col);
|
||||
} else if (col.type === JVxeTypes.rowDragSort) {
|
||||
dragSortColumn = col;
|
||||
columns.push(col);
|
||||
container.push(col);
|
||||
} else {
|
||||
col.params = column;
|
||||
args.columns = container;
|
||||
handlerCol(args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
props.columns.forEach((column: JVxeColumn) => handleColumn(column, columns));
|
||||
|
||||
handleInnerColumn(args, seqColumn, handleSeqColumn);
|
||||
handleInnerColumn(args, selectionColumn, handleSelectionColumn);
|
||||
handleInnerColumn(args, expandColumn, handleExpandColumn);
|
||||
@ -250,6 +264,7 @@ function handleDragSortColumn({ props, data, col, columns, renderOptions }: Hand
|
||||
align: 'center',
|
||||
// update-begin--author:liaozhiyang---date:20240417---for:【QQYUN-8785】online表单列位置的id未做限制,拖动其他列到id列上面,同步数据库时报错
|
||||
params: {
|
||||
insertRow: props.insertRow,
|
||||
notAllowDrag: props.notAllowDrag,
|
||||
...col?.params,
|
||||
},
|
||||
|
||||
@ -455,7 +455,9 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
/** 获取表格表单里的值 */
|
||||
function getValues(callback, rowIds) {
|
||||
let tableData = getTableData({ rowIds: rowIds });
|
||||
callback('', tableData);
|
||||
// update-begin--author:liaozhiyang---date:20241227---for:【issues/7631】JVxeTable组件的getValues回调函数参数修正
|
||||
callback(tableData, tableData);
|
||||
// update-end--author:liaozhiyang---date:20241227---for:【issues/7631】JVxeTable组件的getValues回调函数参数修正
|
||||
}
|
||||
|
||||
type getTableDataOptions = {
|
||||
@ -638,7 +640,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
async function clearSelection() {
|
||||
const xTable = getXTable();
|
||||
let event = { $table: xTable, target: instanceRef.value };
|
||||
if (props.rowSelectionType === JVxeTypes.rowRadio) {
|
||||
if (['radio', JVxeTypes.rowRadio].includes(props.rowSelectionType ?? '')) {
|
||||
await xTable.clearRadioRow();
|
||||
handleVxeRadioChange(event);
|
||||
} else {
|
||||
@ -653,7 +655,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
*/
|
||||
function getSelectionData(isFull?: boolean) {
|
||||
const xTable = getXTable();
|
||||
if (props.rowSelectionType === JVxeTypes.rowRadio) {
|
||||
if (['radio', JVxeTypes.rowRadio].includes(props.rowSelectionType ?? '')) {
|
||||
let row = xTable.getRadioRecord(isFull);
|
||||
if (isNull(row)) {
|
||||
return [];
|
||||
@ -740,7 +742,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
async function removeSelection() {
|
||||
let xTable = getXTable();
|
||||
let res;
|
||||
if (props.rowSelectionType === JVxeTypes.rowRadio) {
|
||||
if (['radio', JVxeTypes.rowRadio].includes(props.rowSelectionType ?? '')) {
|
||||
res = await xTable.removeRadioRow();
|
||||
} else {
|
||||
res = await xTable.removeCheckboxRow();
|
||||
@ -857,7 +859,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
||||
function getSelectedData(isFull?: boolean) {
|
||||
const xTable = getXTable();
|
||||
let rows:any[] = []
|
||||
if (props.rowSelectionType === JVxeTypes.rowRadio) {
|
||||
if (['radio', JVxeTypes.rowRadio].includes(props.rowSelectionType ?? '')) {
|
||||
let row = xTable.getRadioRecord(isFull);
|
||||
if (isNull(row)) {
|
||||
return [];
|
||||
|
||||
@ -16,6 +16,8 @@ export function useToolbar(props: JVxeTableProps, data: JVxeDataProps, methods:
|
||||
hasBtnAuth: methods.hasBtnAuth,
|
||||
selectedRowIds: data.selectedRowIds.value,
|
||||
custom: props.custom,
|
||||
addBtnCfg: props.addBtnCfg,
|
||||
removeBtnCfg: props.removeBtnCfg,
|
||||
// 新增事件
|
||||
onAdd: () => {
|
||||
// update-begin--author:liaozhiyang---date:20240521---for:【TV360X-212】online新增字段就出校验提示
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
/* JVxeTable 行编辑 权限 */
|
||||
import { usePermissionStoreWithOut } from '/@/store/modules/permission';
|
||||
|
||||
const permissionStore = usePermissionStoreWithOut();
|
||||
|
||||
/**
|
||||
* JVxe 专用,获取权限
|
||||
* @param prefix
|
||||
*/
|
||||
export function getJVxeAuths(prefix) {
|
||||
const permissionStore = usePermissionStoreWithOut();
|
||||
prefix = getPrefix(prefix);
|
||||
let { authList, allAuthList } = permissionStore;
|
||||
let authsMap = new Map<string, typeof allAuthList[0]>();
|
||||
|
||||
@ -42,6 +42,8 @@ export const vxeProps = () => ({
|
||||
rowExpand: propTypes.bool.def(false),
|
||||
// 展开行配置
|
||||
expandConfig: propTypes.object.def(() => ({})),
|
||||
// 是否可插入行
|
||||
insertRow: propTypes.bool.def(true),
|
||||
// 页面是否在加载中
|
||||
loading: propTypes.bool.def(false),
|
||||
// 表格高度
|
||||
@ -113,6 +115,11 @@ export const vxeProps = () => ({
|
||||
// 不允许拖拽的行 [{'key':field,'value':value}]
|
||||
notAllowDrag: propTypes.array.def(() => []),
|
||||
// update-end--author:liaozhiyang---date:20240417---for:【QQYUN-8785】online表单列位置的id未做限制,拖动其他列到id列上面,同步数据库时报错
|
||||
|
||||
// 新增按钮配置
|
||||
addBtnCfg: propTypes.object,
|
||||
// 删除按钮配置
|
||||
removeBtnCfg: propTypes.object,
|
||||
});
|
||||
|
||||
export const vxeEmits = ['save', 'added', 'removed', 'inserted', 'dragged', 'selectRowChange', 'pageChange', 'valueChange', 'blur'];
|
||||
|
||||
@ -70,9 +70,12 @@
|
||||
// update-begin--author:liaozhiyang---date:20231218---for:【QQYUN-6366】升级到antd4.x
|
||||
.ant-modal {
|
||||
.ant-modal-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// right: 0;
|
||||
top: 13px;
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@ -13,6 +13,10 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
|
||||
VITE_GLOB_APP_OPEN_QIANKUN,
|
||||
VITE_GLOB_DOMAIN_URL,
|
||||
VITE_GLOB_ONLINE_VIEW_URL,
|
||||
|
||||
// 【JEECG作为乾坤子应用】
|
||||
VITE_GLOB_QIANKUN_MICRO_APP_NAME,
|
||||
VITE_GLOB_QIANKUN_MICRO_APP_ENTRY,
|
||||
} = getAppEnvConfig();
|
||||
|
||||
// if (!/[a-zA-Z\_]*/.test(VITE_GLOB_APP_SHORT_NAME)) {
|
||||
@ -36,7 +40,19 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
|
||||
urlPrefix: VITE_GLOB_API_URL_PREFIX,
|
||||
uploadUrl: VITE_GLOB_DOMAIN_URL,
|
||||
viewUrl: VITE_GLOB_ONLINE_VIEW_URL,
|
||||
|
||||
// 【JEECG作为乾坤子应用】是否以乾坤子应用模式启动
|
||||
isQiankunMicro: VITE_GLOB_QIANKUN_MICRO_APP_NAME != null && VITE_GLOB_QIANKUN_MICRO_APP_NAME !== '',
|
||||
// 【JEECG作为乾坤子应用】乾坤子应用入口
|
||||
qiankunMicroAppEntry: VITE_GLOB_QIANKUN_MICRO_APP_ENTRY,
|
||||
};
|
||||
|
||||
// 【JEECG作为乾坤子应用】乾坤子应用下,需要定义一下
|
||||
if (!window['_CONFIG']) {
|
||||
window['_CONFIG'] = {}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
window._CONFIG['domianURL'] = VITE_GLOB_DOMAIN_URL;
|
||||
return glob as Readonly<GlobConfig>;
|
||||
};
|
||||
|
||||
@ -34,13 +34,19 @@ export function useMethods() {
|
||||
reader.onload = async () => {
|
||||
if(reader.result){
|
||||
if(reader.result.toString().indexOf("success") !=-1){
|
||||
const { success, message } = JSON.parse(reader.result.toString());
|
||||
if (!success) {
|
||||
createMessage.warning("导出失败,失败原因:"+ message);
|
||||
}else{
|
||||
// update-begin---author:liaozhiyang---date:2025-02-11---for:【issues/7738】文件中带"success"导出报错 ---
|
||||
try {
|
||||
const { success, message } = JSON.parse(reader.result.toString());
|
||||
if (!success) {
|
||||
createMessage.warning('导出失败,失败原因:' + message);
|
||||
} else {
|
||||
exportExcel(name, isXlsx, data);
|
||||
}
|
||||
return;
|
||||
} catch (error) {
|
||||
exportExcel(name, isXlsx, data);
|
||||
}
|
||||
return;
|
||||
// update-end---author:liaozhiyang---date:2025-02-11---for:【issues/7738】文件中带"success"导出报错 ---
|
||||
}
|
||||
}
|
||||
exportExcel(name, isXlsx, data);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :style="getPlaceholderDomStyle" v-if="getIsShowPlaceholderDom"></div>
|
||||
<div :style="getWrapStyle" :class="getClass">
|
||||
<LayoutHeader v-if="getShowInsetHeaderRef" />
|
||||
<LayoutHeader v-if="getShowHeader" />
|
||||
<MultipleTabs v-if="getShowTabs" />
|
||||
</div>
|
||||
</template>
|
||||
@ -11,6 +11,8 @@
|
||||
import LayoutHeader from './index.vue';
|
||||
import MultipleTabs from '../tabs/index.vue';
|
||||
|
||||
import { useAppStore } from "@/store/modules/app";
|
||||
import { useGlobSetting } from "/@/hooks/setting";
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||
@ -19,6 +21,8 @@
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useLayoutHeight } from '../content/useContentViewHeight';
|
||||
import { TabsThemeEnum } from '/@/enums/appEnum';
|
||||
import { MenuTypeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
// update-begin--author:liaozhiyang---date:20240407---for:【QQYUN-8774】网站header区域加高
|
||||
const HEADER_HEIGHT = 60;
|
||||
// update-begin--author:liaozhiyang---date:20240407---for:【【QQYUN-8774】网站header区域加高
|
||||
@ -35,15 +39,30 @@
|
||||
const { setHeaderHeight } = useLayoutHeight();
|
||||
const { prefixCls } = useDesign('layout-multiple-header');
|
||||
|
||||
const { getCalcContentWidth, getSplit } = useMenuSetting();
|
||||
const appStore = useAppStore()
|
||||
const glob = useGlobSetting()
|
||||
|
||||
const { getCalcContentWidth, getSplit, getMenuType } = useMenuSetting();
|
||||
const { getIsMobile } = useAppInject();
|
||||
const { getFixed, getShowInsetHeaderRef, getShowFullHeaderRef, getHeaderTheme, getShowHeader } = useHeaderSetting();
|
||||
const { getFixed, getShowInsetHeaderRef, getShowFullHeaderRef, getHeaderTheme } = useHeaderSetting();
|
||||
|
||||
const { getFullContent } = useFullContent();
|
||||
|
||||
const { getShowMultipleTab, getTabsTheme } = useMultipleTabSetting();
|
||||
|
||||
const getShowHeader = computed(() => {
|
||||
// 控制是否显示顶部
|
||||
if (appStore.mainAppProps.hideHeader) {
|
||||
return false;
|
||||
}
|
||||
return unref(getShowInsetHeaderRef);
|
||||
})
|
||||
|
||||
const getShowTabs = computed(() => {
|
||||
// 控制是否显示多Tabs切换
|
||||
if (appStore.mainAppProps.hideMultiTabs) {
|
||||
return false;
|
||||
}
|
||||
return unref(getShowMultipleTab) && !unref(getFullContent);
|
||||
});
|
||||
|
||||
@ -53,7 +72,7 @@
|
||||
|
||||
const getWrapStyle = computed((): CSSProperties => {
|
||||
const style: CSSProperties = {};
|
||||
if (unref(getFixed)) {
|
||||
if (unref(getFixed) && !glob.isQiankunMicro) {
|
||||
style.width = unref(getIsMobile) ? '100%' : unref(getCalcContentWidth);
|
||||
}
|
||||
if (unref(getShowFullHeaderRef)) {
|
||||
@ -80,10 +99,12 @@
|
||||
|
||||
const getPlaceholderDomStyle = computed((): CSSProperties => {
|
||||
let height = 0;
|
||||
if ((unref(getShowFullHeaderRef) || !unref(getSplit)) && unref(getShowHeader) && !unref(getFullContent)) {
|
||||
// update-begin--author:liaozhiyang---date:20241216---for:【issues/7561】主题切换为顶部混合模式时,页面顶部内容显示不出来,被遮盖
|
||||
if ((unref(getShowFullHeaderRef) || !unref(getSplit)) && unref(getShowHeader) && !unref(getFullContent) || unref(getMenuType) == MenuTypeEnum.MIX) {
|
||||
height += HEADER_HEIGHT;
|
||||
}
|
||||
if (unref(getShowMultipleTab) && !unref(getFullContent)) {
|
||||
// update-end--author:liaozhiyang---date:20241216---for:【issues/7561】主题切换为顶部混合模式时,页面顶部内容显示不出来,被遮盖
|
||||
if (unref(getShowTabs) && !unref(getFullContent)) {
|
||||
height += unref(getTabsThemeHeight);
|
||||
}
|
||||
setHeaderHeight(height);
|
||||
@ -93,10 +114,15 @@
|
||||
});
|
||||
|
||||
const getClass = computed(() => {
|
||||
return [prefixCls, `${prefixCls}--${unref(getHeaderTheme)}`, { [`${prefixCls}--fixed`]: unref(getIsFixed) }];
|
||||
return [prefixCls, `${prefixCls}--${unref(getHeaderTheme)}`, {
|
||||
[`${prefixCls}--fixed`]: unref(getIsFixed),
|
||||
// 【JEECG作为乾坤子应用】
|
||||
[`${prefixCls}--qiankun-micro`]: glob.isQiankunMicro,
|
||||
}];
|
||||
});
|
||||
|
||||
return {
|
||||
glob,
|
||||
getClass,
|
||||
prefixCls,
|
||||
getPlaceholderDomStyle,
|
||||
@ -104,7 +130,7 @@
|
||||
getWrapStyle,
|
||||
getIsShowPlaceholderDom,
|
||||
getShowTabs,
|
||||
getShowInsetHeaderRef,
|
||||
getShowHeader,
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -126,5 +152,11 @@
|
||||
z-index: @multiple-tab-fixed-z-index;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// 【JEECG作为乾坤子应用】
|
||||
&--qiankun-micro {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -129,6 +129,9 @@
|
||||
// update-begin--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
||||
createMessage.success(t('layout.header.refreshCacheComplete'));
|
||||
// update-end--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
||||
// update-begin--author:wangshuai---date:20241112---for:【issues/7433】vue3 数据字典优化建议
|
||||
userStore.setAllDictItems(res.result);
|
||||
// update-end--author:wangshuai---date:20241112---for:【issues/7433】vue3 数据字典优化建议
|
||||
} else {
|
||||
// update-begin--author:liaozhiyang---date:20240124---for:【QQYUN-7970】国际化
|
||||
createMessage.error(t('layout.header.refreshCacheFailure'));
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
|
||||
<SettingDrawer v-if="getShowSetting" :class="`${prefixCls}-action__item`" />
|
||||
<!-- ai助手 -->
|
||||
<!--<Aide></Aide>-->
|
||||
<Aide></Aide>
|
||||
</div>
|
||||
</Header>
|
||||
<LoginSelect ref="loginSelectRef" @success="loginSelectOk"></LoginSelect>
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
import { ScrollContainer } from '/@/components/Container';
|
||||
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
import { useGlobSetting } from "/@/hooks/setting";
|
||||
import { useSplitMenu } from './useLayoutMenu';
|
||||
import { openWindow } from '/@/utils';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
@ -56,6 +57,8 @@
|
||||
|
||||
const { prefixCls } = useDesign('layout-menu');
|
||||
|
||||
const glob = useGlobSetting()
|
||||
|
||||
const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
|
||||
|
||||
const { getIsMobile } = useAppInject();
|
||||
@ -67,6 +70,11 @@
|
||||
const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
|
||||
|
||||
const getUseScroll = computed(() => {
|
||||
// 【JEECG作为乾坤子应用】在乾坤子应用下,菜单不固定
|
||||
if (glob.isQiankunMicro) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
!unref(getIsHorizontal) &&
|
||||
(unref(getIsSidebarType) || props.splitType === MenuSplitTyeEnum.LEFT || props.splitType === MenuSplitTyeEnum.NONE)
|
||||
@ -75,7 +83,9 @@
|
||||
|
||||
const getWrapperStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
|
||||
// update-begin--author:liaozhiyang---date:20241216---for:【issues/7548】侧边栏导航模式时会导致下面菜单滚动显示不全
|
||||
height: `calc(100% - ${unref(getIsShowLogo) ? '60px' : '0px'})`,
|
||||
// update-end--author:liaozhiyang---date:20241216---for:【issues/7548】侧边栏导航模式时会导致下面菜单滚动显示不全
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@ -30,12 +30,15 @@
|
||||
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
import { useAppStore } from "@/store/modules/app";
|
||||
import { useGlobSetting } from "/@/hooks/setting";
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useTrigger, useDragLine, useSiderEvent } from './useLayoutSider';
|
||||
import { useAppInject } from '/@/hooks/web/useAppInject';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
import DragBar from './DragBar.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutSideBar',
|
||||
components: { Sider: Layout.Sider, LayoutMenu, DragBar, LayoutTrigger },
|
||||
@ -48,6 +51,9 @@
|
||||
|
||||
const { prefixCls } = useDesign('layout-sideBar');
|
||||
|
||||
const glob = useGlobSetting()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const { getIsMobile } = useAppInject();
|
||||
|
||||
const { getTriggerAttr, getShowTrigger } = useTrigger(getIsMobile);
|
||||
@ -65,6 +71,10 @@
|
||||
});
|
||||
|
||||
const showClassSideBarRef = computed(() => {
|
||||
// 控制是否显示侧边栏
|
||||
if (appStore.mainAppProps.hideSider) {
|
||||
return false;
|
||||
}
|
||||
return unref(getSplit) ? !unref(getMenuHidden) : true;
|
||||
});
|
||||
|
||||
@ -74,6 +84,8 @@
|
||||
{
|
||||
[`${prefixCls}--fixed`]: unref(getMenuFixed),
|
||||
[`${prefixCls}--mix`]: unref(getIsMixMode) && !unref(getIsMobile),
|
||||
// 【JEECG作为乾坤子应用】
|
||||
[`${prefixCls}--qiankun-micro`]: glob.isQiankunMicro,
|
||||
},
|
||||
];
|
||||
});
|
||||
@ -131,6 +143,11 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// 【JEECG作为乾坤子应用】
|
||||
&--qiankun-micro {
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
&--mix {
|
||||
top: @header-height;
|
||||
height: calc(100% - @header-height);
|
||||
|
||||
@ -145,7 +145,9 @@ html[data-theme='light'] {
|
||||
}
|
||||
|
||||
.ant-tabs-extra-content {
|
||||
margin-top: 2px;
|
||||
// update-begin--author:liaozhiyang---date:20241016---for:【issues/7345】标签样式切换到极简模式样式错乱
|
||||
// margin-top: 2px;
|
||||
// update-end--author:liaozhiyang---date:20241016---for:【issues/7345】标签样式切换到极简模式样式错乱
|
||||
line-height: @multiple-height !important;
|
||||
}
|
||||
|
||||
|
||||
@ -19,18 +19,21 @@
|
||||
</template>
|
||||
|
||||
<template #rightExtra v-if="getShowRedo || getShowQuick">
|
||||
<TabRedo v-if="getShowRedo" />
|
||||
<!-- <TabContent isExtra :tabItem="$route" v-if="getShowQuick" /> -->
|
||||
<!-- 列表页全屏
|
||||
<FoldButton v-if="getShowFold" />-->
|
||||
<!-- <FullscreenOutlined /> -->
|
||||
<router-link to="/ai" class="ai-icon">
|
||||
<a-tooltip title="AI助手" placement="left">
|
||||
<svg t="1706259688149" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2056" width="17" height="17">
|
||||
<path d="M826.368 325.632c0-7.168 2.048-10.24 10.24-10.24h123.904c7.168 0 10.24 2.048 10.24 10.24v621.568c0 7.168-2.048 10.24-10.24 10.24h-122.88c-8.192 0-10.24-4.096-10.24-10.24l-1.024-621.568z m-8.192-178.176c0-50.176 35.84-79.872 79.872-79.872 48.128 0 79.872 32.768 79.872 79.872 0 52.224-33.792 79.872-81.92 79.872-46.08 1.024-77.824-27.648-77.824-79.872zM462.848 584.704C441.344 497.664 389.12 307.2 368.64 215.04h-2.048c-16.384 92.16-58.368 247.808-92.16 369.664h188.416zM243.712 712.704l-62.464 236.544c-2.048 7.168-4.096 8.192-12.288 8.192H54.272c-8.192 0-10.24-2.048-8.192-12.288l224.256-783.36c4.096-13.312 7.168-26.624 8.192-65.536 0-6.144 2.048-8.192 7.168-8.192H450.56c6.144 0 8.192 2.048 10.24 8.192l250.88 849.92c2.048 7.168 0 10.24-7.168 10.24H573.44c-7.168 0-10.24-2.048-12.288-7.168l-65.536-236.544c1.024 1.024-251.904 0-251.904 0z" fill="#333333" p-id="19816"></path>
|
||||
</svg>
|
||||
</a-tooltip>
|
||||
</router-link>
|
||||
<div class="rightExtra">
|
||||
<TabRedo v-if="getShowRedo" />
|
||||
<!-- <TabContent isExtra :tabItem="$route" v-if="getShowQuick" /> -->
|
||||
<!-- 列表页全屏
|
||||
<FoldButton v-if="getShowFold" />-->
|
||||
<!-- <FullscreenOutlined /> -->
|
||||
<router-link to="/ai" class="ai-icon">
|
||||
<a-tooltip title="AI助手" placement="left">
|
||||
<!-- <svg t="1706259688149" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2056" width="17" height="17">-->
|
||||
<!-- <path d="M826.368 325.632c0-7.168 2.048-10.24 10.24-10.24h123.904c7.168 0 10.24 2.048 10.24 10.24v621.568c0 7.168-2.048 10.24-10.24 10.24h-122.88c-8.192 0-10.24-4.096-10.24-10.24l-1.024-621.568z m-8.192-178.176c0-50.176 35.84-79.872 79.872-79.872 48.128 0 79.872 32.768 79.872 79.872 0 52.224-33.792 79.872-81.92 79.872-46.08 1.024-77.824-27.648-77.824-79.872zM462.848 584.704C441.344 497.664 389.12 307.2 368.64 215.04h-2.048c-16.384 92.16-58.368 247.808-92.16 369.664h188.416zM243.712 712.704l-62.464 236.544c-2.048 7.168-4.096 8.192-12.288 8.192H54.272c-8.192 0-10.24-2.048-8.192-12.288l224.256-783.36c4.096-13.312 7.168-26.624 8.192-65.536 0-6.144 2.048-8.192 7.168-8.192H450.56c6.144 0 8.192 2.048 10.24 8.192l250.88 849.92c2.048 7.168 0 10.24-7.168 10.24H573.44c-7.168 0-10.24-2.048-12.288-7.168l-65.536-236.544c1.024 1.024-251.904 0-251.904 0z" fill="#333333" p-id="19816"></path>-->
|
||||
<!-- </svg>-->
|
||||
<svg t="1737024931936" class="icon" viewBox="0 0 3011 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4248" width="256" height="256"><path d="M2028.242824 558.561882h415.021176V445.620706h-346.352941V321.415529h346.352941V210.823529l-328.463059 10.842353a2367.969882 2367.969882 0 0 0-31.021176-127.09647c341.955765-4.397176 602.352941-13.492706 781.131294-27.286588l41.441882 124.265411-320.933647 14.095059v115.772235h307.802353v124.205177h-307.802353v112.941176h375.506824v127.096471h-375.506824v113.844706c0 30.117647-5.782588 56.982588-17.468235 80.474353a114.447059 114.447059 0 0 1-50.778353 53.187764c-22.287059 11.926588-41.261176 19.154824-56.922353 21.684706-15.36 2.770824-82.522353 5.300706-201.426824 7.529412a5065.065412 5065.065412 0 0 0-31.984941-142.155294c64.632471 4.999529 114.447059 7.529412 149.624471 7.529412 44.574118 0 66.861176-23.190588 66.861176-69.632v-72.463059h-415.081411v-127.096471zM1685.624471 956.717176a1296.865882 1296.865882 0 0 0-27.286589-133.662117 2187.745882 2187.745882 0 0 0 96.978824 3.794823c18.191059 0 32.587294-4.758588 43.248941-14.155294 10.661647-9.697882 17.468235-23.491765 20.239059-41.381647 3.132235-17.889882 6.023529-66.379294 8.432941-145.408 2.590118-79.390118 3.614118-179.621647 3.373177-300.754823h-109.206589c-3.734588 212.389647-24.455529 364.604235-62.102588 456.523294-37.345882 91.919059-77.161412 156.491294-119.567059 193.837176-28.551529-27.888941-59.632941-54.392471-93.123764-79.510588-142.757647 12.830118-265.456941 25.298824-368.037648 37.165176l-15.962352-126.132705c14.095059-0.602353 28.190118-1.385412 42.345411-2.349177V88.003765h377.374118v687.043764c12.227765-1.204706 24.154353-2.349176 35.779765-3.312941 50.838588-95.653647 77.040941-244.555294 78.607058-446.58447h-85.172705V200.944941h87.04c0.301176-47.706353 0.481882-100.412235 0.481882-158.117647h125.168941c0 58.368-0.301176 111.073882-0.963765 158.117647H1957.647059l-9.878588 525.613177c-1.566118 62.464-5.481412 104.688941-11.745883 126.614588-6.324706 22.287059-16.805647 41.441882-31.563294 57.404235-14.757647 16.022588-32.768 27.105882-54.091294 33.430588-21.082353 6.264471-75.896471 10.480941-164.743529 12.649412z m-321.837177-759.567058h-140.227765V327.077647h140.227765V197.150118z m-140.227765 359.604706h140.227765V426.767059h-140.227765v129.867294z m140.227765 229.616941v-129.92753h-140.227765v140.288l140.227765-10.36047zM963.764706 114.326588V843.294118h-155.286588V114.326588H963.764706zM716.679529 843.294118H547.297882l-54.573176-167.032471H227.689412L174.140235 843.294118H5.662118l266.842353-728.96753h182.512941L716.739765 843.294118zM455.981176 556.212706L373.157647 303.585882c-5.300706-16.022588-9.035294-37.165176-11.264-63.548235h-4.216471a269.010824 269.010824 0 0 1-12.709647 61.680941L261.662118 556.212706H455.981176z" fill="#1F1F1F" p-id="4249"></path></svg>
|
||||
</a-tooltip>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
</Tabs>
|
||||
</div>
|
||||
@ -162,16 +165,28 @@
|
||||
:deep(.anticon) {
|
||||
display: inline-block;
|
||||
}
|
||||
.ai-icon{
|
||||
float: right;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
width: 36px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
color: @text-color;
|
||||
text-align: center;
|
||||
border-left: 1px solid @border-color-base;
|
||||
// update-begin--author:liaozhiyang---date:20241016---for:【issues/7345】标签样式切换到极简模式样式错乱
|
||||
.rightExtra {
|
||||
display: flex;
|
||||
:deep(svg) {
|
||||
&:not(.icon) {
|
||||
vertical-align: -0.3em;
|
||||
}
|
||||
}
|
||||
.ai-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
width: 50px;
|
||||
padding: 0 4px;
|
||||
height: 50px;
|
||||
color: @text-color;
|
||||
text-align: center;
|
||||
border-left: 1px solid @border-color-base;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20241016---for:【issues/7345】标签样式切换到极简模式样式错乱
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { MainAppProps } from "#/main";
|
||||
import 'uno.css';
|
||||
import '/@/design/index.less';
|
||||
import 'ant-design-vue/dist/reset.css';
|
||||
@ -8,7 +9,7 @@ import App from './App.vue';
|
||||
import { createApp } from 'vue';
|
||||
import { initAppConfigStore } from '/@/logics/initAppConfig';
|
||||
import { setupErrorHandle } from '/@/logics/error-handle';
|
||||
import { router, setupRouter } from '/@/router';
|
||||
import { router, createRouter, setupRouter } from '/@/router';
|
||||
import { setupRouterGuard } from '/@/router/guard';
|
||||
import { setupStore } from '/@/store';
|
||||
import { setupGlobDirectives } from '/@/directives';
|
||||
@ -16,20 +17,47 @@ import { setupI18n } from '/@/locales/setupI18n';
|
||||
import { registerGlobComp } from '/@/components/registerGlobComp';
|
||||
import { registerThirdComp } from '/@/settings/registerThirdComp';
|
||||
import { useSso } from '/@/hooks/web/useSso';
|
||||
import { checkIsQiankunMicro } from "/@/qiankun/micro";
|
||||
import { autoUseQiankunMicro } from "/@/qiankun/micro/qiankunMicro";
|
||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||
|
||||
// 注册online模块lib
|
||||
import { registerPackages } from '/@/utils/monorepo/registerPackages';
|
||||
|
||||
async function bootstrap() {
|
||||
// 程序入口
|
||||
async function main() {
|
||||
if (checkIsQiankunMicro()) {
|
||||
// 【JEECG作为乾坤子应用】以乾坤子应用模式启动
|
||||
// await autoUseQiankunMicro(bootstrap)
|
||||
await autoUseQiankunMicro(bootstrap)
|
||||
} else {
|
||||
// 获取参数
|
||||
const props = getMainAppProps();
|
||||
// 普通启动
|
||||
await bootstrap(props)
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
async function bootstrap(props?: MainAppProps) {
|
||||
// 创建应用实例
|
||||
const app = createApp(App);
|
||||
// 【QQYUN-6329】
|
||||
window.appRootInstance = app;
|
||||
// 多语言配置,异步情况:语言文件可以从服务器端获得
|
||||
await setupI18n(app);
|
||||
window['JAppRootInstance'] = app;
|
||||
|
||||
// 创建路由
|
||||
createRouter();
|
||||
|
||||
// 配置存储
|
||||
setupStore(app);
|
||||
|
||||
// 配置参数
|
||||
setupProps(props);
|
||||
|
||||
// 多语言配置,异步情况:语言文件可以从服务器端获得
|
||||
await setupI18n(app);
|
||||
|
||||
// 初始化内部系统配置
|
||||
initAppConfigStore();
|
||||
|
||||
@ -61,9 +89,45 @@ async function bootstrap() {
|
||||
await router.isReady();
|
||||
|
||||
// 挂载应用
|
||||
app.mount('#app', true);
|
||||
app.mount(getMountContainer(props), true);
|
||||
|
||||
console.log(" vue3 app 加载完成!")
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
// 获取应用挂载容器
|
||||
function getMountContainer(props?: MainAppProps) {
|
||||
const id = '#app';
|
||||
if (!props?.container?.querySelector) {
|
||||
return id;
|
||||
}
|
||||
return props.container.querySelector(id) ?? id;
|
||||
}
|
||||
|
||||
// 获取主应用参数
|
||||
function getMainAppProps(): MainAppProps {
|
||||
// 从 queryString 中获取
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
// 隐藏侧边栏(菜单)
|
||||
let hideSider = searchParams.get('hideSider') === 'true';
|
||||
// 隐藏顶部
|
||||
let hideHeader = searchParams.get('hideHeader') === 'true';
|
||||
// 隐藏 多Tab 切换
|
||||
let hideMultiTabs = searchParams.get('hideMultiTabs') === 'true';
|
||||
|
||||
return {
|
||||
hideSider,
|
||||
hideHeader,
|
||||
hideMultiTabs
|
||||
}
|
||||
}
|
||||
|
||||
// 配置主应用参数
|
||||
function setupProps(props?: MainAppProps) {
|
||||
if (!props) {
|
||||
return
|
||||
}
|
||||
const appStore = useAppStoreWithOut();
|
||||
appStore.setMainAppProps(props);
|
||||
}
|
||||
|
||||
12
jeecgboot-vue3/src/qiankun/micro/index.ts
Normal file
12
jeecgboot-vue3/src/qiankun/micro/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import {qiankunWindow} from 'vite-plugin-qiankun/dist/helper'
|
||||
|
||||
/**
|
||||
* 【JEECG作为乾坤子应用】【判断当前是否是以乾坤子应用的模式运行】
|
||||
*/
|
||||
export function checkIsQiankunMicro(): boolean {
|
||||
return !!qiankunWindow.__POWERED_BY_QIANKUN__;
|
||||
}
|
||||
|
||||
export function getGlobal() {
|
||||
return (checkIsQiankunMicro() ? qiankunWindow : window) as Window
|
||||
}
|
||||
57
jeecgboot-vue3/src/qiankun/micro/qiankunMicro.ts
Normal file
57
jeecgboot-vue3/src/qiankun/micro/qiankunMicro.ts
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 【JEECG作为乾坤子应用】
|
||||
*/
|
||||
import type {App} from 'vue';
|
||||
import type {MainAppProps} from "#/main";
|
||||
|
||||
import {destroyStore} from "@/store";
|
||||
import {destroyRouter} from "@/router";
|
||||
import {clearComponent} from "@/components/jeecg/JVxeTable/src/componentMap";
|
||||
|
||||
import {renderWithQiankun} from 'vite-plugin-qiankun/dist/helper';
|
||||
|
||||
/**
|
||||
* 以乾坤子应用模式运行
|
||||
* @param render
|
||||
*/
|
||||
export async function useQiankunMicroApp(render: (props?: MainAppProps) => Promise<App>) {
|
||||
let instance: Nullable<App> = null;
|
||||
|
||||
// 注册乾坤子应用生命周期函数
|
||||
renderWithQiankun({
|
||||
async mount(props) {
|
||||
console.debug('[qiankun-micro] mount - props :', props)
|
||||
instance = await render({
|
||||
container: props.container!,
|
||||
hideSider: props.hideSider,
|
||||
hideHeader: props.hideHeader,
|
||||
hideMultiTabs: props.hideMultiTabs,
|
||||
});
|
||||
},
|
||||
bootstrap() {
|
||||
console.debug('[qiankun-micro] bootstrap');
|
||||
},
|
||||
update(props) {
|
||||
console.debug('[qiankun-micro] update: ', props);
|
||||
},
|
||||
unmount(props) {
|
||||
console.debug('[qiankun-micro] unmount: ', props);
|
||||
|
||||
destroyStore();
|
||||
destroyRouter();
|
||||
|
||||
if (instance) {
|
||||
clearComponent();
|
||||
instance.unmount();
|
||||
instance._container.innerHTML = '';
|
||||
instance = null;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return instance!
|
||||
}
|
||||
|
||||
export async function autoUseQiankunMicro(fn: Fn) {
|
||||
return useQiankunMicroApp(fn)
|
||||
}
|
||||
@ -3,6 +3,9 @@ export const REDIRECT_NAME = 'Redirect';
|
||||
export const PARENT_LAYOUT_NAME = 'ParentLayout';
|
||||
|
||||
export const PAGE_NOT_FOUND_NAME = 'PageNotFound';
|
||||
// update-begin--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
export const PAGE_NOT_FOUND_NAME_404 = 'PageNotFound404';
|
||||
// update-end--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
|
||||
export const EXCEPTION_COMPONENT = () => import('/@/views/sys/exception/Exception.vue');
|
||||
|
||||
|
||||
@ -9,9 +9,10 @@ import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
|
||||
|
||||
import { RootRoute } from '/@/router/routes';
|
||||
|
||||
import { isOAuth2AppEnv } from '/@/views/sys/login/useLogin';
|
||||
import {isOAuth2AppEnv, isOAuth2DingAppEnv} from '/@/views/sys/login/useLogin';
|
||||
import { OAUTH2_THIRD_LOGIN_TENANT_ID } from "/@/enums/cacheEnum";
|
||||
import { setAuthCache } from "/@/utils/auth";
|
||||
import { PAGE_NOT_FOUND_NAME_404 } from '/@/router/constant';
|
||||
|
||||
const LOGIN_PATH = PageEnum.BASE_LOGIN;
|
||||
//auth2登录路由
|
||||
@ -158,16 +159,23 @@ export function createPermissionGuard(router: Router) {
|
||||
//==============================【首次登录并且是企业微信或者钉钉的情况下才会调用】==================
|
||||
//判断是免登录页面,如果页面包含/tenantId/,那么就直接前往主页
|
||||
if(isOAuth2AppEnv() && to.path.indexOf("/tenantId/") != -1){
|
||||
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
||||
//update-begin---author:wangshuai---date:2024-11-08---for:【TV360X-2958】钉钉登录后打开了敲敲云,换其他账号登录后,再打开敲敲云显示的是原来账号的应用---
|
||||
if (isOAuth2DingAppEnv()) {
|
||||
next(OAUTH2_LOGIN_PAGE_PATH);
|
||||
} else {
|
||||
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-11-08---for:【TV360X-2958】钉钉登录后打开了敲敲云,换其他账号登录后,再打开敲敲云显示的是原来账号的应用---
|
||||
return;
|
||||
}
|
||||
//==============================【首次登录并且是企业微信或者钉钉的情况下才会调用】==================
|
||||
|
||||
// update-begin--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
// Jump to the 404 page after processing the login
|
||||
if (from.path === LOGIN_PATH && to.name === PAGE_NOT_FOUND_ROUTE.name && to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME)) {
|
||||
if (from.path === LOGIN_PATH && to.name === PAGE_NOT_FOUND_NAME_404 && to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME)) {
|
||||
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
||||
return;
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
|
||||
//update-begin---author:scott ---date:2024-02-21 for:【QQYUN-8326】刷新首页,不需要重新获取用户信息---
|
||||
// // get userinfo while last fetch time is empty
|
||||
@ -199,8 +207,8 @@ export function createPermissionGuard(router: Router) {
|
||||
|
||||
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw);
|
||||
permissionStore.setDynamicAddedRoute(true);
|
||||
|
||||
if (to.name === PAGE_NOT_FOUND_ROUTE.name) {
|
||||
// update-begin--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
if (to.name === PAGE_NOT_FOUND_NAME_404) {
|
||||
// 动态添加路由后,此处应当重定向到fullPath,否则会加载404页面内容
|
||||
next({ path: to.fullPath, replace: true, query: to.query });
|
||||
} else {
|
||||
@ -209,5 +217,6 @@ export function createPermissionGuard(router: Router) {
|
||||
const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect };
|
||||
next(nextData);
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import type { App } from 'vue';
|
||||
|
||||
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
|
||||
import { basicRoutes } from './routes';
|
||||
import {createRouter as createVueRouter, destroyRouter, router} from './router'
|
||||
|
||||
// 白名单应该包含基本静态路由
|
||||
const WHITE_NAME_LIST: string[] = [];
|
||||
@ -13,22 +13,26 @@ const getRouteNames = (array: any[]) =>
|
||||
});
|
||||
getRouteNames(basicRoutes);
|
||||
|
||||
// app router
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.VITE_PUBLIC_PATH),
|
||||
routes: basicRoutes as unknown as RouteRecordRaw[],
|
||||
strict: true,
|
||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||
});
|
||||
/**
|
||||
* 创建路由实例
|
||||
*/
|
||||
export function createRouter() {
|
||||
let router = createVueRouter({
|
||||
routes: basicRoutes as unknown as RouteRecordRaw[],
|
||||
strict: true,
|
||||
scrollBehavior: () => ({left: 0, top: 0}),
|
||||
})
|
||||
|
||||
// TODO 【QQYUN-4517】【表单设计器】记录分享路由守卫测试
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
//console.group('【QQYUN-4517】beforeEach');
|
||||
//console.warn('from', from);
|
||||
//console.warn('to', to);
|
||||
//console.groupEnd();
|
||||
next();
|
||||
});
|
||||
// TODO 【QQYUN-4517】【表单设计器】记录分享路由守卫测试
|
||||
// @ts-ignore
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
//console.group('【QQYUN-4517】beforeEach');
|
||||
//console.warn('from', from);
|
||||
//console.warn('to', to);
|
||||
//console.groupEnd();
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
// reset router
|
||||
export function resetRouter() {
|
||||
@ -44,3 +48,8 @@ export function resetRouter() {
|
||||
export function setupRouter(app: App<Element>) {
|
||||
app.use(router);
|
||||
}
|
||||
|
||||
export {
|
||||
router,
|
||||
destroyRouter,
|
||||
}
|
||||
|
||||
40
jeecgboot-vue3/src/router/router.ts
Normal file
40
jeecgboot-vue3/src/router/router.ts
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 路由实例存储文件,请勿轻易添加其他代码,防止出现 HMR 或其他问题
|
||||
*/
|
||||
import type {Router, RouterHistory} from 'vue-router';
|
||||
import {createRouter as createVueRouter, createWebHistory, RouterOptions} from 'vue-router';
|
||||
|
||||
export let router: Router = null as unknown as Router;
|
||||
|
||||
export function setRouter(r: Router) {
|
||||
router = r
|
||||
}
|
||||
|
||||
let webHistory: Nullable<RouterHistory> = null;
|
||||
|
||||
/**
|
||||
* 创建路由
|
||||
* @param options 参数
|
||||
*/
|
||||
export function createRouter(options: Partial<RouterOptions>) {
|
||||
webHistory = createWebHistory(import.meta.env.VITE_PUBLIC_PATH);
|
||||
// app router
|
||||
let router = createVueRouter({
|
||||
history: webHistory,
|
||||
routes: [],
|
||||
...options,
|
||||
});
|
||||
|
||||
setRouter(router)
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
// 销毁路由
|
||||
export function destroyRouter() {
|
||||
setRouter(null as unknown as Router);
|
||||
if (webHistory) {
|
||||
webHistory.destroy();
|
||||
}
|
||||
webHistory = null
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
import type { AppRouteRecordRaw } from '/@/router/types';
|
||||
import { t } from '/@/hooks/web/useI18n';
|
||||
import { REDIRECT_NAME, LAYOUT, EXCEPTION_COMPONENT, PAGE_NOT_FOUND_NAME } from '/@/router/constant';
|
||||
import { REDIRECT_NAME, LAYOUT, EXCEPTION_COMPONENT, PAGE_NOT_FOUND_NAME, PAGE_NOT_FOUND_NAME_404 } from '/@/router/constant';
|
||||
|
||||
// 404 on a page
|
||||
export const PAGE_NOT_FOUND_ROUTE: AppRouteRecordRaw = {
|
||||
path: '/:path(.*)*',
|
||||
|
||||
name: PAGE_NOT_FOUND_NAME,
|
||||
component: LAYOUT,
|
||||
meta: {
|
||||
@ -15,7 +16,9 @@ export const PAGE_NOT_FOUND_ROUTE: AppRouteRecordRaw = {
|
||||
children: [
|
||||
{
|
||||
path: '/:path(.*)*',
|
||||
name: PAGE_NOT_FOUND_NAME,
|
||||
// update-begin--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
name: PAGE_NOT_FOUND_NAME_404,
|
||||
// update-end--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
component: EXCEPTION_COMPONENT,
|
||||
meta: {
|
||||
title: 'ErrorPage',
|
||||
|
||||
@ -109,6 +109,10 @@ const setting: ProjectConfig = {
|
||||
type: MenuTypeEnum.SIDEBAR,
|
||||
// 菜单主题
|
||||
theme: ThemeEnum.DARK,
|
||||
// update-begin--author:liaozhiyang---date:20241203---for:【issues/7522】解决menuSetting ts警告
|
||||
// 左侧导航栏文字颜色调整区分彩色和暗黑 (不对应配置)
|
||||
isThemeBright: false,
|
||||
// update-end--author:liaozhiyang---date:20241203---for:【issues/7522】解决menuSetting ts警告
|
||||
// 分割菜单
|
||||
split: false,
|
||||
// 顶部菜单布局
|
||||
@ -146,7 +150,7 @@ const setting: ProjectConfig = {
|
||||
// 动画配置
|
||||
transitionSetting: {
|
||||
// 是否开启切换动画
|
||||
// The disabled state will also disable pageLoadinng
|
||||
// The disabled state will also disable pageLoading
|
||||
enable: true,
|
||||
|
||||
// 动画名 Route basic switching animation
|
||||
|
||||
@ -1,9 +1,19 @@
|
||||
import type { App } from 'vue';
|
||||
import type { Pinia } from 'pinia';
|
||||
import { createPinia } from 'pinia';
|
||||
const store = createPinia();
|
||||
|
||||
let store: Nullable<Pinia> = null;
|
||||
|
||||
export function setupStore(app: App<Element>) {
|
||||
if (store == null) {
|
||||
store = createPinia();
|
||||
}
|
||||
app.use(store);
|
||||
}
|
||||
|
||||
// 销毁store
|
||||
export function destroyStore() {
|
||||
store = null;
|
||||
}
|
||||
|
||||
export { store };
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { MainAppProps } from "#/main";
|
||||
import type { ProjectConfig, HeaderSetting, MenuSetting, TransitionSetting, MultiTabsSetting } from '/#/config';
|
||||
import type { BeforeMiniState } from '/#/store';
|
||||
|
||||
@ -20,7 +21,9 @@ interface AppState {
|
||||
// When the window shrinks, remember some states, and restore these states when the window is restored
|
||||
beforeMiniInfo: BeforeMiniState;
|
||||
// 页面跳转临时参数存储
|
||||
messageHrefParams: any
|
||||
messageHrefParams: any,
|
||||
// 应用参数
|
||||
mainAppProps: MainAppProps,
|
||||
}
|
||||
let timeId: TimeoutHandle;
|
||||
export const useAppStore = defineStore({
|
||||
@ -30,7 +33,8 @@ export const useAppStore = defineStore({
|
||||
pageLoading: false,
|
||||
projectConfig: Persistent.getLocal(PROJ_CFG_KEY),
|
||||
beforeMiniInfo: {},
|
||||
messageHrefParams: {}
|
||||
messageHrefParams: {},
|
||||
mainAppProps: {},
|
||||
}),
|
||||
getters: {
|
||||
getPageLoading(): boolean {
|
||||
@ -62,7 +66,10 @@ export const useAppStore = defineStore({
|
||||
},
|
||||
getMessageHrefParams():any{
|
||||
return this.messageHrefParams;
|
||||
}
|
||||
},
|
||||
getMainAppProps(): MainAppProps {
|
||||
return this.mainAppProps;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setPageLoading(loading: boolean): void {
|
||||
@ -104,7 +111,14 @@ export const useAppStore = defineStore({
|
||||
setMessageHrefParams(params: any): void {
|
||||
this.messageHrefParams = params;
|
||||
},
|
||||
|
||||
|
||||
// 设置主应用参数
|
||||
setMainAppProps(args: MainAppProps) {
|
||||
this.mainAppProps.hideHeader = args.hideHeader ?? false;
|
||||
this.mainAppProps.hideSider = args.hideSider ?? false;
|
||||
this.mainAppProps.hideMultiTabs = args.hideMultiTabs ?? false;
|
||||
},
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ import type { RouteLocationNormalized, RouteLocationRaw, Router } from 'vue-rout
|
||||
import { toRaw, unref } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { store } from '/@/store';
|
||||
import { PAGE_NOT_FOUND_NAME_404 } from '/@/router/constant';
|
||||
|
||||
import { useGo, useRedo } from '/@/hooks/web/usePage';
|
||||
import { Persistent } from '/@/utils/cache/persistent';
|
||||
@ -152,15 +153,17 @@ export const useMultipleTabStore = defineStore({
|
||||
|
||||
async addTab(route: RouteLocationNormalized) {
|
||||
const { path, name, fullPath, params, query, meta } = getRawRoute(route);
|
||||
// update-begin--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
// 404 The page does not need to add a tab
|
||||
if (
|
||||
path === PageEnum.ERROR_PAGE ||
|
||||
path === PageEnum.BASE_LOGIN ||
|
||||
!name ||
|
||||
[REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)
|
||||
[REDIRECT_ROUTE.name, PAGE_NOT_FOUND_NAME_404].includes(name as string)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:202401127---for:【issues/7500】vue-router4.5.0版本路由name:PageNotFound同名导致登录进不去
|
||||
|
||||
let updateIndex = -1;
|
||||
// Existing pages, do not add tabs repeatedly
|
||||
|
||||
@ -249,7 +249,10 @@ export const useUserStore = defineStore({
|
||||
try {
|
||||
const { goHome = true, mode, ...loginParams } = params;
|
||||
const data = await phoneLoginApi(loginParams, mode);
|
||||
const { token } = data;
|
||||
//update-begin---author:wangshuai---date:2024-11-25---for:【issues/7488】手机号码登录,在请求头中无法获取租户id---
|
||||
const { token , userInfo } = data;
|
||||
this.setTenant(userInfo!.loginTenantId);
|
||||
//update-end---author:wangshuai---date:2024-11-25---for:【issues/7488】手机号码登录,在请求头中无法获取租户id---
|
||||
// save token
|
||||
this.setToken(token);
|
||||
return this.afterLoginAction(goHome, data);
|
||||
|
||||
@ -3,6 +3,7 @@ import type { GlobEnvConfig } from '/#/config';
|
||||
import { warn } from '/@/utils/log';
|
||||
import pkg from '../../package.json';
|
||||
import { getConfigFileName } from '../../build/getConfigFileName';
|
||||
import { getGlobal } from "@/qiankun/micro";
|
||||
|
||||
export function getCommonStoragePrefix() {
|
||||
const { VITE_GLOB_APP_SHORT_NAME } = getAppEnvConfig();
|
||||
@ -17,10 +18,12 @@ export function getStorageShortName() {
|
||||
export function getAppEnvConfig() {
|
||||
const ENV_NAME = getConfigFileName(import.meta.env);
|
||||
|
||||
const global = getGlobal();
|
||||
|
||||
const ENV = (import.meta.env.DEV
|
||||
? // Get the global configuration (the configuration will be extracted independently when packaging)
|
||||
(import.meta.env as unknown as GlobEnvConfig)
|
||||
: window[ENV_NAME as any]) as unknown as GlobEnvConfig;
|
||||
: global[ENV_NAME as any]) as unknown as GlobEnvConfig;
|
||||
|
||||
const {
|
||||
VITE_GLOB_APP_TITLE,
|
||||
@ -33,6 +36,10 @@ export function getAppEnvConfig() {
|
||||
VITE_GLOB_APP_CAS_BASE_URL,
|
||||
VITE_GLOB_DOMAIN_URL,
|
||||
VITE_GLOB_ONLINE_VIEW_URL,
|
||||
|
||||
// 【JEECG作为乾坤子应用】
|
||||
VITE_GLOB_QIANKUN_MICRO_APP_NAME,
|
||||
VITE_GLOB_QIANKUN_MICRO_APP_ENTRY,
|
||||
} = ENV;
|
||||
|
||||
// if (!/^[a-zA-Z\_]*$/.test(VITE_GLOB_APP_SHORT_NAME)) {
|
||||
@ -52,6 +59,10 @@ export function getAppEnvConfig() {
|
||||
VITE_GLOB_APP_CAS_BASE_URL,
|
||||
VITE_GLOB_DOMAIN_URL,
|
||||
VITE_GLOB_ONLINE_VIEW_URL,
|
||||
|
||||
// 【JEECG作为乾坤子应用】
|
||||
VITE_GLOB_QIANKUN_MICRO_APP_NAME,
|
||||
VITE_GLOB_QIANKUN_MICRO_APP_ENTRY,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -140,6 +140,15 @@ const transform: AxiosTransform = {
|
||||
config.params = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// update-begin--author:sunjianlei---date:220241019---for:【JEECG作为乾坤子应用】作为乾坤子应用启动时,拼接请求路径
|
||||
if (globSetting.isQiankunMicro) {
|
||||
if (config.url && config.url.startsWith('/')) {
|
||||
config.url = globSetting.qiankunMicroAppEntry + config.url
|
||||
}
|
||||
}
|
||||
// update-end--author:sunjianlei---date:220241019---for:【JEECG作为乾坤子应用】作为乾坤子应用启动时,拼接请求路径
|
||||
|
||||
return config;
|
||||
},
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import type { FormSchema } from "@/components/Form";
|
||||
|
||||
import { unref } from 'vue';
|
||||
import { isObject } from '/@/utils/is';
|
||||
|
||||
import Big from 'big.js';
|
||||
// update-begin--author:sunjianlei---date:20220408---for: 【VUEN-656】配置外部网址打不开,原因是带了#号,需要替换一下
|
||||
export const URL_HASH_TAB = `__AGWE4H__HASH__TAG__PWHRG__`;
|
||||
// update-end--author:sunjianlei---date:20220408---for: 【VUEN-656】配置外部网址打不开,原因是带了#号,需要替换一下
|
||||
@ -123,7 +123,7 @@ export function cloneObject(obj) {
|
||||
|
||||
export const withInstall = <T>(component: T, alias?: string) => {
|
||||
//console.log("---初始化---", component)
|
||||
|
||||
|
||||
const comp = component as any;
|
||||
comp.install = (app: App) => {
|
||||
// @ts-ignore
|
||||
@ -254,7 +254,9 @@ export function numToUpper(value) {
|
||||
}
|
||||
};
|
||||
let lth = value.toString().length;
|
||||
value *= 100;
|
||||
// update-begin--author:liaozhiyang---date:20241202---for:【issues/7493】numToUpper方法返回解决错误
|
||||
value = new Big(value).times(100);
|
||||
// update-end--author:liaozhiyang---date:20241202---for:【issues/7493】numToUpper方法返回解决错误
|
||||
value += '';
|
||||
let length = value.length;
|
||||
if (lth <= 8) {
|
||||
@ -520,6 +522,10 @@ export function useConditionFilter() {
|
||||
data.view = 'number';
|
||||
}
|
||||
switch (data.view) {
|
||||
case 'file':
|
||||
case 'image':
|
||||
case 'password':
|
||||
return commonConditionOptions;
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
case 'umeditor':
|
||||
@ -550,3 +556,22 @@ export function useConditionFilter() {
|
||||
};
|
||||
return { filterCondition };
|
||||
}
|
||||
// 获取url中的参数
|
||||
export const getUrlParams = (url) => {
|
||||
const result = {
|
||||
url: '',
|
||||
params: {},
|
||||
};
|
||||
const list = url.split('?');
|
||||
result.url = list[0];
|
||||
const params = list[1];
|
||||
if (params) {
|
||||
const list = params.split('&');
|
||||
list.forEach((ele) => {
|
||||
const dic = ele.split('=');
|
||||
const label = dic[0];
|
||||
result.params[label] = dic[1];
|
||||
});
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
@ -1,23 +1,15 @@
|
||||
<template>
|
||||
<div v-if="visible" ref="aideWrapRef" class="aide-wrap" @click="handleGo">
|
||||
<div class="icon">
|
||||
<svg t="1706259688149" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2056" width="17" height="17">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M427.904 492.608a16.896 16.896 0 0 0 0 24.96l438.528 426.368a54.272 54.272 0 0 0 77.056 0 50.752 50.752 0 0 0 0-74.88L504.96 442.688a18.112 18.112 0 0 0-25.664 0l-51.392 49.92z m-12.16-137.728l-70.272-58.624a36.48 36.48 0 0 0-46.208 0l-46.144 38.464c-13.248 11.008-13.248 27.52 0 38.464l70.336 58.624a24.32 24.32 0 0 0 30.784 0l61.568-51.264c8.768-7.36 8.768-18.304 0-25.664z m-160.64 448c23.68-78.72 81.152-140.8 158.4-165.696a13.12 13.12 0 0 0 0-24.832C338.24 587.52 278.848 527.424 255.104 446.656c-3.968-12.416-19.84-12.416-23.808 0-23.68 78.72-81.152 140.8-158.4 165.696a13.12 13.12 0 0 0 0 24.832c75.264 24.896 134.656 84.928 158.4 165.76 3.968 10.304 19.84 10.304 23.808 0zM621.184 71.04a203.584 203.584 0 0 1-132.096 132.096 11.008 11.008 0 0 0 0 20.48 203.584 203.584 0 0 1 132.16 132.16 11.008 11.008 0 0 0 20.48 0 203.584 203.584 0 0 1 132.096-132.16 11.008 11.008 0 0 0 0-20.48 203.584 203.584 0 0 1-132.096-132.096c-3.776-9.28-18.624-9.28-20.48 0zM191.488 282.368c15.936-48.512 53.76-83.968 105.536-98.88 7.936-1.92 7.936-13.056 0-14.976-51.776-14.912-89.6-50.368-105.536-98.88-1.984-7.488-13.952-7.488-15.936 0-15.936 48.512-53.76 83.968-105.536 98.88-7.936 1.92-7.936 13.056 0 14.976 51.84 14.912 89.6 50.368 105.6 98.88 1.92 7.488 13.888 7.488 15.872 0z"
|
||||
p-id="2057"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<a-popconfirm
|
||||
:open="popconfirmVisible"
|
||||
placement="topRight"
|
||||
title="确定AI助手退出吗?"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
>
|
||||
<span class="text">AI助手</span>
|
||||
<img :src="aiImage" alt="ai助手" />
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
@ -28,6 +20,7 @@
|
||||
import { AIDE_FLAG } from '/@/enums/cacheEnum';
|
||||
import { getToken } from '/@/utils/auth';
|
||||
import { getAuthCache, setAuthCache, removeAuthCache } from '/@/utils/auth';
|
||||
import aiImage from './images/ai.png';
|
||||
const visible = ref(1);
|
||||
const aideWrapRef = ref(null);
|
||||
const popconfirmVisible = ref(false);
|
||||
@ -63,11 +56,10 @@
|
||||
.aide-wrap {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
right: 5px;
|
||||
transform: translate(0, -50%);
|
||||
background-color: @primary-color;
|
||||
height: 46px;
|
||||
width: 46px;
|
||||
height: 33px;
|
||||
width: 33px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<BasicForm @register="register" />
|
||||
</CollapseContainer>
|
||||
|
||||
<CollapseContainer title="超过3行自动收起,折叠时保留2行" class="mt-4">
|
||||
<CollapseContainer title="超过5列自动收起,折叠时保留2行" class="mt-4">
|
||||
<BasicForm @register="register1" />
|
||||
</CollapseContainer>
|
||||
</PageWrapper>
|
||||
@ -175,11 +175,12 @@
|
||||
labelWidth: 120,
|
||||
schemas: [...getSchamas(), ...getAppendSchemas(), { field: '', component: 'Divider', label: '更多字段' }, ...extraSchemas],
|
||||
actionColOptions: {
|
||||
span: 24,
|
||||
span: 8,
|
||||
},
|
||||
compact: true,
|
||||
showAdvancedButton: true,
|
||||
alwaysShowLines: 2,
|
||||
autoAdvancedCol: 2,
|
||||
alwaysShowLines: 1,
|
||||
});
|
||||
return {
|
||||
register,
|
||||
|
||||
@ -1,27 +1,17 @@
|
||||
<template>
|
||||
<PageWrapper>
|
||||
<a-card :bordered="false">
|
||||
<BasicTable @register="registerTable" />
|
||||
</a-card>
|
||||
<BasicTable @register="registerTable" :striped="true" />
|
||||
</PageWrapper>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { PageWrapper } from '/@/components/Page';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { mapTableTotalSummary } from '/@/utils/common/compUtils';
|
||||
|
||||
const [registerTable] = useTable({
|
||||
rowKey: 'id',
|
||||
bordered: true,
|
||||
canResize: false,
|
||||
columns: [
|
||||
{ title: '姓名', dataIndex: 'name' },
|
||||
{ title: '贡献点', dataIndex: 'point' },
|
||||
{ title: '等级', dataIndex: 'level' },
|
||||
{ title: '更新时间', dataIndex: 'updateTime' },
|
||||
],
|
||||
dataSource: [
|
||||
const dataSource = ref<any>([]);
|
||||
setTimeout(() => {
|
||||
dataSource.value = [
|
||||
{ id: 0, name: '张三', point: 23, level: 3, updateTime: '2019-8-14' },
|
||||
{ id: 1, name: '小鹿', point: 33, level: 9, updateTime: '2019-8-10' },
|
||||
{ id: 2, name: '小王', point: 6, level: 1, updateTime: '2019-8-13' },
|
||||
@ -35,9 +25,22 @@
|
||||
{ id: 10, name: '小赵', point: 33, level: 2, updateTime: '2019-8-10' },
|
||||
{ id: 11, name: '李华', point: 33, level: 8, updateTime: '2019-8-10' },
|
||||
{ id: 12, name: '小康', point: 33, level: 5, updateTime: '2019-8-10' },
|
||||
];
|
||||
}, 1e3);
|
||||
const [registerTable] = useTable({
|
||||
rowKey: 'id',
|
||||
bordered: true,
|
||||
canResize: true,
|
||||
columns: [
|
||||
{ title: '姓名', width: 500, dataIndex: 'name' },
|
||||
{ title: '贡献点', width: 500, dataIndex: 'point' },
|
||||
{ title: '等级', width: 500, dataIndex: 'level' },
|
||||
{ title: '更新时间', width: 500, dataIndex: 'updateTime' },
|
||||
],
|
||||
dataSource: dataSource,
|
||||
// 显示底部合计
|
||||
showSummary: true,
|
||||
striped: true,
|
||||
// 底部合计计算方法
|
||||
summaryFunc: onSummary,
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
actuatorList = '/actuator/httptrace-new/',
|
||||
actuatorList = '/actuator/jeecghttptrace/',
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -3,11 +3,8 @@
|
||||
<template #headerContent>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="flex-1">
|
||||
<a :href="GITHUB_URL" target="_blank">
|
||||
<!-- {{ name }}-->
|
||||
JeecgBoot
|
||||
</a>
|
||||
是一款基于BPM的低代码开发平台!前后端分离架构 SpringBoot 2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot引领新低代码开发模式 OnlineCoding-> 代码生成器-> 手工MERGE, 帮助Java项目解决70%的重复工作,让开发更多关注业务,既能快速提高效率,节省研发成本,同时又不失灵活性!一系列低代码能力:Online表单、Online报表、Online图表、表单设计、流程设计、报表设计、大屏设计 等等...。
|
||||
<a :href="GITHUB_URL" target="_blank">{{ name }}</a>
|
||||
是一款基于BPM的低代码平台!前后端分离架构 SpringBoot 2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Shiro,JWT,支持微服务。强大的代码生成器让前后端代码一键生成,实现低代码开发! JeecgBoot引领新低代码开发模式 OnlineCoding-> 代码生成器-> 手工MERGE, 帮助Java项目解决70%的重复工作,让开发更多关注业务,既能快速提高效率,节省研发成本,同时又不失灵活性!一系列低代码能力:Online表单、Online报表、Online图表、表单设计、流程设计、报表设计、大屏设计 等等...。
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -4,14 +4,17 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { isOAuth2AppEnv, sysOAuth2Login } from '/@/views/sys/login/useLogin';
|
||||
import {isOAuth2AppEnv, sysOAuth2Callback, sysOAuth2Login} from '/@/views/sys/login/useLogin';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { router } from '/@/router';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import {getTenantId} from "/@/utils/auth";
|
||||
import { getAuthCache, getTenantId, getToken } from "/@/utils/auth";
|
||||
import { OAUTH2_THIRD_LOGIN_TENANT_ID } from "@/enums/cacheEnum";
|
||||
import { defHttp } from "@/utils/http/axios";
|
||||
import { requestAuthCode } from "dingtalk-jsapi";
|
||||
|
||||
const isOAuth = ref<boolean>(isOAuth2AppEnv());
|
||||
const env = ref<any>({ thirdApp: false, wxWork: false, dingtalk: false });
|
||||
@ -55,7 +58,8 @@
|
||||
} else if (env.value.wxWork) {
|
||||
sysOAuth2Login('wechat_enterprise');
|
||||
} else if (env.value.dingtalk) {
|
||||
sysOAuth2Login('dingtalk');
|
||||
//新版钉钉登录
|
||||
dingdingLogin();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,4 +88,43 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 钉钉登录
|
||||
*/
|
||||
function dingdingLogin() {
|
||||
//先获取钉钉的企业id,如果没有配置 还是走原来的逻辑,走原来的逻辑 需要判断存不存在token,存在token直接去首页
|
||||
let tenantId = getAuthCache(OAUTH2_THIRD_LOGIN_TENANT_ID) || 0;
|
||||
let url = `/sys/thirdLogin/get/corpId/clientId?tenantId=${tenantId}`;
|
||||
//update-begin---author:wangshuai---date:2024-12-09---for:不要使用getAction online里面的,要用defHttp---
|
||||
defHttp.get({ url:url },{ isTransformResponse: false }).then((res) => {
|
||||
//update-end---author:wangshuai---date:2024-12-09---for:不要使用getAction online里面的,要用defHttp---
|
||||
if (res.success) {
|
||||
if(res.result && res.result.corpId && res.result.clientId){
|
||||
requestAuthCode({ corpId: res.result.corpId, clientId: res.result.clientId }).then((res) => {
|
||||
let { code } = res;
|
||||
sysOAuth2Callback(code);
|
||||
});
|
||||
}else{
|
||||
toOldAuthLogin();
|
||||
}
|
||||
} else {
|
||||
toOldAuthLogin();
|
||||
}
|
||||
}).catch((err) => {
|
||||
toOldAuthLogin();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 旧版钉钉登录
|
||||
*/
|
||||
function toOldAuthLogin() {
|
||||
let token = getToken();
|
||||
if (token) {
|
||||
router.replace({ path: PageEnum.BASE_HOME });
|
||||
} else {
|
||||
sysOAuth2Login('dingtalk');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -174,6 +174,13 @@ export function isOAuth2AppEnv() {
|
||||
return /wxwork|dingtalk/i.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是钉钉环境
|
||||
*/
|
||||
export function isOAuth2DingAppEnv() {
|
||||
return /dingtalk/i.test(navigator.userAgent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台构造oauth2登录地址
|
||||
* @param source
|
||||
@ -191,3 +198,19 @@ export function sysOAuth2Login(source) {
|
||||
window.location.href = url;
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20220629 for:[issues/I5BG1I]vue3不支持auth2登录------------
|
||||
|
||||
//update-begin---author:wangshuai ---date:20241108 for:[QQYUN-9421]vue3新版auth登录,用户不用点击登录------------
|
||||
/**
|
||||
* 后台callBack
|
||||
* @param code
|
||||
*/
|
||||
export function sysOAuth2Callback(code:string) {
|
||||
let url = `${window._CONFIG['domianURL']}/sys/thirdLogin/oauth2/dingding/login`;
|
||||
url += `?state=${encodeURIComponent(window.location.origin)}&authCode=${code}`;
|
||||
let tenantId = getAuthCache(OAUTH2_THIRD_LOGIN_TENANT_ID);
|
||||
if(tenantId){
|
||||
url += `&tenantId=${tenantId}`;
|
||||
}
|
||||
window.location.href = url;
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20241108 for:[QQYUN-9421]vue3新版auth登录,用户不用点击登录------------
|
||||
|
||||
@ -15,6 +15,15 @@ export const thirdAppFormSchema: FormSchema[] = [
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
label: 'CorpId',
|
||||
field: 'corpId',
|
||||
component: 'Input',
|
||||
ifShow: ({ values }) => {
|
||||
return values.thirdType === 'dingtalk';
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'Agentld',
|
||||
field: 'agentId',
|
||||
@ -32,12 +41,6 @@ export const thirdAppFormSchema: FormSchema[] = [
|
||||
field: 'clientSecret',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: 'agentAppSecret',
|
||||
field: 'agentAppSecret',
|
||||
component: 'Input',
|
||||
ifShow: false,
|
||||
},{
|
||||
label: '启用',
|
||||
field: 'status',
|
||||
|
||||
@ -21,6 +21,12 @@
|
||||
</div>
|
||||
</template>
|
||||
<div class="base-desc">完成步骤1后,填入Agentld、 AppKey、AppSecret后 可对接应用与同步通讯录</div>
|
||||
<div class="flex-flow">
|
||||
<div class="base-title">CorpId</div>
|
||||
<div class="base-message">
|
||||
<a-input-password v-model:value="appConfigData.corpId" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-flow">
|
||||
<div class="base-title">Agentld</div>
|
||||
<div class="base-message">
|
||||
|
||||
@ -82,7 +82,6 @@
|
||||
agentId: '',
|
||||
clientId: '',
|
||||
clientSecret: '',
|
||||
agentAppSecret: '',
|
||||
});
|
||||
//企业微信钉钉配置modal
|
||||
const [registerAppConfigModal, { openModal }] = useModal();
|
||||
|
||||
@ -88,6 +88,8 @@
|
||||
...adaptiveColProps,
|
||||
style: { textAlign: 'left' },
|
||||
},
|
||||
showResetButton: !!departId.value,
|
||||
showSubmitButton: !!departId.value,
|
||||
},
|
||||
// 【issues/1064】列设置的 cacheKey
|
||||
tableSetting: { cacheKey: 'depart_user_departInfo' },
|
||||
|
||||
@ -87,6 +87,8 @@
|
||||
...adaptiveColProps,
|
||||
style: { textAlign: 'left' },
|
||||
},
|
||||
showResetButton: !!departId.value,
|
||||
showSubmitButton: !!departId.value,
|
||||
},
|
||||
// 【issues/1064】列设置的 cacheKey
|
||||
tableSetting: { cacheKey: 'depart_user_userInfo' },
|
||||
|
||||
@ -12,10 +12,10 @@
|
||||
<DepartBaseInfoTab :data="departData" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="用户信息" key="user-info">
|
||||
<DepartUserInfoTab :data="departData" />
|
||||
<DepartUserInfoTab :key="reRender" :data="departData" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="部门角色" key="role-info">
|
||||
<DepartRoleInfoTab :data="departData" />
|
||||
<DepartRoleInfoTab :key="reRender" :data="departData" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
@ -38,8 +38,16 @@
|
||||
// 当前选中的部门信息
|
||||
let departData = ref({});
|
||||
|
||||
const reRender = ref(-1);
|
||||
|
||||
// 左侧树选择后触发
|
||||
function onTreeSelect(data) {
|
||||
// update-begin--author:liaozhiyang---date:20250106---for:【issues/7658】我的部门无部门列表数据时,点击查询或者重置能查出数据
|
||||
if (reRender.value == -1) {
|
||||
// 重新渲染组件
|
||||
reRender.value = Math.random();
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20250106---for:【issues/7658】我的部门无部门列表数据时,点击查询或者重置能查出数据
|
||||
departData.value = data;
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { formSchema } from './fill.rule.data';
|
||||
import { saveFillRule, updateFillRule } from './fill.rule.api';
|
||||
import {useMessage} from "@/hooks/web/useMessage";
|
||||
|
||||
const { createMessage: $message } = useMessage();
|
||||
|
||||
//设置标题
|
||||
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
|
||||
@ -43,6 +46,20 @@
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
let formValue = await validate();
|
||||
|
||||
// 检查参数是否合法
|
||||
let ruleParams = formValue.ruleParams;
|
||||
if (!!ruleParams) {
|
||||
ruleParams = JSON.parse(ruleParams);
|
||||
for (const key of Object.keys(ruleParams)) {
|
||||
// online 保留字检查
|
||||
if (key === 'onl_watch') {
|
||||
$message.error('参数名称不能是onl_watch');
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setModalProps({ confirmLoading: true });
|
||||
if (isUpdate.value) {
|
||||
let allFieldsValue = getFieldsValue();
|
||||
|
||||
@ -4,14 +4,17 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { isOAuth2AppEnv, sysOAuth2Login } from '/@/views/sys/login/useLogin';
|
||||
import { isOAuth2AppEnv, sysOAuth2Callback, sysOAuth2Login } from '/@/views/sys/login/useLogin';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { router } from '/@/router';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import {getTenantId} from "/@/utils/auth";
|
||||
import { getAuthCache, getTenantId, getToken } from "/@/utils/auth";
|
||||
import { requestAuthCode } from 'dingtalk-jsapi';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { OAUTH2_THIRD_LOGIN_TENANT_ID } from "/@/enums/cacheEnum";
|
||||
|
||||
const isOAuth = ref<boolean>(isOAuth2AppEnv());
|
||||
const env = ref<any>({ thirdApp: false, wxWork: false, dingtalk: false });
|
||||
@ -55,7 +58,8 @@
|
||||
} else if (env.value.wxWork) {
|
||||
sysOAuth2Login('wechat_enterprise');
|
||||
} else if (env.value.dingtalk) {
|
||||
sysOAuth2Login('dingtalk');
|
||||
//新版钉钉登录
|
||||
dingdingLogin();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,4 +88,43 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 钉钉登录
|
||||
*/
|
||||
function dingdingLogin() {
|
||||
//先获取钉钉的企业id,如果没有配置 还是走原来的逻辑,走原来的逻辑 需要判断存不存在token,存在token直接去首页
|
||||
let tenantId = getAuthCache(OAUTH2_THIRD_LOGIN_TENANT_ID) || 0;
|
||||
let url = `/sys/thirdLogin/get/corpId/clientId?tenantId=${tenantId}`;
|
||||
//update-begin---author:wangshuai---date:2024-12-09---for:不要使用getAction online里面的,要用defHttp---
|
||||
defHttp.get({ url:url },{ isTransformResponse: false }).then((res) => {
|
||||
//update-end---author:wangshuai---date:2024-12-09---for:不要使用getAction online里面的,要用defHttp---
|
||||
if (res.success) {
|
||||
if(res.result && res.result.corpId && res.result.clientId){
|
||||
requestAuthCode({ corpId: res.result.corpId, clientId: res.result.clientId }).then((res) => {
|
||||
let { code } = res;
|
||||
sysOAuth2Callback(code);
|
||||
});
|
||||
}else{
|
||||
toOldAuthLogin();
|
||||
}
|
||||
} else {
|
||||
toOldAuthLogin();
|
||||
}
|
||||
}).catch((err) => {
|
||||
toOldAuthLogin();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 旧版钉钉登录
|
||||
*/
|
||||
function toOldAuthLogin() {
|
||||
let token = getToken();
|
||||
if (token) {
|
||||
router.replace({ path: PageEnum.BASE_HOME });
|
||||
} else {
|
||||
sysOAuth2Login('dingtalk');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -230,11 +230,15 @@
|
||||
defaultCheckedKeys.value = permResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// VUE角色授权重复保存 #352
|
||||
async function doSave(params) {
|
||||
loading.value = true;
|
||||
await saveRolePermission(params);
|
||||
try {
|
||||
await saveRolePermission(params);
|
||||
} catch (e) {
|
||||
loading.value = false;
|
||||
}
|
||||
setTimeout(()=>{
|
||||
loading.value = false;
|
||||
}, 500)
|
||||
|
||||
@ -26,12 +26,12 @@
|
||||
>邀请用户加入</a-button
|
||||
>
|
||||
<a-button
|
||||
preIcon="ant-design:plus-outlined"
|
||||
preIcon="ant-design:sliders-outlined"
|
||||
type="primary"
|
||||
@click="handlePack"
|
||||
style="margin-right: 5px"
|
||||
:disabled="selectedRowKeys.length === 0"
|
||||
>套餐</a-button
|
||||
>套餐管理</a-button
|
||||
>
|
||||
<a-button type="primary" @click="recycleBinClick" preIcon="ant-design:hdd-outlined">回收站</a-button>
|
||||
</template>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
<TableAction :actions="getActions(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!-- 产品包 -->
|
||||
<!-- 套餐包 -->
|
||||
<TenantPackMenuModal @register="registerPackMenuModal" @success="handleSuccess"/>
|
||||
</div>
|
||||
</template>
|
||||
@ -66,7 +66,7 @@
|
||||
{
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除租户产品包',
|
||||
title: '是否确认删除租户套餐包',
|
||||
confirm: handleDelete.bind(null, record.id),
|
||||
},
|
||||
},
|
||||
@ -74,7 +74,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑产品包
|
||||
* 编辑套餐包
|
||||
*/
|
||||
function handleAdd() {
|
||||
packModal(true, {
|
||||
@ -86,7 +86,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* 删除默认产品包
|
||||
* 删除默认套餐包
|
||||
*/
|
||||
async function handleDelete(id) {
|
||||
await deleteTenantPack({ ids: id }, handleSuccess);
|
||||
@ -104,7 +104,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增产品包
|
||||
* 新增套餐包
|
||||
*/
|
||||
async function handlePack() {
|
||||
if (unref(selectedRowKeys).length > 1) {
|
||||
@ -124,12 +124,12 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除产品包
|
||||
* 批量删除套餐包
|
||||
*/
|
||||
async function handlePackBatch() {
|
||||
Modal.confirm({
|
||||
title: '删除租户产品包',
|
||||
content: '是否删除租户产品包',
|
||||
title: '删除租户套餐包',
|
||||
content: '是否删除租户套餐包',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
|
||||
@ -11,6 +11,13 @@
|
||||
style="margin-right: 5px"
|
||||
>批量删除
|
||||
</a-button>
|
||||
<a-button
|
||||
preIcon="ant-design:sync-outlined"
|
||||
type="primary"
|
||||
@click="handleSyncDefaultPack"
|
||||
style="margin-right: 5px"
|
||||
>初始化默认套餐
|
||||
</a-button>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getActions(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
@ -24,7 +31,7 @@
|
||||
import { reactive, ref, unref } from 'vue';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
import { packColumns, userColumns, packFormSchema } from '../tenant.data';
|
||||
import { getTenantUserList, leaveTenant, packList, deleteTenantPack } from '../tenant.api';
|
||||
import { getTenantUserList, leaveTenant, packList, deleteTenantPack, syncDefaultTenantPack } from '../tenant.api';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import TenantPackMenuModal from './TenantPackMenuModal.vue';
|
||||
@ -64,7 +71,7 @@
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
|
||||
// Emits声明
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
//是否显示新增和编辑产品包
|
||||
//是否显示新增和编辑套餐包
|
||||
const showPackAddAndEdit = ref<boolean>(false);
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
@ -73,7 +80,7 @@
|
||||
success();
|
||||
});
|
||||
//设置标题
|
||||
const title = '租户产品包列表';
|
||||
const title = '租户个性化套餐包';
|
||||
|
||||
//表单提交事件
|
||||
async function handleSubmit(v) {
|
||||
@ -115,40 +122,40 @@
|
||||
});
|
||||
}
|
||||
|
||||
//默认系统产品包不允许删除,包含(超级管理员、组织账户管理员、组织应用管理员)
|
||||
//默认系统套餐包不允许删除,包含(超级管理员、组织账户管理员、组织应用管理员)
|
||||
const packCode = reactive<any>(['superAdmin','accountAdmin','appAdmin']);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
/**
|
||||
* 删除产品包
|
||||
* 删除套餐包
|
||||
* @param 删除
|
||||
*/
|
||||
async function handleDelete(record) {
|
||||
//update-begin---author:wangshuai ---date:20230222 for:系统默认产品包不允许删除------------
|
||||
//update-begin---author:wangshuai ---date:20230222 for:系统默认套餐包不允许删除------------
|
||||
if(packCode.indexOf(record.packCode) != -1){
|
||||
createMessage.warning("默认系统产品包不允许删除");
|
||||
createMessage.warning("默认系统套餐包不允许删除");
|
||||
return;
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20230222 for:系统默认产品包不允许删除------------
|
||||
//update-end---author:wangshuai ---date:20230222 for:系统默认套餐包不允许删除------------
|
||||
await deleteTenantPack({ ids: record.id }, success);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除产品包
|
||||
* 批量删除套餐包
|
||||
*/
|
||||
async function handlePackBatch() {
|
||||
let value = selectedRows.value;
|
||||
if(value && value.length>0){
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if(packCode.indexOf(value[i].packCode) != -1){
|
||||
createMessage.warning("默认系统产品包不允许删除");
|
||||
createMessage.warning("默认系统套餐包不允许删除");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '删除租户产品包',
|
||||
content: '是否删除租户产品包',
|
||||
title: '删除租户套餐包',
|
||||
content: '是否删除租户套餐包',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
@ -157,6 +164,18 @@
|
||||
})
|
||||
}
|
||||
|
||||
async function handleSyncDefaultPack() {
|
||||
Modal.confirm({
|
||||
title: '初始化默认套餐包',
|
||||
content: '是否初始化默认套餐包',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
await syncDefaultTenantPack({tenantId: unref(tenantId)}, success);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 新增表单
|
||||
@ -171,7 +190,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 产品包下面的用户
|
||||
* 套餐包下面的用户
|
||||
* @param record
|
||||
*/
|
||||
function seeTenantPackUser(record) {
|
||||
@ -193,7 +212,7 @@
|
||||
{
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除租户产品包',
|
||||
title: '是否确认删除租户套餐包',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
},
|
||||
},
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
});
|
||||
//租户
|
||||
const tenantId = ref<number>();
|
||||
//产品包类型
|
||||
//套餐包类型
|
||||
const packType = ref<number>();
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
@ -36,14 +36,14 @@
|
||||
console.log(data.record)
|
||||
await setFieldsValue({ ...data.record });
|
||||
}
|
||||
//update-begin---author:wangshuai ---date:20230705 for:【QQYUN-5685】2 产品包增加一个查看:添加底部有没有按钮及表单禁用------------
|
||||
//update-begin---author:wangshuai ---date:20230705 for:【QQYUN-5685】2 套餐包增加一个查看:添加底部有没有按钮及表单禁用------------
|
||||
setModalProps({ confirmLoading: false, showCancelBtn:!!data?.showFooter, showOkBtn:!!data?.showFooter });
|
||||
// 隐藏底部时禁用整个表单
|
||||
setProps({ disabled: !data?.showFooter })
|
||||
//update-end---author:wangshuai ---date:20230705 for:【QQYUN-5685】2 产品包增加一个查看:添加底部有没有按钮及表单禁用------------
|
||||
//update-end---author:wangshuai ---date:20230705 for:【QQYUN-5685】2 套餐包增加一个查看:添加底部有没有按钮及表单禁用------------
|
||||
});
|
||||
//设置标题
|
||||
const title = computed(() => (unref(isUpdate) ? '编辑租户产品包' : '新增租户产品包'));
|
||||
const title = computed(() => (unref(isUpdate) ? '编辑租户套餐包' : '新增租户套餐包'));
|
||||
//表单提交事件
|
||||
async function handleSubmit(v) {
|
||||
const values = await validate();
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
return tenantPackData.tenantId;
|
||||
})
|
||||
|
||||
//产品包信息
|
||||
//套餐包信息
|
||||
const tenantPackData = reactive<any>({});
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user