v3.9.0 里程碑版本发布

This commit is contained in:
JEECG
2025-11-26 11:25:35 +08:00
parent 1f73837b7d
commit 9919ae2bc5
380 changed files with 11450 additions and 4555 deletions

View File

@ -1,9 +1,7 @@
<template>
<div :class="[prefixCls, getLayoutContentMode]" v-loading="getOpenPageLoading && getPageLoading">
<PageLayout />
<!-- update-begin-author:zyf date:20211129 for:qiankun 挂载子应用盒子 -->
<div id="content" class="app-view-box" v-if="openQianKun == 'true'"></div>
<!-- update-end-author:zyf date:20211129 for: qiankun 挂载子应用盒子-->
</div>
</template>
<script lang="ts">

View File

@ -73,9 +73,8 @@
@prefix-cls: ~'@{namespace}-layout-footer';
@normal-color: rgba(0, 0, 0, 0.45);
// update-begin-author:liusq date:2023-7-12 for: [issues/608] dark 模式下底部 footer 文字 hover 样式导致文字消失
// 代码逻辑说明: [issues/608] dark 模式下底部 footer 文字 hover 样式导致文字消失
@hover-color: v-bind(hoverColor);
// update-end-author:liusq date:2023-7-12 for: [issues/608] dark 模式下底部 footer 文字 hover 样式导致文字消失
.@{prefix-cls} {
color: @normal-color;
text-align: center;

View File

@ -23,9 +23,8 @@
import { TabsThemeEnum } from '/@/enums/appEnum';
import { MenuTypeEnum } from '/@/enums/menuEnum';
// update-begin--author:liaozhiyang---date:20240407---for【QQYUN-8774】网站header区域加高
// 代码逻辑说明: 【QQYUN-8774】网站header区域加高
const HEADER_HEIGHT = 60;
// update-begin--author:liaozhiyang---date:20240407---for【【QQYUN-8774】网站header区域加高
// updateBy:sunjianlei---updateDate:2021-09-03---修改tab切换栏样式更改高度
const TABS_HEIGHT = 32;
@ -99,11 +98,10 @@
const getPlaceholderDomStyle = computed((): CSSProperties => {
let height = 0;
// update-begin--author:liaozhiyang---date:20241216---for【issues/7561】主题切换为顶部混合模式时页面顶部内容显示不出来被遮盖
// 代码逻辑说明: 【issues/7561】主题切换为顶部混合模式时页面顶部内容显示不出来被遮盖
if ((unref(getShowFullHeaderRef) || !unref(getSplit)) && unref(getShowHeader) && !unref(getFullContent) || unref(getMenuType) == MenuTypeEnum.MIX) {
height += HEADER_HEIGHT;
}
// update-end--author:liaozhiyang---date:20241216---for【issues/7561】主题切换为顶部混合模式时页面顶部内容显示不出来被遮盖
if (unref(getShowTabs) && !unref(getFullContent)) {
height += unref(getTabsThemeHeight);
}
@ -141,11 +139,10 @@
.@{prefix-cls} {
transition: width 0.2s;
flex: 0 0 auto;
// update-begin--author:liaozhiyang---date:20250818---for【issues/8709】LayoutContent样式多出1px
// 代码逻辑说明: 【issues/8709】LayoutContent样式多出1px
// &--dark {
// margin-left: -1px;
// }
// update-end--author:liaozhiyang---date:20250818---for【issues/8709】LayoutContent样式多出1px
&--fixed {
position: fixed;

View File

@ -163,7 +163,7 @@
margin-bottom: 2px;
}
}
// update-begin--author:liaozhiyang---date:20240408---for【QQYUN-8922】面包屑样式调整
// 代码逻辑说明: 【QQYUN-8922】面包屑样式调整
&--light {
.ant-breadcrumb-link {
color: rgba(0, 0, 0, 0.85);
@ -219,5 +219,4 @@
}
}
}
// update-end--author:liaozhiyang---date:20240408---for【QQYUN-8922】面包屑样式调整
</style>

View File

@ -26,7 +26,7 @@
setup() {
const { t } = useI18n();
const [register, { openModal }] = useModal();
// update-begin--author:liaozhiyang---date:20230901---for【QQYUN-6333】空路由问题—首次访问资源太大
// 代码逻辑说明: 【QQYUN-6333】空路由问题—首次访问资源太大
const lockModalVisible = ref(false);
const modalRef = ref(null);
async function handleLock() {
@ -34,7 +34,6 @@
await getRefPromise(modalRef);
openModal(true);
}
// update-end--author:liaozhiyang---date:20230901---for【QQYUN-6333】空路由问题—首次访问资源太大
return {
t,
register,

View File

@ -43,11 +43,10 @@
const [register, { closeModal }] = useModalInner();
const [registerForm, { validateFields, resetFields }] = useForm({
//update-begin---author:wangshuai---date:2024-04-08---for:【QQYUN-8895】锁屏样式修改---
// 代码逻辑说明: 【QQYUN-8895】锁屏样式修改---
labelWidth: 74,
labelAlign:'left',
wrapperCol:{},
//update-end---author:wangshuai---date:2024-04-08---for:【QQYUN-8895】锁屏样式修改---
showActionButtonGroup: false,
schemas: [
{

View File

@ -0,0 +1,207 @@
<template>
<BasicModal
v-bind="$attrs"
@register="registerModal"
:title="getTitle"
:width="500"
@ok="handleSubmit"
:keyboard="false"
:maskClosable="false"
:closable="false"
:bodyStyle="{ padding: '10px 20px 20px 20px' }"
:ok-button-props="{ loading: confirmLoading }"
:cancel-button-props="{ style: { display: 'none' } }"
destroyOnClose
>
<div>
<span class="pwd-topbar">您当前密码和系统密码一致请修改密码</span>
<BasicForm @register="registerForm" />
</div>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form';
import { useMessage } from '/@/hooks/web/useMessage';
import { useI18n } from '/@/hooks/web/useI18n';
import { rules } from '@/utils/helper/validator';
import { defHttp } from '@/utils/http/axios';
import { useUserStore } from '@/store/modules/user';
const emit = defineEmits(['success', 'register']);
const { t } = useI18n();
const { createMessage } = useMessage();
const confirmLoading = ref(false);
const oldPassword = ref('');
// 判断密码是否为连续的数字或字母
function lxStr (password) {
let arr = password.split('');
let flag = true;
for (let i = 1; i < arr.length - 1; i++) {
let firstIndex = arr[i - 1].charCodeAt();
let secondIndex = arr[i].charCodeAt();
let thirdIndex = arr[i + 1].charCodeAt();
thirdIndex - secondIndex == 1;
secondIndex - firstIndex == 1;
if ((thirdIndex - secondIndex === 1) && (secondIndex - firstIndex === 1)) {
flag = false;
}
}
if (!flag) {
return flag
}
return flag
}
// 表单配置
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 100,
schemas: [
{
label: t('layout.changePassword.newPassword'),
field: 'password',
component: 'StrengthMeter',
componentProps: {
placeholder: t('layout.changePassword.pleaseEnterNewPassword'),
},
rules: [
{
required: true,
message: t('layout.changePassword.pleaseEnterNewPassword'),
},
{
validator:(_, value)=>{
if(!value){
return Promise.resolve();
}
//不能使用系统密码作为新密码
if(value === oldPassword.value){
return Promise.reject('不能使用系统密码作为新密码!');
}
//密码由8位数字、大小写字母和特殊符号组成
let reg = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/;
if(!reg.test(value)){
return Promise.reject('密码由 8 位及以上数字、大小写字母和特殊符号组成!');
}
return Promise.resolve();
}
},
/* {
// 使用一个函数来自定义验证逻辑,客户使用这个
validator: (_, value) => {
// 如果密码为空,直接返回 resolve() 让 required 规则去处理
if (!value) {
return Promise.resolve();
}
//不能使用系统密码作为新密码
if(value === oldPassword.value){
return Promise.reject('不能使用系统密码作为新密码!');
}
// 1. 长度不低于8位
if (value.length < 8) {
return Promise.reject('密码长度不能少于8位');
}
// 2. 必须包含数字、字母大小写、特殊字符
// 使用正则表达式进行匹配
const hasNumber = /[0-9]/.test(value);
const hasLowercase = /[a-z]/.test(value);
const hasUppercase = /[A-Z]/.test(value);
const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~`]/.test(value);
if (!(hasNumber && hasLowercase && hasUppercase && hasSpecialChar)) {
return Promise.reject('密码必须包含数字、大小写字母和特殊字符');
}
if(!lxStr(value)){
return Promise.reject('密码不能出现3位及3为以上的数字或字母');
}
//不能相同字符如111、aaa连续3位或3位以上
const reg2 = /(\w)*(\w)\2{2}(\w)*!/g
if (reg2.test(value)) {
console.log('密码不能出现相同字符连续3位或3位以上')
return false
}
// 如果所有规则都通过,返回 resolve()
return Promise.resolve();
}
}*/
],
},
{
label: t('layout.changePassword.confirmNewPassword'),
field: 'confirmpassword',
component: 'InputPassword',
dynamicRules: ({ values }) => rules.confirmPassword(values, true),
},
],
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
resetFields();
setModalProps({ confirmLoading: false });
oldPassword.value = decodeURIComponent(data.oldPassword)
});
const getTitle = computed(() => '修改密码');
const userStore = useUserStore();
const { createMessage: $message } = useMessage();
// 提交处理
async function handleSubmit() {
try {
const values = await validate();
setModalProps({ confirmLoading: true });
//提交表单
let params = Object.assign({ username: userStore.getUserInfo.username, oldpassword: oldPassword.value }, values);
defHttp.put({ url: '/sys/user/updatePassword', params }, { isTransformResponse: false }).then((res) => {
if (res.success) {
$message.info({
content:'密码修改成功请重新登录2s后自动退出登录',
duration: 2
})
//3s后返回登录页面
setTimeout(()=>{
userStore.logout(true);
},2000)
//关闭弹窗
closeModal();
//关闭弹窗
closeModal();
} else {
$message.warning(res.message);
}
});
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
<style lang="less" scoped>
:deep(.ant-form-item) {
margin-bottom: 20px;
}
.pwd-topbar{
width: 400px;
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
background: linear-gradient(90deg, #fff7e6, #fff1b8);
border: 1px solid #ffd591;
border-left: 0;
border-right: 0;
color: #ad6800;
position: relative;
margin-bottom: 10px;
left: 36px;
}
</style>

View File

@ -1,21 +1,23 @@
<template>
<div :class="prefixCls">
<Badge :count="count" :overflowCount="9" :offset="[-4, 10]" :numberStyle="numberStyle" @click="clickBadge">
<Badge :count="messageCount" :overflowCount="9" :offset="[-4, 18]" :numberStyle="numberStyle" @click="clickBadge('')">
<BellOutlined />
</Badge>
<DynamicNotice ref="dynamicNoticeRef" v-bind="dynamicNoticeProps" />
<DetailModal @register="registerDetail" />
<sys-message-modal @register="registerMessageModal" @refresh="reloadCount"></sys-message-modal>
<sys-message-modal @register="registerMessageModal" @refresh="reloadCount" :messageCount="messageCount"></sys-message-modal>
<!-- 修改密码弹窗 -->
<ChangePasswordModal @register="changePwdModal"></ChangePasswordModal>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, ref, unref, reactive, onMounted, getCurrentInstance } from 'vue';
import { Popover, Tabs, Badge } from 'ant-design-vue';
import { BellOutlined } from '@ant-design/icons-vue';
import { tabListData } from './data';
import { listCementByUser, editCementSend } from './notify.api';
// import { tabListData } from './data';
import { getUnreadMessageCount, editCementSend, clearAllUnReadMessage } from './notify.api';
import NoticeList from './NoticeList.vue';
import DetailModal from '/@/views/monitor/mynews/DetailModal.vue';
import DynamicNotice from '/@/views/monitor/mynews/DynamicNotice.vue';
@ -27,8 +29,12 @@
import { readAllMsg } from '/@/views/monitor/mynews/mynews.api';
import { getToken } from '/@/utils/auth';
import md5 from 'crypto-js/md5';
import { useRouter } from 'vue-router';
import SysMessageModal from '/@/views/system/message/components/SysMessageModal.vue'
import ChangePasswordModal from './ChangePasswordModal.vue'
import { ElectronEnum } from '/@/enums/jeecgEnum';
import { defHttp } from "@/utils/http/axios";
export default defineComponent({
components: {
@ -41,6 +47,7 @@
DetailModal,
DynamicNotice,
SysMessageModal,
ChangePasswordModal,
},
setup() {
const { prefixCls } = useDesign('header-notify');
@ -49,22 +56,32 @@
const glob = useGlobSetting();
const dynamicNoticeProps = reactive({ path: '', formData: {} });
const [registerDetail, detailModal] = useModal();
const listData = ref(tabListData);
const count = computed(() => {
let count = 0;
for (let i = 0; i < listData.value.length; i++) {
count += listData.value[i].count;
}
return count;
});
const router = useRouter();
// const listData = ref(tabListData);
// const count = computed(() => {
// let count = 0;
// for (let i = 0; i < listData.value.length; i++) {
// count += listData.value[i].count;
// }
// return count;
// });
const chatRef = ref();
const [registerMessageModal, { openModal: openMessageModal }] = useModal();
function clickBadge(){
//消息列表弹窗前去除角标
for (let i = 0; i < listData.value.length; i++) {
listData.value[i].count = 0;
}
openMessageModal(true, {})
const [registerBookModal, { openModal: openBookModal }] = useModal();
const [changePwdModal, { openModal: openPwdModal }] = useModal();
//通知消息类型
const noticeType = ref<string>('system');
//未读消息
const unReadNum = ref<any>({});
function clickBadge(value){
// //消息列表弹窗前去除角标
// for (let i = 0; i < listData.value.length; i++) {
// listData.value[i].count = 0;
// }
// 代码逻辑说明: 【QQYUN-12162】OA项目改造系统重消息拆分目前消息都在一起 需按分类进行拆分---
openMessageModal(true, { noticeType: value })
}
const popoverVisible = ref<boolean>(false);
@ -72,6 +89,7 @@
initWebSocket();
});
const messageCount = ref<number>(0)
function mapAnnouncement(item) {
return {
...item,
@ -84,13 +102,23 @@
// 获取系统消息
async function loadData() {
try {
let { anntMsgList, sysMsgList, anntMsgTotal, sysMsgTotal } = await listCementByUser({
pageSize: 5,
});
listData.value[0].list = anntMsgList.map(mapAnnouncement);
listData.value[1].list = sysMsgList.map(mapAnnouncement);
listData.value[0].count = anntMsgTotal;
listData.value[1].count = sysMsgTotal;
// let { anntMsgList, sysMsgList, anntMsgTotal, sysMsgTotal } = await listCementByUser({
// pageSize: 5,
// });
// listData.value[0].list = anntMsgList.map(mapAnnouncement);
// listData.value[1].list = sysMsgList.map(mapAnnouncement);
// listData.value[0].count = anntMsgTotal;
// listData.value[1].count = sysMsgTotal;
//let msgCount = anntMsgTotal+sysMsgTotal;
let msgCount = await getUnreadMessageCount();
// 代码逻辑说明: 【QQYUN-12162】OA项目改造系统重消息拆分目前消息都在一起 需按分类进行拆分---
unReadNum.value = msgCount;
messageCount.value = msgCount.count?msgCount.count:0;
// 代码逻辑说明: 【JHHB-13】桌面应用消息通知
if (glob.isElectronPlatform) {
window[ElectronEnum.ELECTRON_API].sendNotifyFlash(messageCount.value);
window[ElectronEnum.ELECTRON_API].trayFlash();
}
} catch (e) {
console.warn('系统消息通知异常:', e);
}
@ -132,15 +160,49 @@
function onWebSocketMessage(data) {
if (data.cmd === 'topic' || data.cmd === 'user') {
//update-begin-author:taoyan date:2022-7-13 for: VUEN-1674【严重bug】系统通知为什么必须刷新右上角才提示
// 代码逻辑说明: VUEN-1674【严重bug】系统通知为什么必须刷新右上角才提示
if(data.noticeType){
noticeType.value = data.noticeType;
}
//后台保存数据太慢 前端延迟刷新消息
setTimeout(()=>{
// 代码逻辑说明: 【JHHB-13】桌面应用消息通知
notification(data);
loadData();
}, 1000)
//update-end-author:taoyan date:2022-7-13 for: VUEN-1674【严重bug】系统通知为什么必须刷新右上角才提示
}
}
// 桌面应用通知
function notification(data) {
if (glob.isElectronPlatform && (data.noticeType || data.cmd == 'email')) {
// 流程、文件、日程、系统、会议
// flow、file、plan、system、meeting
let title = '';
let msgTxt = '';
let path = '';
if (data.noticeType === 'flow') {
title = '流程';
path = '/task/myHandleTaskInfo';
} else if (data.noticeType === 'file') {
title = '文件';
path = '/file';
} else if (data.noticeType === 'plan') {
title = '日程';
path = '/plan/view';
} else if (data.noticeType === 'system') {
title = '系统';
path = '/monitor/mynews';
} else if (data.noticeType === 'meeting') {
title = '会议';
path = '/meeting';
} else if (data.cmd === 'email') {
title = '邮件';
path = '/eoa/email?type=inbox';
}
msgTxt = data.msgTxt ?? '查看详情';
window[ElectronEnum.ELECTRON_API].sendNotification(`有新的${title}消息`, msgTxt, path);
}
}
// 清空消息
function onEmptyNotify() {
popoverVisible.value = false;
@ -155,10 +217,49 @@
}
}
/**
* 获取消息未读数
*/
function getSystemUnreadNum() {
}
function clickAddressBook() {
openBookModal(true,{})
}
/**
* 清除全部未读消息
*/
function clearAllUnMessage() {
clearAllUnReadMessage().then((res) =>{
if(res.success){
loadData();
}
})
}
//验证是否为默认密码
verifyIzDefaultPwd();
/**
* 验证是否为默认密码
*/
function verifyIzDefaultPwd() {
defHttp.get({ url: "/sys/user/verifyIzDefaultPwd" } ,{ isTransformResponse: false }).then((res) =>{
if(res.success){
if(res.message.indexOf('yes') != -1){
openPwdModal(true,{
oldPassword: res.message.split("_")[1]
})
}
}
})
}
return {
prefixCls,
listData,
count,
// listData,
// count,
clickBadge,
registerMessageModal,
reloadCount,
@ -168,6 +269,13 @@
popoverVisible,
registerDetail,
dynamicNoticeProps,
chatRef,
getSystemUnreadNum,
clickAddressBook,
registerBookModal,
messageCount,
clearAllUnMessage,
changePwdModal,
};
},
});
@ -177,7 +285,7 @@
@prefix-cls: ~'@{namespace}-header-notify';
.@{prefix-cls} {
padding-top: 2px;
/* padding-top: 2px;*/
&__overlay {
max-width: 340px;

View File

@ -145,12 +145,10 @@
function onWebSocketMessage(data) {
console.log('---onWebSocketMessage---', data)
if (data.cmd === 'topic' || data.cmd === 'user') {
//update-begin-author:taoyan date:2022-7-13 for: VUEN-1674【严重bug】系统通知为什么必须刷新右上角才提示
//后台保存数据太慢 前端延迟刷新消息
setTimeout(()=>{
loadData();
}, 1000)
//update-end-author:taoyan date:2022-7-13 for: VUEN-1674【严重bug】系统通知为什么必须刷新右上角才提示
}
}

View File

@ -37,7 +37,7 @@
<Icon icon="ant-design:gold-outline" />
</template>
<template v-for="depart in departList" :key="depart.orgCode">
<a-select-option :value="depart.orgCode">{{ depart.departName }}</a-select-option>
<a-select-option :value="depart.orgCode">{{ getShortDeptName(depart) }} </a-select-option>
</template>
</a-select>
</a-form-item>
@ -94,6 +94,16 @@
const validate_status1 = ref('');
//弹窗显隐
const visible = ref(false);
//获取部门缩写
const getShortDeptName = computed(()=>{
return (depart) => {
let deptName = depart.departNameAbbr || depart.departPathName || depart.departName;
if (deptName.length > 18) {
return '...' + deptName.substring(deptName.length-18, deptName.length) ;
}
return deptName;
};
})
/**
* 弹窗打开前处理
*/
@ -126,8 +136,12 @@
return;
}
let currentDepart = result.list.filter((item) => item.orgCode == result.orgCode);
departList.value = result.list;
departSelected.value = currentDepart && currentDepart.length > 0 ? result.orgCode : '';
//筛选出用户的部门信息(排除公司或者岗位配置)
const userDeparts = result.list.filter((item) => item.orgCategory == '2');
departList.value = userDeparts;
// 代码逻辑说明: JHHB-790 用户部门变更,会出现这个情况(因为之前设置的这里只切换部门,过滤了公司和岗位信息)
const hasCurrentDepart = userDeparts.some(item => item.orgCode == result.orgCode);
departSelected.value = hasCurrentDepart && currentDepart && currentDepart.length > 0 ? result.orgCode : '';
currentDepartName.value = currentDepart && currentDepart.length > 0 ? currentDepart[0].departName : '';
isMultiDepart.value = true;
}

View File

@ -25,9 +25,8 @@
},
setup(props) {
const instance = getCurrentInstance();
// update-begin--author:liaozhiyang---date:20240717---for【issues/6855】组件使用key作props报警告改为itemKey
// 代码逻辑说明: 【issues/6855】组件使用key作props报警告改为itemKey
const itemKey = computed(() => props.itemKey || instance?.vnode?.props?.itemKey);
// update-end--author:liaozhiyang---date:20240717---for【issues/6855】组件使用key作props报警告改为itemKey
return { itemKey };
},
});

View File

@ -20,7 +20,7 @@
const $message = useMessage();
const formRef = ref();
const username = ref('');
// update-begin--author:liaozhiyang---date:20240124---for【QQYUN-7970】国际化
// 代码逻辑说明: 【QQYUN-7970】国际化
const title = ref(t('layout.changePassword.changePassword'));
//表单配置
const [registerForm, { resetFields, validate, clearValidate }] = useForm({
@ -43,6 +43,10 @@
required: true,
message: t('layout.changePassword.pleaseEnterNewPassword'),
},
{
pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
message: '密码由 8 位及以上数字、大小写字母和特殊符号组成!',
},
],
},
{
@ -56,7 +60,6 @@
wrapperCol: null,
labelWidth: localeStore.getLocale == 'zh_CN' ? 100 : 160,
});
// update-end--author:liaozhiyang---date:20240124---for【QQYUN-7970】国际化
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner();

View File

@ -35,7 +35,7 @@
// components
import { Dropdown, Menu } from 'ant-design-vue';
import { defineComponent, computed, ref } from 'vue';
import { defineComponent, computed, ref, nextTick } from 'vue';
import { SITE_URL } from '/@/settings/siteSetting';
@ -57,7 +57,7 @@
import { removeAuthCache, setAuthCache } from '/src/utils/auth';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { getRefPromise } from '/@/utils/index';
import { refreshDragCache, refreshHomeCache } from "@/api/common/api";
import { refreshDragCache } from "@/api/common/api";
type MenuEvent = 'logout' | 'doc' | 'lock' | 'cache' | 'depart' | 'defaultHomePage' | 'password' | 'account';
const { createMessage } = useMessage();
@ -82,7 +82,6 @@
const userStore = useUserStore();
const go = useGo();
const passwordVisible = ref(false);
const homeSelectVisible = ref(false);
const lockActionVisible = ref(false);
const lockActionRef = ref(null);
@ -105,12 +104,11 @@
* 多部门弹窗逻辑
*/
const loginSelectRef = ref();
// update-begin--author:liaozhiyang---date:20230901---for【QQYUN-6333】空路由问题—首次访问资源太大
// 代码逻辑说明: 【QQYUN-6333】空路由问题—首次访问资源太大
async function handleLock() {
await getRefPromise(lockActionRef);
openModal(true);
}
// update-end--author:liaozhiyang---date:20230901---for【QQYUN-6333】空路由问题—首次访问资源太大
// login out
function handleLoginOut() {
userStore.confirmLoginOut();
@ -130,16 +128,11 @@
const res = await queryAllDictItems();
removeAuthCache(DB_DICT_DATA_KEY);
setAuthCache(DB_DICT_DATA_KEY, res.result);
// update-begin--author:liaozhiyang---date:20240124---for【QQYUN-7970】国际化
createMessage.success(t('layout.header.refreshCacheComplete'));
// update-end--author:liaozhiyang---date:20240124---for【QQYUN-7970】国际化
// update-begin--author:wangshuai---date:20241112---for【issues/7433】vue3 数据字典优化建议
// 代码逻辑说明: 【issues/7433】vue3 数据字典优化建议
userStore.setAllDictItems(res.result);
// update-end--author:wangshuai---date:20241112---for【issues/7433】vue3 数据字典优化建议
} else {
// update-begin--author:liaozhiyang---date:20240124---for【QQYUN-7970】国际化
createMessage.error(t('layout.header.refreshCacheFailure'));
// update-end--author:liaozhiyang---date:20240124---for【QQYUN-7970】国际化
}
}
// 切换部门
@ -148,13 +141,12 @@
}
// 修改密码
const updatePasswordRef = ref();
// update-begin--author:liaozhiyang---date:20230901---for【QQYUN-6333】空路由问题—首次访问资源太大
// 代码逻辑说明: 【QQYUN-6333】空路由问题—首次访问资源太大
async function updatePassword() {
passwordVisible.value = true;
await getRefPromise(updatePasswordRef);
updatePasswordRef.value.show(userStore.getUserInfo.username);
}
// update-end--author:liaozhiyang---date:20230901---for【QQYUN-6333】空路由问题—首次访问资源太大
function handleMenuClick(e: { key: MenuEvent }) {
switch (e.key) {
case 'logout':
@ -176,9 +168,8 @@
updatePassword();
break;
case 'account':
//update-begin---author:wangshuai ---date:20221125 for进入用户设置页面------------
// 代码逻辑说明: 进入用户设置页面------------
go(`/system/usersetting`);
//update-end---author:wangshuai ---date:20221125 for进入用户设置页面--------------
break;
}
}
@ -247,15 +238,14 @@
}
&-dropdown-overlay {
// update-begin--author:liaozhiyang---date:20231226---for【QQYUN-7512】顶部账号划过首次弹出时位置会变更一下
// 代码逻辑说明: 【QQYUN-7512】顶部账号划过首次弹出时位置会变更一下
width: 160px;
// update-end--author:liaozhiyang---date:20231226---for【QQYUN-7512】顶部账号划过首次弹出时位置会变更一下
.ant-dropdown-menu-item {
min-width: 160px;
}
}
}
// update-begin--author:liaozhiyang---date:20250702---for【QQYUN-13013】切换到英文模式下拉菜单宽度有点窄
// 代码逻辑说明: 【QQYUN-13013】切换到英文模式下拉菜单宽度有点窄
html[lang="en"] {
.@{prefix-cls} {
&-dropdown-overlay {
@ -263,5 +253,4 @@
}
}
}
// update-end--author:liaozhiyang---date:20250702---for【QQYUN-13013】切换到英文模式下拉菜单宽度有点窄
</style>

