35 Commits

Author SHA1 Message Date
zhangdaiscott
3c0f15bb6e 【issues/860】生成的一对多代码,热更新之后点击新增卡死 2023-12-08 21:20:17 +08:00
zhangdaiscott
348a8a3f6a JeecgBoot 3.6.1版本发布——ONLINE专题版本 2023-12-08 17:19:16 +08:00
zhangdaiscott
2ee3d66d7e JeecgBoot 3.6.1版本发布——ONLINE专题版本 2023-12-08 12:56:52 +08:00
zhangdaiscott
06a13a9acd JeecgBoot 3.6.1版本发布——ONLINE专题版本 2023-12-07 12:00:34 +08:00
zhangdaiscott
08f4c122db 升级online模块到3.6.0版本 2023-12-07 11:10:52 +08:00
zhangdaiscott
40fe2ed0fe 【issues/897】JSearchSelect组件添加class/style样式不生效 2023-12-05 14:30:55 +08:00
zhangdaiscott
c2bb591582 【issues/638】表格合计,列表table和合计table滚动联动 2023-12-05 12:04:15 +08:00
zhangdaiscott
37521946f8 【issues/872】MarkdownViewer组件无样式 2023-12-05 12:02:30 +08:00
zhangdaiscott
4c61aa136a 【issues/5564】解决tsconfig.json找不到“vite/client”的类型定义文件错误 2023-12-05 12:01:52 +08:00
zhangdaiscott
a67f074690 【issues/5595】BasicTable组件hideSelectAll: true无法隐藏全选框 2023-12-01 21:25:21 +08:00
zhangdaiscott
75bf9784e4 【issues/872】MarkdownViewer组件无样式 2023-12-01 21:23:52 +08:00
zhangdaiscott
29c1145a29 【issues/869】JCodeEditor组件初始化时没有设置mode 2023-12-01 21:23:10 +08:00
zhangdaiscott
d0ff2225c7 动态路由匹配右键重新加载404 2023-11-23 23:01:27 +08:00
zhangdaiscott
7f6f07f72c vxe-table removeRows方法加上异步删除 2023-11-23 22:58:46 +08:00
zhangdaiscott
0e45068cbd 【issues/5579】密码组件第一次输入值规则校验没触发 2023-11-23 22:57:00 +08:00
zhangdaiscott
e70455df94 【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件 2023-11-23 22:56:17 +08:00
zhangdaiscott
80b9f0cfee 【issues/863】关闭选择部门弹窗,再打开之前勾选的消失了 2023-11-22 21:23:57 +08:00
zhangdaiscott
256594e384 通知公告中发布的富文本消息,在我的消息中查看没有样式 2023-11-19 22:05:42 +08:00
zhangdaiscott
5eeab9c448 【issues/846】上传多个列表只显示一个 2023-11-19 22:03:44 +08:00
zhangdaiscott
f4b902011e online菜单名字和页面title不一致 2023-11-10 19:49:55 +08:00
zhangdaiscott
ab28f8fd87 【issues/839】BasicTable表格的更多操作按钮禁用还能点击弹出气泡框 2023-11-10 19:49:37 +08:00
zhangdaiscott
98dc3b87e1 关闭除屑优化,防止删除重要代码,导致打包后功能出现异常 2023-11-08 11:50:48 +08:00
zhangdaiscott
9b87a03522 我的租户菜单加提醒:需要在多租户模式下使用,否则数据会出现混乱 2023-11-05 10:34:32 +08:00
zhangdaiscott
bffd067985 【issues/825】tabel的列设置隐藏列保存后切换路由问题[重置没勾选] 2023-11-04 17:39:10 +08:00
zhangdaiscott
df17b4b6f1 【issues/638】表格合计,列自定义隐藏或展示时,合计栏会错位 2023-11-04 17:39:04 +08:00
zhangdaiscott
0b1c464e2c 【issues/828】解决卡死问题 2023-11-04 17:36:21 +08:00
zhangdaiscott
734068c685 解决登录报错 Cannot destructure property "userlnfo' of (intermediate value)' as it is undefined. #812 2023-10-31 13:46:48 +08:00
zhangdaiscott
ce1aa4264f [issues/5514]组件页面显示错位 2023-10-30 22:00:26 +08:00
zhangdaiscott
38d0e5602b 【严重bug修复】online删除字段,其他tab不同步删除导致的问题
issues/815、issues/813
2023-10-30 15:33:21 +08:00
zhangdaiscott
ff3634ffd8 [issues/788]判断有设置数值才去加载 2023-10-29 17:04:33 +08:00
zhangdaiscott
1cc2d16bfd [issues/788]判断有设置数值才去加载 2023-10-29 17:04:17 +08:00
zhangdaiscott
7741ad0de2 【issues/803】JIput updateSchema不生效 2023-10-29 17:03:58 +08:00
zhangdaiscott
afecda73a7 群满,增加新群⑧825232878 2023-10-26 17:15:47 +08:00
zhangdaiscott
44f51ab6cb 字典项配置增加颜色选择 2023-10-24 20:23:03 +08:00
zhangdaiscott
a3cba83533 公告不需要导入导出注释掉 2023-10-24 20:22:34 +08:00
46 changed files with 1886 additions and 1107 deletions

View File

