42 Commits

Author SHA1 Message Date
JEECG
868029b732 Merge pull request #1270 from hunao0221/master
fix: 修正前端运行Command
2024-05-23 11:20:18 +08:00
胡闹
83c3607fb2 fix: 修正前端运行Command
前端运行命令应该为`pnpm dev`
2024-05-23 11:00:26 +08:00
JEECG
936c11db47 【issues/6191】apiSelect多次请求 2024-05-10 10:06:07 +08:00
JEECG
801186779f 【issues/1147】登录跳转时去掉发布路径的最后一个/以解决404问题 2024-05-10 09:59:30 +08:00
JEECG
4c3b37a82b 修改tinymce段落下拉框的字体和样式 2024-05-01 00:07:47 +08:00
JEECG
2792bd9975 为了提高issue处理效率,请按格式发帖 2024-04-28 15:50:56 +08:00
JEECG
24df8d2356 角色授权操作不方便 2024-04-26 18:31:09 +08:00
JEECG
4aa4f702ba 如果你是启动报错,请说明你的前端环境 2024-04-26 15:14:59 +08:00
JEECG
9a078db469 如果你是启动报错,请说明你的前端环境 2024-04-26 15:12:24 +08:00
JEECG
1674937950 门人员组件点击重置未清空(selectedRowKeys.value=[],watch没监听到加deep) 2024-04-26 13:44:14 +08:00
JEECG
ffebec59bf 发现弹窗modal性能问题
basicModal不设置maxHeight或height会一直执行setModalHeight,需即使销毁MutationObserver
2024-04-26 13:43:41 +08:00
JEECG
19d1e0ddbc 用户编辑设置生日,保存失败 2024-04-26 13:31:51 +08:00
JEECG
02c3bb830c 【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义 2024-04-25 16:32:21 +08:00
JEECG
abf21d6c58 【issues/1146】BasicTable使用headerCell全选框出不来 --- 2024-04-25 16:30:39 +08:00
JEECG
d183fc5274 【issues/1165】解决canResize为true时第一行校验不过 --- 2024-04-25 16:29:17 +08:00
JEECG
d418e7d3e5 【issues/1175】解决vxetable鼠标hover之后title显示不对的问题 --- 2024-04-25 16:28:21 +08:00
JEECG
404541f956 【issues/1137】BasicTable自适应高度计算没有减去尾部高度 --- 2024-04-25 16:26:54 +08:00
JEECG
207f4a39c9 springboot3分支,online表单开页面,导入数据库表功能无法使用 #6146 2024-04-23 16:36:21 +08:00
JEECG
885a745ba7 修复【issues/1102】设置单点登录后页面,进入首页提示404,也没有绘制侧边栏 #1102 2024-04-23 09:25:56 +08:00
JEECG
ec1649629d 增加新QQ群:808791225 2024-04-15 15:19:35 +08:00
JEECG
6f060e456a rangepicker等时间控件报错(vue3.4以上版本有问题) 2024-03-28 22:05:49 +08:00
JEECG
94b38f7689 移动端效果,弹窗默认统一全屏,实现更好的适配效果 2024-03-27 11:28:06 +08:00
JEECG
325cc93e03 build/utils.ts 修复 #1130 2024-03-27 11:27:12 +08:00
JEECG
9eb7031685 rangepicker等时间控件报错(vue3.4以上版本有问题) 2024-03-26 22:16:38 +08:00
JEECG
8540e8d2ae 移动端效果,弹窗默认统一全屏,实现更好的适配效果 2024-03-26 22:15:03 +08:00
JEECG
09a1a497b9 BasicTable在使用clickToRowSelect=true下,selection-change 事件在触发多次 2024-03-26 22:10:20 +08:00
JEECG
228c133583 AUTO 在线表单富文本字段,上传图片按钮突兀而且遮挡了 TinyMCE 控件栏的全屏按钮 #1129 2024-03-26 21:57:52 +08:00
JEECG
c48041a2b5 行选择卡顿问题在3.6.3版本依然存在 #1120 2024-03-25 16:00:52 +08:00
JEECG
8d984846af 打包后黑色主题下菜单tab标签不跟随系统主题颜色变化,开发模式下没问题 #1115 2024-03-25 15:47:07 +08:00
JEECG
cc67661f11 BasicModal组件在非全屏的情况下最大高度获取异常,不论内容高度是否超出屏幕高度,都等于内容高度 2024-03-22 14:30:34 +08:00
JEECG
33cb844792 发布路径不以/结尾资源会加载失败 --- 2024-03-22 14:29:14 +08:00
JEECG
68a26826c7 vue3.4以上版本导致角色抽屉隐藏footer逻辑错误(去掉toRow,否者props变化不会触发computed) 2024-03-22 14:27:28 +08:00
JEECG
6de260014d 优化效果 2024-03-18 19:56:31 +08:00
JEECG
4573a82018 提供yarn安装lock 2024-03-18 19:56:15 +08:00
JEECG
7ff461a677 formSchema props支持动态修改 2024-03-18 11:22:25 +08:00
JEECG
41490b3dc8 系统用户详情抽屉title更改 2024-03-18 11:05:35 +08:00
JEECG
0db23723fb 菜单国际化优化 2024-03-18 11:05:07 +08:00
JEECG
e4424ba3b1 注释掉vue2与vue3菜单切换 2024-03-18 11:04:43 +08:00
JEECG
b4539da84c 搜索菜单不区分大小写,同时支持外部连接打开 2024-03-18 11:02:55 +08:00
JEECG
3e01894db5 vue3.4以上版本导致角色抽屉隐藏footer逻辑错误 2024-03-18 11:02:23 +08:00
JEECG
f8fc40a287 注释调整 2024-03-18 10:58:34 +08:00
JEECG
e1e3d04629 【性能优化】大组件改成按需加载 2024-03-18 10:44:12 +08:00
50 changed files with 10905 additions and 191 deletions

View File

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

View File