View File

@ -171,13 +171,11 @@
const loginSelectRef = ref();
function showLoginSelect() {
//update-begin---author:liusq Date:20220101 for判断登录进来是否需要弹窗选择租户----
//判断是否是登陆进来
const loginInfo = toRaw(userStore.getLoginInfo) || {};
if (!!loginInfo.isLogin) {
loginSelectRef.value.show(loginInfo);
}
//update-end---author:liusq Date:20220101 for判断登录进来是否需要弹窗选择租户----
}
function loginSelectOk() {
@ -223,25 +221,23 @@
</script>
<style lang="less">
@import './index.less';
//update-begin---author:scott ---date:2022-09-30 for默认隐藏顶部菜单面包屑-----------
//顶部欢迎语展示样式
@prefix-cls: ~'@{namespace}-layout-header';
.ant-layout .@{prefix-cls} {
display: flex;
padding: 0 8px;
// update-begin--author:liaozhiyang---date:20240407---for【QQYUN-8762】顶栏高度
// 代码逻辑说明: 【QQYUN-8762】顶栏高度
height: @header-height;
// update-end--author:liaozhiyang---date:20240407---for【QQYUN-8762】顶栏高度
align-items: center;
.headerIntroductionClass {
margin-right: 4px;
margin-bottom: 2px;
border-bottom: 0px;
border-left: 0px;
}
&--light {
.headerIntroductionClass {
color: #000;
@ -256,6 +252,5 @@
color: rgba(255, 255, 255, 1);
}
}
//update-end---author:scott ---date::2022-09-30 for默认隐藏顶部菜单面包屑--------------
}
</style>

View File

@ -86,9 +86,8 @@
&-main {
width: 100%;
// update-begin--author:liaozhiyang---date:20250818---for【issues/8709】LayoutContent样式多出1px
// 代码逻辑说明:【issues/8709】LayoutContent样式多出1px
// margin-left: 1px;
// update-end--author:liaozhiyang---date:20250818---for【issues/8709】LayoutContent样式多出1px
}
}
</style>