@@ -1,11 +1,11 @@
JEECG BOOT 低代码开发平台Vue3前端
===============
当前最新版本: 3.6.0发布时间2023-10-23
当前最新版本: 3.6.1发布时间2023-12-11
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](http://jeecg.com/aboutusIndex)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.6.0-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/version-3.6.1-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
@@ -47,7 +47,7 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue3、TypeScript 等新技术
- 官方文档:[http://help.jeecg.com](http://help.jeecg.com)
- 官方网站: [http://www.jeecg.com](http://www.jeecg.com)
- 快速入门:[快速入门](http://jeecg.com/doc/quickstart) | [常见问题](http://help.jeecg.com/qa.html) | [视频教程](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://help.jeecg.com/vue3/codegen/online.html)
- QQ交流群⑦791696430、683903138
- QQ交流群⑧825232878、⑦791696430(满)、683903138(满)
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex)| [敲敲云零代码](https://www.qiaoqiaoyun.com)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取

View File

@@ -1,10 +1,10 @@
{
"name": "jeecgboot-vue3",
"version": "3.6.0",
"version": "3.6.1",
"author": {
"name": "jeecg",
"name": "北京国炬信息技术有限公司",
"email": "jeecgos@163.com",
"url": "https://github.com/jeecgboot/jeecgboot-vue3"
"url": "http://guojusoft.com"
},
"scripts": {
"pinstall": "pnpm install",
@@ -21,7 +21,7 @@
"husky:install": "husky install"
},
"dependencies": {
"@jeecg/online": "3.5.3-vite4",
"@jeecg/online": "3.6.0-beta",
"@qiaoqiaoyun/drag-free": "^1.1.4",
"@iconify/iconify": "^3.1.1",
"@ant-design/colors": "^7.0.0",
@@ -166,7 +166,7 @@
"bugs": {
"url": "https://github.com/jeecgboot/jeecgboot-vue3/issues"
},
"homepage": "https://github.com/jeecgboot/jeecgboot-vue3",
"homepage": "https://www.jeecg.com",
"engines": {
"node": "^12 || >=14"
}

2176
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,9 @@
:disabled="item.disabled"
:class="[{ 'is-pop-confirm': item.popConfirm }, item.class ?? []]"
>
<a-popconfirm v-if="popconfirm && item.popConfirm" v-bind="getPopConfirmAttrs(item.popConfirm)">
<!-- update-begin--author:liaozhiyang---date:20231110---forissues/839BasicTable表格的更多操作按钮禁用还能点击弹出气泡框 -->
<a-popconfirm :disabled="item.disabled" v-if="popconfirm && item.popConfirm" v-bind="getPopConfirmAttrs(item.popConfirm)">
<!-- update-end--author:liaozhiyang---date:20231110---forissues/839BasicTable表格的更多操作按钮禁用还能点击弹出气泡框 -->
<template #icon v-if="item.popConfirm.icon">
<Icon v-if="item.iconColor" :icon="item.popConfirm.icon" :color="item.iconColor" />
<Icon v-else :icon="item.popConfirm.icon" />
@@ -41,7 +43,7 @@
</template>
<script lang="ts" setup>
import { computed, PropType } from 'vue';
import { computed, PropType, ref } from 'vue';
import type { DropMenu } from './typing';
import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
import { Icon } from '/@/components/Icon';

View File

@@ -113,6 +113,10 @@
},
{ deep: true }
);
//监听数值修改,查询数据
watchEffect(() => {
props.value && handleFetch();
});
async function fetch() {
const api = props.api;

View File

@@ -94,6 +94,9 @@
// 启用代码折叠相关功能:结束
// 光标行高亮
styleActiveLine: true,
// update-begin--author:liaozhiyang---date:20231201---for【issues/869】JCodeEditor组件初始化时没有设置mode
mode: props.language,
// update-begin--author:liaozhiyang---date:20231201---for【issues/869】JCodeEditor组件初始化时没有设置mode
//代码格式化
extraKeys: {
Tab: function autoFormat(editor) {

View File

@@ -31,7 +31,7 @@
</div>
</template>
<script lang="ts">
import { defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted } from 'vue';
import { defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted, nextTick } from 'vue';
import { LoadingOutlined, UploadOutlined } from '@ant-design/icons-vue';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { propTypes } from '/@/utils/propTypes';
@@ -175,28 +175,36 @@
*/
function handleChange({ file, fileList, event }) {
initTag.value = false;
uploadFileList.value = fileList;
// update-begin--author:liaozhiyang---date:20231116---for【issues/846】上传多个列表只显示一个
// uploadFileList.value = fileList;
if (file.status === 'error') {
createMessage.error(`${file.name} 上传失败.`);
}
let fileUrls = [];
//上传完成
let noUploadingFileCount = 0;
if (file.status != 'uploading') {
fileList.forEach((file) => {
if (file.status === 'done') {
//update-begin---author:wangshuai ---date:20221121 for[issues/248]原生表单内使用图片组件,关闭弹窗图片组件值不会被清空------------
initTag.value = true;
//update-end---author:wangshuai ---date:20221121 for[issues/248]原生表单内使用图片组件,关闭弹窗图片组件值不会被清空------------
fileUrls.push(file.response.message);
}
if (file.status != 'uploading') {
noUploadingFileCount++;
}
});
if (file.status === 'removed') {
handleDelete(file);
}
if (noUploadingFileCount == fileList.length) {
state.value = fileUrls.join(',');
emit('update:value', fileUrls.join(','));
// update-begin---author:wangshuai ---date:20221121 for[issues/248]原生表单内使用图片组件,关闭弹窗图片组件值不会被清空------------
nextTick(() => {
initTag.value = true;
});
// update-end---author:wangshuai ---date:20221121 for[issues/248]原生表单内使用图片组件,关闭弹窗图片组件值不会被清空------------
}
}
// emitData.value = fileUrls.join(',');
state.value = fileUrls.join(',');
emit('update:value', fileUrls.join(','));
// update-end--author:liaozhiyang---date:20231116---for【issues/846】上传多个列表只显示一个
}
/**

View File

@@ -3,10 +3,11 @@
</template>
<script lang="ts">
import { defineComponent, PropType, ref, watchEffect, unref, watch } from 'vue';
import { defineComponent, PropType, ref, watchEffect, unref, watch, computed } from 'vue';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { propTypes } from '/@/utils/propTypes';
import { JInputTypeEnum } from '/@/enums/jeecgEnum.ts';
import { omit } from 'lodash-es';
export default defineComponent({
name: 'JInput',
@@ -22,8 +23,12 @@
const attrs = useAttrs();
//表单值
const showText = ref('');
// update-begin--author:liaozhiyang---date:20231026---for【issues/803】JIput updateSchema不生效
//绑定属性
const getBindValue = Object.assign({}, unref(props), unref(attrs));
const getBindValue = computed(() => {
return omit(Object.assign({}, unref(props), unref(attrs)), ['value']);
});
// update-end--author:liaozhiyang---date:20231026---for【issues/803】JIput updateSchema不生效
//监听类型变化
watch(
() => props.type,

View File

@@ -83,7 +83,9 @@
setup(props, { emit, refs }) {
const options = ref<any[]>([]);
const loading = ref(false);
const attrs = useAttrs();
// update-begin--author:liaozhiyang---date:20231205---for【issues/897】JSearchSelect组件添加class/style样式不生效
const attrs = useAttrs({'excludeDefaultKeys': false});
// update-end--author:liaozhiyang---date:20231205---for【issues/897】JSearchSelect组件添加class/style样式不生效
const selectedValue = ref([]);
const selectedAsyncValue = ref([]);
const lastLoad = ref(0);

View File

@@ -100,6 +100,16 @@
xl: 10,
xxl: 10,
},
//update-begin-author:liusq date:2023-10-30 for: [issues/5514]组件页面显示错位
actionColOptions: {
xs: 24,
sm: 8,
md: 8,
lg: 8,
xl: 8,
xxl: 8,
},
//update-end-author:liusq date:2023-10-30 for: [issues/5514]组件页面显示错位
schemas: [
{
label: '职务名称',

View File

@@ -67,6 +67,16 @@
xl: 14,
xxl: 14,
},
//update-begin-author:liusq date:2023-10-30 for: [issues/5514]组件页面显示错位
actionColOptions: {
xs: 24,
sm: 8,
md: 8,
lg: 8,
xl: 8,
xxl: 8,
},
//update-end-author:liusq date:2023-10-30 for: [issues/5514]组件页面显示错位
schemas: [
{
label: '角色名称',

View File

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

View File

@@ -1,5 +1,6 @@
import { inject, reactive, ref, watch, unref, Ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { isEmpty } from '@/utils/is';
export function useSelectBiz(getList, props) {
//接收下拉框选项
@@ -25,7 +26,10 @@ export function useSelectBiz(getList, props) {
watch(
selectValues,
() => {
if (selectValues['change'] == false) {
//update-begin-author:liusq---date:2023-10-19--for: [issues/788]判断有设置数值才去加载
//if (selectValues['change'] == false && !isEmpty(selectValues['value'])) {
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 = {};
params[props.rowKey] = selectValues['value'].join(',');

View File

@@ -1,11 +1,14 @@
<template>
<div v-html="getHtmlData" :class="$props.class" class="markdown-viewer"></div>
<!-- <div v-html="getHtmlData" :class="$props.class" class="markdown-viewer markdown-body"></div> -->
<!-- update-begin--author:liaozhiyang---date:20231201---forissues/872MarkdownViewer组件无样式 -->
<div v-html="getHtmlData" :class="$props.class" class="markdown-viewer vditor-reset"></div>
<!-- update-begin--author:liaozhiyang---date:20231201---forissues/872MarkdownViewer组件无样式 -->
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import showdown from 'showdown';
import 'vditor/dist/index.css';
const converter = new showdown.Converter();
converter.setOption('tables', true);
const props = defineProps({

View File

@@ -42,19 +42,23 @@
function handleChange(e: ChangeEvent) {
innerValueRef.value = e.target.value;
// update-end--author:liaozhiyang---date:20231122---for【issues/5579】密码组件第一次输入值规则校验没触发
emit('change', e.target.value);
// update-end--author:liaozhiyang---date:20231122---for【issues/5579】密码组件第一次输入值规则校验没触发
}
watchEffect(() => {
innerValueRef.value = props.value || '';
});
watch(
() => unref(innerValueRef),
(val) => {
emit('change', val);
}
);
// update-end--author:liaozhiyang---date:20231122---for【issues/5579】密码组件第一次输入值规则校验没触发
// watch(
// () => unref(innerValueRef),
// (val) => {
// emit('change', val);
// }
// );
// update-end--author:liaozhiyang---date:20231122---for【issues/5579】密码组件第一次输入值规则校验没触发
return {
getPasswordStrength,
handleChange,

View File

@@ -375,38 +375,6 @@
emit('register', tableAction, formActions);
// update-begin--author:liaozhiyang---date:20230804---for【issues/638】表格合计列表table和合计table滚动联动
if (getProps.value.showSummary) {
let tableBody;
const handleSroll = function () {
const scrollLeft = this.scrollLeft;
tableBody.forEach((elem) => (elem.scrollLeft = scrollLeft));
};
onMounted(() => {
const unwatch = watch(
getDataSourceRef,
(newVal) => {
if (newVal.length > 0) {
setTimeout(() => {
unwatch();
tableBody = wrapRef.value.querySelectorAll('.ant-table-body');
tableBody.forEach((elem) => {
elem.addEventListener('scroll', handleSroll, false);
});
}, 0);
console.log("---表格合计滚动---")
}
},
{ immediate: true }
);
});
onUnmounted(() => {
if (tableBody.length) {
tableBody.forEach((elem) => elem.removeEventListener('scroll', handleSroll));
}
});
}
// update-begin--author:liaozhiyang---date:20230804---for【issues/638】表格合计列表table和合计table滚动联动
return {
tableElRef,

View File

@@ -1,10 +1,17 @@
<!-- 自定义选择列表头实现部分 -->
<template>
<!-- update-begin--author:liaozhiyang---date:20231130---forissues/5595BasicTable组件hideSelectAll: true无法隐藏全选框 -->
<template v-if="isRadio">
<!-- radio不存在全选所以放个空标签 -->
<span></span>
</template>
<a-checkbox :disabled="disabled" v-else :checked="checked" :indeterminate="isHalf" @update:checked="onChange" />
<template v-else>
<template v-if="hideSelectAll">
<span></span>
</template>
<a-checkbox :disabled="disabled" v-else :checked="checked" :indeterminate="isHalf" @update:checked="onChange" />
</template>
<!-- update-end--author:liaozhiyang---date:20231130---forissues/5595BasicTable组件hideSelectAll: true无法隐藏全选框 -->
</template>
<script setup lang="ts">
import { computed } from 'vue';
@@ -23,6 +30,10 @@
type: Number,
required: true,
},
hideSelectAll: {
type: Boolean,
default: false,
},
// update-begin--author:liaozhiyang---date:20231016---for【QQYUN-6774】解决checkbox禁用后全选仍能勾选问题
disabled: {
type: Boolean,

View File

@@ -67,7 +67,10 @@
const getColumns = computed(() => {
const dataSource = unref(getDataSource);
const columns: BasicColumn[] = cloneDeep(table.getColumns());
let columns: BasicColumn[] = cloneDeep(table.getColumns());
// update-begin--author:liaozhiyang---date:220230804---for【issues/638】表格合计列自定义隐藏或展示时合计栏会错位
columns = columns.filter((item) => !item.defaultHidden);
// update-begin--author:liaozhiyang---date:220230804---for【issues/638】表格合计列自定义隐藏或展示时合计栏会错位
const index = columns.findIndex((item) => item.flag === INDEX_COLUMN_FLAG);
const hasRowSummary = dataSource.some((item) => Reflect.has(item, SUMMARY_ROW_KEY));
const hasIndexSummary = dataSource.some((item) => Reflect.has(item, SUMMARY_INDEX_KEY));

View File

@@ -289,7 +289,15 @@
// reset columns
function reset() {
state.checkedList = [...state.defaultCheckList];
// state.checkedList = [...state.defaultCheckList];
// update-begin--author:liaozhiyang---date:20231103---for【issues/825】tabel的列设置隐藏列保存后切换路由问题[重置没勾选]
state.checkedList = table
.getColumns({ ignoreAction: true })
.map((item) => {
return item.dataIndex || item.title;
})
.filter(Boolean) as string[];
// update-end--author:liaozhiyang---date:20231103---for【issues/825】tabel的列设置隐藏列保存后切换路由问题[重置没勾选]
state.checkAll = true;
plainOptions.value = unref(cachePlainOptions);
plainSortOptions.value = unref(cachePlainOptions);

View File

@@ -277,9 +277,6 @@ export function useColumns(
columns = columns.filter((item) => item.key !== CUS_SEL_COLUMN_KEY);
// update-enb--author:sunjianlei---date:220230630---for【QQYUN-5571】自封装选择列解决数据行选择卡顿问题
// update-begin--author:liaozhiyang---date:220230804---for【issues/638】表格合计列自定义隐藏或展示时合计栏会错位
columns = columns.filter((item) => !item.defaultHidden);
// update-begin--author:liaozhiyang---date:220230804---for【issues/638】表格合计列自定义隐藏或展示时合计栏会错位
if (sort) {
columns = sortFixedColumn(columns);
}

View File

@@ -39,6 +39,9 @@ export function useCustomSelection(
const selectedKeys = ref<string[]>([]);
// 选择的行
const selectedRows = ref<Recordable[]>([]);
// 变更的行
let changeRows: Recordable[] = [];
let allSelected: boolean = false;
// 扁平化数据children数据也会放到一起
const flattedData = computed(() => {
@@ -120,6 +123,7 @@ export function useCustomSelection(
pageSize: currentPageSize.value,
// 【QQYUN-6774】解决checkbox禁用后全选仍能勾选问题
disabled: flattedData.value.length == 0,
hideSelectAll: unref(propsRef)?.rowSelection?.hideSelectAll,
};
});
@@ -127,8 +131,10 @@ export function useCustomSelection(
watch(
() => unref(propsRef)?.rowSelection?.selectedRowKeys,
(val: string[]) => {
if (Array.isArray(val)) {
setSelectedRowKeys(val);
// 解决selectedRowKeys在页面调用处使用ref失效
const value = unref(val);
if (Array.isArray(value)) {
setSelectedRowKeys(value);
}
},
{ immediate: true }
@@ -184,11 +190,17 @@ export function useCustomSelection(
// 选择全部
function onSelectAll(checked: boolean) {
// update-begin--author:liaozhiyang---date:20231122---for【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件
if (unref(propsRef)?.rowSelection?.onSelectAll) {
allSelected = checked;
changeRows = getInvertRows(selectedRows.value);
}
// update-end--author:liaozhiyang---date:20231122---for【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件
// 取消全选
if (!checked) {
selectedKeys.value = [];
selectedRows.value = [];
emitChange();
emitChange('all');
return;
}
let modal: Nullable<ReturnType<ModalFunc>> = null;
@@ -219,7 +231,7 @@ export function useCustomSelection(
if (hidden.length > 0) {
return batchesSelectAll(hidden, checked, minSelect);
} else {
emitChange();
emitChange('all');
}
};
@@ -250,7 +262,7 @@ export function useCustomSelection(
call();
} else {
setTimeout(() => {
emitChange();
emitChange('all');
// update-begin--author:liaozhiyang---date:20230811---for【QQYUN-5687】批量选择提示成功后又来一个提示
setTimeout(() =>resolve(), 0);
// update-end--author:liaozhiyang---date:20230811---for【QQYUN-5687】批量选择提示成功后又来一个提示
@@ -289,7 +301,7 @@ export function useCustomSelection(
}
// 调用用户自定义的onChange事件
function emitChange() {
function emitChange(mode = 'single') {
const { rowSelection } = unref(propsRef);
if (rowSelection) {
const { onChange } = rowSelection;
@@ -303,6 +315,14 @@ export function useCustomSelection(
keys: getSelectRowKeys(),
rows: getSelectRows(),
});
// update-begin--author:liaozhiyang---date:20231122---for【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件
if (mode == 'all') {
const rowSelection = unref(propsRef)?.rowSelection;
if (rowSelection?.onSelectAll) {
rowSelection.onSelectAll(allSelected, toRaw(getSelectRows()), toRaw(changeRows));
}
}
// update-end--author:liaozhiyang---date:20231122---for【issues/5577】BasicTable组件全选和取消全选时不触发
}
// 用于判断是否是自定义选择列
@@ -432,6 +452,7 @@ export function useCustomSelection(
// 设置选择的key
function setSelectedRowKeys(rowKeys: string[]) {
const isSomeRowKeys = selectedKeys.value === rowKeys;
selectedKeys.value = rowKeys;
const allSelectedRows = findNodeAll(
toRaw(unref(flattedData)).concat(toRaw(unref(selectedRows))),
@@ -445,16 +466,58 @@ export function useCustomSelection(
const found = allSelectedRows.find((item) => getRecordKey(item) === key);
found && trueSelectedRows.push(found);
});
// update-begin--author:liaozhiyang---date:20230823---forQQYUN-6283】点击表格清空rowSelect里面的selectedRowKeys没置空。
// update-begin--author:liaozhiyang---date:20230811---for【issues/657】浏览器卡死问题
if (trueSelectedRows.length || !rowKeys.length) {
// update-begin--author:liaozhiyang---date:20231103---forissues/828】解决卡死问题
if (!(isSomeRowKeys && equal(selectedRows.value, trueSelectedRows))) {
selectedRows.value = trueSelectedRows;
emitChange();
}
// update-end--author:liaozhiyang---date:20230811---for【issues/657】】浏览器卡死问题
// update-end--author:liaozhiyang---date:20230823---for【QQYUN-6283】点击表格清空rowSelect里面的selectedRowKeys没置空。
// update-end--author:liaozhiyang---date:20231103---for【issues/828】解决卡死问题
}
/**
*2023-11-03
*廖志阳
*检测selectedRows.value和trueSelectedRows是否相等防止死循环
*/
function equal(oldVal, newVal) {
let oldKeys = [],
newKeys = [];
if (oldVal.length === newVal.length) {
oldKeys = oldVal.map((item) => getRecordKey(item));
newKeys = newVal.map((item) => getRecordKey(item));
for (let i = 0, len = oldKeys.length; i < len; i++) {
const findItem = newKeys.find((item) => item === oldKeys[i]);
if (!findItem) {
return false;
}
}
return true;
}
return false;
}
/**
*2023-11-22
*廖志阳
*根据全选或者反选返回源数据中这次需要变更的数据
*/
function getInvertRows(rows: any): any {
const allRows = findNodeAll(toRaw(unref(flattedData)), () => true, {
children: propsRef.value.childrenColumnName ?? 'children',
});
if (rows.length === 0 || rows.length === allRows.length) {
return allRows;
} else {
const allRowsKey = allRows.map((item) => getRecordKey(item));
rows.forEach((rItem) => {
const rItemKey = getRecordKey(rItem);
const findIndex = allRowsKey.findIndex((item) => rItemKey === item);
if (findIndex != -1) {
allRowsKey.splice(findIndex, 1);
allRows.splice(findIndex, 1);
}
});
}
return allRows;
}
function getSelectRows<T = Recordable>() {
return unref(selectedRows) as T[];
}

View File

@@ -302,7 +302,9 @@
watch(
() => props.value,
() => {
state.checkedKeys = toRaw(props.value || []);
// update-end--author:liaozhiyang---date:20231122---for【issues/863】关闭选择部门弹窗再打开之前勾选的消失了
state.checkedKeys = toRaw(props.value || props.checkedKeys || []);
// update-end--author:liaozhiyang---date:20231122---for【issues/863】关闭选择部门弹窗再打开之前勾选的消失了
},
{ immediate: true },
);

View File

@@ -18,8 +18,13 @@ import JVxeTextareaCell from './components/cells/JVxeTextareaCell.vue';
// import JVxeDepartSelectCell from './components/cells/JVxeDepartSelectCell.vue'
// import JVxeUserSelectCell from './components/cells/JVxeUserSelectCell.vue'
const componentMap = new Map<JVxeTypes | string, JVxeVueComponent>();
let componentMap = new Map<JVxeTypes | string, JVxeVueComponent>();
// update-begin--author:liaozhiyang---date:20231208---for【issues/860】生成的一对多代码热更新之后点击新增卡死[暂时先解决]
const JVxeComponents = 'JVxeComponents__';
if (import.meta.env.DEV && componentMap.size === 0 && window[JVxeComponents] && window[JVxeComponents].size > 0) {
componentMap = window[JVxeComponents];
}
// update-end--author:liaozhiyang---date:20231027---for【issues/860】生成的一对多代码热更新之后点击新增卡死[暂时先解决]
/** span 组件结尾 */
export const spanEnds: string = ':span';
@@ -50,11 +55,17 @@ export function addComponent(type: JVxeTypes, component: JVxeVueComponent, spanC
if (spanComponent) {
componentMap.set(type + spanEnds, spanComponent);
}
// 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 function deleteComponent(type: JVxeTypes) {
componentMap.delete(type);
componentMap.delete(type + spanEnds);
// 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】生成的一对多代码热更新之后点击新增卡死[暂时先解决]
}
/** 定义内置自定义组件 */

View File

@@ -639,13 +639,45 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
}
/** 删除一行或多行数据 */
async function removeRows(rows) {
async function removeRows(rows, asyncRemove = false) {
// update-begin--author:liaozhiyang---date:20231123---forvxe-table removeRows方法加上异步删除
const xTable = getXTable();
const res = await xTable.remove(rows);
let removeEvent: any = { deleteRows: rows, $table: xTable };
trigger('removed', removeEvent);
await recalcSortNumber();
return res;
const removeEvent: any = { deleteRows: rows, $table: xTable };
if (asyncRemove) {
const selectedRows = Array.isArray(rows) ? rows : [rows];
const deleteOldRows = filterNewRows(selectedRows);
if (deleteOldRows.length) {
return new Promise((resolve) => {
// 确认删除,只有调用这个方法才会真删除
removeEvent.confirmRemove = async () => {
const insertRecords = xTable.getInsertRecords();
selectedRows.forEach((item) => {
// 删除新添加的数据id
if (insertRecords.includes(item)) {
delete item.id;
}
});
const res = await xTable.remove(rows);
await recalcSortNumber();
resolve(res);
};
trigger('removed', removeEvent);
});
} else {
// 全新的行立马删除,不等待。
const res = await xTable.remove(rows);
removeEvent.confirmRemove = () => {};
trigger('removed', removeEvent);
await recalcSortNumber();
return res;
}
} else {
const res = await xTable.remove(rows);
trigger('removed', removeEvent);
await recalcSortNumber();
return res;
}
// update-end--author:liaozhiyang---date:20231123---forvxe-table removeRows方法加上异步删除
}
/** 根据id删除一行或多行 */
@@ -781,7 +813,6 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
emit(name, event);
}
/**
* 获取选中的行-和 getSelectionData 区别在于对于新增的行也会返回ID
* 用于onlinePopForm

View File

@@ -20,21 +20,34 @@ export function useToolbar(props: JVxeTableProps, data: JVxeDataProps, methods:
// 保存事件
onSave: () => methods.trigger('save'),
onRemove() {
let $table = methods.getXTable();
let deleteRows = methods.filterNewRows(data.selectedRows.value);
const $table = methods.getXTable();
// update-begin--author:liaozhiyang---date:20231018---for【QQYUN-6805】修复asyncRemove字段不生效
// 触发删除事件
if (deleteRows.length > 0) {
let removeEvent: any = { deleteRows, $table};
if (props.asyncRemove) {
if (data.selectedRows.value.length > 0) {
const deleteOldRows = methods.filterNewRows(data.selectedRows.value);
const removeEvent: any = { deleteRows: data.selectedRows.value, $table };
const insertRecords = $table.getInsertRecords();
if (props.asyncRemove && deleteOldRows.length) {
data.selectedRows.value.forEach((item) => {
// 删除新添加的数据id
if (insertRecords.includes(item)) {
delete item.id;
}
});
// 确认删除,只有调用这个方法才会真删除
removeEvent.confirmRemove = () => methods.removeSelection();
} else {
if (props.asyncRemove) {
// asyncRemove删除的只有新增的数据时防止调用confirmRemove报错
removeEvent.confirmRemove = () => {};
}
methods.removeSelection();
}
methods.trigger('removed', removeEvent);
} else {
methods.removeSelection();
}
// update-end--author:liaozhiyang---date:20231018---for【QQYUN-6805】修复asyncRemove字段不生效
},
// 清除选择事件
onClearSelection: () => methods.clearSelection(),

View File

@@ -131,8 +131,7 @@
<template #label>
<span :title="item.label" class="label-text">{{ item.label }}</span>
</template>
<JOnlineSearchSelect v-model:value="queryParam[item.field]" :placeholder="'请选择' + item.label" :sql="item.sql">
</JOnlineSearchSelect>
<JOnlineSearchSelect v-model:value="queryParam[item.field]" :placeholder="'请选择'+item.label" :fieldId="item.fieldId"/>
</a-form-item>
<a-form-item v-else-if="item.view === CompTypeEnum.SelUser" :labelCol="labelCol" :class="'jeecg-online-search'">

View File

@@ -1,10 +1,14 @@
import { nextTick, onMounted, onActivated } from 'vue';
export function onMountedOrActivated(hook: Fn) {
type HookArgs = {
type: 'mounted' | 'activated';
}
export function onMountedOrActivated(hook: Fn<HookArgs, any>) {
let mounted: boolean;
onMounted(() => {
hook();
hook({type: 'mounted'});
nextTick(() => {
mounted = true;
});
@@ -12,7 +16,7 @@ export function onMountedOrActivated(hook: Fn) {
onActivated(() => {
if (mounted) {
hook();
hook({type: 'activated'});
}
});
}

View File

@@ -7,6 +7,7 @@ import { unref } from 'vue';
import { useRouter } from 'vue-router';
import { REDIRECT_NAME } from '/@/router/constant';
import { useUserStore } from '/@/store/modules/user';
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
export type RouteLocationRawEx = Omit<RouteLocationRaw, 'path'> & { path: PageEnum };
@@ -51,40 +52,27 @@ export const useRedo = (_router?: Router) => {
resolve(false);
return;
}
// update-begin--author:liaozhiyang---date:20231123---for【QQYUN-7099】动态路由匹配右键重新加载404
const tabStore = useMultipleTabStore();
if (name && Object.keys(params).length > 0) {
//update-begin-author:taoyan date:2022-10-19 for: VUEN-2356 【vue3】online表单、表单设计器 功能测试 右键刷新时 404
if(isDynamicRoute(params, name)){
params['_redirect_type'] = 'path';
params['path'] = fullPath;
}else{
params['_redirect_type'] = 'name';
params['path'] = String(name);
}
//update-end-author:taoyan date:2022-10-19 for: VUEN-2356 【vue3】online表单、表单设计器 功能测试 右键刷新时 404
tabStore.setRedirectPageParam({
redirect_type: 'name',
name: String(name),
params,
query,
});
params['path'] = String(name);
} else {
params['_redirect_type'] = 'path';
tabStore.setRedirectPageParam({
redirect_type: 'path',
path: fullPath,
query,
});
params['path'] = fullPath;
}
// update-end--author:liaozhiyang---date:20231123---for【QQYUN-7099】动态路由匹配右键重新加载404
push({ name: REDIRECT_NAME, params, query }).then(() => resolve(true));
});
}
return redo;
};
/**
* 判断是不是动态路由的跳转
* @param params
* @param name
*/
function isDynamicRoute(params, name){
let arr = Object.keys(params);
let flag = false;
for(let i=0;i<arr.length;i++){
let key = '@'+arr[i];
if((name as string).indexOf(key)>0){
flag = true;
break;
}
}
return flag;
}

View File

@@ -4,8 +4,8 @@ import { useTitle as usePageTitle } from '@vueuse/core';
import { useGlobSetting } from '/@/hooks/setting';
import { useRouter } from 'vue-router';
import { useLocaleStore } from '/@/store/modules/locale';
import { REDIRECT_NAME } from '/@/router/constant';
import { getMenus } from '/@/router/menus';
/**
* Listening to page changes and dynamically changing site titles
@@ -26,10 +26,43 @@ export function useTitle() {
if (route.name === REDIRECT_NAME) {
return;
}
const tTitle = t(route?.meta?.title as string);
pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`;
// update-begin--author:liaozhiyang---date:20231110---for【QQYUN-6938】online菜单名字和页面title不一致
if (route.params && Object.keys(route.params).length) {
getMenus().then((menus) => {
const getTitle = getMatchingRouterName(menus, route.fullPath);
let tTitle = '';
if (getTitle) {
tTitle = t(getTitle);
} else {
tTitle = t(route?.meta?.title as string);
};
pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`;
});
} else {
const tTitle = t(route?.meta?.title as string);
pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`;
}
// update-end--author:liaozhiyang---date:20231110---for【QQYUN-6938】online菜单名字和页面title不一致
},
{ immediate: true }
);
}
/**
2023-11-09
liaozhiyang
获取路由匹配模式的真实页面名字
*/
function getMatchingRouterName(menus, path) {
for (let i = 0, len = menus.length; i < len; i++) {
const item = menus[i];
if (item.path === path && !item.redirect && !item.paramPath) {
return item.meta?.title;
} else if (item.children?.length) {
const result = getMatchingRouterName(item.children, path);
if (result) {
return result;
}
}
}
return '';
}

View File

@@ -14,11 +14,21 @@ import { MULTIPLE_TABS_KEY } from '/@/enums/cacheEnum';
import projectSetting from '/@/settings/projectSetting';
import { useUserStore } from '/@/store/modules/user';
import type { LocationQueryRaw, RouteParamsRaw } from 'vue-router';
export interface MultipleTabState {
cacheTabList: Set<string>;
tabList: RouteLocationNormalized[];
lastDragEndIndex: number;
redirectPageParam: null | redirectPageParamType;
}
interface redirectPageParamType {
redirect_type: string;
name?: string;
path?: string;
query: LocationQueryRaw;
params?: RouteParamsRaw;
}
function handleGotoPage(router: Router) {
@@ -45,6 +55,8 @@ export const useMultipleTabStore = defineStore({
tabList: cacheTab ? Persistent.getLocal(MULTIPLE_TABS_KEY) || [] : [],
// Index of the last moved tab
lastDragEndIndex: 0,
// 重定向时存储的路由参数
redirectPageParam: null,
}),
getters: {
getTabList(): RouteLocationNormalized[] {
@@ -348,6 +360,9 @@ export const useMultipleTabStore = defineStore({
await this.updateCacheTab();
}
},
setRedirectPageParam(data) {
this.redirectPageParam = data;
},
},
});

View File

@@ -190,7 +190,7 @@ export const useUserStore = defineStore({
//update-end---author:wangshuai ---date:20230424 for【QQYUN-5195】登录之后直接刷新页面导致没有进入创建组织页面------------
// 当前页面打开
window.open(redirect, '_self')
return;
return data;
}
// update-end-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题

View File

@@ -6,6 +6,9 @@ import { reactive } from "vue";
import { getTenantId, getToken } from "/@/utils/auth";
import { useUserStoreWithOut } from "/@/store/modules/user";
import { Modal } from "ant-design-vue";
import { defHttp } from "@/utils/http/axios";
const globSetting = useGlobSetting();
const baseApiUrl = globSetting.domainUrl;
/**
@@ -459,3 +462,52 @@ export function replaceUserInfoByExpression(expression: string | any[]) {
// @ts-ignore
return isString ? replace(expression) : expression.map(replace);
}
/**
* 设置租户缓存,当租户退出的时候
*
* @param tenantId
*/
export async function userExitChangeLoginTenantId(tenantId){
const userStore = useUserStoreWithOut();
//step 1 获取用户租户
const url = '/sys/tenant/getCurrentUserTenant'
let currentTenantId = null;
const data = await defHttp.get({ url });
if(data && data.list){
let arr = data.list;
if(arr.length>0){
//step 2.判断当前id是否存在用户租户中
let filterTenantId = arr.filter((item) => item.id == tenantId);
//存在说明不是退出的不是当前租户,还用用来的租户即可
if(filterTenantId && filterTenantId.length>0){
currentTenantId = tenantId;
}else{
//不存在默认第一个
currentTenantId = arr[0].id
}
}
}
userStore.setTenant(currentTenantId);
//切换租户后要刷新首页
window.location.reload();
}
/**
* 我的租户模块需要开启多租户提示
*
* @param title 标题
*/
export function tenantSaasMessage(title){
let tenantId = getTenantId();
if(!tenantId){
Modal.confirm({
title:title,
content: '此菜单需要在多租户模式下使用,否则数据会出现混乱',
okText: '确认',
okType: 'danger',
// @ts-ignore
cancelButtonProps: { style: { display: 'none' } },
})
}
}

View File

@@ -216,7 +216,7 @@
key: 'action',
type: JVxeTypes.slot,
fixed: 'right',
minWidth: 100,
minWidth: 120,
align: 'center',
slotName: 'myAction',
},
@@ -291,12 +291,18 @@
console.log('查看: ', { props });
}
// async function onDeleteRow(props) {
// // 同步调用删除方法
// const res = await tableRef.value?.removeRows(props.row);
// if (res && res.rows.length > 0) {
// createMessage.success('删除成功');
// }
// }
async function onDeleteRow(props) {
// 调用删除方法
const res = await tableRef.value?.removeRows(props.row);
if (res && res.rows.length > 0) {
createMessage.success('删除成功');
}
// 异步调用删除方法
const res = await tableRef.value?.removeRows(props.row, true);
console.log('删除成功~', res);
}
function handleValueChange(event) {
@@ -361,8 +367,13 @@
}
function doDelete(deleteRows) {
let rowId;
return new Promise((resolve) => {
let rowId = deleteRows.filter((row) => row.id);
if (Array.isArray(deleteRows)) {
rowId = deleteRows.filter((row) => row.id);
} else {
rowId = deleteRows.id;
}
console.log('删除 rowId: ', rowId);
setTimeout(() => resolve(true), 1500);
});

View File

@@ -3,8 +3,7 @@
<a-card class="daily-article">
<a-card-meta :title="content.titile" :description="'发布人:' + content.sender + ' 发布时间: ' + content.sendTime"> </a-card-meta>
<a-divider />
<span v-html="content.msgContent" class="article-content"></span>
<div v-html="content.msgContent" class="article-content"></div>
<div>
<a-button v-if="hasHref" @click="jumpToHandlePage">前往办理<ArrowRightOutlined /></a-button>
</div>
@@ -17,6 +16,8 @@
import { ArrowRightOutlined } from '@ant-design/icons-vue';
import { useRouter } from 'vue-router'
import xss from 'xss'
import { options } from './XssWhiteList'
const router = useRouter()
import { ref, unref } from 'vue';
@@ -29,7 +30,9 @@
//data.record.msgContent = '<p>2323</p><input onmouseover=alert(1)>xss test';
//update-begin-author:taoyan date:2022-7-14 for: VUEN-1702 【禁止问题】sql注入漏洞
if(data.record.msgContent){
data.record.msgContent = xss(data.record.msgContent)
//update-begin---author:wangshuai---date:2023-11-15---for:【QQYUN-7049】3.6.0版本 通知公告中发布的富文本消息,在我的消息中查看没有样式---
data.record.msgContent = xss(data.record.msgContent,options);
//update-end---author:wangshuai---date:2023-11-15---for:【QQYUN-7049】3.6.0版本 通知公告中发布的富文本消息,在我的消息中查看没有样式---
}
//update-end-author:taoyan date:2022-7-14 for: VUEN-1702 【禁止问题】sql注入漏洞
content.value = data.record;

View File

@@ -0,0 +1,41 @@
//xss攻击白名单列表
export const options = {
whiteList: {
h1: ['style'],
h2: ['style'],
h3: ['style'],
h4: ['style'],
h5: ['style'],
h6: ['style'],
hr: ['style'],
span: ['style'],
strong: ['style'],
b: ['style'],
i: ['style'],
br: [],
p: ['style'],
pre: ['style'],
code: ['style'],
a: ['style', 'target', 'href', 'title', 'rel'],
img: ['style', 'src', 'title','width','height'],
div: ['style'],
table: ['style', 'width', 'border', 'height'],
tr: ['style'],
td: ['style', 'width', 'colspan'],
th: ['style', 'width', 'colspan'],
tbody: ['style'],
ul: ['style'],
li: ['style'],
ol: ['style'],
dl: ['style'],
dt: ['style'],
em: ['style'],
cite: ['style'],
section: ['style'],
header: ['style'],
footer: ['style'],
blockquote: ['style'],
audio: ['autoplay', 'controls', 'loop', 'preload', 'src'],
video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width'],
},
};

View File

@@ -4,27 +4,27 @@
<script lang="ts" setup>
import { unref } from 'vue';
import { useRouter } from 'vue-router';
import { useMultipleTabStore } from '/@/store/modules/multipleTab';
// update-begin--author:liaozhiyang---date:20231123---for【QQYUN-7099】动态路由匹配右键重新加载404
const { currentRoute, replace } = useRouter();
const { params, query } = unref(currentRoute);
const { path, _redirect_type = 'path' } = params;
Reflect.deleteProperty(params, '_redirect_type');
Reflect.deleteProperty(params, 'path');
const { path } = params;
const tabStore = useMultipleTabStore();
const redirectPageParam = tabStore.redirectPageParam;
const _path = Array.isArray(path) ? path.join('/') : path;
if (_redirect_type === 'name') {
replace({
name: _path,
query,
params,
});
} else {
replace({
path: _path.startsWith('/') ? _path : '/' + _path,
query,
});
if (redirectPageParam) {
if (redirectPageParam.redirect_type === 'name') {
replace({
name: redirectPageParam.name,
query: redirectPageParam.query,
params: redirectPageParam.params,
});
} else {
replace({
path: _path.startsWith('/') ? _path : '/' + _path,
query,
});
}
}
// update-end--author:liaozhiyang---date:20231123---for【QQYUN-7099】动态路由匹配右键重新加载404
</script>

View File

@@ -1,6 +1,22 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit" width="800px">
<BasicForm @register="registerForm" />
<!-- update-begin---author:wangshuai---date:2023-10-23---for:QQYUN-6804后台模式字典没有颜色配置--- -->
<BasicForm @register="registerForm" >
<template #itemColor="{ model, field }">
<div class="item-tool">
<div
v-for="(item,index) in Colors"
:style="{ color: item[0] }"
:class="model.itemColor===item[0]?'item-active':''"
class="item-color"
@click="itemColorClick(item)">
<div class="item-color-border"></div>
<div class="item-back" :style="{ background: item[0] }"></div>
</div>
</div>
</template>
</BasicForm>
<!-- update-end---author:wangshuai---date:2023-10-23---for:QQYUN-6804后台模式字典没有颜色配置--- -->
</BasicModal>
</template>
<script lang="ts" setup>
@@ -9,6 +25,8 @@
import { BasicForm, useForm } from '/src/components/Form';
import { itemFormSchema } from '../dict.data';
import { saveOrUpdateDictItem } from '../dict.api';
import { Colors } from '/@/utils/dict/DictColors.js'
// 声明Emits
const emit = defineEmits(['success', 'register']);
const props = defineProps({ dictId: String });
@@ -60,4 +78,49 @@
setModalProps({ confirmLoading: false });
}
}
/**
* 字典颜色点击事件
*
* @param index
* @param item
* @param model
*/
function itemColorClick(item) {
console.log(item)
setFieldsValue({ itemColor: item[0] })
}
</script>
<style lang="less" scoped>
/*begin 字典颜色配置样式*/
.item-tool{
display: flex;
flex-wrap: wrap;
.item-color{
width: 18px;
display: flex;
justify-content: center;
cursor: pointer;
align-items: center;
margin-right: 10px;
}
.item-back{
width: 18px;
height: 18px;
border-radius: 50%;
}
}
.item-color-border{
visibility: hidden;
}
.item-active .item-color-border{
visibility: visible;
position: absolute;
border: 1px solid;
width: 24px;
height: 24px;
border-radius: 50%;
}
/*end 字典颜色配置样式*/
</style>

View File

@@ -2,6 +2,8 @@ import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { dictItemCheck } from './dict.api';
import { rules } from '/@/utils/helper/validator';
import { h } from "vue";
export const columns: BasicColumn[] = [
{
title: '字典名称',
@@ -93,6 +95,17 @@ export const dictItemColumns: BasicColumn[] = [
dataIndex: 'itemValue',
width: 80,
},
{
title: '字典颜色',
dataIndex: 'itemColor',
width: 80,
align:'center',
customRender:({ text }) => {
return h('div', {
style: {"background": text, "width":"18px","height":"18px","border-radius":"50%","margin":"0 auto"}
})
}
},
];
export const dictItemSearchFormSchema: FormSchema[] = [
@@ -159,6 +172,12 @@ export const itemFormSchema: FormSchema[] = [
];
},
},
{
label: '颜色值',
field: 'itemColor',
component: 'Input',
slot:'itemColor'
},
{
label: '描述',
field: 'description',

View File

@@ -3,8 +3,8 @@
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<template #tableTitle>
<a-button preIcon="ant-design:plus-outlined" type="primary" @click="handleAdd">新增</a-button>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<!-- <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>-->
<!-- <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>-->
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>

View File

@@ -30,7 +30,7 @@
<RoleDesc @register="registerDesc"></RoleDesc>
</template>
<script lang="ts" name="system-role" setup>
import { ref } from 'vue';
import { onMounted, ref } from 'vue';
import { BasicTable, TableAction } from '/@/components/Table';
import { useDrawer } from '/@/components/Drawer';
import { useModal } from '/@/components/Modal';
@@ -41,6 +41,8 @@
import { listByTenant, deleteRole, batchDeleteRole, getExportUrl, getImportUrl } from './role.api';
import { useListPage } from '/@/hooks/system/useListPage';
import { getLoginTenantName } from "/@/views/system/tenant/tenant.api";
import { tenantSaasMessage } from "@/utils/common/compUtils";
const showFooter = ref(true);
const [roleUserDrawer, { openDrawer: openRoleUserDrawer }] = useDrawer();
const [registerDrawer, { openDrawer }] = useDrawer();
@@ -167,6 +169,10 @@
async function getTenantName(){
loginTenantName.value = await getLoginTenantName();
}
onMounted(()=>{
tenantSaasMessage('租户角色')
})
</script>
<style scoped lang="less">

View File

@@ -27,7 +27,7 @@
<script lang="ts" name="tenant-system-user" setup>
//ts语法
import { ref, unref } from 'vue';
import { onMounted, ref, unref } from 'vue';
import { BasicTable, TableAction, ActionItem } from '/@/components/Table';
import UserDrawer from '../user/UserDrawer.vue';
import JThirdAppButton from '/@/components/jeecg/thirdApp/JThirdAppButton.vue';
@@ -48,6 +48,7 @@
import { changeOwenUserTenant } from "/@/views/system/usersetting/UserSetting.api";
import { getLoginTenantName } from "/@/views/system/tenant/tenant.api";
import TenantUserDrawer from './components/TenantUserDrawer.vue';
import { tenantSaasMessage } from "@/utils/common/compUtils";
const { createMessage, createConfirm } = useMessage();
@@ -157,7 +158,9 @@
},
{
label: '离职',
onClick: handleQuit.bind(null, record.username),
//update-begin---author:wangshuai---date:2023-10-25---for:【QQYUN-6822】9.离职交接人选的是自己,完成之后数据没了---
onClick: handleQuit.bind(null, record.id),
//update-end---author:wangshuai---date:2023-10-25---for:【QQYUN-6822】9.离职交接人选的是自己,完成之后数据没了---
//update-begin---author:wangshuai ---date:20230130 for[QQYUN-3974]租户的创建人 不应该有离职按钮------------
ifShow: () =>{
return record.status === '1' && record.username!== record.createBy;
@@ -278,6 +281,10 @@
loginTenantName.value = await getLoginTenantName();
}
//update-end---author:wangshuai ---date:20230710 for【QQYUN-5723】4、显示当前登录租户------------
onMounted(()=>{
tenantSaasMessage('租户用户')
})
</script>
<style scoped>

View File

@@ -30,7 +30,7 @@
</div>
</template>
<script lang="ts" name="my-tenant-list" setup>
import { ref, unref } from 'vue';
import { onMounted, ref, unref } from 'vue';
import { BasicTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { invitationUserJoin, getTenantPageListByUserId } from '../tenant.api';
@@ -43,6 +43,7 @@
import TenantPackList from '../pack/TenantPackList.vue';
import { getTenantId } from '/@/utils/auth';
import { useUserStore } from '/@/store/modules/user';
import { tenantSaasMessage } from "@/utils/common/compUtils";
const { createMessage } = useMessage();
const [registerModal, { openModal }] = useModal();
@@ -137,4 +138,9 @@
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
onMounted(()=>{
//提示信息
tenantSaasMessage('我的租户')
})
</script>

View File

@@ -191,6 +191,7 @@ export const formSchema: FormSchema[] = [
api: getAllRolesListNoByTenant,
labelField: 'roleName',
valueField: 'id',
immediate: false,
},
},
{
@@ -228,6 +229,7 @@ export const formSchema: FormSchema[] = [
numberToString: true,
labelField: 'name',
valueField: 'id',
immediate: false,
},
},
{

View File

@@ -69,42 +69,6 @@
<Icon icon="ant-design:edit-outlined" class="footer-icon" />
<span>查看租户名片</span>
</span>
<span
v-if="item.userTenantStatus !== '3' && item.auth"
@click.stop="footerClick('tenantSetting', item)"
class="font-color333 flex-flow margin-right40 font-size13 pointer"
>
<Icon icon="ant-design:tool-outlined" class="footer-icon" />
<span>租户管理</span>
</span>
<span v-else-if="item.userTenantStatus === '3' && item.auth" class="font-color9e flex-flow margin-right40 font-size13">
<Icon icon="ant-design:tool-outlined" class="footer-icon" />
<span>租户管理</span>
</span>
<span
v-if="item.userTenantStatus !== '3' && !item.auth"
@click.stop="footerClick('tenantSetting', item)"
class="font-color333 flex-flow margin-right40 font-size13 pointer"
>
<Icon icon="ant-design:tool-outlined" class="footer-icon" />
<span>申请角色权限</span>
</span>
<span v-else-if="item.userTenantStatus === '3' && !item.auth" class="font-color9e flex-flow margin-right40 font-size13">
<Icon icon="ant-design:tool-outlined" class="footer-icon" />
<span>申请角色权限</span>
</span>
<span
v-if="item.userTenantStatus !== '3'"
@click.stop="footerClick('tenantSetting', item)"
class="font-color333 flex-flow margin-right40 font-size13 pointer"
>
<Icon icon="ant-design:gold-outlined" class="footer-icon" />
<span>我的汇报关系</span>
</span>
<span v-else class="font-color9e flex-flow margin-right40 font-size13">
<Icon icon="ant-design:gold-outlined" class="footer-icon" />
<span>我的汇报关系</span>
</span>
<span
v-if="item.userTenantStatus !== '3'"
@click.stop="footerClick('exitTenant', item)"
@@ -226,7 +190,7 @@ import { onMounted, ref, unref } from "vue";
import { getTenantListByUserId, cancelApplyTenant, exitUserTenant, changeOwenUserTenant, agreeOrRefuseJoinTenant } from "./UserSetting.api";
import { useUserStore } from "/@/store/modules/user";
import { CollapseContainer } from "/@/components/Container";
import { getFileAccessHttpUrl } from "/@/utils/common/compUtils";
import { getFileAccessHttpUrl, userExitChangeLoginTenantId } from "/@/utils/common/compUtils";
import headerImg from "/@/assets/images/header.jpg";
import {useMessage} from "/@/hooks/web/useMessage";
import { initDictOptions } from '/@/utils/dict';
@@ -424,11 +388,7 @@ const userDetail = ref({
if (res.success) {
createMessage.success(res.message);
cancelVisible.value = false;
//update-begin---author:wangshuai ---date:20230703 for【QQYUN-5632】退出租户后 再点击主页 已退出的租户应用还可以操作------------
userStore.setTenant(null);
//update-end---author:wangshuai ---date:20230703 for【QQYUN-5632】退出租户后 再点击主页 已退出的租户应用还可以操作------------
//切换租户后要刷新首页
window.location.reload();
userExitChangeLoginTenantId(unref(myTenantInfo).tenantUserId);
} else {
if (res.message === 'assignedOwen') {
//需要指定变更者
@@ -480,9 +440,9 @@ const userDetail = ref({
changeOwenUserTenant({ userId:unref(tenantOwen), tenantId:unref(myTenantInfo).tenantUserId }).then((res) =>{
if(res.success){
createMessage.success(res.message);
userStore.setTenant(null);
//切换租户后要刷新首页
window.location.reload();
//update-begin---author:wangshuai---date:2023-10-23---for:【QQYUN-6822】7、登录拥有多个租户身份的用户退出租户只剩下一个租户后显示为空---
userExitChangeLoginTenantId(unref(myTenantInfo).tenantUserId);
//update-end---author:wangshuai---date:2023-10-23---for:【QQYUN-6822】7、登录拥有多个租户身份的用户退出租户只剩下一个租户后显示为空---
} else {
createMessage.warning(res.message);
}

View File

@@ -18,7 +18,7 @@
"experimentalDecorators": true,
"lib": ["dom", "esnext"],
"types": ["vite/client", "jest"],
"typeRoots": ["./node_modules/@types/", "./types"],
"typeRoots": ["./node_modules/@types/", "./types","./node_modules"],
"noImplicitAny": false,
"skipLibCheck": true,
"paths": {

View File

@@ -75,6 +75,8 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
cssTarget: 'chrome80',
outDir: OUTPUT_DIR,
rollupOptions: {
// 关闭除屑优化,防止删除重要代码,导致打包后功能出现异常
treeshake: false,
output: {
chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称