@@ -47,7 +47,7 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue4、TypeScript 等新技术
- 官方文档:[https://help.jeecg.com](https://help.jeecg.com)
- 官方网站: [https://www.jeecg.com](https://www.jeecg.com)
- 快速入门:[快速入门](http://jeecg.com/doc/quickstart) | [常见问题](http://help.jeecg.com/qa.html) | [视频教程](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://help.jeecg.com/vue3/codegen/online.html)
- QQ交流群⑧825232878、⑦791696430(满)、683903138(满)
- QQ交流群⑨808791225、⑧825232878(满)、⑦791696430(满)、683903138(满)、其他满
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)| [敲敲云零代码](https://www.qiaoqiaoyun.com)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
@@ -86,7 +86,7 @@ VITE_GLOB_DOMAIN_URL=http://localhost:8080/jeecg-boot
- run
```bash
pnpm serve
pnpm dev
```

View File

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

View File

@@ -21,7 +21,7 @@
"husky:install": "husky install"
},
"dependencies": {
"@jeecg/online": "3.6.2-beta",
"@jeecg/online": "3.6.2-GA",
"@iconify/iconify": "^3.1.1",
"@ant-design/colors": "^7.0.2",
"@ant-design/icons-vue": "^7.0.1",

View File

@@ -35,6 +35,11 @@
if (newValue === ThemeEnum.DARK) {
appTheme.value.algorithm = theme.darkAlgorithm;
}
// update-begin--author:liaozhiyang---date:20240322---for【QQYUN-8570】生产环境暗黑模式下主题色不生效
if (import.meta.env.PROD) {
changeTheme(appStore.getProjectConfig.themeColor);
}
// update-end--author:liaozhiyang---date:20240322---for【QQYUN-8570】生产环境暗黑模式下主题色不生效
appTheme.value = {
...appTheme.value,
};

View File

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

View File

@@ -12,6 +12,7 @@ export interface SearchResult {
name: string;
path: string;
icon?: string;
internalOrExternal: boolean;
}
// Translate special characters
@@ -23,7 +24,7 @@ function transform(c: string) {
function createSearchReg(key: string) {
const keys = [...key].map((item) => transform(item));
const str = ['', ...keys, ''].join('.*');
return new RegExp(str);
return new RegExp(str, 'i');
}
export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>, emit: EmitType) {
@@ -68,12 +69,13 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) {
const ret: SearchResult[] = [];
filterMenu.forEach((item) => {
const { name, path, icon, children, hideMenu, meta } = item;
const { name, path, icon, children, hideMenu, meta, internalOrExternal } = item;
if (!hideMenu && reg.test(name) && (!children?.length || meta?.hideChildrenInMenu)) {
ret.push({
name: parent?.name ? `${parent.name} > ${name}` : name,
path,
icon,
internalOrExternal
});
}
if (!meta?.hideChildrenInMenu && Array.isArray(children) && children.length) {
@@ -149,7 +151,14 @@ export function useMenuSearch(refs: Ref<HTMLElement[]>, scrollWrap: Ref<ElRef>,
const to = result[index];
handleClose();
await nextTick();
go(to.path);
// update-begin--author:liaozhiyang---date:20230803---for【QQYUN-8369】搜索区分大小写外部链接新页打开
if (to.internalOrExternal) {
window.open(to.path, '_blank');
} else {
go(to.path);
}
// update-end--author:liaozhiyang---date:20230803---for【QQYUN-8369】搜索区分大小写外部链接新页打开
}
// close search modal

View File

@@ -59,7 +59,9 @@
instance && emit('register', drawerInstance, instance.uid);
const getMergeProps = computed((): DrawerProps => {
return deepMerge(toRaw(props), unref(propsRef));
// update-begin--author:liaozhiyang---date:20240320---for【QQYUN-8389】vue3.4以上版本导致角色抽屉隐藏footer逻辑错误去掉toRow,否者props变化不会触发computed
return { ...deepMerge(props, unref(propsRef)) };
// update-end--author:liaozhiyang---date:20240320---for【QQYUN-8389】vue3.4以上版本导致角色抽屉隐藏footer逻辑错误去掉toRow,否者props变化不会触发computed
});
const getProps = computed((): DrawerProps => {

View File

@@ -158,7 +158,11 @@
}
//update-end---author:wangshuai ---date:20221124 for[issues/215]列表页查询框(日期选择框)设置初始时间,一进入页面时,后台报日期转换类型错误的------------
});
schema.defaultValue = def;
// update-begin--author:liaozhiyang---date:20240328---for【issues/1114】rangepicker等时间控件报错vue3.4以上版本有问题)
def.forEach((item, index) => {
defaultValue[index] = item;
});
// update-end--author:liaozhiyang---date:20240328---for【issues/1114】rangepicker等时间控件报错vue3.4以上版本有问题)
}
}
}

View File

@@ -1,6 +1,14 @@
/**
* 目前实现了异步加载的组件清单
* JAreaLinkage
* JEditor
* JMarkdownEditor
* JCodeEditor
* JEasyCron
*/
import type { Component } from 'vue';
import type { ComponentType } from './types/index';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
/**
* Component list, register here to setting it in the form
*/
@@ -29,7 +37,7 @@ import { StrengthMeter } from '/@/components/StrengthMeter';
import { IconPicker } from '/@/components/Icon';
import { CountdownInput } from '/@/components/CountDown';
//自定义组件
import JAreaLinkage from './jeecg/components/JAreaLinkage.vue';
// import JAreaLinkage from './jeecg/components/JAreaLinkage.vue';
import JSelectUser from './jeecg/components/JSelectUser.vue';
import JSelectPosition from './jeecg/components/JSelectPosition.vue';
import JSelectRole from './jeecg/components/JSelectRole.vue';
@@ -37,10 +45,10 @@ import JImageUpload from './jeecg/components/JImageUpload.vue';
import JDictSelectTag from './jeecg/components/JDictSelectTag.vue';
import JSelectDept from './jeecg/components/JSelectDept.vue';
import JAreaSelect from './jeecg/components/JAreaSelect.vue';
import JEditor from './jeecg/components/JEditor.vue';
import JMarkdownEditor from './jeecg/components/JMarkdownEditor.vue';
// import JEditor from './jeecg/components/JEditor.vue';
// import JMarkdownEditor from './jeecg/components/JMarkdownEditor.vue';
import JSelectInput from './jeecg/components/JSelectInput.vue';
import JCodeEditor from './jeecg/components/JCodeEditor.vue';
// import JCodeEditor from './jeecg/components/JCodeEditor.vue';
import JCategorySelect from './jeecg/components/JCategorySelect.vue';
import JSelectMultiple from './jeecg/components/JSelectMultiple.vue';
import JPopup from './jeecg/components/JPopup.vue';
@@ -50,7 +58,7 @@ import JPopupDict from './jeecg/components/JPopupDict.vue';
import JSwitch from './jeecg/components/JSwitch.vue';
import JTreeDict from './jeecg/components/JTreeDict.vue';
import JInputPop from './jeecg/components/JInputPop.vue';
import { JEasyCron } from './jeecg/components/JEasyCron';
// import { JEasyCron } from './jeecg/components/JEasyCron';
import JCheckbox from './jeecg/components/JCheckbox.vue';
import JInput from './jeecg/components/JInput.vue';
import JTreeSelect from './jeecg/components/JTreeSelect.vue';
@@ -104,7 +112,10 @@ componentMap.set('Upload', BasicUpload);
componentMap.set('Divider', Divider);
//注册自定义组件
componentMap.set('JAreaLinkage', JAreaLinkage);
componentMap.set(
'JAreaLinkage',
createAsyncComponent(() => import('./jeecg/components/JAreaLinkage.vue'))
);
componentMap.set('JSelectPosition', JSelectPosition);
componentMap.set('JSelectUser', JSelectUser);
componentMap.set('JSelectRole', JSelectRole);
@@ -112,10 +123,19 @@ componentMap.set('JImageUpload', JImageUpload);
componentMap.set('JDictSelectTag', JDictSelectTag);
componentMap.set('JSelectDept', JSelectDept);
componentMap.set('JAreaSelect', JAreaSelect);
componentMap.set('JEditor', JEditor);
componentMap.set('JMarkdownEditor', JMarkdownEditor);
componentMap.set(
'JEditor',
createAsyncComponent(() => import('./jeecg/components/JEditor.vue'))
);
componentMap.set(
'JMarkdownEditor',
createAsyncComponent(() => import('./jeecg/components/JMarkdownEditor.vue'))
);
componentMap.set('JSelectInput', JSelectInput);
componentMap.set('JCodeEditor', JCodeEditor);
componentMap.set(
'JCodeEditor',
createAsyncComponent(() => import('./jeecg/components/JCodeEditor.vue'))
);
componentMap.set('JCategorySelect', JCategorySelect);
componentMap.set('JSelectMultiple', JSelectMultiple);
componentMap.set('JPopup', JPopup);
@@ -125,7 +145,10 @@ componentMap.set('JPopupDict', JPopupDict);
componentMap.set('JSwitch', JSwitch);
componentMap.set('JTreeDict', JTreeDict);
componentMap.set('JInputPop', JInputPop);
componentMap.set('JEasyCron', JEasyCron);
componentMap.set(
'JEasyCron',
createAsyncComponent(() => import('./jeecg/components/JEasyCron/EasyCronInput.vue'))
);
componentMap.set('JCheckbox', JCheckbox);
componentMap.set('JInput', JInput);
componentMap.set('JTreeSelect', JTreeSelect);

View File

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

View File

@@ -105,6 +105,22 @@
return disabled;
});
// update-begin--author:liaozhiyang---date:20240308---for【QQYUN-8377】formSchema props支持动态修改
const getDynamicPropsValue = computed(() => {
const { dynamicPropsVal, dynamicPropskey } = props.schema;
if (dynamicPropskey == null) {
return null;
} else {
const { [dynamicPropskey]: itemValue } = unref(getComponentsProps);
let value = itemValue;
if (isFunction(dynamicPropsVal)) {
value = dynamicPropsVal(unref(getValues));
return value;
}
}
});
// update-end--author:liaozhiyang---date:20240308---for【QQYUN-8377】formSchema props支持动态修改
function getShow(): { isShow: boolean; isIfShow: boolean } {
const { show, ifShow } = props.schema;
const { showAdvancedButton } = props.formProps;
@@ -276,6 +292,12 @@
...unref(getComponentsProps),
disabled: unref(getDisable),
};
// update-begin--author:liaozhiyang---date:20240308---for【QQYUN-8377】formSchema props支持动态修改
const dynamicPropskey = props.schema.dynamicPropskey;
if (dynamicPropskey) {
propsData[dynamicPropskey] = unref(getDynamicPropsValue);
}
// update-end--author:liaozhiyang---date:20240308---for【QQYUN-8377】formSchema props支持动态修改
const isCreatePlaceholder = !propsData.disabled && autoSetPlaceHolder;
// RangePicker place是一个数组
@@ -315,21 +337,19 @@
//update-begin-author:taoyan date:2022-9-7 for: VUEN-2061【样式】online表单超出4个 .. 省略显示
//label宽度支持自定义
const { label, helpMessage, helpComponentProps, subLabel, labelLength } = props.schema;
let showLabel:string = (label+'')
if(labelLength && showLabel.length>4){
let showLabel: string = label + '';
if (labelLength && showLabel.length > 4) {
showLabel = showLabel.substr(0, labelLength);
}
const titleObj = {title: label}
const titleObj = { title: label };
const renderLabel = subLabel ? (
<span>
{label} <span class="text-secondary">{subLabel}</span>
</span>
) : labelLength ? (
<label {...titleObj}>{showLabel}</label>
) : (
labelLength ? (
<label {...titleObj}>{showLabel}</label>
) : (
label
)
label
);
//update-end-author:taoyan date:2022-9-7 for: VUEN-2061【样式】online表单超出4个 .. 省略显示
const getHelpMessage = isFunction(helpMessage) ? helpMessage(unref(getValues)) : helpMessage;
@@ -391,14 +411,14 @@
}
const { baseColProps = {} } = props.formProps;
// update-begin--author:liaozhiyang---date:20230803---for【issues-641】调整表格搜索表单的span配置无效
// update-begin--author:liaozhiyang---date:20230803---for【issues-641】调整表格搜索表单的span配置无效
const { getIsMobile } = useAppInject();
let realColProps;
realColProps = { ...baseColProps, ...colProps };
if (colProps['span'] && !unref(getIsMobile)) {
['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].forEach((name) => delete realColProps[name]);
}
// update-end--author:liaozhiyang---date:20230803---for【issues-641】调整表格搜索表单的span配置无效
// update-end--author:liaozhiyang---date:20230803---for【issues-641】调整表格搜索表单的span配置无效
const { isIfShow, isShow } = getShow();
const values = unref(getValues);

View File

@@ -192,6 +192,11 @@ export interface FormSchema {
dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean);
dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[];
// update-begin--author:liaozhiyang---date:20240308---for【QQYUN-8377】formSchema props支持动态修改
// 设置组件props的key
dynamicPropskey?: string;
dynamicPropsVal?: ((renderCallbackParams: RenderCallbackParams) => any);
// update-end--author:liaozhiyang---date:20240308---for【QQYUN-8377】formSchema props支持动态修改
// 这个属性自定义的 用于自定义的业务 比如在表单打开的时候修改表单的禁用状态但是又不能重写componentProps因为他的内容太多了所以使用dynamicDisabled和buss实现
buss?: any;

View File

@@ -1,6 +1,7 @@
import { registerComponent, registerAsyncComponent } from '/@/components/jeecg/JVxeTable';
import { registerComponent, registerAsyncComponent, registerASyncComponentReal } from '/@/components/jeecg/JVxeTable';
import { JVxeTypes } from '/@/components/jeecg/JVxeTable/types';
import { DictSearchSpanCell, DictSearchInputCell } from './src/components/JVxeSelectDictSearchCell';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export async function registerJVxeCustom() {
// ----------------- ⚠ 注意事项 ⚠ -----------------
@@ -23,5 +24,8 @@ export async function registerJVxeCustom() {
// 注册【部门选择】组件
await registerAsyncComponent(JVxeTypes.departSelect, import('./src/components/JVxeDepartSelectCell.vue'));
// 注册【省市区选择】组件
await registerAsyncComponent(JVxeTypes.pca, import('./src/components/JVxePcaCell.vue'));
registerASyncComponentReal(
JVxeTypes.pca,
createAsyncComponent(() => import('./src/components/JVxePcaCell.vue'))
);
}

View File

@@ -65,6 +65,9 @@
import { useFullScreen } from './hooks/useModalFullScreen';
import { omit } from 'lodash-es';
import { useDesign } from '/@/hooks/web/useDesign';
import { useAppInject } from '/@/hooks/web/useAppInject';
export default defineComponent({
name: 'BasicModal',
components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
@@ -94,13 +97,21 @@
if (instance) {
emit('register', modalMethods, instance.uid);
}
const { getIsMobile } = useAppInject();
// Custom title component: get title
const getMergeProps = computed((): Recordable => {
return {
const result = {
...props,
...(unref(propsRef) as any),
};
// update-begin--author:liaozhiyang---date:20240326---for【QQYUN-8643】弹窗移动端弹窗统一全屏
if (getIsMobile.value) {
result.canFullscreen = false;
result.defaultFullscreen = true;
}
// update-end--author:liaozhiyang---date:20240326---for【QQYUN-8643】弹窗移动端弹窗统一全屏
return result;
});
//update-begin-author:liusq date:2023-05-25 for:【issues/4856】Modal控件设置 :title = null 无效
//是否未设置标题
@@ -153,6 +164,11 @@
watchEffect(() => {
fullScreenRef.value = !!props.defaultFullscreen;
// update-begin--author:liaozhiyang---date:20240326---for【QQYUN-8643】弹窗移动端弹窗统一全屏
if (getIsMobile.value) {
fullScreenRef.value = true
}
// update-end--author:liaozhiyang---date:20240326---for【QQYUN-8643】弹窗移动端弹窗统一全屏
});
watchEffect(() => {
@@ -210,6 +226,11 @@
}
if (Reflect.has(props, 'defaultFullscreen')) {
fullScreenRef.value = !!props.defaultFullscreen;
// update-begin--author:liaozhiyang---date:20240326---for【QQYUN-8643】弹窗移动端弹窗统一全屏
if (getIsMobile.value) {
fullScreenRef.value = true
}
// update-end--author:liaozhiyang---date:20240326---for【QQYUN-8643】弹窗移动端弹窗统一全屏
}
}
@@ -295,4 +316,9 @@
.jeecg-modal-content {
height: 100%;
}
html[data-theme='dark'] {
.jeecg-comment-outer {
border-left: 1px solid rgba(253, 253, 253, 0.12);
}
}
</style>

View File

@@ -45,16 +45,36 @@
useWindowSizeFn(setModalHeight.bind(null, false));
useMutationObserver(
spinRef,
() => {
setModalHeight();
},
{
attributes: true,
subtree: true,
}
);
// update-begin--author:liaozhiyang---date:2024-04-18---for【QQYUN-9035】basicModal不设置maxHeight或height会一直执行setModalHeight需即使销毁MutationObserver
let observer,
recordCount: any = {};
if (!(props.maxHeight || props.height)) {
observer = useMutationObserver(
spinRef,
() => {
setModalHeight({
source: 'muob',
callBack: (height) => {
const count = recordCount[height];
if (count) {
recordCount[height] = ++recordCount[height];
if (count > 5) {
observer.stop();
recordCount = null;
}
} else {
recordCount[height] = 1;
}
},
});
},
{
attributes: true,
subtree: true,
}
);
}
// update-end--author:liaozhiyang---date:2024-04-18---for【QQYUN-9035】basicModal不设置maxHeight或height会一直执行setModalHeight需即使销毁MutationObserver
createModalContext({
redoModalHeight: setModalHeight,
@@ -124,16 +144,21 @@
});
}
async function setModalHeight() {
async function setModalHeight(option?) {
console.log("---------性能监控--------setModalHeight----------")
const options = option || {};
const source = options.source;
const callBack = options.callBack;
// 解决在弹窗关闭的时候监听还存在,导致再次打开弹窗没有高度
// 加上这个,就必须在使用的时候传递父级的visible
if (!props.visible) return;
const wrapperRefDom = unref(wrapperRef);
if (!wrapperRefDom) return;
const bodyDom = wrapperRefDom.$el.parentElement;
// update-begin--author:liaozhiyang---date:20240320---for【QQYUN-8573】BasicModal组件在非全屏的情况下最大高度获取异常不论内容高度是否超出屏幕高度都等于内容高度
const bodyDom = wrapperRefDom.$el.parentElement?.parentElement?.parentElement;
// update-end--author:liaozhiyang---date:20240320---forBasicModal组件在非全屏的情况下最大高度获取异常不论内容高度是否超出屏幕高度都等于内容高度
if (!bodyDom) return;
bodyDom.style.padding = '0';
// bodyDom.style.padding = '0';
await nextTick();
try {
@@ -162,6 +187,12 @@
} else {
realHeightRef.value = props.height ? props.height : realHeight > maxHeight ? maxHeight : realHeight;
}
// update-begin--author:liaozhiyang---date:2024-04-18---for【QQYUN-9035】basicModal不设置maxHeight或height会一直执行setModalHeight需即使销毁MutationObserver
if (source == 'muob') {
callBack(realHeightRef.value);
}
// update-end--author:liaozhiyang---date:2024-04-18---for【QQYUN-9035】basicModal不设置maxHeight或height会一直执行setModalHeight需即使销毁MutationObserver
emit('height-change', unref(realHeightRef));
} catch (error) {
console.log(error);

View File

@@ -20,7 +20,13 @@
<Table ref="tableElRef" v-bind="getBindValues" :rowClassName="getRowClassName" v-show="getEmptyDataIsShowTable" @resizeColumn="handleResizeColumn" @change="handleTableChange">
<!-- antd的原生插槽直接传递 -->
<template #[item]="data" v-for="item in slotNamesGroup.native" :key="item">
<slot :name="item" v-bind="data || {}"></slot>
<!-- update-begin--author:liaozhiyang---date:20240424---forissues/1146BasicTable使用headerCell全选框出不来 -->
<template v-if="item === 'headerCell'">
<CustomSelectHeader v-if="isCustomSelection(data.column)" v-bind="selectHeaderProps" />
<slot v-else :name="item" v-bind="data || {}"></slot>
</template>
<slot v-else :name="item" v-bind="data || {}"></slot>
<!-- update-begin--author:liaozhiyang---date:20240424---forissues/1146BasicTable使用headerCell全选框出不来 -->
</template>
<template #headerCell="{ column }">
<!-- update-begin--author:sunjianlei---date:220230630---forQQYUN-5571自封装选择列解决数据行选择卡顿问题 -->
@@ -260,7 +266,7 @@
/*if (slots.expandedRowRender) {
propsData = omit(propsData, 'scroll');
}*/
//update-end---author:wangshuai ---date:20230214 for[QQYUN-4237]代码生成 内嵌子表模式 没有滚动条------------
//update-end---author:wangshuai ---date:20230214 for[QQYUN-4237]代码生成 内嵌子表模式 没有滚动条------------
// update-begin--author:sunjianlei---date:220230630---for【QQYUN-5571】自封装选择列解决数据行选择卡顿问题
// 自定义选择列,需要去掉原生的
@@ -393,6 +399,7 @@
tableAction,
redoHeight,
handleResizeColumn: (w, col) => {
console.log('col',col);
col.width = w;
},
getFormProps: getFormProps as any,

View File

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

View File

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

View File

@@ -2,7 +2,7 @@ import type { BasicColumn } from '/@/components/Table';
import type { Ref, ComputedRef } from 'vue';
import type { BasicTableProps, PaginationProps, TableRowSelection } from '/@/components/Table';
import { computed, nextTick, onUnmounted, ref, toRaw, unref, watch, watchEffect } from 'vue';
import { omit } from 'lodash-es';
import { omit, isEqual } from 'lodash-es';
import { throttle } from 'lodash-es';
import { Checkbox, Radio } from 'ant-design-vue';
import { isFunction } from '/@/utils/is';
@@ -128,17 +128,44 @@ export function useCustomSelection(
});
// 监听传入的selectedRowKeys
// update-begin--author:liaozhiyang---date:20240306---for【QQYUN-8390】部门人员组件点击重置未清空selectedRowKeys.value=[]watch没监听到加deep
watch(
() => unref(propsRef)?.rowSelection?.selectedRowKeys,
(val: string[]) => {
// 解决selectedRowKeys在页面调用处使用ref失效
const value = unref(val);
if (Array.isArray(value)) {
if (Array.isArray(value) && !sameArray(value, selectedKeys.value)) {
setSelectedRowKeys(value);
}
},
{ immediate: true }
{
immediate: true,
deep: true
}
);
// update-end--author:liaozhiyang---date:20240306---for【QQYUN-8390】部门人员组件点击重置未清空selectedRowKeys.value=[]watch没监听到加deep
/**
* 2024-03-06
* liaozhiyang
* 判断是否同一个数组 (引用地址,长度,元素位置信息相同才是同一个数组。数组元素只有字符串)
*/
function sameArray(a, b) {
if (a === b) {
if (a.length === b.length) {
return a.toString() === b.toString();
} else {
return false;
}
} else {
// update-begin--author:liaozhiyang---date:20240425---for【QQYUN-9123】popupdict打开弹窗打开程序运行
if (isEqual(a, b)) {
return true;
}
// update-end--author:liaozhiyang---date:20240425---for【QQYUN-9123】popupdict打开弹窗打开程序运行
return false;
}
}
// 当任意一个变化时,触发同步检测
watch([selectedKeys, selectedRows], () => {
@@ -387,6 +414,9 @@ export function useCustomSelection(
key={'j-select__' + recordKey}
checked={selectedKeys.value.includes(recordKey)}
onUpdate:checked={(checked) => onSelect(record, checked)}
// update-begin--author:liaozhiyang---date:20230326---for【QQYUN-8694】BasicTable在使用clickToRowSelect=true下selection-change 事件在触发多次
onClick={(e) => e.stopPropagation()}
// update-end--author:liaozhiyang---date:20230326---for【QQYUN-8694】BasicTable在使用clickToRowSelect=true下selection-change 事件在触发多次
/>
);
}
@@ -412,6 +442,9 @@ export function useCustomSelection(
key={'j-select__' + recordKey}
checked={selectedKeys.value.includes(recordKey)}
onUpdate:checked={(checked) => onSelect(record, checked)}
// update-begin--author:liaozhiyang---date:20230326---for【QQYUN-8694】BasicTable在使用clickToRowSelect=true下selection-change 事件在触发多次
onClick={(e) => e.stopPropagation()}
// update-end--author:liaozhiyang---date:20230326---for【QQYUN-8694】BasicTable在使用clickToRowSelect=true下selection-change 事件在触发多次
/>
);
}

View File

@@ -7,6 +7,7 @@ import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
import { useModalContext } from '/@/components/Modal';
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
import { useDebounceFn } from '@vueuse/core';
import componentSetting from '/@/settings/componentSetting';
export function useTableScroll(
propsRef: ComputedRef<BasicTableProps>,
@@ -118,14 +119,13 @@ export function useTableScroll(
}
let footerHeight = 0;
if (!isBoolean(pagination)) {
if (!footerEl) {
footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement;
} else {
const offsetHeight = footerEl.offsetHeight;
footerHeight += offsetHeight || 0;
}
// update-begin--author:liaozhiyang---date:20240424---for【issues/1137】BasicTable自适应高度计算没有减去尾部高度
footerEl = tableEl.querySelector('.ant-table-footer');
if (footerEl) {
const offsetHeight = footerEl.offsetHeight;
footerHeight = offsetHeight || 0;
}
// update-end--author:liaozhiyang---date:20240424---for【issues/1137】BasicTable自适应高度计算没有减去尾部高度
let headerHeight = 0;
if (headEl) {
@@ -180,10 +180,13 @@ export function useTableScroll(
const getScrollRef = computed(() => {
const tableHeight = unref(tableHeightRef);
const { canResize, scroll } = unref(propsRef);
const { table } = componentSetting;
return {
x: unref(getScrollX),
y: canResize ? tableHeight : null,
scrollToFirstRowOnChange: false,
// update-begin--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
scrollToFirstRowOnChange: table.scrollToFirstRowOnChange,
// update-end--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
...scroll,
};
});

View File

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

View File

@@ -152,6 +152,7 @@ export interface BasicTableProps<T = any> {
inset?: boolean;
// 显示表格设置
showTableSetting?: boolean;
// 表格上方操作按钮设置
tableSetting?: TableSetting;
// 斑马纹
striped?: boolean;
@@ -205,7 +206,6 @@ export interface BasicTableProps<T = any> {
canResize?: boolean;
// 自适应高度偏移, 计算结果-偏移量
resizeHeightOffset?: number;
// 在分页改变的时候清空选项
clearSelectOnPageChange?: boolean;
//
@@ -319,7 +319,9 @@ export interface BasicTableProps<T = any> {
* you need to add style .ant-table td { white-space: nowrap; }.
* @type object
*/
scroll?: { x?: number | true | 'max-content'; y?: number };
// update-begin--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
scroll?: { x?: number | true | 'max-content'; y?: number; scrollToFirstRowOnChange?: boolean };
// update-end--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
/**
* Whether to show table header

View File

@@ -118,7 +118,12 @@
const initOptions = computed(() => {
const { height, options, toolbar, plugins, menubar } = props;
const publicPath = import.meta.env.VITE_PUBLIC_PATH || '/';
let publicPath = import.meta.env.VITE_PUBLIC_PATH || '/';
// update-begin--author:liaozhiyang---date:20240320---for【QQYUN-8571】发布路径不以/结尾资源会加载失败
if (!publicPath.endsWith('/')) {
publicPath += '/';
}
// update-end--author:liaozhiyang---date:20240320---for【QQYUN-8571】发布路径不以/结尾资源会加载失败
return {
selector: `#${unref(tinymceId)}`,
height,

View File

@@ -106,7 +106,7 @@
.@{prefix-cls} {
position: absolute;
top: 4px;
top: 8px;
right: 10px;
z-index: 20;
@@ -114,5 +114,12 @@
position: fixed;
z-index: 10000;
}
// update-begin--author:liaozhiyang---date:20230326---for【QQYUN-8647】online tinymce组件上传图片按遮挡了控件栏的全屏按钮
.ant-btn {
padding: 2px 4px;
font-size: 12px;
height: 24px;
}
// update-end--author:liaozhiyang---date:20230326---for【QQYUN-8647】online tinymce组件上传图片按遮挡了控件栏的全屏按钮
}
</style>

View File

@@ -19,6 +19,7 @@
toRaw,
watch,
onMounted,
nextTick,
} from 'vue';
import TreeHeader from './components/TreeHeader.vue';
import { Tree, Spin, Empty } from 'ant-design-vue';
@@ -68,6 +69,7 @@
...fieldNames,
};
});
const treeRef = ref<any>(null);
const getBindValues = computed(() => {
let propsData = {
@@ -88,28 +90,35 @@
emit('update:selectedKeys', v);
},
onCheck: (v: CheckKeys, e) => {
let currentValue = toRaw(state.checkedKeys) as KeyType[];
if (isArray(currentValue) && searchState.startSearch) {
//update-begin-author:liusq---date:20230404--for: [issue/429]树搜索点击事件失效---
const value = e.node.eventKey;
currentValue = difference(currentValue, getChildrenKeys(value));
if (e.checked) {
currentValue.push(value);
}
//update-begin-author:liusq---date:20230404--for: [issue/429]树搜索点击事件失效---
state.checkedKeys = currentValue;
} else {
state.checkedKeys = v;
}
const rawVal = toRaw(state.checkedKeys);
emit('update:value', rawVal);
emit('check', rawVal, e);
handleCheck(v, e);
},
onRightClick: handleRightClick,
};
return omit(propsData, 'treeData', 'class');
});
/**
* 2024-04-26
* liaozhiyang
* 【issues/1151】层级独立时勾选了父级然后点击层级关联子级视觉上勾选了但是保存子级没存上(把函数独立出来复用)
* */
const handleCheck = (v: CheckKeys, e?) => {
let currentValue = toRaw(state.checkedKeys) as KeyType[];
if (isArray(currentValue) && searchState.startSearch && e) {
// update-begin-author:liusq---date:20230404--for: [issue/429]树搜索点击事件失效---
const value = e.node.eventKey;
currentValue = difference(currentValue, getChildrenKeys(value));
if (e.checked) {
currentValue.push(value);
}
// update-begin-author:liusq---date:20230404--for: [issue/429]树搜索点击事件失效---
state.checkedKeys = currentValue;
} else {
state.checkedKeys = v;
}
const rawVal = toRaw(state.checkedKeys);
emit('update:value', rawVal);
emit('check', rawVal, e);
};
const getTreeData = computed((): TreeItem[] =>
searchState.startSearch ? searchState.searchData : unref(treeDataRef),
@@ -317,10 +326,18 @@
emit('change', v);
},
);
watchEffect(() => {
state.checkStrictly = props.checkStrictly;
});
// update-begin--author:liaozhiyang---date:20240426---for【issues/1151】层级独立时勾选了父级然后点击层级关联子级视觉上勾选了但是保存子级没存上
watch(
() => props.checkStrictly,
() => {
state.checkStrictly = props.checkStrictly;
nextTick(() => {
const value = treeRef.value?.checkedKeys;
handleCheck([...value]);
});
}
);
// update-end--author:liaozhiyang---date:20240426---for【issues/1151】层级独立时勾选了父级然后点击层级关联子级视觉上勾选了但是保存子级没存上
const instance: TreeActionType = {
setExpandedKeys,
@@ -444,7 +461,7 @@
)}
<Spin spinning={unref(props.loading)} tip="加载中...">
<ScrollContainer style={scrollStyle} v-show={!unref(getNotFound)}>
<Tree {...unref(getBindValues)} showIcon={false} treeData={treeData.value} />
<Tree ref={treeRef} {...unref(getBindValues)} showIcon={false} treeData={treeData.value} />
</ScrollContainer>
<Empty
v-show={unref(getNotFound)}

View File

@@ -1,4 +1,4 @@
export { default as JVxeTable } from './src/JVxeTable';
export { registerJVxeTable } from './src/install';
export { deleteComponent } from './src/componentMap';
export { registerComponent, registerAsyncComponent } from './src/utils/registerUtils';
export { registerComponent, registerAsyncComponent, registerASyncComponentReal } from './src/utils/registerUtils';

View File

@@ -69,6 +69,10 @@ export default defineComponent({
key: layer + effectIdx.value + randomString(6),
class: ['j-vxe-reload-effect-span', `layer-${layer}`],
style: {},
// update-begin--author:liaozhiyang---date:20240424---for【issues/1175】解决vxetable鼠标hover之后title显示不对的问题
title: vNode,
// update-end--author:liaozhiyang---date:20240424---for【issues/1175】解决vxetable鼠标hover之后title显示不对的问题
};
if (layer === 'top') {
// 最新渲染的在下面

View File

@@ -17,6 +17,19 @@ export function isRegistered(type: JVxeTypes | string) {
return componentMap.has(type);
}
/**
* 2024-03-08
* liaozhiyang
* 异步注册vxe自定义组件
* 【QQYUN-8241】
* @param type
* @param promise
*/
export function registerASyncComponentReal(type: JVxeTypes, component) {
addComponent(type, component);
registerOneComponent(type);
}
/**
* 注册vxe自定义组件
*

View File

@@ -1,8 +1,8 @@
import type { App } from 'vue';
import { Icon } from './Icon';
import AIcon from '/@/components/jeecg/AIcon.vue';
//Tinymce富文本
import Editor from '/@/components/Tinymce/src/Editor.vue'
// //Tinymce富文本
// import Editor from '/@/components/Tinymce/src/Editor.vue'
import { Button, JUploadButton } from './Button';
@@ -61,6 +61,7 @@ import {
} from 'ant-design-vue';
const compList = [AntButton.Group, Icon, AIcon, JUploadButton];
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export function registerGlobComp(app: App) {
compList.forEach((comp) => {
@@ -68,7 +69,13 @@ export function registerGlobComp(app: App) {
});
//仪表盘依赖Tinymce需要提前加载没办法按需加载了
app.component(Editor.name, Editor);
//app.component(Editor.name, Editor);
app.component(
'Tinymce',
createAsyncComponent(() => import('./Tinymce/src/Editor.vue'), {
loading: true,
})
);
app.use(Select)
.use(Alert)
@@ -119,5 +126,5 @@ export function registerGlobComp(app: App) {
.use(Cascader)
.use(Rate)
.use(Progress);
console.log("---初始化--- 全局注册Antd、仪表盘、流程设计器、online、流程等组件--------------")
console.log("---初始化---全局注册Antd等组件--------------")
}

View File

@@ -162,3 +162,17 @@ html[data-theme='dark'] .ant-input-affix-wrapper-textarea-with-clear-btn {
}
}
// update-end--author:liaozhiyang---date:20230108---for【QQYUN-7855】table页码同步3.x页面效果
//update-begin--author:wangshuai---date:20240429---for修改tinymce段落下拉框的字体和样式
.tox .tox-tbtn__select-label{
font-size: 14px;
}
.tox .tox-tbtn--select{
width: 80px !important;
}
.tox .tox-collection__item-label {
font-size: 14px !important;
}
//update-end--author:wangshuai---date:20240429---for修改tinymce段落下拉框的字体和样式

View File

@@ -89,3 +89,12 @@ img, video {
// box-shadow: none;
// }
// update-end--author:liaozhiyang---date:20231116---for【QQYUN-7011】online表单多了一个蓝色的边框
// update-begin--author:liaozhiyang---date:20240424---for【issues/1175】解决vxetable鼠标hover之后title显示不对的问题
.vxe-cell {
pointer-events: none;
> * {
pointer-events: auto;
}
}
// update-end--author:liaozhiyang---date:20240424---for【issues/1175】解决vxetable鼠标hover之后title显示不对的问题

View File

@@ -1,10 +1,19 @@
import { getThemeColors, generateColors } from '../../../build/config/themeConfig';
import { replaceStyleVariables } from '@rys-fe/vite-plugin-theme/es/client';
import {
replaceStyleVariables,
loadDarkThemeCss,
replaceCssColors,
darkCssIsReady,
linkID,
styleTagId,
appendCssToDom,
getStyleDom,
} from '@rys-fe/vite-plugin-theme/es/client';
import { mixLighten, mixDarken, tinycolor } from '@rys-fe/vite-plugin-theme/es/colorUtils';
import { useAppStore } from '/@/store/modules/app';
import { defHttp } from '/@/utils/http/axios';
let cssText = '';
export async function changeTheme(color: string) {
// update-begin--author:liaozhiyang---date:20231218---for【QQYUN-6366】升级到antd4.x
const appStore = useAppStore();
@@ -16,17 +25,32 @@ export async function changeTheme(color: string) {
tinycolor,
color,
});
let res = await replaceStyleVariables({
colorVariables: [...getThemeColors(color), ...colors],
});
fixDark();
return res;
// update-begin--author:liaozhiyang---date:20240322---for【QQYUN-8570】生产环境暗黑模式下主题色不生效
if (import.meta.env.PROD && appStore.getDarkMode === 'dark') {
if (!darkCssIsReady && !cssText) {
await loadDarkThemeCss();
}
const el: HTMLLinkElement = document.getElementById(linkID) as HTMLLinkElement;
if (el?.href) {
// cssText = await fetchCss(el.href) as string;
!cssText && (cssText = await defHttp.get({ url: el.href }, { isTransformResponse: false }));
const colorVariables = [...getThemeColors(color), ...colors];
const processCss = await replaceCssColors(cssText, colorVariables);
appendCssToDom(getStyleDom(styleTagId) as HTMLStyleElement, processCss);
}
} else {
await replaceStyleVariables({
colorVariables: [...getThemeColors(color), ...colors],
});
fixDark();
}
// update-end--author:liaozhiyang---date:20240322---for【QQYUN-8570】生产环境暗黑模式下主题色不生效
}
// 【LOWCOD-2262】修复黑暗模式下切换皮肤无效的问题
async function fixDark() {
let el = document.getElementById('__VITE_PLUGIN_THEME__');
// update-begin--author:liaozhiyang---date:20240322---for【QQYUN-8570】生产环境暗黑模式下主题色不生效
const el = document.getElementById(styleTagId);
// update-end--author:liaozhiyang---date:20240322---for【QQYUN-8570】生产环境暗黑模式下主题色不生效
if (el) {
el.innerHTML = el.innerHTML.replace(/\\["']dark\\["']/g, `'dark'`);
}

View File

@@ -174,7 +174,11 @@ export function createPermissionGuard(router: Router) {
// }
// }
//update-end---author:scott ---date::2024-02-21 for【QQYUN-8326】刷新首页不需要重新获获取用户信息---
// update-begin--author:liaozhiyang---date:20240321---for【QQYUN-8572】表格行选择卡顿问题customRender中字典引起的
if (userStore.getLastUpdateTime === 0) {
userStore.setAllDictItemsByLocal();
}
// update-end--author:liaozhiyang---date:20240321---for【QQYUN-8572】表格行选择卡顿问题customRender中字典引起的
if (permissionStore.getIsDynamicAddedRoute) {
next();
return;

View File

@@ -47,6 +47,9 @@ export default {
defaultFilterFn: (data: Partial<Recordable<string[]>>) => {
return data;
},
// update-begin--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
scrollToFirstRowOnChange: false,
// update-end--author:liaozhiyang---date:20240424---for【issues/1188】BasicTable加上scrollToFirstRowOnChange类型定义
},
// 滚动组件配置
scrollbar: {

View File

@@ -2,12 +2,13 @@ import type { App } from 'vue';
import { registerJVxeTable } from '/@/components/jeecg/JVxeTable';
import { registerJVxeCustom } from '/@/components/JVxeCustom';
// 注册全局聊天表情包
import { Picker } from 'emoji-mart-vue-fast/src';
// // 注册全局聊天表情包
// import { Picker } from 'emoji-mart-vue-fast/src';
// 注册全局dayjs
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export async function registerThirdComp(app: App) {
//---------------------------------------------------------------------
@@ -17,8 +18,22 @@ export async function registerThirdComp(app: App) {
await registerJVxeCustom();
//---------------------------------------------------------------------
// 注册全局聊天表情包
app.component('Picker', Picker);
//app.component('Picker', Picker);
app.component(
'Picker',
createAsyncComponent(() => {
return new Promise((resolve, rejected) => {
import('emoji-mart-vue-fast/src')
.then((res) => {
const { Picker } = res;
resolve(Picker);
})
.catch((err) => {
rejected(err);
});
});
})
);
//---------------------------------------------------------------------
// 注册全局dayjs
dayjs.locale('zh-cn');

View File

@@ -18,7 +18,7 @@ import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
import { filter } from '/@/utils/helper/treeHelper';
import { getBackMenuAndPerms, switchVue3Menu } from '/@/api/sys/menu';
import { getBackMenuAndPerms } from '/@/api/sys/menu';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageEnum } from '/@/enums/pageEnum';
@@ -224,39 +224,39 @@ export const usePermissionStore = defineStore({
routeList = await this.changePermissionCode();
//routeList = (await getMenuList()) as AppRouteRecordRaw[];
// update-begin----author:sunjianlei---date:20220315------for: 判断是否是 vue3 版本的菜单 ---
let hasIndex: boolean = false;
let hasIcon: boolean = false;
for (let menuItem of routeList) {
// 条件1判断组件是否是 layouts/default/index
if (!hasIndex) {
hasIndex = menuItem.component === 'layouts/default/index';
}
// 条件2判断图标是否带有 冒号
if (!hasIcon) {
hasIcon = !!menuItem.meta?.icon?.includes(':');
}
// 满足任何一个条件都直接跳出循环
if (hasIcon || hasIndex) {
break;
}
}
// 两个条件都不满足,就弹出提示框
if (!hasIcon && !hasIndex) {
// 延迟1.5秒之后再出现提示,否则提示框出不来
setTimeout(
() =>
createWarningModal({
title: '检测提示',
content:
'当前菜单表是 <b>Vue2版本</b>,导致菜单加载异常!<br>点击确认切换到Vue3版菜单',
onOk:function () {
switchVue3Menu();
location.reload();
}
}),
100
);
}
// let hasIndex: boolean = false;
// let hasIcon: boolean = false;
// for (let menuItem of routeList) {
// // 条件1判断组件是否是 layouts/default/index
// if (!hasIndex) {
// hasIndex = menuItem.component === 'layouts/default/index';
// }
// // 条件2判断图标是否带有 冒号
// if (!hasIcon) {
// hasIcon = !!menuItem.meta?.icon?.includes(':');
// }
// // 满足任何一个条件都直接跳出循环
// if (hasIcon || hasIndex) {
// break;
// }
// }
// // 两个条件都不满足,就弹出提示框
// if (!hasIcon && !hasIndex) {
// // 延迟1.5秒之后再出现提示,否则提示框出不来
// setTimeout(
// () =>
// createWarningModal({
// title: '检测提示',
// content:
// '当前菜单表是 <b>Vue2版本</b>,导致菜单加载异常!<br>点击确认切换到Vue3版菜单',
// onOk:function () {
// switchVue3Menu();
// location.reload();
// }
// }),
// 100
// );
// }
// update-end----author:sunjianlei---date:20220315------for: 判断是否是 vue3 版本的菜单 ---
} catch (error) {
console.error(error);

View File

@@ -19,11 +19,15 @@ import { useGlobSetting } from '/@/hooks/setting';
import { JDragConfigEnum } from '/@/enums/jeecgEnum';
import { useSso } from '/@/hooks/web/useSso';
import { isOAuth2AppEnv } from "/@/views/sys/login/useLogin";
import { getUrlParam } from "@/utils";
interface dictType {
[key: string]: any;
}
interface UserState {
userInfo: Nullable<UserInfo>;
token?: string;
roleList: RoleEnum[];
dictItems?: [];
dictItems?: dictType | null;
sessionTimeout?: boolean;
lastUpdateTime: number;
tenantid?: string | number;
@@ -41,7 +45,7 @@ export const useUserStore = defineStore({
// 角色列表
roleList: [],
// 字典
dictItems: [],
dictItems: null,
// session过期时间
sessionTimeout: false,
// Last fetch time
@@ -109,6 +113,16 @@ export const useUserStore = defineStore({
this.dictItems = dictItems;
setAuthCache(DB_DICT_DATA_KEY, dictItems);
},
setAllDictItemsByLocal() {
// update-begin--author:liaozhiyang---date:20240321---for【QQYUN-8572】表格行选择卡顿问题customRender中字典引起的
if (!this.dictItems) {
const allDictItems = getAuthCache(DB_DICT_DATA_KEY);
if (allDictItems) {
this.dictItems = allDictItems;
}
}
// update-end--author:liaozhiyang---date:20240321---for【QQYUN-8572】表格行选择卡顿问题customRender中字典引起的
},
setTenant(id) {
this.tenantid = id;
setAuthCache(TENANT_ID, id);
@@ -121,7 +135,7 @@ export const useUserStore = defineStore({
},
resetState() {
this.userInfo = null;
this.dictItems = [];
this.dictItems = null;
this.token = '';
this.roleList = [];
this.sessionTimeout = false;
@@ -196,18 +210,29 @@ export const useUserStore = defineStore({
if (redirect && goHome) {
//update-end---author:wangshuai ---date:20230424 for【QQYUN-5195】登录之后直接刷新页面导致没有进入创建组织页面------------
// update-begin--author:liaozhiyang---date:20240104---for【QQYUN-7804】部署生产环境登录跳转404问题
const publicPath = import.meta.env.VITE_PUBLIC_PATH;
let publicPath = import.meta.env.VITE_PUBLIC_PATH;
if (publicPath && publicPath != '/') {
// update-begin--author:liaozhiyang---date:20240509---for【issues/1147】登录跳转时去掉发布路径的最后一个/以解决404问题
if (publicPath.endsWith('/')) {
publicPath = publicPath.slice(0, -1);
}
redirect = publicPath + redirect;
}
// update-end--author:liaozhiyang---date:20240104---forQQYUN-7804】部署生产环境登录跳转404问题
// update-end--author:liaozhiyang---date:20240509---forissues/1147】登录跳转时去掉发布路径的最后一个/以解决404问题
// 当前页面打开
window.open(redirect, '_self')
return data;
}
// update-end-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
goHome && (await router.replace((userInfo && userInfo.homePath) || PageEnum.BASE_HOME));
//update-begin---author:wangshuai---date:2024-04-03---for:【issues/1102】设置单点登录后页面进入首页提示404也没有绘制侧边栏 #1102---
let ticket = getUrlParam('ticket');
if(ticket){
goHome && (window.location.replace((userInfo && userInfo.homePath) || PageEnum.BASE_HOME));
}else{
goHome && (await router.replace((userInfo && userInfo.homePath) || PageEnum.BASE_HOME));
}
//update-end---author:wangshuai---date:2024-04-03---for:【issues/1102】设置单点登录后页面进入首页提示404也没有绘制侧边栏 #1102---
}
return data;
},

View File

@@ -1,7 +1,7 @@
import { isObject, isString } from '/@/utils/is';
import dayjs from "dayjs";
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm';
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
export function joinTimestamp<T extends boolean>(join: boolean, restful: T): T extends true ? string : object;

View File

@@ -2,8 +2,8 @@
<BasicForm
ref="formElRef"
:class="'jee-select-demo-form'"
:labelCol="{ span: 5 }"
:wrapperCol="{ span: 15 }"
:labelCol="{ span: 6 }"
:wrapperCol="{ span: 14 }"
:showResetButton="false"
:showSubmitButton="false"
:schemas="schemas"

View File

@@ -710,4 +710,60 @@ export const schemas: FormSchema[] = [
span: 12,
},
},
{
field: 'sex',
component: 'JDictSelectTag',
label: '性别(控制下方课程options)',
helpMessage: ['component模式','性别不同,下方课程展示选项不同'],
componentProps: {
dictCode: 'sex',
type: 'radioButton',
onChange: (value) => {
console.log(value);
},
},
colProps: {
span: 12,
},
},
{
field: 'sex',
component: 'JEllipsis',
label: '选中值',
colProps: { span: 12 },
},
{
field: 'course',
component: 'Select',
label: '课程',
dynamicPropskey: 'options',
dynamicPropsVal: ({ model }) => {
let options;
if (model.sex == 1) {
return [
{ value: '0', label: 'java - 男' },
{ value: '1', label: 'vue - 男' },
];
} else if (model.sex == 2) {
return [
{ value: '2', label: '瑜伽 - 女' },
{ value: '3', label: '美甲 - 女' },
];
} else {
return [];
}
},
componentProps: {
disabled: false,
},
colProps: {
span: 12,
},
},
{
field: 'course',
component: 'JEllipsis',
label: '选中值',
colProps: { span: 12 },
},
];

View File

@@ -18,11 +18,7 @@
// labelWidth: 150,
schemas: formSchema,
showActionButtonGroup: false,
// update-begin--author:liaozhiyang---date:20231017---for【issues/790】弹窗内文本框不居中问题
labelWidth: 100,
labelCol: null,
wrapperCol: null,
// update-end--author:liaozhiyang---date:20231017---for【issues/790】弹窗内文本框不居中问题
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {

View File

@@ -10,6 +10,7 @@
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { list, saveOrUpdateMenu } from './menu.api';
import { useDrawerAdaptiveWidth } from '/@/hooks/jeecg/useAdaptiveWidth';
import { useI18n } from "/@/hooks/web/useI18n";
// 声明Emits
const emit = defineEmits(['success', 'register']);
const { adaptiveWidth } = useDrawerAdaptiveWidth();
@@ -41,7 +42,9 @@
updateSchema([
{
field: 'parentId',
componentProps: { treeData },
// update-begin--author:liaozhiyang---date:20240306---for【QQYUN-8379】菜单管理页菜单国际化
componentProps: { treeData: translateMenu(treeData, 'name') },
// update-end--author:liaozhiyang---date:20240306---for【QQYUN-8379】菜单管理页菜单国际化
},
{
field: 'name',
@@ -113,4 +116,26 @@
}
//update-end---author:wangshuai ---date:20230204 for[QQYUN-4058]菜单添加智能化处理------------
}
/**
* 2024-03-06
* liaozhiyang
* 翻译菜单名称
*/
function translateMenu(data, key) {
if (data?.length) {
const { t } = useI18n();
data.forEach((item) => {
if (item[key]) {
if (item[key].includes("t('") && t) {
item[key] = new Function('t', `return ${item[key]}`)(t);
}
}
if (item.children?.length) {
translateMenu(item.children, key);
}
});
}
return data;
}
</script>

View File

@@ -39,11 +39,13 @@
import { columns,searchFormSchema } from './menu.data';
import { list, deleteMenu, batchDeleteMenu } from './menu.api';
import { useDefIndexStore } from "@/store/modules/defIndex";
import { useI18n } from "/@/hooks/web/useI18n";
const checkedKeys = ref<Array<string | number>>([]);
const showFooter = ref(true);
const [registerDrawer, { openDrawer }] = useDrawer();
const [registerDrawer1, { openDrawer: openDataRule }] = useDrawer();
const { t } = useI18n();
// 自定义菜单名称列渲染
columns[0].customRender = function ({text, record}) {
@@ -51,6 +53,11 @@
if (isDefIndex) {
text += '(默认首页)'
}
// update-begin--author:liaozhiyang---date:20240306---for【QQYUN-8379】菜单管理页菜单国际化
if (text.includes("t('") && t) {
return new Function('t', `return ${text}`)(t);
}
// update-end--author:liaozhiyang---date:20240306---for【QQYUN-8379】菜单管理页菜单国际化
return text
}

View File

@@ -124,9 +124,10 @@
import { FilterOutlined, CloseOutlined, BellFilled, ExclamationOutlined, PlusOutlined } from '@ant-design/icons-vue';
import JSelectUser from '/@/components/Form/src/jeecg/components/JSelectUser.vue';
import { ref, unref, reactive, computed } from 'vue';
import SysMessageList from './SysMessageList.vue'
// import SysMessageList from './SysMessageList.vue'
import UserSelectModal from '/@/components/Form/src/jeecg/components/modal/UserSelectModal.vue'
import DetailModal from '/@/views/monitor/mynews/DetailModal.vue';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export default {
name: 'SysMessageModal',
@@ -137,7 +138,7 @@
BellFilled,
ExclamationOutlined,
JSelectUser,
SysMessageList,
SysMessageList: createAsyncComponent(() => import('./SysMessageList.vue')),
UserSelectModal,
PlusOutlined,
DetailModal
@@ -170,7 +171,9 @@
rangeDate: searchParams.rangeDate,
}
if(activeKey.value == 'all'){
allMessageRef.value.reload(params);
getRefPromise(allMessageRef).then(() => {
allMessageRef.value.reload(params);
});
}else{
starMessageRef.value.reload(params);
}
@@ -279,6 +282,21 @@
searchParams.fromUser = ''
searchParams.realname = ''
}
function getRefPromise(componentRef) {
return new Promise((resolve) => {
(function next() {
let ref = componentRef.value;
if (ref) {
resolve(ref);
} else {
setTimeout(() => {
next();
}, 100);
}
})();
});
}
function clearAll(){
searchParams.fromUser='';

View File

@@ -25,8 +25,8 @@
:checkedKeys="checkedKeys"
:expandedKeys="expandedKeys"
:selectedKeys="selectedKeys"
:checkStrictly="checkStrictly"
:clickRowToExpand="false"
:checkStrictly="true"
title="所拥有的的权限"
@check="onCheck"
@select="onTreeNodeSelect"
@@ -48,8 +48,8 @@
</template>
<script lang="ts" setup>
import { ref, computed, unref, onMounted } from 'vue';
import { BasicDrawer, useDrawer, useDrawerInner } from '/src/components/Drawer';
import { BasicTree, TreeItem } from '/src/components/Tree';
import { BasicDrawer, useDrawer, useDrawerInner } from '/@/components/Drawer';
import { BasicTree, TreeItem } from '/@/components/Tree';
import { PopConfirmButton } from '/@/components/Button';
import RoleDataRuleDrawer from './RoleDataRuleDrawer.vue';
import { queryTreeListForRole, queryRolePermission, saveRolePermission } from '../role.api';
@@ -60,7 +60,7 @@
//树的全部节点信息
const allTreeKeys = ref([]);
//树的选择节点信息
const checkedKeys = ref([]);
const checkedKeys = ref<any>([]);
const defaultCheckedKeys = ref([]);
//树的选中的节点信息
const selectedKeys = ref([]);
@@ -71,8 +71,8 @@
//展开折叠的key
const expandedKeys = ref<any>([]);
//父子节点选中状态是否关联
const checkStrictly = ref<boolean>(true);
//父子节点选中状态是否关联 true不关联false关联
const checkStrictly = ref<boolean>(false);
const [registerDrawer1, { openDrawer: openDataRuleDrawer }] = useDrawer();
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
await reset();
@@ -114,10 +114,58 @@
}
/**
* 点击选中
* 2024-04-26
* liaozhiyang
*/
function onCheck(o) {
checkedKeys.value = o.checked ? o.checked : o;
function onCheck(o, e) {
// checkStrictly: true=>层级独立false=>层级关联.
if (checkStrictly.value) {
checkedKeys.value = o.checked ? o.checked : o;
} else {
const keys = getNodeAllKey(e.node, 'children', 'key');
if (e.checked) {
// 反复操作下可能会有重复的keys得用new Set去重下
checkedKeys.value = [...new Set([...checkedKeys.value, ...keys])];
} else {
const result = removeMatchingItems(checkedKeys.value, keys);
checkedKeys.value = result;
}
}
}
/**
* 2024-04-26
* liaozhiyang
* 删除相匹配数组的项
*/
function removeMatchingItems(arr1, arr2) {
// 使用哈希表记录 arr2 中的元素
const hashTable = {};
for (const item of arr2) {
hashTable[item] = true;
}
// 使用 filter 方法遍历第一个数组,过滤出不在哈希表中存在的项
return arr1.filter((item) => !hashTable[item]);
}
/**
* 2024-04-26
* liaozhiyang
* 获取当前节点及以下所有子孙级的key
*/
function getNodeAllKey(node: any, children: any, key: string) {
const result: any = [];
result.push(node[key]);
const recursion = (data) => {
data.forEach((item: any) => {
result.push(item[key]);
if (item[children]?.length) {
recursion(item[children]);
}
});
};
node[children]?.length && recursion(node[children]);
return result;
}
/**
* 选中节点,打开数据权限抽屉
*/

View File

@@ -137,7 +137,15 @@
//update-end-author:taoyan date:2022-5-24 for: VUEN-1117【issue】0523周开源问题
});
//获取标题
const getTitle = computed(() => (!unref(isUpdate) ? '新增用户' : '编辑用户'));
const getTitle = computed(() => {
// update-begin--author:liaozhiyang---date:20240306---for【QQYUN-8389】系统用户详情抽屉title更改
if (!unref(isUpdate)) {
return '新增用户';
} else {
return unref(showFooter) ? '编辑用户' : '用户详情';
}
// update-end--author:liaozhiyang---date:20240306---for【QQYUN-8389】系统用户详情抽屉title更改
});
const { adaptiveWidth } = useDrawerAdaptiveWidth();
//提交事件

2
types/axios.d.ts vendored
View File

@@ -10,7 +10,7 @@ export interface RequestOptions {
isTransformResponse?: boolean;
// 是否返回本地响应头,需要获取响应头时使用此属性
isReturnNativeResponse?: boolean;
// Whether to join url
// 默认将prefix 添加到url
joinPrefix?: boolean;
// 接口地址,如果保留为空,则使用默认值
apiUrl?: string;

View File

@@ -82,13 +82,12 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
// manualChunks配置 (依赖包从大到小排列)
manualChunks: {
'tinymce-vendor': ['tinymce','@tinymce/tinymce-vue'],
'echarts-vendor': ['echarts'],
// vue vue-router合并打包
'vue-vendor': ['vue', 'vue-router'],
'antd-vue-vendor': ['ant-design-vue','@ant-design/icons-vue','@ant-design/colors'],
'vxe-table-vendor': ['vxe-table','vxe-table-plugin-antd','xe-utils'],
'codemirror-vendor': ['codemirror'],
'jeecg-online-vendor': ['@jeecg/online'],
'cron-parser-vendor': ['cron-parser'],
'emoji-mart-vue-fast': ['emoji-mart-vue-fast'],
'china-area-data-vendor': ['china-area-data']
},
},
},

10190
yarn.lock Normal file

File diff suppressed because it is too large Load Diff