View File

@ -83,9 +83,8 @@
const getWrapperStyle = computed((): CSSProperties => {
return {
// update-begin--author:liaozhiyang---date:20241216---for【issues/7548】侧边栏导航模式时会导致下面菜单滚动显示不全
// 代码逻辑说明: 【issues/7548】侧边栏导航模式时会导致下面菜单滚动显示不全
height: `calc(100% - ${unref(getIsShowLogo) ? '60px' : '0px'})`,
// update-end--author:liaozhiyang---date:20241216---for【issues/7548】侧边栏导航模式时会导致下面菜单滚动显示不全
};
});
@ -116,7 +115,7 @@
* click menu
* @param menu
*/
//update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
// 代码逻辑说明: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
const localeStore = useLocaleStore();
function handleMenuClick(path: string, item) {
if (item) {
@ -124,7 +123,6 @@
}
go(path);
}
//update-end-author:taoyan date:2022-6-1 for: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
/**
* before click menu
@ -174,11 +172,10 @@
});
</script>
<style lang="less" scoped>
// update-begin--author:liaozhiyang---date:20230803---for【QQYUN-5872】菜单优化上下滚动条去掉
// 代码逻辑说明: 【QQYUN-5872】菜单优化上下滚动条去掉
.scroll-container :deep(.scrollbar__bar) {
display: none;
}
// update-end--author:liaozhiyang---date:20230803---for【QQYUN-5872】菜单优化上下滚动条去掉
</style>
<style lang="less">
@prefix-cls: ~'@{namespace}-layout-menu';

View File

@ -36,7 +36,6 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
if (unref(splitNotLeft) || unref(getIsMobile)) return;
const { meta } = unref(currentRoute);
const currentActiveMenu = meta.currentActiveMenu as string;
// update-begin--author:liaozhiyang---date:20250908---for【QQYUN-13718】一级菜单默认重定向到子菜单但子菜单未授权导致点击一级菜单加载不出子菜单
// 顶部混合模式且顶部左侧组合菜单开始时
if (unref(getMenuType) === MenuTypeEnum.MIX && unref(getSplit)) {
// 404页面时跳转到重定向的路径
@ -49,7 +48,6 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
}
}
}
// update-end--author:liaozhiyang---date:20250908---for【QQYUN-13718】一级菜单默认重定向到子菜单但子菜单未授权导致点击一级菜单加载不出子菜单
let parentPath = await getCurrentParentPath(path);
if (!parentPath) {
parentPath = await getCurrentParentPath(currentActiveMenu);
@ -76,9 +74,7 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
watch(
() => getSplit.value,
() => {
// update-begin--author:liaozhiyang---date:20240919---for【issues/7209】顶部左侧组合菜单关闭之后左侧导航没还原
// if (unref(splitNotLeft)) return;
// update-end--author:liaozhiyang---date:20240919---for【issues/7209】顶部左侧组合菜单关闭之后左侧导航没还原
genMenus();
}
);

View File

@ -52,7 +52,7 @@
function handleClick(color: string) {
props.event && baseHandler(props.event, color);
}
// update-begin--author:liaozhiyang---date:20240417---for:【QQYUN-8927】暗黑主题下不允许切换顶栏主题和菜单主题
// 代码逻辑说明: 【QQYUN-8927】暗黑主题下不允许切换顶栏主题和菜单主题
watch(
() => getDarkMode.value,
(newValue) => {
@ -60,7 +60,6 @@
},
{ immediate: true }
);
// update-end--author:liaozhiyang---date:20240417---for:【QQYUN-8927】暗黑主题下不允许切换顶栏主题和菜单主题
return {
prefixCls,
handleClick,
@ -77,9 +76,8 @@
flex-wrap: wrap;
margin: 16px 0;
justify-content: space-around;
// update-begin--author:liaozhiyang---date:20231220---for【QQYUN-7677】antd4兼容改造勾选垂直居中
// 代码逻辑说明: 【QQYUN-7677】antd4兼容改造勾选垂直居中
line-height: 1.3;
// update-end--author:liaozhiyang---date:20231220---for【QQYUN-7677】antd4兼容改造勾选垂直居中
&__item {
width: 20px;
height: 20px;

View File

@ -9,7 +9,8 @@ import { changeTheme } from '/@/logics/theme';
import { updateDarkTheme } from '/@/logics/theme/dark';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { HEADER_PRESET_BG_COLOR_LIST, APP_PRESET_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/designSetting';
import { HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/designSetting';
import { getThemeColorByMenuType } from '/@/utils/getThemeColorByMenuType';
import { isObject } from '/@/utils/is';
import { ThemeEnum } from '/@/enums/appEnum';
import { APP__THEME__COLOR } from '/@/enums/cacheEnum';
@ -25,10 +26,12 @@ export function layoutHandler(event: HandlerEnum, value: any) {
const isMixSidebarMenu = isObject(value) && value.type == MenuTypeEnum.MIX_SIDEBAR && value.mode == MenuModeEnum.INLINE;
const appStore = useAppStore();
const darkMode = appStore.getDarkMode === ThemeEnum.DARK;
// 根据菜单类型动态获取主题色
const dynamicThemeColor = getThemeColorByMenuType(value.type);
if (isHTopMenu) {
baseHandler(event, value);
baseHandler(HandlerEnum.HEADER_THEME, HEADER_PRESET_BG_COLOR_LIST[2]);
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, APP_PRESET_COLOR_LIST[2]);
baseHandler(HandlerEnum.HEADER_THEME, HEADER_PRESET_BG_COLOR_LIST[4]);
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, dynamicThemeColor);
if (darkMode) {
updateHeaderBgColor();
updateSidebarBgColor();
@ -42,12 +45,12 @@ export function layoutHandler(event: HandlerEnum, value: any) {
updateHeaderBgColor();
updateSidebarBgColor();
}
// 顶部混合导航模式主题色改成绿
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, APP_PRESET_COLOR_LIST[2]);
// 顶部混合导航模式使用动态主题色
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, dynamicThemeColor);
baseHandler(HandlerEnum.TABS_THEME, tabsThemeOptions[1].value);
} else if (isMixSidebarMenu) {
baseHandler(event, value);
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, APP_PRESET_COLOR_LIST[1]);
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, dynamicThemeColor);
baseHandler(HandlerEnum.HEADER_THEME, HEADER_PRESET_BG_COLOR_LIST[0]);
baseHandler(HandlerEnum.MENU_THEME, SIDE_BAR_BG_COLOR_LIST[0]);
if (darkMode) {
@ -63,16 +66,15 @@ export function layoutHandler(event: HandlerEnum, value: any) {
updateHeaderBgColor();
updateSidebarBgColor();
}
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, APP_PRESET_COLOR_LIST[1]);
baseHandler(HandlerEnum.CHANGE_THEME_COLOR, dynamicThemeColor);
baseHandler(HandlerEnum.TABS_THEME, tabsThemeOptions[1].value);
}
// update-begin--author:liaozhiyang---date:20250825---for:【QQYUN-13600】默认顶部混合导航模式且启用顶部左侧导航切换到其他模式时导航刷新后菜单样式混乱
// 代码逻辑说明: 【QQYUN-13600】默认顶部混合导航模式且启用顶部左侧导航切换到其他模式时导航刷新后菜单样式混乱
if (isMixMenu) {
baseHandler(HandlerEnum.MENU_SPLIT, true);
} else {
baseHandler(HandlerEnum.MENU_SPLIT, false);
}
// update-end--author:liaozhiyang---date:20250825---for:【QQYUN-13600】默认顶部混合导航模式且启用顶部左侧导航切换到其他模式时导航刷新后菜单样式混乱
}
export function baseHandler(event: HandlerEnum, value: any) {
@ -109,9 +111,8 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
if (getThemeColor.value === value) {
return {};
}
// update-begin--author:liaozhiyang---date:20240417---for:【QQYUN-8925】系统主题颜色供页面加载使用
// 代码逻辑说明: 【QQYUN-8925】系统主题颜色供页面加载使用
localStorage.setItem(APP__THEME__COLOR, value);
// update-end--author:liaozhiyang---date:20240417---for:【QQYUN-8925】系统主题颜色供页面加载使用
changeTheme(value);
return { themeColor: value };
@ -207,10 +208,9 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
case HandlerEnum.COLOR_WEAK:
updateColorWeak(value);
return { colorWeak: value };
// update-begin--author:liaozhiyang---date:20250407---for【QQYUN-10952】AI助手支持通过设置来配置是否显示
// 代码逻辑说明: 【QQYUN-10952】AI助手支持通过设置来配置是否显示
case HandlerEnum.AI_ICON_SHOW:
return { aiIconShow: value };
// update-end--author:liaozhiyang---date:20250407---for【QQYUN-10952】AI助手支持通过设置来配置是否显示
case HandlerEnum.SHOW_LOGO:
return { showLogo: value };

View File

@ -288,7 +288,7 @@
}
}
// update-begin--author:liaozhiyang---date:20240417---for【QQYUN-8927】侧边折叠导航模式区分彩色模式
// 代码逻辑说明: 【QQYUN-8927】侧边折叠导航模式区分彩色模式
watch(
() => appStore.getProjectConfig.menuSetting,
(menuSetting) => {
@ -296,7 +296,6 @@
},
{ immediate: true, deep: true }
);
// update-end--author:liaozhiyang---date:20240417---for【QQYUN-8927】侧边折叠导航模式区分彩色模式
return {
t,

View File

@ -44,7 +44,7 @@
const { prefixCls } = useDesign('multiple-tabs-content');
const { t } = useI18n();
//update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
// 代码逻辑说明: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
const localeStore = useLocaleStore();
const getTitle = computed(() => {
const { tabItem: { meta, fullPath } = {} } = props;
@ -54,7 +54,6 @@
}
return meta && t(meta.title as string);
});
//update-end-author:taoyan date:2022-6-1 for: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
const getIsTabs = computed(() => !props.isExtra);

View File

@ -164,7 +164,7 @@
:deep(.anticon) {
display: inline-block;
}
// update-begin--author:liaozhiyang---date:20241016---for【issues/7345】标签样式切换到极简模式样式错乱
// 代码逻辑说明: 【issues/7345】标签样式切换到极简模式样式错乱
.rightExtra {
display: flex;
:deep(svg) {
@ -183,6 +183,5 @@
border-left: 1px solid @border-color-base;
}
}
// update-end--author:liaozhiyang---date:20241016---for【issues/7345】标签样式切换到极简模式样式错乱
}
</style>

View File

@ -24,10 +24,8 @@ export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: Comp
const getTargetTab = computed((): RouteLocationNormalized => {
return unref(getIsTabs) ? tabContentProps.tabItem : unref(currentRoute);
});
// update-begin--author:liaozhiyang---date:20250701---for【QQYUN-12994】门户
// 隐藏下拉菜单中的门户设计项
const { getHideHomeDesign, isHideHomeDesign } = useHideHomeDesign(currentRoute);
// update-end--author:liaozhiyang---date:20250701---for【QQYUN-12994】门户
/**
* @description: drop-down list
@ -45,7 +43,6 @@ export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: Comp
const isCurItem = curItem ? curItem.path === path : false;
const index = state.currentIndex;
const refreshDisabled = !isCurItem;
// update-begin--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
// Close left
const closeLeftDisabled = () => {
if (index === 0) {
@ -69,11 +66,8 @@ export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: Comp
// Close right
const closeRightDisabled = index === tabStore.getTabList.length - 1 && tabStore.getLastDragEndIndex >= 0;
// update-end--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
// update-begin--author:liaozhiyang---date:20250701---for【QQYUN-12994】门户
// 隐藏下拉菜单中的门户设计项
getHideHomeDesign(isCurItem, path);
// update-end--author:liaozhiyang---date:20250701---for【QQYUN-12994】门户
const dropMenuList: DropMenu[] = [
{
icon: 'jam:refresh-reverse',
@ -100,9 +94,8 @@ export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: Comp
icon: 'mdi:arrow-left',
event: MenuEventEnum.CLOSE_LEFT,
text: t('layout.multipleTab.closeLeft'),
// update-begin--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
// 代码逻辑说明: 【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
disabled: closeLeftDisabled(),
// update-end--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
divider: false,
},
{
@ -116,9 +109,8 @@ export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: Comp
icon: 'material-symbols:arrows-outward',
event: MenuEventEnum.CLOSE_OTHER,
text: t('layout.multipleTab.closeOther'),
// update-begin--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
// 代码逻辑说明: 【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
disabled: closeOtherDisabled(),
// update-end--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
},
// {
// icon: 'clarity:minus-line',
@ -157,33 +149,23 @@ export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: Comp
break;
// Close left
case MenuEventEnum.CLOSE_LEFT:
// update-begin--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
closeLeft(state.current);
// update-end--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
break;
// Close right
case MenuEventEnum.CLOSE_RIGHT:
// update-begin--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
closeRight(state.current);
// update-end--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
break;
// Close other
case MenuEventEnum.CLOSE_OTHER:
// update-begin--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
closeOther(state.current);
// update-end--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
break;
// Close all
case MenuEventEnum.CLOSE_ALL:
// update-begin--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
closeAll(state.current);
// update-end--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
break;
// Close all
case MenuEventEnum.HOME_DESIGN:
// update-begin--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
changeDesign();
// update-end--author:liaozhiyang---date:20240605---for【TV360X-732】非当前页右键关闭左侧、关闭右侧、关闭其它功能正常使用
break;
}
}

View File

@ -73,9 +73,8 @@
}
return tabStore.getCachedTabList;
});
// update-begin--author:liaozhiyang---date:20250826---for:【QQYUN-13593】空白页美化
// 代码逻辑说明: 【QQYUN-13593】空白页美化
const { pageTip, getPageTip, effectVars } = useEmpty();
// update-end--author:liaozhiyang---date:20250826---for:【QQYUN-13593】空白页美化
return {
getTransitionName,
openCache,