JeecgBoot 3.6.0大版本发布

pull/824/head
zhangdaiscott 2023-10-18 14:55:25 +08:00
parent abd4b7d102
commit 8ff3f4db25
192 changed files with 8983 additions and 5898 deletions

1
.gitignore vendored
View File

@ -29,6 +29,7 @@ pnpm-debug.log*
*.sln *.sln
*.sw? *.sw?
/os_del.cmd /os_del.cmd
os_del.cmd
/.vscode/ /.vscode/
/.history/ /.history/
/svn clear.bat /svn clear.bat

View File

@ -1,11 +1,11 @@
JEECG BOOT 低代码开发平台Vue3前端 JEECG BOOT 低代码开发平台Vue3前端
=============== ===============
当前最新版本: 3.5.5发布时间2023-09-22 当前最新版本: 3.6.0发布时间2023-10-23
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE) [![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/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/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.5.5-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot) [![](https://img.shields.io/badge/version-3.6.0-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 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) [![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)

View File

@ -20,7 +20,7 @@ import { configSvgIconsPlugin } from './svgSprite';
// import PkgConfig from 'vite-plugin-package-config'; // import PkgConfig from 'vite-plugin-package-config';
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
const {VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv; const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv;
const vitePlugins: (PluginOption | PluginOption[])[] = [ const vitePlugins: (PluginOption | PluginOption[])[] = [
// have to // have to

View File

@ -1,6 +1,6 @@
{ {
"name": "jeecgboot-vue3", "name": "jeecgboot-vue3",
"version": "3.5.5", "version": "3.6.0",
"author": { "author": {
"name": "jeecg", "name": "jeecg",
"email": "jeecgos@163.com", "email": "jeecgos@163.com",
@ -28,8 +28,8 @@
"@ant-design/icons-vue": "^6.1.0", "@ant-design/icons-vue": "^6.1.0",
"@logicflow/core": "^1.2.12", "@logicflow/core": "^1.2.12",
"@logicflow/extension": "^1.2.13", "@logicflow/extension": "^1.2.13",
"@vue/shared": "^3.3.4",
"@vue/runtime-core": "^3.3.4", "@vue/runtime-core": "^3.3.4",
"@vue/shared": "^3.3.4",
"@vueuse/shared": "^10.4.1", "@vueuse/shared": "^10.4.1",
"@vueuse/core": "^10.4.1", "@vueuse/core": "^10.4.1",
"@zxcvbn-ts/core": "^3.0.3", "@zxcvbn-ts/core": "^3.0.3",

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -85,7 +85,17 @@ export function getUserInfo() {
const userStore = useUserStoreWithOut(); const userStore = useUserStoreWithOut();
userStore.setToken(''); userStore.setToken('');
setAuthCache(TOKEN_KEY, null); setAuthCache(TOKEN_KEY, null);
router.push(PageEnum.BASE_LOGIN);
// update-begin-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
router.push({
path: PageEnum.BASE_LOGIN,
query: {
// 传入当前的路由,登录成功后跳转到当前路由
redirect: router.currentRoute.value.fullPath,
}
});
// update-end-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
} }
// update-end--author:zyf---date:20220425---for:【VUEN-76】捕获接口超时异常,跳转到登录界面 // update-end--author:zyf---date:20220425---for:【VUEN-76】捕获接口超时异常,跳转到登录界面
}); });
@ -146,9 +156,15 @@ export const passwordChange = (params) => defHttp.get({ url: Api.passwordChange,
* @description: * @description:
*/ */
export function thirdLogin(params, mode: ErrorMessageMode = 'modal') { export function thirdLogin(params, mode: ErrorMessageMode = 'modal') {
//==========begin 第三方登录/auth2登录需要传递租户id===========
let tenantId = "0";
if(!params.tenantId){
tenantId = params.tenantId;
}
//==========end 第三方登录/auth2登录需要传递租户id===========
return defHttp.get<LoginResultModel>( return defHttp.get<LoginResultModel>(
{ {
url: `${Api.thirdLogin}/${params.token}/${params.thirdType}`, url: `${Api.thirdLogin}/${params.token}/${params.thirdType}/${tenantId}`,
}, },
{ {
errorMessageMode: mode, errorMessageMode: mode,

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -62,10 +62,13 @@
padding-left: 7px; padding-left: 7px;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
//
&.light { &.jeecg-layout-mix-sider-logo,&.jeecg-layout-menu-logo{
border-bottom: 1px solid @border-color-base; background:@sider-logo-bg-color;
} }
// &.light {
// border-bottom: 1px solid @border-color-base;
// }
&.collapsed-show-title { &.collapsed-show-title {
padding-left: 20px; padding-left: 20px;

View File

@ -12,7 +12,7 @@
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import CountButton from './CountButton.vue'; import CountButton from './CountButton.vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { useRuleFormItem } from '/@/hooks/component/useFormItem'; import { useRuleFormItem } from '/@/hooks/component/useFormItemSingle';
const props = { const props = {
value: { type: String }, value: { type: String },

View File

@ -10,22 +10,26 @@
v-bind="getAttr(item.event)" v-bind="getAttr(item.event)"
@click="handleClickMenu(item)" @click="handleClickMenu(item)"
:disabled="item.disabled" :disabled="item.disabled"
:class="[{ 'is-pop-confirm': item.popConfirm }, (item.class ?? [])]" :class="[{ 'is-pop-confirm': item.popConfirm }, item.class ?? []]"
> >
<a-popconfirm v-if="popconfirm && item.popConfirm" v-bind="getPopConfirmAttrs(item.popConfirm)"> <a-popconfirm v-if="popconfirm && item.popConfirm" v-bind="getPopConfirmAttrs(item.popConfirm)">
<template #icon v-if="item.popConfirm.icon"> <template #icon v-if="item.popConfirm.icon">
<Icon v-if="item.iconColor" :icon="item.popConfirm.icon" :color="item.iconColor"/> <Icon v-if="item.iconColor" :icon="item.popConfirm.icon" :color="item.iconColor" />
<Icon v-else :icon="item.popConfirm.icon"/> <Icon v-else :icon="item.popConfirm.icon" />
</template> </template>
<div class="dropdown-event-area"> <div class="dropdown-event-area">
<Icon :icon="item.icon" v-if="item.icon && item.iconColor" :color="item.iconColor"/> <Icon :icon="item.icon" v-if="item.icon && item.iconColor" :color="item.iconColor" />
<Icon :icon="item.icon" v-else-if="item.icon"/> <Icon :icon="item.icon" v-else-if="item.icon" />
<span class="ml-1">{{ item.text }}</span> <span class="ml-1">{{ item.text }}</span>
</div> </div>
</a-popconfirm> </a-popconfirm>
<!-- 设置动态插槽 -->
<template v-else-if="item.slot">
<slot :name="item.slot" :label="item.text"></slot>
</template>
<template v-else> <template v-else>
<Icon :icon="item.icon" v-if="item.icon && item.iconColor" :color="item.iconColor"/> <Icon :icon="item.icon" v-if="item.icon && item.iconColor" :color="item.iconColor" />
<Icon :icon="item.icon" v-else-if="item.icon"/> <Icon :icon="item.icon" v-else-if="item.icon" />
<span class="ml-1">{{ item.text }}</span> <span class="ml-1">{{ item.text }}</span>
</template> </template>
</a-menu-item> </a-menu-item>

View File

@ -61,6 +61,7 @@ import JRangeNumber from './jeecg/components/JRangeNumber.vue';
import UserSelect from './jeecg/components/userSelect/index.vue'; import UserSelect from './jeecg/components/userSelect/index.vue';
import JRangeDate from './jeecg/components/JRangeDate.vue' import JRangeDate from './jeecg/components/JRangeDate.vue'
import JRangeTime from './jeecg/components/JRangeTime.vue' import JRangeTime from './jeecg/components/JRangeTime.vue'
import RoleSelectInput from './jeecg/components/roleSelect/RoleSelectInput.vue';
const componentMap = new Map<ComponentType, Component>(); const componentMap = new Map<ComponentType, Component>();
@ -131,6 +132,9 @@ componentMap.set('JRangeNumber', JRangeNumber);
componentMap.set('UserSelect', UserSelect); componentMap.set('UserSelect', UserSelect);
componentMap.set('RangeDate', JRangeDate); componentMap.set('RangeDate', JRangeDate);
componentMap.set('RangeTime', JRangeTime); componentMap.set('RangeTime', JRangeTime);
componentMap.set('RoleSelect', RoleSelectInput);
export function add(compName: ComponentType, component: Component) { export function add(compName: ComponentType, component: Component) {
componentMap.set(compName, component); componentMap.set(compName, component);

View File

@ -206,10 +206,15 @@
} }
function renderComponent() { function renderComponent() {
const { renderComponentContent, component, field, changeEvent = 'change', valueField } = props.schema; const { renderComponentContent, component, field, changeEvent = 'change', valueField, componentProps } = props.schema;
const isCheck = component && ['Switch', 'Checkbox'].includes(component); const isCheck = component && ['Switch', 'Checkbox'].includes(component);
// update-begin--author:liaozhiyang---date:20231013---forQQYUN-6679input
let isTrim = false;
if (component === 'Input' && componentProps && componentProps.trim) {
isTrim = true;
}
// update-end--author:liaozhiyang---date:20231013---forQQYUN-6679input
const eventKey = `on${upperFirst(changeEvent)}`; const eventKey = `on${upperFirst(changeEvent)}`;
// update-begin--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur' // update-begin--author:liaozhiyang---date:20230922---forissues/752dynamicRules 使 trigger: 'blur'
const on = { const on = {
@ -219,7 +224,18 @@
propsData[eventKey](...args); propsData[eventKey](...args);
} }
const target = e ? e.target : null; const target = e ? e.target : null;
const value = target ? (isCheck ? target.checked : target.value) : e; // update-begin--author:liaozhiyang---date:20231013---forQQYUN-6679input
let value;
if (target) {
if (isCheck) {
value = target.checked;
} else {
value = isTrim ? target.value.trim() : target.value;
}
} else {
value = e;
}
// update-end--author:liaozhiyang---date:20231013---forQQYUN-6679input
props.setFormModel(field, value); props.setFormModel(field, value);
//props.validateFields([field], { triggerName: 'change' }).catch((_) => {}); //props.validateFields([field], { triggerName: 'change' }).catch((_) => {});
}, },

View File

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

View File

@ -152,11 +152,14 @@
<style lang="less" scoped> <style lang="less" scoped>
.area-select { .area-select {
width: 100%; width: 100%;
display: flex;
/* update-begin-author:taoyan date:2023-2-18 for: QQYUN-4292【online表单】高级查询 2.省市县样式问题 */
/* display: flex;*/
.ant-select { .ant-select {
width: 33.3%; width: calc(33.3% - 7px)
} }
/* update-end-author:taoyan date:2023-2-18 for: QQYUN-4292【online表单】高级查询 2.省市县样式问题 */
.ant-select:not(:first-child) { .ant-select:not(:first-child) {
margin-left: 10px; margin-left: 10px;

View File

@ -1,5 +1,5 @@
<template> <template>
<div v-bind="boxBindProps"> <div ref="containerRef" v-bind="boxBindProps">
<!-- 全屏按钮 --> <!-- 全屏按钮 -->
<a-icon v-if="fullScreen" class="full-screen-icon" :type="fullScreenIcon" @click="onToggleFullScreen" /> <a-icon v-if="fullScreen" class="full-screen-icon" :type="fullScreenIcon" @click="onToggleFullScreen" />
<textarea ref="textarea" v-bind="getBindValue"></textarea> <textarea ref="textarea" v-bind="getBindValue"></textarea>
@ -45,6 +45,8 @@
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { isJsonObjectString } from '/@/utils/is.ts'; import { isJsonObjectString } from '/@/utils/is.ts';
//
import { useCodeHinting } from '../hooks/useCodeHinting';
export default defineComponent({ export default defineComponent({
name: 'JCodeEditor', name: 'JCodeEditor',
@ -61,9 +63,12 @@
zIndex: propTypes.any.def(999), zIndex: propTypes.any.def(999),
theme: propTypes.string.def('idea'), theme: propTypes.string.def('idea'),
language: propTypes.string.def(''), language: propTypes.string.def(''),
//
keywords: propTypes.array.def([]),
}, },
emits: ['change', 'update:value'], emits: ['change', 'update:value'],
setup(props, { emit }) { setup(props, { emit }) {
const containerRef = ref(null);
const { prefixCls } = useDesign('code-editer'); const { prefixCls } = useDesign('code-editer');
const CodeMirror = window.CodeMirror || _CodeMirror; const CodeMirror = window.CodeMirror || _CodeMirror;
const emitData = ref<object>(); const emitData = ref<object>();
@ -121,6 +126,10 @@
} }
return _props; return _props;
}); });
// update-begin--author:liaozhiyang---date:20230904---forQQYUN-5955online js
const { codeHintingMount, codeHintingRegistry } = useCodeHinting(CodeMirror, props.keywords, props.language);
codeHintingRegistry();
// update-end--author:liaozhiyang---date:20230904---forQQYUN-5955online js
/** /**
* 监听组件值 * 监听组件值
*/ */
@ -171,6 +180,9 @@
coder.on('change', onChange); coder.on('change', onChange);
// //
setValue(innerValue, false); setValue(innerValue, false);
// update-begin--author:liaozhiyang---date:20230904---forQQYUN-5955online js
codeHintingMount(coder);
// update-end--author:liaozhiyang---date:20230904---forQQYUN-5955online js
} }
// //
@ -206,6 +218,7 @@
} }
//update-end-author:taoyan date:2022-10-18 for: VUEN-2480bugonline vue3 8online js //update-end-author:taoyan date:2022-10-18 for: VUEN-2480bugonline vue3 8online js
return { return {
state, state,
textarea, textarea,
@ -215,7 +228,8 @@
isFullScreen, isFullScreen,
fullScreenIcon, fullScreenIcon,
onToggleFullScreen, onToggleFullScreen,
refresh refresh,
containerRef,
}; };
}, },
}); });
@ -295,4 +309,9 @@
border: 1px solid #ddd; border: 1px solid #ddd;
} }
} }
.CodeMirror-hints.idea {
z-index: 1001;
max-width: 600px;
max-height: 300px;
}
</style> </style>

View File

@ -11,7 +11,7 @@
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
const props = defineProps({ const props = defineProps({
value: propTypes.oneOfType([propTypes.string, propTypes.array]), value: propTypes.oneOfType([propTypes.string, propTypes.number, propTypes.array]),
length: propTypes.number.def(25), length: propTypes.number.def(25),
}); });
// //

View File

@ -37,7 +37,7 @@
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { getFileAccessHttpUrl, getRandom } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl, getHeaders, getRandom } from '/@/utils/common/compUtils';
import { uploadUrl } from '/@/api/common/api'; import { uploadUrl } from '/@/api/common/api';
import { getToken } from '/@/utils/auth'; import { getToken } from '/@/utils/auth';
@ -94,9 +94,7 @@
return path.substring(path.lastIndexOf('/') + 1); return path.substring(path.lastIndexOf('/') + 1);
}; };
//token //token
const headers = ref<object>({ const headers = getHeaders();
'X-Access-Token': getToken(),
});
// //
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
// //

View File

@ -125,7 +125,9 @@
// //
props.setFieldsValue && props.setFieldsValue(values); props.setFieldsValue && props.setFieldsValue(values);
// update-begin--author:liaozhiyang---date:20230831---forissues/5288popup // update-begin--author:liaozhiyang---date:20230831---forissues/5288popup
// update-begin--author:liaozhiyang---date:20230811---forissues/5213JPopupchange
emit('popUpChange', values); emit('popUpChange', values);
// update-end--author:liaozhiyang---date:20230811---forissues/5213JPopupchange
// update-begin--author:liaozhiyang---date:20230831---forissues/5288popup // update-begin--author:liaozhiyang---date:20230831---forissues/5288popup
} }

View File

@ -116,7 +116,7 @@
watch( watch(
() => props.dictOptions, () => props.dictOptions,
(val) => { (val) => {
if (val && val.length > 0) { if (val && val.length >= 0) {
options.value = [...val]; options.value = [...val];
} }
}, },

View File

@ -2,7 +2,7 @@
<template> <template>
<div> <div>
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" @change="handleChange"/> <JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" @change="handleChange"/>
<DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" /> <DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :multiple="multiple" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">

View File

@ -30,7 +30,7 @@
}, },
rowKey: { rowKey: {
type: String, type: String,
default: 'code', default: 'id',
}, },
params: { params: {
type: Object, type: Object,

View File

@ -2,7 +2,7 @@
<template> <template>
<div> <div>
<JSelectBiz @change="handleChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz> <JSelectBiz @change="handleChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs"></JSelectBiz>
<UserSelectModal :rowKey="rowKey" @register="regModal" @getSelectResult="setValue" v-bind="getBindValue"></UserSelectModal> <UserSelectModal :rowKey="rowKey" @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" :excludeUserIdList="excludeUserIdList"></UserSelectModal>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -37,6 +37,13 @@
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
//id
excludeUserIdList:{
type: Array,
default: () => [],
}
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
}, },
emits: ['options-change', 'change', 'update:value'], emits: ['options-change', 'change', 'update:value'],
setup(props, { emit }) { setup(props, { emit }) {
@ -84,6 +91,17 @@
} }
}); });
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
const excludeUserIdList = ref<any>([]);
/**
* 需要监听一下excludeUserIdList否则modal获取不到
*/
watch(()=>props.excludeUserIdList,(data)=>{
excludeUserIdList.value = data;
},{ immediate: true })
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
/** /**
* 打卡弹出框 * 打卡弹出框
*/ */
@ -141,6 +159,7 @@
regModal, regModal,
setValue, setValue,
handleOpen, handleOpen,
excludeUserIdList,
handleChange, handleChange,
}; };
}, },

View File

@ -17,7 +17,7 @@
<div class="ant-upload-text">{{ text }}</div> <div class="ant-upload-text">{{ text }}</div>
</div> </div>
</template> </template>
<a-button v-else-if="buttonVisible" :disabled="isMaxCount || disabled"> <a-button v-else-if="buttonVisible" :disabled="buttonDisabled">
<Icon icon="ant-design:upload-outlined" /> <Icon icon="ant-design:upload-outlined" />
<span>{{ text }}</span> <span>{{ text }}</span>
</a-button> </a-button>
@ -36,7 +36,7 @@
import { useAttrs } from '/@/hooks/core/useAttrs'; import { useAttrs } from '/@/hooks/core/useAttrs';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { UploadTypeEnum } from './upload.data'; import { UploadTypeEnum } from './upload.data';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl, getHeaders } from '/@/utils/common/compUtils';
import UploadItemActions from './components/UploadItemActions.vue'; import UploadItemActions from './components/UploadItemActions.vue';
const { createMessage, createConfirm } = useMessage(); const { createMessage, createConfirm } = useMessage();
@ -67,11 +67,11 @@
removeConfirm: propTypes.bool.def(false), removeConfirm: propTypes.bool.def(false),
beforeUpload: propTypes.func, beforeUpload: propTypes.func,
disabled: propTypes.bool.def(false), disabled: propTypes.bool.def(false),
//
replaceLastOne: propTypes.bool.def(false),
}); });
const headers = reactive({ const headers = getHeaders();
'X-Access-Token': getToken(),
});
const fileList = ref<any[]>([]); const fileList = ref<any[]>([]);
const uploadGoOn = ref<boolean>(true); const uploadGoOn = ref<boolean>(true);
// refs // refs
@ -80,6 +80,20 @@
const isMaxCount = computed(() => props.maxCount > 0 && fileList.value.length >= props.maxCount); const isMaxCount = computed(() => props.maxCount > 0 && fileList.value.length >= props.maxCount);
// //
const isImageMode = computed(() => props.fileType === UploadTypeEnum.image); const isImageMode = computed(() => props.fileType === UploadTypeEnum.image);
//
const buttonDisabled = computed(()=>{
if(props.disabled === true){
return true;
}
if(isMaxCount.value === true){
if(props.replaceLastOne === true){
return false
}else{
return true;
}
}
return false
});
// props attrs // props attrs
const bindProps = computed(() => { const bindProps = computed(() => {
//update-begin-author:liusq date:20220411 for: [issue/455]accept //update-begin-author:liusq date:20220411 for: [issue/455]accept
@ -311,7 +325,9 @@
return; return;
} }
} }
emitValue(newFileList); //update-begin---author:liusq ---date:20230914 for[issues/5327]UploadreturnUrlfalse'[object Object]' ------------
emitValue(JSON.stringify(newFileList));
//update-end---author:liusq ---date:20230914 for[issues/5327]UploadreturnUrlfalse'[object Object]' ------------
} }
} }
} }

View File

@ -11,6 +11,7 @@
@check="onCheck" @check="onCheck"
:fieldNames="fieldNames" :fieldNames="fieldNames"
:checkedKeys="checkedKeys" :checkedKeys="checkedKeys"
:multiple="multiple"
:checkStrictly="getCheckStrictly" :checkStrictly="getCheckStrictly"
/> />
<!--树操作部分--> <!--树操作部分-->
@ -39,6 +40,7 @@
import { BasicTree, TreeActionType } from '/@/components/Tree'; import { BasicTree, TreeActionType } from '/@/components/Tree';
import { useTreeBiz } from '/@/components/Form/src/jeecg/hooks/useTreeBiz'; import { useTreeBiz } from '/@/components/Form/src/jeecg/hooks/useTreeBiz';
import {propTypes} from "/@/utils/propTypes"; import {propTypes} from "/@/utils/propTypes";
import { omit } from 'lodash-es';
export default defineComponent({ export default defineComponent({
name: 'DeptSelectModal', name: 'DeptSelectModal',
@ -65,13 +67,14 @@
//update-begin-author:taoyan date:2022-10-28 for: //update-begin-author:taoyan date:2022-10-28 for:
let propValue = props.value === ''?[]:props.value; let propValue = props.value === ''?[]:props.value;
//update-begin-author:liusq date:2023-05-26 for: [issues/538]JSelectDept dynamicDisabled //update-begin-author:liusq date:2023-05-26 for: [issues/538]JSelectDept dynamicDisabled
const getBindValue = Object.assign({}, unref(props), unref(attrs), {value: propValue},{disabled: false}); let temp = Object.assign({}, unref(props), unref(attrs), {value: propValue},{disabled: false});
const getBindValue = omit(temp, 'multiple');
//update-end-author:liusq date:2023-05-26 for: [issues/538]JSelectDept dynamicDisabled //update-end-author:liusq date:2023-05-26 for: [issues/538]JSelectDept dynamicDisabled
//update-end-author:taoyan date:2022-10-28 for: //update-end-author:taoyan date:2022-10-28 for:
const queryUrl = getQueryUrl(); const queryUrl = getQueryUrl();
const [{ visibleChange, checkedKeys, getCheckStrictly, getSelectTreeData, onCheck, onLoadData, treeData, checkALL, expandAll, onSelect }] = const [{ visibleChange, checkedKeys, getCheckStrictly, getSelectTreeData, onCheck, onLoadData, treeData, checkALL, expandAll, onSelect }] =
useTreeBiz(treeRef, queryUrl, getBindValue); useTreeBiz(treeRef, queryUrl, getBindValue, props);
const searchInfo = ref(props.params); const searchInfo = ref(props.params);
const tree = ref([]); const tree = ref([]);
//treeNodekeytreeData //treeNodekeytreeData

View File

@ -78,7 +78,8 @@
canResize: false, canResize: false,
bordered: true, bordered: true,
size: 'small', size: 'small',
rowKey: 'code', //rowKey,
rowKey: props.rowKey,
}; };
const getBindValue = Object.assign({}, unref(props), unref(attrs), config); const getBindValue = Object.assign({}, unref(props), unref(attrs), config);
const [{ rowSelection, visibleChange, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows }] = useSelectBiz( const [{ rowSelection, visibleChange, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows }] = useSelectBiz(
@ -176,6 +177,7 @@
selectedTable, selectedTable,
selectRows, selectRows,
handleDeleteSelected, handleDeleteSelected,
searchInfo,
}; };
}, },
}); });

View File

@ -5,7 +5,7 @@
v-bind="$attrs" v-bind="$attrs"
@register="register" @register="register"
:title="modalTitle" :title="modalTitle"
width="900px" :width="showSelected ? '1200px' : '900px'"
wrapClassName="j-user-select-modal" wrapClassName="j-user-select-modal"
@ok="handleOk" @ok="handleOk"
destroyOnClose destroyOnClose
@ -24,6 +24,7 @@
:searchInfo="searchInfo" :searchInfo="searchInfo"
:rowSelection="rowSelection" :rowSelection="rowSelection"
:indexColumnProps="indexColumnProps" :indexColumnProps="indexColumnProps"
:afterFetch="afterFetch"
> >
<!-- update-begin-author:taoyan date:2022-5-25 for: VUEN-1112一对多 用户选择 未显示选择条数及清空 --> <!-- update-begin-author:taoyan date:2022-5-25 for: VUEN-1112一对多 用户选择 未显示选择条数及清空 -->
<template #tableTitle></template> <template #tableTitle></template>
@ -48,7 +49,7 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, unref, ref } from 'vue'; import { defineComponent, unref, ref, watch } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { getUserList } from '/@/api/common/api'; import { getUserList } from '/@/api/common/api';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
@ -72,6 +73,13 @@
type: String, type: String,
default: '选择用户', default: '选择用户',
}, },
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
//id
excludeUserIdList: {
type: Array,
default: [],
},
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
}, },
emits: ['register', 'getSelectResult'], emits: ['register', 'getSelectResult'],
setup(props, { emit, refs }) { setup(props, { emit, refs }) {
@ -107,6 +115,15 @@
getBindValue getBindValue
); );
const searchInfo = ref(props.params); const searchInfo = ref(props.params);
// update-begin--author:liaozhiyang---date:20230811---forissues/657
watch(rowSelection.selectedRowKeys, (newVal) => {
//update-begin---author:wangshuai ---date: 20230829 fornull------------
if(tableRef.value){
tableRef.value.setSelectedRowKeys(newVal);
}
//update-end---author:wangshuai ---date: 20230829 fornull------------
});
// update-end--author:liaozhiyang---date:20230811---forissues/657
//form //form
const formConfig = { const formConfig = {
baseColProps: { baseColProps: {
@ -210,6 +227,29 @@
}); });
} }
//update-begin---author:wangshuai ---date:20230703 forQQYUN-56855------------
/**
* 用户返回结果逻辑查询
*/
function afterFetch(record) {
let excludeList = props.excludeUserIdList;
if(!excludeList){
return record;
}
let arr:any[] = [];
//id
if(excludeList.length>0 && record && record.length>0){
for(let item of record){
if(excludeList.indexOf(item.id)<0){
arr.push({...item})
}
}
return arr;
}
return record;
}
//update-end---author:wangshuai ---date:20230703 forQQYUN-56855------------
return { return {
//config, //config,
handleOk, handleOk,
@ -227,6 +267,7 @@
handleDeleteSelected, handleDeleteSelected,
tableScroll, tableScroll,
tableRef, tableRef,
afterFetch,
}; };
}, },
}); });

View File

@ -0,0 +1,232 @@
<template>
<div>
<div @click="showModal" :class="disabled ? 'select-input disabled-select' : 'select-input'">
<template v-if="selectedList.length > 0">
<template v-for="(item, index) in selectedList">
<SelectedUserItem v-if="index < maxCount" :info="item" @unSelect="unSelect" query />
</template>
</template>
<span v-else style="height: 30px; line-height: 30px; display: inline-block; margin-left: 7px; color: #bfbfbf">请选择</span>
<div v-if="ellipsisInfo.status" class="user-selected-item">
<div class="user-select-ellipsis">
<span style="color: red">+{{ ellipsisInfo.count }}...</span>
</div>
</div>
</div>
<RoleSelectModal :appId="currentAppId" :multi="multi" :getContainer="getContainer" title="选择组织角色" @register="registerRoleModal" @selected="onSelected" />
</div>
</template>
<script lang="ts">
import { useModal } from '/@/components/Modal';
import { defHttp } from '/@/utils/http/axios';
import { computed, ref, watch, watchEffect, defineComponent } from 'vue';
import RoleSelectModal from './RoleSelectModal.vue';
import SelectedUserItem from '../userSelect/SelectedUserItem.vue';
import { Form } from 'ant-design-vue';
import { useUserStore } from '/@/store/modules/user';
const maxCount = 2;
export default defineComponent({
name: 'RoleSelectInput',
components: {
RoleSelectModal,
SelectedUserItem,
},
props: {
disabled: {
type: Boolean,
default: false,
},
store: {
type: String,
default: 'id',
},
value: {
type: String,
default: '',
},
multi: {
type: Boolean,
default: false,
},
getContainer: {
type: Function,
default: null,
},
appId: {
type: String,
default: '',
},
},
emits: ['update:value', 'change'],
setup(props, { emit }) {
const formItemContext = Form.useInjectFormItemContext();
const selectedList = ref<any[]>([]);
const loading = ref(true);
const [registerRoleModal, { openModal: openRoleModal, closeModal: closeRoleModal }] = useModal();
function showModal(e) {
e.preventDefault();
e.stopPropagation();
let list = selectedList.value.map((item) => item.id);
openRoleModal(true, {
list,
});
}
const ellipsisInfo = computed(() => {
let max = maxCount;
let len = selectedList.value.length;
if (len > max) {
return { status: true, count: len - max };
} else {
return { status: false };
}
});
function unSelect(id) {
console.log('unSelectUser', id);
loading.value = false;
let arr = selectedList.value;
let index = -1;
for (let i = 0; i < arr.length; i++) {
if (arr[i].id == id) {
index = i;
break;
}
}
if (index >= 0) {
arr.splice(index, 1);
selectedList.value = arr;
onSelectedChange();
}
}
function onSelectedChange() {
let temp: any[] = [];
let arr = selectedList.value;
if (arr && arr.length > 0) {
temp = arr.map((k) => {
return k[props.store];
});
}
let str = temp.join(',');
emit('update:value', str);
emit('change', str);
formItemContext.onFieldChange();
console.log('选中数据', str);
}
function onSelected(_v, values) {
console.log('角色选择完毕:', values);
loading.value = false;
if (values && values.length > 0) {
selectedList.value = values;
} else {
selectedList.value = [];
}
onSelectedChange();
closeRoleModal();
}
//
const currentAppId = ref('');
const userStore = useUserStore();
watchEffect(() => {
let tenantId = userStore.getTenant;
let appId = props.appId;
if (appId) {
currentAppId.value = appId;
} else {
currentAppId.value = new Date().getTime() + '-' + tenantId;
}
});
watch(
() => props.value,
async (val) => {
if (val) {
if (loading.value === true) {
await getRoleList(val);
}
} else {
selectedList.value = [];
}
loading.value = true;
},
{ immediate: true }
);
/**
* 获取角色列表
* @param ids
*/
async function getRoleList(ids) {
const url = '/sys/role/listByTenant';
let params = {
[props.store]: ids,
pageSize: 200
};
// roleCode
if (props.store === 'code') {
params.roleCode = ids;
}
selectedList.value = [];
const data = await defHttp.get({ url, params }, { isTransformResponse: false });
console.log('getRoleList>>', data);
if (data.success) {
const { records } = data.result;
let arr: any[] = [];
if (records && records.length > 0) {
for (let item of records) {
arr.push({
id: item.id,
name: item.name || item.roleName,
code: item.roleCode,
checked: true,
selectType: 'sys_role',
});
}
}
selectedList.value = arr;
} else {
console.error(data.message);
}
}
return {
selectedList,
ellipsisInfo,
maxCount,
registerRoleModal,
closeRoleModal,
showModal,
onSelected,
unSelect,
currentAppId,
};
},
});
</script>
<style scoped lang="less">
.select-input {
padding: 0 5px;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 3px;
box-sizing: border-box;
display: flex;
color: #9e9e9e;
font-size: 14px;
flex-wrap: nowrap;
min-height: 32px;
overflow-x: hidden;
&.disabled-select {
cursor: not-allowed;
background-color: #f5f5f5 !important;
}
}
</style>

View File

@ -99,19 +99,25 @@
// //
const [register] = useModalInner(() => { const [register] = useModalInner((data) => {
let list = dataList.value; let list = dataList.value;
if(!list || list.length ==0 ){ if(!list || list.length ==0 ){
} }else{
for(let item of list){ let selectedIdList = data.list || [];
item.checked = false for(let item of list){
if(selectedIdList.indexOf(item.id)>=0){
item.checked = true;
}else{
item.checked = false;
}
}
} }
}); });
// //
function handleOk() { function handleOk() {
let arr = toRaw(selectedIdList.value); let arr = toRaw(selectedIdList.value);
emit('selected', arr); emit('selected', arr, toRaw(selectedList.value));
} }
const dataList = ref<any[]>([]); const dataList = ref<any[]>([]);
@ -161,6 +167,7 @@
arr.push({ arr.push({
id: item.id, id: item.id,
name: item.name || item.roleName, name: item.name || item.roleName,
code: item.roleCode,
selectType: props.type, selectType: props.type,
checked: false checked: false
}) })
@ -177,6 +184,13 @@
function onSelect(e, item) { function onSelect(e, item) {
prevent(e); prevent(e);
console.log('onselect'); console.log('onselect');
// false
if(props.multi === false){
let list = dataList.value;
for(let item of list){
item.checked = false;
}
}
item.checked = !item.checked; item.checked = !item.checked;
} }

View File

@ -14,6 +14,12 @@
<span style="width: 24px; height: 24px; line-height: 20px; margin-right: 3px; display: inline-block"> <span style="width: 24px; height: 24px; line-height: 20px; margin-right: 3px; display: inline-block">
<a-avatar v-if="info.avatar" :src="getFileAccessHttpUrl(info.avatar)" :size="24"></a-avatar> <a-avatar v-if="info.avatar" :src="getFileAccessHttpUrl(info.avatar)" :size="24"></a-avatar>
<a-avatar v-else-if="info.avatarIcon" class="ant-btn-primary" :size="24" >
<template #icon>
<Icon :icon=" 'ant-design:'+info.avatarIcon " style="font-size: 16px;margin-top: 4px"/>
</template>
</a-avatar>
<a-avatar v-else-if="info.selectType == 'sys_role'" :size="24" style="background-color: rgb(255, 173, 0);"> <a-avatar v-else-if="info.selectType == 'sys_role'" :size="24" style="background-color: rgb(255, 173, 0);">
<template #icon> <template #icon>
<team-outlined style="font-size: 16px"/> <team-outlined style="font-size: 16px"/>

View File

@ -8,6 +8,11 @@
</div> </div>
<div> <div>
<a-avatar v-if="item.avatar" :src="getFileAccessHttpUrl(item.avatar)"></a-avatar> <a-avatar v-if="item.avatar" :src="getFileAccessHttpUrl(item.avatar)"></a-avatar>
<a-avatar v-else-if="item.avatarIcon" class="ant-btn-primary">
<template #icon>
<Icon :icon=" 'ant-design:'+item.avatarIcon " style="margin-top: 4px;font-size: 24px;"/>
</template>
</a-avatar>
<a-avatar v-else> <a-avatar v-else>
<template #icon><UserOutlined /></template> <template #icon><UserOutlined /></template>
</a-avatar> </a-avatar>
@ -15,9 +20,10 @@
<div :style="nameStyle"> <div :style="nameStyle">
{{ item.realname }} {{ item.realname }}
</div> </div>
<div :style="departStyle"> <div :style="departStyle" class="ellipsis" :title="item.orgCodeTxt">
{{ item.orgCodeTxt }} {{ item.orgCodeTxt }}
</div> </div>
<div style="width: 1px"></div>
</div> </div>
</a-list-item> </a-list-item>
</template> </template>
@ -166,10 +172,16 @@
<style lang="less"> <style lang="less">
.user-select-user-info { .user-select-user-info {
display: flex; display: flex;
width: 100%;
> div { > div {
height: 36px; height: 36px;
line-height: 36px; line-height: 36px;
margin-right: 10px; margin-right: 10px;
} }
.ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
} }
</style> </style>

View File

@ -12,6 +12,9 @@
v-model:expandedKeys="expandedKeys" v-model:expandedKeys="expandedKeys"
@select="onSelect" @select="onSelect"
> >
<template #title="{ title, key }">
<FolderFilled style="color: #9e9e9e"/><span style="margin-left: 5px">{{ title }}</span>
</template>
</a-tree> </a-tree>
</div> </div>
</a-col> </a-col>
@ -27,11 +30,13 @@
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import UserList from './UserList.vue'; import UserList from './UserList.vue';
import { FolderFilled } from '@ant-design/icons-vue';
export default { export default {
name: 'DepartUserList', name: 'DepartUserList',
components: { components: {
UserList, UserList,
FolderFilled
}, },
props: { props: {
searchText: { searchText: {

View File

@ -2,7 +2,11 @@
<a-row> <a-row>
<a-col :span="12"> <a-col :span="12">
<div :style="containerStyle"> <div :style="containerStyle">
<a-tree v-if="treeData.length > 0" showIcon :treeData="treeData" :selectedKeys="selectedKeys" @select="onSelect"> </a-tree> <a-tree v-if="treeData.length > 0" showIcon :treeData="treeData" :selectedKeys="selectedKeys" @select="onSelect">
<template #title="{ title, key }">
<UserOutlined style="color: #9e9e9e"/><span style="margin-left: 5px">{{ title }}</span>
</template>
</a-tree>
</div> </div>
</a-col> </a-col>
<a-col :span="12" style="padding-left: 10px"> <a-col :span="12" style="padding-left: 10px">
@ -17,11 +21,13 @@
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import UserList from './UserList.vue'; import UserList from './UserList.vue';
import { UserOutlined } from '@ant-design/icons-vue';
export default { export default {
name: 'RoleUserList', name: 'RoleUserList',
components: { components: {
UserList, UserList,
UserOutlined
}, },
props: { props: {
searchText: { searchText: {

View File

@ -92,8 +92,10 @@
const APagination = Pagination; const APagination = Pagination;
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { computed, ref, toRaw } from 'vue'; import {computed, ref, toRaw, unref} from 'vue';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
import { mySelfData } from './useUserSelect'
export default { export default {
name: 'UserSelectModal', name: 'UserSelectModal',
components: { components: {
@ -120,6 +122,11 @@
type: Boolean, type: Boolean,
default: false, default: false,
}, },
//
inSuperQuery:{
type: Boolean,
default: false,
}
}, },
emits: ['selected', 'register'], emits: ['selected', 'register'],
setup(props, { emit }) { setup(props, { emit }) {
@ -154,6 +161,8 @@
if (props.izExcludeMy) { if (props.izExcludeMy) {
excludeUserIdList.value.push(userStore.getUserInfo.id); excludeUserIdList.value.push(userStore.getUserInfo.id);
} }
//
loadUserList();
}); });
// //
@ -215,14 +224,26 @@
} }
const data = await defHttp.get({ url, params }, { isTransformResponse: false }); const data = await defHttp.get({ url, params }, { isTransformResponse: false });
if (data.success) { if (data.success) {
const { records, total } = data.result; let { records, total } = data.result;
//id0
if(unref(excludeUserIdList) && unref(excludeUserIdList).length>0){
total = total - unref(excludeUserIdList).length;
}
totalRecord.value = total; totalRecord.value = total;
initCurrentUserData(records);
userDataList.value = records; userDataList.value = records;
} else { } else {
console.error(data.message); console.error(data.message);
} }
console.log('loadUserList', data); console.log('loadUserList', data);
} }
//
function initCurrentUserData(records) {
if(pageNo.value==1 && props.inSuperQuery === true){
records.unshift({...mySelfData})
}
}
/*--------------加载数据---------------*/ /*--------------加载数据---------------*/
/*--------------选中/取消选中---------------*/ /*--------------选中/取消选中---------------*/

View File

@ -19,7 +19,7 @@
<a-button v-if="showAddButton" shape="circle" @click="onShowModal"><PlusOutlined /></a-button> <a-button v-if="showAddButton" shape="circle" @click="onShowModal"><PlusOutlined /></a-button>
</div> </div>
<user-select-modal :multi="multi" :getContainer="getContainer" @register="registerModal" @selected="onSelected" :izExcludeMy="izExcludeMy"></user-select-modal> <user-select-modal :inSuperQuery="inSuperQuery" :multi="multi" :getContainer="getContainer" @register="registerModal" @selected="onSelected" :izExcludeMy="izExcludeMy"></user-select-modal>
</div> </div>
</template> </template>
@ -31,6 +31,7 @@
import UserSelectModal from './UserSelectModal.vue'; import UserSelectModal from './UserSelectModal.vue';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import SelectedUserItem from './SelectedUserItem.vue'; import SelectedUserItem from './SelectedUserItem.vue';
import { mySelfExpress, mySelfData } from './useUserSelect'
export default defineComponent({ export default defineComponent({
name: 'UserSelect', name: 'UserSelect',
@ -74,6 +75,11 @@
izExcludeMy:{ izExcludeMy:{
type: Boolean, type: Boolean,
default: false, default: false,
},
//
inSuperQuery:{
type: Boolean,
default: false,
} }
}, },
emits: ['update:value', 'change'], emits: ['update:value', 'change'],
@ -150,19 +156,41 @@
); );
async function getUserList(ids) { async function getUserList(ids) {
const url = '/sys/user/list'; let hasUserExpress = false;
let params = { let paramIds = ids;
[props.store]: ids, let idList = [];
};
selectedUserList.value = []; selectedUserList.value = [];
const data = await defHttp.get({ url, params }, { isTransformResponse: false }); if(ids){
if (data.success) { // update-begin-author:sunjianlei date:20230330 for:
const { records } = data.result; let tempArray = ids.split(',').map(s => s.trim()).filter(s => s != '');
selectedUserList.value = records; if (tempArray.includes(mySelfExpress)) {
} else { hasUserExpress = true;
console.error(data.message); idList = tempArray.filter(item => item != mySelfExpress);
} else {
idList = tempArray;
}
// update-end-author:sunjianlei date:20230330 for:
}
if(idList.length>0){
paramIds = idList.join(',')
const url = '/sys/user/list';
let params = {
[props.store]: paramIds,
};
const data = await defHttp.get({ url, params }, { isTransformResponse: false });
console.log('getUserList', data);
if (data.success) {
const { records } = data.result;
selectedUserList.value = records;
} else {
console.error(data.message);
}
}
if(hasUserExpress){
let temp = selectedUserList.value;
temp.push({...mySelfData})
} }
console.log('getUserList', data);
} }
const showAddButton = computed(() => { const showAddButton = computed(() => {

View File

@ -0,0 +1,11 @@
/**
*
*/
export const mySelfExpress = '#{sys_user_code}';
/**
*
*/
export const mySelfData = {
id: mySelfExpress, username: mySelfExpress, realname: '当前用户', avatarIcon: 'idcard-outlined', avatarColor: 'rgb(75 176 79)'
}

View File

@ -0,0 +1,69 @@
export const useCodeHinting = (CodeMirror, keywords, language) => {
const currentKeywords: any = [...keywords];
const codeHintingMount = (coder) => {
if (keywords.length) {
coder.setOption('mode', language);
setTimeout(() => {
coder!.on('cursorActivity', function () {
coder?.showHint({
completeSingle: false,
// container: containerRef.value
});
});
}, 1e3);
}
};
const codeHintingRegistry = () => {
const funcsHint = (cm, callback) => {
// 获取光标位置
const cur = cm.getCursor();
// 获取当前单词的信息
const token = cm.getTokenAt(cur);
const start = token.start;
const end = cur.ch;
const str = token.string;
if (str.length) {
const findIdx = (a, b) => a.toLowerCase().indexOf(b.toLowerCase());
let list = currentKeywords
.filter((item) => {
const index = findIdx(item, str);
return (index === 0 || index === 1) && (item.length != str.length || item.length - 1 != str.length);
})
.sort((a, b) => {
if (findIdx(a, str) < findIdx(b, str)) {
return -1;
} else {
return 1;
}
});
// 有点去掉点
// list = list.map(item => {
// if(item.indexOf(".") === 0){
// return item.substring(1);
// }
// return item;
// });
if (list.length === 1 && (list[0] === str || list[0].substring(1) === str)) {
list = [];
}
if (list.length) {
callback({
list: list,
from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end),
});
}
}
};
funcsHint.async = true;
funcsHint.supportsSelection = true;
// 自动补全
keywords.length && CodeMirror.registerHelper('hint', language, funcsHint);
};
return {
codeHintingRegistry,
codeHintingMount,
};
};

View File

@ -3,7 +3,7 @@ import { inject, reactive, ref, computed, unref, watch, nextTick } from 'vue';
import { TreeActionType } from '/@/components/Tree'; import { TreeActionType } from '/@/components/Tree';
import { listToTree } from '/@/utils/common/compUtils'; import { listToTree } from '/@/utils/common/compUtils';
export function useTreeBiz(treeRef, getList, props) { export function useTreeBiz(treeRef, getList, props, realProps) {
//接收下拉框选项 //接收下拉框选项
const selectOptions = inject('selectOptions', ref<Array<object>>([])); const selectOptions = inject('selectOptions', ref<Array<object>>([]));
//接收已选择的值 //接收已选择的值
@ -19,7 +19,7 @@ export function useTreeBiz(treeRef, getList, props) {
//是否是打开弹框模式 //是否是打开弹框模式
const openModal = ref(false); const openModal = ref(false);
// 是否开启父子关联,如果不可以多选,就始终取消父子关联 // 是否开启父子关联,如果不可以多选,就始终取消父子关联
const getCheckStrictly = computed(() => (props.multiple ? props.checkStrictly : true)); const getCheckStrictly = computed(() => (realProps.multiple ? props.checkStrictly : true));
// 是否是首次加载回显,只有首次加载,才会显示 loading // 是否是首次加载回显,只有首次加载,才会显示 loading
let isFirstLoadEcho = true; let isFirstLoadEcho = true;
@ -88,7 +88,7 @@ export function useTreeBiz(treeRef, getList, props) {
function onCheck(keys, info) { function onCheck(keys, info) {
if (props.checkable == true) { if (props.checkable == true) {
// 如果不能多选,就只保留最后一个选中的 // 如果不能多选,就只保留最后一个选中的
if (!props.multiple) { if (!realProps.multiple) {
if (info.checked) { if (info.checked) {
//update-begin-author:taoyan date:20220408 for: 单选模式下设定rowKey无法选中数据- //update-begin-author:taoyan date:20220408 for: 单选模式下设定rowKey无法选中数据-
checkedKeys.value = [info.node.eventKey]; checkedKeys.value = [info.node.eventKey];

View File

@ -147,6 +147,7 @@ export type ComponentType =
| 'LinkTableForQuery' | 'LinkTableForQuery'
| 'CascaderPcaForQuery' | 'CascaderPcaForQuery'
| 'UserSelect' | 'UserSelect'
| 'RoleSelect'
| 'RangeDate' | 'RangeDate'
| 'RangeNumber' | 'RangeNumber'
| 'linkRecordSelect' | 'linkRecordSelect'

View File

@ -4,14 +4,14 @@
<a-popover placement="bottomLeft" trigger="click" v-model="visible" :overlayClassName="`${prefixCls}-popover`"> <a-popover placement="bottomLeft" trigger="click" v-model="visible" :overlayClassName="`${prefixCls}-popover`">
<template #title> <template #title>
<div class="flex justify-between"> <div class="flex justify-between">
<a-input :placeholder="t('component.icon.search')" @change="debounceHandleSearchChange" allowClear /> <a-input :placeholder="t('component.icon.search')" v-model:value="searchIconValue" @change="debounceHandleSearchChange" allowClear />
</div> </div>
</template> </template>
<template #content> <template #content>
<div v-if="getPaginationList.length"> <div v-if="getPaginationList.length">
<ScrollContainer class="border border-solid border-t-0"> <ScrollContainer class="border border-solid border-t-0">
<ul class="flex flex-wrap px-2"> <ul class="flex flex-wrap px-2" style="padding-right: 0">
<li <li
v-for="icon in getPaginationList" v-for="icon in getPaginationList"
:key="icon" :key="icon"
@ -27,7 +27,7 @@
</ul> </ul>
</ScrollContainer> </ScrollContainer>
<div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize"> <div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize">
<a-pagination showLessItems size="small" :pageSize="pageSize" :total="getTotal" @change="handlePageChange" /> <a-pagination showLessItems v-model:current="current" :page-size-options="pageSizeOptions" size="small" v-model:pageSize="pageSize" v-model:total="getTotal" @change="handlePageChange" />
</div> </div>
</div> </div>
<template v-else <template v-else
@ -36,9 +36,9 @@
</template> </template>
<span class="cursor-pointer px-2 py-1 flex items-center" v-if="isSvgMode && currentSelect"> <span class="cursor-pointer px-2 py-1 flex items-center" v-if="isSvgMode && currentSelect">
<SvgIcon :name="currentSelect" /> <SvgIcon :name="currentSelect" @click="currentSelectClick"/>
</span> </span>
<Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else /> <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else @click="currentSelectClick"/>
</a-popover> </a-popover>
</template> </template>
</a-input> </a-input>
@ -85,7 +85,6 @@
const props = defineProps({ const props = defineProps({
value: propTypes.string, value: propTypes.string,
width: propTypes.string.def('100%'), width: propTypes.string.def('100%'),
pageSize: propTypes.number.def(140),
copy: propTypes.bool.def(false), copy: propTypes.bool.def(false),
mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'), mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
disabled: propTypes.bool.def(true), disabled: propTypes.bool.def(true),
@ -107,8 +106,16 @@
const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100); const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value); const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
const { createMessage } = useMessage(); const { createMessage } = useMessage();
//
const current = ref<number>(1);
//
const pageSize = ref<number>(140);
//
const pageSizeOptions = ref<any>(['10', '20', '50', '100', '140'])
//
const searchIconValue = ref<string>('');
const { getPaginationList, getTotal, setCurrentPage } = usePagination(currentList, props.pageSize); const { getPaginationList, getTotal, setCurrentPage, setPageSize } = usePagination(currentList, pageSize.value);
watchEffect(() => { watchEffect(() => {
currentSelect.value = props.value; currentSelect.value = props.value;
@ -122,7 +129,12 @@
} }
); );
function handlePageChange(page: number) { function handlePageChange(page: number,size: number) {
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
current.value = page;
pageSize.value = size;
setPageSize(size);
//update-end---author:wangshuai ---date:20230522 forissues/4947------------
setCurrentPage(page); setCurrentPage(page);
} }
@ -147,13 +159,30 @@
function handleSearchChange(e: ChangeEvent) { function handleSearchChange(e: ChangeEvent) {
const value = e.target.value; const value = e.target.value;
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
setCurrentPage(1);
current.value = 1;
//update-end---author:wangshuai ---date:20230522 forissues/4947------------
if (!value) { if (!value) {
setCurrentPage(1);
currentList.value = icons; currentList.value = icons;
return; return;
} }
currentList.value = icons.filter((item) => item.includes(value)); currentList.value = icons.filter((item) => item.includes(value));
} }
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
/**
* 图标点击重置页数
*/
function currentSelectClick() {
setCurrentPage(1);
setPageSize(140);
current.value = 1;
pageSize.value = 140;
currentList.value = icons;
searchIconValue.value = '';
}
//update-begin---author:wangshuai ---date:20230522 forissues/4947------------
</script> </script>
<style lang="less"> <style lang="less">
@prefix-cls: ~'@{namespace}-icon-picker'; @prefix-cls: ~'@{namespace}-icon-picker';
@ -164,7 +193,7 @@
} }
&-popover { &-popover {
width: 300px; width: 400px;
.ant-popover-inner-content { .ant-popover-inner-content {
padding: 0; padding: 0;

View File

@ -18,8 +18,9 @@
const { innerValue, row, originColumn, cellProps, handleChangeCommon } = useJVxeComponent(props); const { innerValue, row, originColumn, cellProps, handleChangeCommon } = useJVxeComponent(props);
const groupId = ref<string>('j-vxe-popup'); const groupId = ref<string>('j-vxe-popup');
const popupProps = computed(() => { const popupProps = computed(() => {
// update-begin--author:liaozhiyang---date:20231009---forissues/5371popup
return { return {
...cellProps, ...cellProps.value,
value: innerValue.value, value: innerValue.value,
field: originColumn.value.field || originColumn.value.key, field: originColumn.value.field || originColumn.value.key,
code: originColumn.value.popupCode, code: originColumn.value.popupCode,
@ -45,6 +46,7 @@
} }
}, },
}; };
// update-end--author:liaozhiyang---date:20231009---forissues/5371popup
}); });
// update-begin--author:liaozhiyang---date:20230811---forissues/675Popup // update-begin--author:liaozhiyang---date:20230811---forissues/675Popup
const handleFocus = () => { const handleFocus = () => {

View File

@ -10,7 +10,7 @@
import { useModalContext } from '../../Modal'; import { useModalContext } from '../../Modal';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated'; import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
import { getToken } from '/@/utils/auth'; import { getTenantId, getToken } from '/@/utils/auth';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined; type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
@ -23,6 +23,7 @@
}, },
emits: ['change', 'get', 'update:value'], emits: ['change', 'get', 'update:value'],
setup(props, { attrs, emit }) { setup(props, { attrs, emit }) {
console.log("---Markdown---初始化---")
const wrapRef = ref<ElRef>(null); const wrapRef = ref<ElRef>(null);
const vditorRef = ref(null) as Ref<Nullable<Vditor>>; const vditorRef = ref(null) as Ref<Nullable<Vditor>>;
const initedRef = ref(false); const initedRef = ref(false);
@ -78,6 +79,7 @@
//update-begin-author:taoyan date:2022-5-24 for: VUEN-1090 markdown //update-begin-author:taoyan date:2022-5-24 for: VUEN-1090 markdown
const uploadUrl = `${window._CONFIG['domianURL']}/sys/common/upload`; const uploadUrl = `${window._CONFIG['domianURL']}/sys/common/upload`;
const token = getToken(); const token = getToken();
const tenantId = getTenantId() ? getTenantId() : '0';
function formatResult(files, responseText): string { function formatResult(files, responseText): string {
let data: any = JSON.parse(responseText); let data: any = JSON.parse(responseText);
// {"success":true,"message":"markdown/aa_1653391146501.png","code":0,"result":null,"timestamp":1653391146501}' // {"success":true,"message":"markdown/aa_1653391146501.png","code":0,"result":null,"timestamp":1653391146501}'
@ -126,6 +128,7 @@
setHeaders() { setHeaders() {
return { return {
'X-Access-Token': token as string, 'X-Access-Token': token as string,
'X-Tenant-Id': tenantId,
}; };
}, },
format(files, response) { format(files, response) {

View File

@ -69,7 +69,7 @@
components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader }, components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
inheritAttrs: false, inheritAttrs: false,
props: basicProps, props: basicProps,
emits: ['visible-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible'], emits: ['visible-change', 'height-change', 'cancel', 'ok', 'register', 'update:visible', 'fullScreen'],
setup(props, { emit, attrs , slots}) { setup(props, { emit, attrs , slots}) {
const visibleRef = ref(false); const visibleRef = ref(false);
const propsRef = ref<Partial<ModalProps> | null>(null); const propsRef = ref<Partial<ModalProps> | null>(null);
@ -234,6 +234,12 @@
} }
//update-end-author:taoyan date:2022-7-18 for: modal slot //update-end-author:taoyan date:2022-7-18 for: modal slot
// update-begin--author:liaozhiyang---date:20230804---forQQYUN-5866
watch(fullScreenRef,(val)=>{
emit('fullScreen',val);
});
// update-begin--author:liaozhiyang---date:20230804---forQQYUN-5866
return { return {
handleCancel, handleCancel,
getBindValue, getBindValue,

View File

@ -31,7 +31,9 @@
<!-- 增加对antdv3.x兼容 --> <!-- 增加对antdv3.x兼容 -->
<template #bodyCell="data"> <template #bodyCell="data">
<!-- update-begin--author:liaozhiyang---date:220230717---forissues-179antd3 一些警告以及报错(针对表格) --> <!-- update-begin--author:liaozhiyang---date:220230717---forissues-179antd3 一些警告以及报错(针对表格) -->
<!-- update-begin--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<template v-if="data.column?.slotsBak?.customRender"> <template v-if="data.column?.slotsBak?.customRender">
<!-- update-end--author:liusq---date:20230921---forissues/770slotsBak异常报错的问题,增加判断column是否存在 -->
<slot :name="data.column.slotsBak.customRender" v-bind="data || {}"></slot> <slot :name="data.column.slotsBak.customRender" v-bind="data || {}"></slot>
</template> </template>
<template v-else> <template v-else>
@ -46,7 +48,7 @@
<script lang="ts"> <script lang="ts">
import type { BasicTableProps, TableActionType, SizeType, ColumnChangeParam, BasicColumn } from './types/table'; import type { BasicTableProps, TableActionType, SizeType, ColumnChangeParam, BasicColumn } from './types/table';
import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect } from 'vue'; import { defineComponent, ref, computed, unref, toRaw, inject, watchEffect, watch, onUnmounted, onMounted } from 'vue';
import { Table } from 'ant-design-vue'; import { Table } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form/index'; import { BasicForm, useForm } from '/@/components/Form/index';
import { PageWrapperFixedHeightKey } from '/@/components/Page/injectionKey'; import { PageWrapperFixedHeightKey } from '/@/components/Page/injectionKey';
@ -265,6 +267,10 @@
delete propsData.rowSelection delete propsData.rowSelection
// update-end--author:sunjianlei---date:220230630---forQQYUN-5571 // update-end--author:sunjianlei---date:220230630---forQQYUN-5571
// update-begin--author:liaozhiyang---date:20230919---forQQYUN-6387
!propsData.isTreeTable && delete propsData.expandIconColumnIndex;
propsData.expandedRowKeys === null && delete propsData.expandedRowKeys;
// update-end--author:liaozhiyang---date:20230919---forQQYUN-6387
propsData = omit(propsData, ['class', 'onChange']); propsData = omit(propsData, ['class', 'onChange']);
return propsData; return propsData;
}); });
@ -369,6 +375,39 @@
emit('register', tableAction, formActions); emit('register', tableAction, formActions);
// update-begin--author:liaozhiyang---date:20230804---forissues/638tabletable
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---forissues/638tabletable
return { return {
tableElRef, tableElRef,
getBindValues, getBindValues,

View File

@ -21,6 +21,11 @@
</template> </template>
<Dropdown :trigger="['hover']" :dropMenuList="getDropdownList" popconfirm v-if="dropDownActions && getDropdownList.length > 0"> <Dropdown :trigger="['hover']" :dropMenuList="getDropdownList" popconfirm v-if="dropDownActions && getDropdownList.length > 0">
<slot name="more"></slot> <slot name="more"></slot>
<!-- 设置插槽 -->
<template v-slot:[item.slot] v-for="(item, index) in getDropdownSlotList" :key="`${index}-${item.label}`">
<slot :name="item.slot"></slot>
</template>
<a-button type="link" size="small" v-if="!$slots.more"> <Icon icon="mdi-light:chevron-down"></Icon> </a-button> <a-button type="link" size="small" v-if="!$slots.more"> <Icon icon="mdi-light:chevron-down"></Icon> </a-button>
</Dropdown> </Dropdown>
</div> </div>
@ -116,6 +121,9 @@
}); });
}); });
const getDropdownSlotList = computed((): any[] => {
return unref(getDropdownList).filter((item) => item.slot);
});
const getAlign = computed(() => { const getAlign = computed(() => {
const columns = (table as TableActionType)?.getColumns?.() || []; const columns = (table as TableActionType)?.getColumns?.() || [];
const actionColumn = columns.find((item) => item.flag === ACTION_COLUMN_FLAG); const actionColumn = columns.find((item) => item.flag === ACTION_COLUMN_FLAG);
@ -139,7 +147,7 @@
isInButton && e.stopPropagation(); isInButton && e.stopPropagation();
} }
return { prefixCls, getActions, getDropdownList, getAlign, onCellClick, getTooltip }; return { prefixCls, getActions, getDropdownList, getDropdownSlotList, getAlign, onCellClick, getTooltip };
}, },
}); });
</script> </script>

View File

@ -1,6 +1,7 @@
import type { BasicColumn, BasicTableProps, CellFormat, GetColumnsParams } from '../types/table'; import type { BasicColumn, BasicTableProps, CellFormat, GetColumnsParams } from '../types/table';
import type { PaginationProps } from '../types/pagination'; import type { PaginationProps } from '../types/pagination';
import type { ComputedRef } from 'vue'; import type { ComputedRef } from 'vue';
import { Table } from 'ant-design-vue';
import { computed, Ref, ref, toRaw, unref, watch, reactive } from 'vue'; import { computed, Ref, ref, toRaw, unref, watch, reactive } from 'vue';
import { renderEditCell } from '../components/editable'; import { renderEditCell } from '../components/editable';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
@ -9,7 +10,7 @@ import { isArray, isBoolean, isFunction, isMap, isString } from '/@/utils/is';
import { cloneDeep, isEqual } from 'lodash-es'; import { cloneDeep, isEqual } from 'lodash-es';
import { formatToDate } from '/@/utils/dateUtil'; import { formatToDate } from '/@/utils/dateUtil';
import { ACTION_COLUMN_FLAG, DEFAULT_ALIGN, INDEX_COLUMN_FLAG, PAGE_SIZE } from '../const'; import { ACTION_COLUMN_FLAG, DEFAULT_ALIGN, INDEX_COLUMN_FLAG, PAGE_SIZE } from '../const';
import { CUS_SEL_COLUMN_KEY } from "./useCustomSelection"; import { CUS_SEL_COLUMN_KEY } from './useCustomSelection';
function handleItem(item: BasicColumn, ellipsis: boolean) { function handleItem(item: BasicColumn, ellipsis: boolean) {
const { key, dataIndex, children } = item; const { key, dataIndex, children } = item;
@ -145,7 +146,7 @@ export function useColumns(
const viewColumns = sortFixedColumn(unref(getColumnsRef)); const viewColumns = sortFixedColumn(unref(getColumnsRef));
const columns = cloneDeep(viewColumns); const columns = cloneDeep(viewColumns);
return columns const result = columns
.filter((column) => { .filter((column) => {
return hasPermission(column.auth) && isIfShow(column); return hasPermission(column.auth) && isIfShow(column);
}) })
@ -184,6 +185,22 @@ export function useColumns(
} }
return reactive(column); return reactive(column);
}); });
// update-begin--author:liaozhiyang---date:20230919---for【QQYUN-6387】展开写法去掉报错
if (propsRef.value.expandedRowKeys) {
let index = 0;
const findIndex = result.findIndex((item) => item.key === CUS_SEL_COLUMN_KEY);
if (findIndex != -1) {
index = findIndex + 1;
}
const next: any = result[index + 1];
let expand = Table.EXPAND_COLUMN;
if (next && (next['fixed'] == true || next['fixed'] == 'left')) {
expand = Object.assign(expand, { fixed: 'left' });
}
result.splice(index, 0, expand);
}
return result;
// update-end--author:liaozhiyang---date:20230919---for【QQYUN-6387】展开写法去掉报错
}); });
watch( watch(
@ -260,6 +277,9 @@ export function useColumns(
columns = columns.filter((item) => item.key !== CUS_SEL_COLUMN_KEY); columns = columns.filter((item) => item.key !== CUS_SEL_COLUMN_KEY);
// update-enb--author:sunjianlei---date:220230630---for【QQYUN-5571】自封装选择列解决数据行选择卡顿问题 // 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) { if (sort) {
columns = sortFixedColumn(columns); columns = sortFixedColumn(columns);
} }

View File

@ -108,6 +108,8 @@ export const basicProps = {
}, },
minHeight: propTypes.number, minHeight: propTypes.number,
maxHeight: propTypes.number, maxHeight: propTypes.number,
// 统一设置列最大宽度
maxColumnWidth: propTypes.number,
dataSource: { dataSource: {
type: Array as PropType<Recordable[]>, type: Array as PropType<Recordable[]>,
default: null, default: null,
@ -136,4 +138,8 @@ export const basicProps = {
type: String as PropType<SizeType>, type: String as PropType<SizeType>,
default: DEFAULT_SIZE, default: DEFAULT_SIZE,
}, },
expandedRowKeys: {
type: Array,
default: null,
},
}; };

View File

@ -189,6 +189,8 @@ export interface BasicTableProps<T = any> {
formConfig?: Partial<FormProps>; formConfig?: Partial<FormProps>;
// 列配置 // 列配置
columns: BasicColumn[]; columns: BasicColumn[];
// 统一设置列最大宽度
maxColumnWidth?: number;
// 是否显示序号列 // 是否显示序号列
showIndexColumn?: boolean; showIndexColumn?: boolean;
// 序号列配置 // 序号列配置
@ -317,7 +319,7 @@ export interface BasicTableProps<T = any> {
* you need to add style .ant-table td { white-space: nowrap; }. * you need to add style .ant-table td { white-space: nowrap; }.
* @type object * @type object
*/ */
scroll?: { x?: number | true; y?: number }; scroll?: { x?: number | true | 'max-content'; y?: number };
/** /**
* Whether to show table header * Whether to show table header

View File

@ -24,7 +24,7 @@
import { useGlobSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { getToken } from '/@/utils/auth'; import { getToken } from '/@/utils/auth';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl, getHeaders } from '/@/utils/common/compUtils';
export default defineComponent({ export default defineComponent({
name: 'TinymceImageUpload', name: 'TinymceImageUpload',
@ -44,7 +44,7 @@
//update-begin-author:taoyan date:2022-5-13 for: //update-begin-author:taoyan date:2022-5-13 for:
function getheader() { function getheader() {
return { 'X-Access-Token': getToken() }; return getHeaders();
} }
function getBizData() { function getBizData() {

View File

@ -4,17 +4,16 @@
// colorpicker/contextmenu/textcolor plugin is now built in to the core editor, please remove it from your editor configuration // colorpicker/contextmenu/textcolor plugin is now built in to the core editor, please remove it from your editor configuration
export const plugins = [ export const plugins = [
'advlist anchor autolink autosave code codesample directionality fullscreen hr insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus template textpattern visualblocks visualchars wordcount image', 'advlist anchor autolink autosave code codesample directionality fullscreen hr insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace tabfocus template textpattern visualblocks visualchars wordcount image',
]; ];
export const toolbar = export const toolbar =
'fullscreen code preview | undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft aligncenter alignright alignjustify | outdent indent lineheight|subscript superscript blockquote| numlist bullist checklist | forecolor backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | insertfile image media pageembed link anchor codesample insertdatetime hr| a11ycheck ltr rtl'; 'fullscreen code preview | undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft aligncenter alignright alignjustify | outdent indent lineheight|subscript superscript blockquote| numlist bullist checklist | forecolor backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | insertfile image media pageembed link anchor codesample insertdatetime hr| a11ycheck ltr rtl';
export const simplePlugins = ['lists image link media table textcolor wordcount contextmenu fullscreen']; export const simplePlugins = 'lists image link fullscreen';
export const simpleToolbar = [ export const simpleToolbar = [
'undo redo formatselect bold italic alignleft aligncenter alignright alignjustify bullist numlist outdent indent', 'undo redo formatselect bold italic alignleft aligncenter alignright alignjustify bullist numlist outdent indent lists image link fullscreen',
'lists link unlink image media table removeformat fullscreen',
]; ];
export const menubar = 'file edit insert view format table'; export const menubar = 'file edit insert view format table';

View File

@ -27,27 +27,20 @@
}, },
setup(props) { setup(props) {
const chartRef = ref<HTMLDivElement | null>(null); const chartRef = ref<HTMLDivElement | null>(null);
const { setOptions, echarts } = useECharts(chartRef as Ref<HTMLDivElement>); const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
const option = reactive({ const option = reactive({
title: { title: {
text: '基础雷达图', text: '基础雷达图',
}, },
legend: { legend: {
data: ['文综', '理综'], data: ['文综'],
}, },
radar: { radar: {
indicator: [ indicator: [{ name: '历史' }, { name: '地理' }, { name: '生物' }, { name: '化学' }, { name: '物理' }, { name: '政治' }],
{ name: '历史', max: 100 },
{ name: '地理', max: 110 },
{ name: '生物', max: 120 },
{ name: '化学', max: 130 },
{ name: '物理', max: 140 },
{ name: '政治', max: 150 },
],
}, },
series: [ series: [
{ {
type: 'radar', type: 'radar' as 'custom',
data: [ data: [
{ {
value: [82, 70, 60, 55, 90, 66], value: [82, 70, 60, 55, 90, 66],
@ -86,7 +79,7 @@
//data //data
data.push(obj); data.push(obj);
}); });
option.radar.indicator = indicator; option.radar.axisName = indicator;
option.series[0]['data'] = data; option.series[0]['data'] = data;
setOptions(option); setOptions(option);
} }

View File

@ -6,7 +6,7 @@
import { useECharts } from '/@/hooks/web/useECharts'; import { useECharts } from '/@/hooks/web/useECharts';
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
export default defineComponent({ export default defineComponent({
name: 'line', name: 'single-line',
props: { props: {
chartData: { chartData: {
type: Array, type: Array,

View File

@ -7,9 +7,6 @@
<span class="inner-button"><upload-outlined />上传</span> <span class="inner-button"><upload-outlined />上传</span>
</a-upload> </a-upload>
</span> </span>
<span class="j-icon">
<span class="inner-button"><folder-outlined />从文件库选择?</span>
</span>
</template> </template>
</a-alert> </a-alert>
@ -72,6 +69,7 @@
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
import { saveOne, useCommentWithFile, useFileList } from './useComment'; import { saveOne, useCommentWithFile, useFileList } from './useComment';
import {useModal} from "/@/components/Modal";
import { Tooltip } from 'ant-design-vue'; import { Tooltip } from 'ant-design-vue';
import HistoryFileList from './HistoryFileList.vue'; import HistoryFileList from './HistoryFileList.vue';
@ -95,6 +93,7 @@
}, },
setup(props) { setup(props) {
// const { createMessage } = useMessage(); // const { createMessage } = useMessage();
const [registerModel, { openModal }] = useModal();
const { userInfo } = useUserStore(); const { userInfo } = useUserStore();
const dataList = ref([]); const dataList = ref([]);
const commentId = ref(''); const commentId = ref('');
@ -141,6 +140,19 @@
await loadFileList(); await loadFileList();
} }
function showFileModal() {
openModal(true, {})
}
function onSelectFileOk(temp) {
let arr = selectFileList.value;
arr.push({
...temp,
exist: true
})
selectFileList.value = arr;
}
return { return {
selectFileList, selectFileList,
beforeUpload, beforeUpload,
@ -153,7 +165,11 @@
queding, queding,
buttonLoading, buttonLoading,
getImageAsBackground, getImageAsBackground,
viewImage viewImage,
registerModel,
showFileModal,
onSelectFileOk,
}; };
}, },
}; };

View File

@ -107,7 +107,9 @@
props: { props: {
tableName: propTypes.string.def(''), tableName: propTypes.string.def(''),
dataId: propTypes.string.def(''), dataId: propTypes.string.def(''),
datetime: propTypes.number.def(1) datetime: propTypes.number.def(1),
//
otherHeight: propTypes.number.def(0),
}, },
setup(props) { setup(props) {
const { createMessage } = useMessage(); const { createMessage } = useMessage();
@ -163,8 +165,9 @@
const commentHeight = ref(300); const commentHeight = ref(300);
const allHeight = ref(300); const allHeight = ref(300);
onMounted(() => { onMounted(() => {
commentHeight.value = window.innerHeight - 57 - 46 - 70 - 160; let otherHeight = props.otherHeight || 0;
allHeight.value = window.innerHeight - 57 - 46 - 53 -20; commentHeight.value = window.innerHeight - 57 - 46 - 70 - 160 - otherHeight;
allHeight.value = window.innerHeight - 57 - 46 - 53 -20 - otherHeight;
}); });
/** /**
@ -247,7 +250,7 @@
} }
}); });
// const storageEmojiIndex = inject('$globalEmojiIndex') //const storageEmojiIndex = inject('$globalEmojiIndex')
const storageEmojiIndex = getGloablEmojiIndex() const storageEmojiIndex = getGloablEmojiIndex()
const { getHtml } = useEmojiHtml(storageEmojiIndex); const { getHtml } = useEmojiHtml(storageEmojiIndex);
const bottomCommentRef = ref() const bottomCommentRef = ref()

View File

@ -2,7 +2,7 @@
<div class="comment-tabs-warp" v-if="showStatus"> <div class="comment-tabs-warp" v-if="showStatus">
<a-tabs @change="handleChange" :animated="false"> <a-tabs @change="handleChange" :animated="false">
<a-tab-pane v-if="showComment" tab="评论" key="comment" class="comment-list-tab"> <a-tab-pane v-if="showComment" tab="评论" key="comment" class="comment-list-tab">
<comment-list :tableName="tableName" :dataId="dataId" :datetime="datetime1"></comment-list> <comment-list :tableName="tableName" :dataId="dataId" :datetime="datetime1" :otherHeight="otherHeight"></comment-list>
</a-tab-pane> </a-tab-pane>
<a-tab-pane v-if="showFiles" tab="文件" key="file"> <a-tab-pane v-if="showFiles" tab="文件" key="file">
<comment-files :tableName="tableName" :dataId="dataId" :datetime="datetime2"></comment-files> <comment-files :tableName="tableName" :dataId="dataId" :datetime="datetime2"></comment-files>
@ -41,6 +41,8 @@
showFiles: propTypes.bool.def(true), showFiles: propTypes.bool.def(true),
// //
showDataLog: propTypes.bool.def(true), showDataLog: propTypes.bool.def(true),
//
otherHeight: propTypes.number.def(0),
}, },
setup(props) { setup(props) {
const showStatus = computed(() => { const showStatus = computed(() => {

View File

@ -9,7 +9,7 @@
<edit-outlined v-else/> <edit-outlined v-else/>
</span> </span>
<span class="log-item-content"> <span class="log-item-content">
<a @click="handleClickPerson">@{{item.createBy}}</a> <a @click="handleClickPerson">@{{item.createName || item.createBy}}</a>
{{ item.dataContent }} {{ item.dataContent }}
</span> </span>
<div class="log-item-date"> <div class="log-item-date">

View File

@ -1,6 +1,6 @@
<template> <template>
<div :class="{'comment-active': commentActive}" style="border: 1px solid #eee; margin: 0; position: relative" @click="handleClickBlank"> <div :class="{'comment-active': commentActive}" style="border: 1px solid #eee; margin: 0; position: relative" @click="handleClickBlank">
<textarea ref="commentRef" v-model="myComment" @input="handleCommentChange" @blur="handleBlur" class="comment-content" :rows="3" placeholder="请输入你的评论,可以@成员" /> <textarea ref="commentRef" v-model="myComment" @keyup.enter="sendComment" @input="handleCommentChange" @blur="handleBlur" class="comment-content" :rows="3" placeholder="请输入你的评论,可以@成员" />
<div class="comment-content comment-html-shower" :class="{'no-content':noConent, 'top-div': showHtml, 'bottom-div': showHtml == false }" v-html="commentHtml" @click="handleClickHtmlShower"></div> <div class="comment-content comment-html-shower" :class="{'no-content':noConent, 'top-div': showHtml, 'bottom-div': showHtml == false }" v-html="commentHtml" @click="handleClickHtmlShower"></div>
<div class="comment-buttons" v-if="commentActive"> <div class="comment-buttons" v-if="commentActive">
<div style="cursor: pointer"> <div style="cursor: pointer">
@ -53,7 +53,7 @@
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import UploadChunk from './UploadChunk.vue'; import UploadChunk from './UploadChunk.vue';
import 'emoji-mart-vue-fast/css/emoji-mart.css'; import 'emoji-mart-vue-fast/css/emoji-mart.css';
import { getGloablEmojiIndex, useEmojiHtml } from './useComment'; import {getGloablEmojiIndex, useEmojiHtml} from './useComment';
const optionsName = { const optionsName = {
categories: { categories: {

View File

@ -7,9 +7,6 @@
<span class="inner-button"><upload-outlined />上传</span> <span class="inner-button"><upload-outlined />上传</span>
</a-upload> </a-upload>
</span> </span>
<span class="j-icon">
<span class="inner-button"><folder-outlined />从文件库选择?</span>
</span>
</template> </template>
</a-alert> </a-alert>
@ -53,6 +50,7 @@
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -60,6 +58,8 @@
import { useFileList } from './useComment'; import { useFileList } from './useComment';
import { Tooltip } from 'ant-design-vue'; import { Tooltip } from 'ant-design-vue';
import { UploadOutlined, FolderOutlined, DownloadOutlined, PaperClipOutlined, DeleteOutlined } from '@ant-design/icons-vue'; import { UploadOutlined, FolderOutlined, DownloadOutlined, PaperClipOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import {useModal} from "/@/components/Modal";
export default { export default {
name: 'UploadChunk', name: 'UploadChunk',
components: { components: {
@ -80,6 +80,8 @@
setup(_p, {emit}) { setup(_p, {emit}) {
const { selectFileList, beforeUpload, handleRemove, getBackground, isImage, getImageSrc, viewImage } = useFileList(); const { selectFileList, beforeUpload, handleRemove, getBackground, isImage, getImageSrc, viewImage } = useFileList();
const [registerModel, { openModal }] = useModal();
function getUploadFileList() { function getUploadFileList() {
let list = toRaw(selectFileList.value); let list = toRaw(selectFileList.value);
console.log(list); console.log(list);
@ -99,6 +101,19 @@
} }
}); });
function showFileModal() {
openModal(true, {})
}
function onSelectFileOk(temp) {
let arr = selectFileList.value;
arr.push({
...temp,
exist: true
})
selectFileList.value = arr;
}
return { return {
selectFileList, selectFileList,
beforeUpload, beforeUpload,
@ -108,7 +123,10 @@
clear, clear,
isImage, isImage,
getImageSrc, getImageSrc,
viewImage viewImage,
registerModel,
showFileModal,
onSelectFileOk
}; };
}, },
}; };

View File

@ -11,6 +11,7 @@ import other from '/@/assets/svg/fileType/other.svg';
import pdf from '/@/assets/svg/fileType/pdf.svg'; import pdf from '/@/assets/svg/fileType/pdf.svg';
import txt from '/@/assets/svg/fileType/txt.svg'; import txt from '/@/assets/svg/fileType/txt.svg';
import word from '/@/assets/svg/fileType/word.svg'; import word from '/@/assets/svg/fileType/word.svg';
import image from '/@/assets/svg/fileType/image.png';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { createImgPreview } from '/@/components/Preview'; import { createImgPreview } from '/@/components/Preview';
import data from "emoji-mart-vue-fast/data/apple.json"; import data from "emoji-mart-vue-fast/data/apple.json";
@ -171,11 +172,28 @@ export function useCommentWithFile(props) {
}); });
} }
/**
* QQYUN-4310
* @param file
*/
async function saveSysFormFile(file){
let url = '/sys/comment/addFile';
let params = {
fileId: file.id,
commentId: uploadData.commentId
}
await defHttp.post({url, params}, { joinParamsToUrl: true, isTransformResponse: false });
}
async function uploadFiles(fileList) { async function uploadFiles(fileList) {
if (fileList && fileList.length > 0) { if (fileList && fileList.length > 0) {
for (let i = 0; i < fileList.length; i++) { for (let i = 0; i < fileList.length; i++) {
let file = toRaw(fileList[i]); let file = toRaw(fileList[i]);
await uploadOne(file.originFileObj); if(file.exist === true){
await saveSysFormFile(file);
}else{
await uploadOne(file.originFileObj);
}
} }
} }
} }
@ -211,6 +229,7 @@ export function useFileList() {
txt: txt, txt: txt,
docx: word, docx: word,
doc: word, doc: word,
image
}; };
function getBackground(item) { function getBackground(item) {
console.log('获取文件背景图', item); console.log('获取文件背景图', item);
@ -231,6 +250,10 @@ export function useFileList() {
} }
} }
function getImageTypeIcon() {
return typeMap['image'];
}
function getBase64(file, id){ function getBase64(file, id){
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
//声明js的文件流 //声明js的文件流
@ -298,6 +321,9 @@ export function useFileList() {
} }
function getImageSrc(file){ function getImageSrc(file){
if(file.exist){
return getFileAccessHttpUrl(file.url);
}
if(isImage(file)){ if(isImage(file)){
let id = file.uid; let id = file.uid;
if(id){ if(id){
@ -318,7 +344,12 @@ export function useFileList() {
* @param item * @param item
*/ */
function getImageAsBackground(item){ function getImageAsBackground(item){
let url = getImageSrc(item); let url;
if(item.exist){
url = getFileAccessHttpUrl(item.url);
}else{
url = getImageSrc(item);
}
if(url){ if(url){
return { return {
"backgroundImage": "url('"+url+"')" "backgroundImage": "url('"+url+"')"
@ -373,7 +404,8 @@ export function useFileList() {
isImage, isImage,
getImageSrc, getImageSrc,
getImageAsBackground, getImageAsBackground,
viewImage viewImage,
getImageTypeIcon
}; };
} }

View File

@ -1,10 +1,12 @@
import type { App } from 'vue'; import type { App } from 'vue';
import { Icon } from './Icon'; import { Icon } from './Icon';
import AIcon from '/@/components/jeecg/AIcon.vue'; import AIcon from '/@/components/jeecg/AIcon.vue';
import { Button, JUploadButton } from './Button';
//Tinymce富文本 //Tinymce富文本
import Editor from '/@/components/Tinymce/src/Editor.vue' import Editor from '/@/components/Tinymce/src/Editor.vue';
import { Button, JUploadButton } from './Button';
// 按需注册antd的组件
import { import {
// Need // Need
Button as AntButton, Button as AntButton,
@ -56,14 +58,11 @@ import {
Cascader, Cascader,
Rate, Rate,
} from 'ant-design-vue'; } from 'ant-design-vue';
const compList = [AntButton.Group, Icon, AIcon, JUploadButton]; const compList = [AntButton.Group, Icon, AIcon, JUploadButton];
//敲敲云—仪表盘设计器(拖拽设计) //敲敲云—仪表盘设计器(拖拽设计)
import DragEngine from '@qiaoqiaoyun/drag-free'; import DragEngine from '@qiaoqiaoyun/drag-free';
if (import.meta.env.DEV) { import('@qiaoqiaoyun/drag-free/lib/index.css');
import('@qiaoqiaoyun/drag-free/lib/index.css');
}
console.log('---初始化--- 全局注册仪表盘--------------'); console.log('---初始化--- 全局注册仪表盘--------------');
export function registerGlobComp(app: App) { export function registerGlobComp(app: App) {
@ -71,9 +70,10 @@ export function registerGlobComp(app: App) {
app.component(comp.name || comp.displayName, comp); app.component(comp.name || comp.displayName, comp);
}); });
//仪表盘依赖Tinymce需要提前加载没办法按需加载了 //仪表盘依赖Tinymce需要提前加载没办法按需加载了
app.component(Editor.name, Editor) app.component(Editor.name, Editor);
app.use(Select) app
.use(Select)
.use(Alert) .use(Alert)
.use(Button) .use(Button)
.use(Breadcrumb) .use(Breadcrumb)

View File

@ -8,6 +8,7 @@ html {
--sider-dark-bg-color: #273352; --sider-dark-bg-color: #273352;
--sider-dark-darken-bg-color: #273352; --sider-dark-darken-bg-color: #273352;
--sider-dark-lighten-bg-color: #273352; --sider-dark-lighten-bg-color: #273352;
--sider-logo-bg-color:linear-gradient(180deg, #000000, #021d37);
} }
@white: #fff; @white: #fff;
@ -64,6 +65,7 @@ html {
// ================================= // =================================
// let -menu // let -menu
@sider-logo-bg-color: var(--sider-logo-bg-color);
@sider-dark-bg-color: var(--sider-dark-bg-color); @sider-dark-bg-color: var(--sider-dark-bg-color);
@sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color); @sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color);
@sider-dark-lighten-bg-color: var(--sider-dark-lighten-bg-color); @sider-dark-lighten-bg-color: var(--sider-dark-lighten-bg-color);

View File

@ -35,6 +35,9 @@ export const LOGIN_INFO_KEY = 'LOGIN__INFO__';
// 聊天UID key // 聊天UID key
export const JEECG_CHAT_UID = 'JEECG_CHAT_UID'; export const JEECG_CHAT_UID = 'JEECG_CHAT_UID';
// 免登录租户id与系统分开避免重复
export const OAUTH2_THIRD_LOGIN_TENANT_ID = 'THIRD_LOGIN_TENANT_ID';
export enum CacheTypeEnum { export enum CacheTypeEnum {
SESSION, SESSION,
LOCAL, LOCAL,

View File

@ -11,4 +11,6 @@ export enum PageEnum {
OAUTH2_LOGIN_PAGE_PATH = '/oauth2-app/login', OAUTH2_LOGIN_PAGE_PATH = '/oauth2-app/login',
//文件路由 //文件路由
SYS_FILES_PATH = '/file/share', SYS_FILES_PATH = '/file/share',
// 邮件中的跳转地址
TOKEN_LOGIN = '/tokenLogin'
} }

View File

@ -0,0 +1,50 @@
import type { UnwrapRef, Ref, WritableComputedRef, DeepReadonly } from 'vue';
import { reactive, readonly, computed, getCurrentInstance, watchEffect, unref, nextTick, toRaw } from 'vue';
import { Form } from 'ant-design-vue';
import { FormItemContext } from 'ant-design-vue/es/form/FormItemContext';
import { isEqual } from 'lodash-es';
export function useRuleFormItem<T extends Recordable, K extends keyof T, V = UnwrapRef<T[K]>>(
props: T,
key?: K,
changeEvent?,
emitData?: Ref<any[] | undefined>
): [WritableComputedRef<V>, (val: V) => void, DeepReadonly<V>, FormItemContext];
export function useRuleFormItem<T extends Recordable>(props: T, key: keyof T = 'value', changeEvent = 'change', emitData?: Ref<any[]>) {
const instance = getCurrentInstance();
const emit = instance?.emit;
const formItemContext = Form.useInjectFormItemContext();
const innerState = reactive({
value: props[key],
});
const defaultState = readonly(innerState);
const setState = (val: UnwrapRef<T[keyof T]>): void => {
innerState.value = val as T[keyof T];
};
watchEffect(() => {
innerState.value = props[key];
});
const state: any = computed({
get() {
return innerState.value == null ? "" : innerState.value;
},
set(value) {
if (isEqual(value, defaultState.value)) return;
innerState.value = value as T[keyof T];
nextTick(() => {
emit?.(changeEvent, value, ...(toRaw(unref(emitData)) || []));
// https://antdv.com/docs/vue/migration-v3-cn
// antDv3升级后需要调用这个方法更新校验的值
nextTick(() => formItemContext.onFieldChange());
});
},
});
return [state, setState, defaultState, formItemContext];
}

View File

@ -10,6 +10,8 @@ import echarts from '/@/utils/lib/echarts';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
export function useECharts(elRef: Ref<HTMLDivElement>, theme: 'light' | 'dark' | 'default' = 'default') { export function useECharts(elRef: Ref<HTMLDivElement>, theme: 'light' | 'dark' | 'default' = 'default') {
console.log("---useECharts---初始化加载---")
const { getDarkMode: getSysDarkMode } = useRootSetting(); const { getDarkMode: getSysDarkMode } = useRootSetting();
const getDarkMode = computed(() => { const getDarkMode = computed(() => {

View File

@ -120,6 +120,22 @@ function createWarningModal(options: ModalOptionsPartial) {
return Modal.warning(createModalOptions(options, 'warning')); return Modal.warning(createModalOptions(options, 'warning'));
} }
interface MOE extends Omit<ModalOptionsEx, 'iconType'> {
iconType?: ModalOptionsEx['iconType'];
}
// 提示框无需传入iconType默认为warning
function createConfirmSync(options: MOE) {
return new Promise((resolve) => {
createConfirm({
iconType: 'warning',
...options,
onOk: () => resolve(true),
onCancel: () => resolve(false),
});
});
}
notification.config({ notification.config({
placement: 'topRight', placement: 'topRight',
duration: 3, duration: 3,
@ -133,6 +149,7 @@ export function useMessage() {
createMessage: Message, createMessage: Message,
notification: notification as NotifyApi, notification: notification as NotifyApi,
createConfirm: createConfirm, createConfirm: createConfirm,
createConfirmSync,
createSuccessModal, createSuccessModal,
createErrorModal, createErrorModal,
createInfoModal, createInfoModal,

View File

@ -2,16 +2,17 @@
<Tooltip :title="t('layout.header.tooltipLock')" placement="bottom" :mouseEnterDelay="0.5" @click="handleLock"> <Tooltip :title="t('layout.header.tooltipLock')" placement="bottom" :mouseEnterDelay="0.5" @click="handleLock">
<LockOutlined /> <LockOutlined />
</Tooltip> </Tooltip>
<LockModal @register="register" /> <LockModal ref="modalRef" v-if="lockModalVisible" @register="register" />
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, computed } from 'vue'; import { defineComponent, computed, ref } from 'vue';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { Tooltip } from 'ant-design-vue'; import { Tooltip } from 'ant-design-vue';
import { LockOutlined } from '@ant-design/icons-vue'; import { LockOutlined } from '@ant-design/icons-vue';
import Icon from '/@/components/Icon'; import Icon from '/@/components/Icon';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import { getRefPromise } from '/@/utils/index';
export default defineComponent({ export default defineComponent({
name: 'LockScreen', name: 'LockScreen',
@ -25,15 +26,21 @@
setup() { setup() {
const { t } = useI18n(); const { t } = useI18n();
const [register, { openModal }] = useModal(); const [register, { openModal }] = useModal();
// update-begin--author:liaozhiyang---date:20230901---forQQYUN-6333访
function handleLock() { const lockModalVisible = ref(false);
const modalRef = ref(null);
async function handleLock() {
lockModalVisible.value = true;
await getRefPromise(modalRef);
openModal(true); openModal(true);
} }
// update-end--author:liaozhiyang---date:20230901---forQQYUN-6333访
return { return {
t, t,
register, register,
handleLock, handleLock,
lockModalVisible,
modalRef,
}; };
}, },
}); });

View File

@ -23,7 +23,8 @@
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { BasicModal, useModalInner } from '/@/components/Modal/index'; import { BasicModal, useModalInner } from '/@/components/Modal/index';
import { BasicForm, useForm } from '/@/components/Form/index'; import BasicForm from '/@/components/Form/src/BasicForm.vue';
import { useForm } from '/@/components/Form/src/hooks/useForm';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
import { useLockStore } from '/@/store/modules/lock'; import { useLockStore } from '/@/store/modules/lock';

View File

@ -155,7 +155,6 @@
} }
} }
return { return {
prefixCls, prefixCls,
listData, listData,

View File

@ -3,6 +3,7 @@ import { defHttp } from '/@/utils/http/axios';
enum Api { enum Api {
listCementByUser = '/sys/annountCement/listByUser', listCementByUser = '/sys/annountCement/listByUser',
editCementSend = '/sys/sysAnnouncementSend/editByAnntIdAndUserId', editCementSend = '/sys/sysAnnouncementSend/editByAnntIdAndUserId',
clearAllUnReadMessage = '/sys/annountCement/clearAllUnReadMessage',
} }
/** /**
@ -12,3 +13,8 @@ enum Api {
export const listCementByUser = (params?) => defHttp.get({ url: Api.listCementByUser, params }); export const listCementByUser = (params?) => defHttp.get({ url: Api.listCementByUser, params });
export const editCementSend = (anntId, params?) => defHttp.put({ url: Api.editCementSend, params: { anntId, ...params } }); export const editCementSend = (anntId, params?) => defHttp.put({ url: Api.editCementSend, params: { anntId, ...params } });
/**
*
*/
export const clearAllUnReadMessage = () => defHttp.post({ url: Api.clearAllUnReadMessage },{ isTransformResponse: false });

View File

@ -50,7 +50,7 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, computed, watch, unref, defineExpose } from 'vue'; import { ref, computed, watch, unref } from 'vue';
import { Avatar } from 'ant-design-vue'; import { Avatar } from 'ant-design-vue';
import { BasicModal } from '/@/components/Modal'; import { BasicModal } from '/@/components/Modal';
import { getUserDeparts, selectDepart } from '/@/views/system/depart/depart.api'; import { getUserDeparts, selectDepart } from '/@/views/system/depart/depart.api';

View File

@ -4,11 +4,12 @@
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, unref, defineExpose } from 'vue'; import { ref, unref } from 'vue';
import { rules } from '/@/utils/helper/validator'; import { rules } from '/@/utils/helper/validator';
import { defHttp } from '/@/utils/http/axios'; import { defHttp } from '/@/utils/http/axios';
import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index'; import BasicForm from '/@/components/Form/src/BasicForm.vue';
import { useForm } from '/@/components/Form/src/hooks/useForm';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
// Emits // Emits
const emit = defineEmits(['register']); const emit = defineEmits(['register']);

View File

@ -27,9 +27,9 @@
</Menu> </Menu>
</template> </template>
</Dropdown> </Dropdown>
<LockAction @register="register" /> <LockAction v-if="lockActionVisible" ref="lockActionRef" @register="register" />
<DepartSelect ref="loginSelectRef" /> <DepartSelect ref="loginSelectRef" />
<UpdatePassword ref="updatePasswordRef" /> <UpdatePassword v-if="passwordVisible" ref="updatePasswordRef" />
</template> </template>
<script lang="ts"> <script lang="ts">
// components // components
@ -56,6 +56,7 @@
import { DB_DICT_DATA_KEY } from '/src/enums/cacheEnum'; import { DB_DICT_DATA_KEY } from '/src/enums/cacheEnum';
import { removeAuthCache, setAuthCache } from '/src/utils/auth'; import { removeAuthCache, setAuthCache } from '/src/utils/auth';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { getRefPromise } from '/@/utils/index';
type MenuEvent = 'logout' | 'doc' | 'lock' | 'cache' | 'depart'; type MenuEvent = 'logout' | 'doc' | 'lock' | 'cache' | 'depart';
const { createMessage } = useMessage(); const { createMessage } = useMessage();
@ -79,6 +80,9 @@
const { getShowDoc, getUseLockPage } = useHeaderSetting(); const { getShowDoc, getUseLockPage } = useHeaderSetting();
const userStore = useUserStore(); const userStore = useUserStore();
const go = useGo(); const go = useGo();
const passwordVisible = ref(false);
const lockActionVisible = ref(false);
const lockActionRef = ref(null);
const getUserInfo = computed(() => { const getUserInfo = computed(() => {
const { realname = '', avatar, desc } = userStore.getUserInfo || {}; const { realname = '', avatar, desc } = userStore.getUserInfo || {};
@ -99,10 +103,12 @@
* 多部门弹窗逻辑 * 多部门弹窗逻辑
*/ */
const loginSelectRef = ref(); const loginSelectRef = ref();
function handleLock() { // update-begin--author:liaozhiyang---date:20230901---forQQYUN-6333访
async function handleLock() {
await getRefPromise(lockActionRef);
openModal(true); openModal(true);
} }
// update-end--author:liaozhiyang---date:20230901---forQQYUN-6333访
// login out // login out
function handleLoginOut() { function handleLoginOut() {
userStore.confirmLoginOut(); userStore.confirmLoginOut();
@ -131,10 +137,13 @@
} }
// //
const updatePasswordRef = ref(); const updatePasswordRef = ref();
function updatePassword() { // update-begin--author:liaozhiyang---date:20230901---forQQYUN-6333访
async function updatePassword() {
passwordVisible.value = true;
await getRefPromise(updatePasswordRef);
updatePasswordRef.value.show(userStore.getUserInfo.username); updatePasswordRef.value.show(userStore.getUserInfo.username);
} }
// update-end--author:liaozhiyang---date:20230901---forQQYUN-6333访
function handleMenuClick(e: { key: MenuEvent }) { function handleMenuClick(e: { key: MenuEvent }) {
switch (e.key) { switch (e.key) {
case 'logout': case 'logout':
@ -174,6 +183,8 @@
getUseLockPage, getUseLockPage,
loginSelectRef, loginSelectRef,
updatePasswordRef, updatePasswordRef,
passwordVisible,
lockActionVisible,
}; };
}, },
}); });

View File

@ -7,6 +7,7 @@
`${prefixCls}__item`, `${prefixCls}__item`,
{ {
[`${prefixCls}__item--active`]: def === color, [`${prefixCls}__item--active`]: def === color,
[`${prefixCls}__item--black`]: color == '#ffffff',
}, },
]" ]"
:style="{ background: color }" :style="{ background: color }"
@ -83,6 +84,11 @@
fill: @white !important; fill: @white !important;
} }
} }
&--black {
svg {
fill: #000 !important;
}
}
} }
} }
</style> </style>

View File

@ -2,11 +2,13 @@ import { colorIsDark, lighten, darken } from '/@/utils/color';
import { useAppStore } from '/@/store/modules/app'; import { useAppStore } from '/@/store/modules/app';
import { ThemeEnum } from '/@/enums/appEnum'; import { ThemeEnum } from '/@/enums/appEnum';
import { setCssVar } from './util'; import { setCssVar } from './util';
import { SIDE_BAR_BG_COLOR_LIST, SIDER_LOGO_BG_COLOR_LIST } from '/@/settings/designSetting';
const HEADER_BG_COLOR_VAR = '--header-bg-color'; const HEADER_BG_COLOR_VAR = '--header-bg-color';
const HEADER_BG_HOVER_COLOR_VAR = '--header-bg-hover-color'; const HEADER_BG_HOVER_COLOR_VAR = '--header-bg-hover-color';
const HEADER_MENU_ACTIVE_BG_COLOR_VAR = '--header-active-menu-bg-color'; const HEADER_MENU_ACTIVE_BG_COLOR_VAR = '--header-active-menu-bg-color';
const SIDER_LOGO_BG_COLOR = '--sider-logo-bg-color';
const SIDER_DARK_BG_COLOR = '--sider-dark-bg-color'; const SIDER_DARK_BG_COLOR = '--sider-dark-bg-color';
const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color'; const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color';
const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color'; const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color';
@ -59,6 +61,10 @@ export function updateSidebarBgColor(color?: string) {
color = appStore.getMenuSetting.bgColor; color = appStore.getMenuSetting.bgColor;
} }
} }
// update-begin--author:liaozhiyang---date:20230811---for【QQYUN-5922】logo背景色渐变
let findIndex = SIDE_BAR_BG_COLOR_LIST.findIndex((item) => item === color);
setCssVar(SIDER_LOGO_BG_COLOR, findIndex == -1 ? 'linear-gradient(180deg, #000000, #282828)' : SIDER_LOGO_BG_COLOR_LIST[findIndex]);
// update-end--author:liaozhiyang---date:20230811---for【QQYUN-5922】llogo背景色渐变
setCssVar(SIDER_DARK_BG_COLOR, color); setCssVar(SIDER_DARK_BG_COLOR, color);
setCssVar(SIDER_DARK_DARKEN_BG_COLOR, darken(color!, 6)); setCssVar(SIDER_DARK_DARKEN_BG_COLOR, darken(color!, 6));
setCssVar(SIDER_LIGHTEN_BG_COLOR, lighten(color!, 5)); setCssVar(SIDER_LIGHTEN_BG_COLOR, lighten(color!, 5));

View File

@ -19,6 +19,7 @@ import { registerPackages } from '/@/utils/monorepo/registerPackages';
// 在本地开发中引入的,以提高浏览器响应速度 // 在本地开发中引入的,以提高浏览器响应速度
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
// @ts-ignore
import('ant-design-vue/dist/antd.less'); import('ant-design-vue/dist/antd.less');
} }
async function bootstrap() { async function bootstrap() {
@ -63,6 +64,8 @@ async function bootstrap() {
// 挂载应用 // 挂载应用
app.mount('#app', true); app.mount('#app', true);
console.log(" vue3 app 加载完成!")
} }
bootstrap(); bootstrap();

View File

@ -18,7 +18,7 @@ export const getParentLayout = (_name?: string) => {
return () => return () =>
new Promise((resolve) => { new Promise((resolve) => {
resolve({ resolve({
name: PARENT_LAYOUT_NAME, name: _name || PARENT_LAYOUT_NAME,
}); });
}); });
}; };

View File

@ -10,6 +10,8 @@ import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
import { RootRoute } from '/@/router/routes'; import { RootRoute } from '/@/router/routes';
import { isOAuth2AppEnv } from '/@/views/sys/login/useLogin'; import { isOAuth2AppEnv } from '/@/views/sys/login/useLogin';
import { OAUTH2_THIRD_LOGIN_TENANT_ID } from "/@/enums/cacheEnum";
import { setAuthCache } from "/@/utils/auth";
const LOGIN_PATH = PageEnum.BASE_LOGIN; const LOGIN_PATH = PageEnum.BASE_LOGIN;
//auth2登录路由 //auth2登录路由
@ -18,11 +20,14 @@ const OAUTH2_LOGIN_PAGE_PATH = PageEnum.OAUTH2_LOGIN_PAGE_PATH;
//分享免登录路由 //分享免登录路由
const SYS_FILES_PATH = PageEnum.SYS_FILES_PATH; const SYS_FILES_PATH = PageEnum.SYS_FILES_PATH;
// 邮件中的跳转地址,对应此路由,携带token免登录直接去办理页面
const TOKEN_LOGIN = PageEnum.TOKEN_LOGIN;
const ROOT_PATH = RootRoute.path; const ROOT_PATH = RootRoute.path;
//update-begin---author:wangshuai ---date:20220629 for[issues/I5BG1I]vue3不支持auth2登录------------ //update-begin---author:wangshuai ---date:20220629 for[issues/I5BG1I]vue3不支持auth2登录------------
//update-begin---author:wangshuai ---date:20221111 for: [VUEN-2472]分享免登录------------ //update-begin---author:wangshuai ---date:20221111 for: [VUEN-2472]分享免登录------------
const whitePathList: PageEnum[] = [LOGIN_PATH, OAUTH2_LOGIN_PAGE_PATH,SYS_FILES_PATH]; const whitePathList: PageEnum[] = [LOGIN_PATH, OAUTH2_LOGIN_PAGE_PATH,SYS_FILES_PATH, TOKEN_LOGIN ];
//update-end---author:wangshuai ---date:20221111 for: [VUEN-2472]分享免登录------------ //update-end---author:wangshuai ---date:20221111 for: [VUEN-2472]分享免登录------------
//update-end---author:wangshuai ---date:20220629 for[issues/I5BG1I]vue3不支持auth2登录------------ //update-end---author:wangshuai ---date:20220629 for[issues/I5BG1I]vue3不支持auth2登录------------
@ -62,7 +67,12 @@ export function createPermissionGuard(router: Router) {
} else if (to.path === LOGIN_PATH && isOAuth2AppEnv() && !token) { } else if (to.path === LOGIN_PATH && isOAuth2AppEnv() && !token) {
//退出登录进入此逻辑 //退出登录进入此逻辑
//如果进入的页面是login页面并且当前是OAuth2app环境并且token为空就进入OAuth2登录页面 //如果进入的页面是login页面并且当前是OAuth2app环境并且token为空就进入OAuth2登录页面
//update-begin---author:wangshuai ---date:20230224 for[QQYUN-3440]新建企业微信和钉钉配置表,通过租户模式隔离------------
if(to.query.tenantId){
setAuthCache(OAUTH2_THIRD_LOGIN_TENANT_ID,to.query.tenantId)
}
next({ path: OAUTH2_LOGIN_PAGE_PATH }); next({ path: OAUTH2_LOGIN_PAGE_PATH });
//update-end---author:wangshuai ---date:20230224 for[QQYUN-3440]新建企业微信和钉钉配置表,通过租户模式隔离------------
return; return;
//update-end---author:wangshuai ---date:20220629 for[issues/I5BG1I]vue3不支持auth2登录------------ //update-end---author:wangshuai ---date:20220629 for[issues/I5BG1I]vue3不支持auth2登录------------
} }
@ -89,6 +99,20 @@ export function createPermissionGuard(router: Router) {
next(); next();
} }
} else { } else {
//update-begin---author:wangshuai ---date:20230302 for只有首次登陆并且是企业微信或者钉钉的情况下才会调用------------
//----------【首次登陆并且是企业微信或者钉钉的情况下才会调用】-----------------------------------------------
//只有首次登陆并且是企业微信或者钉钉的情况下才会调用
let href = window.location.href;
//判断当前是auth2页面并且是钉钉/企业微信并且包含tenantId参数
if(isOAuth2AppEnv() && href.indexOf("/tenantId/")!= -1){
let params = to.params;
if(params && params.path && params.path.length>0){
//直接获取参数最后一位
setAuthCache(OAUTH2_THIRD_LOGIN_TENANT_ID,params.path[params.path.length-1])
}
}
//---------【首次登陆并且是企业微信或者钉钉的情况下才会调用】------------------------------------------------
//update-end---author:wangshuai ---date:20230302 for只有首次登陆并且是企业微信或者钉钉的情况下才会调用------------
// 如果当前是在OAuth2APP环境就跳转到OAuth2登录页面否则跳转到登录页面 // 如果当前是在OAuth2APP环境就跳转到OAuth2登录页面否则跳转到登录页面
path = isOAuth2AppEnv() ? OAUTH2_LOGIN_PAGE_PATH : LOGIN_PATH; path = isOAuth2AppEnv() ? OAUTH2_LOGIN_PAGE_PATH : LOGIN_PATH;
} }
@ -100,16 +124,38 @@ export function createPermissionGuard(router: Router) {
//update-end---author:wangshuai ---date:20220629 for[issues/I5BG1I]vue3 Auth2未实现------------ //update-end---author:wangshuai ---date:20220629 for[issues/I5BG1I]vue3 Auth2未实现------------
replace: true, replace: true,
}; };
if (to.path) {
//update-begin---author:scott ---date:2023-04-24 for【QQYUN-4713】登录代码调整逻辑有问题改造待观察--
if (to.fullPath) {
console.log("to.fullPath 1",to.fullPath)
console.log("to.path 2",to.path)
let getFullPath = to.fullPath;
if(getFullPath=='/' || getFullPath=='/500' || getFullPath=='/400' || getFullPath=='/login?redirect=/' || getFullPath=='/login?redirect=/login?redirect=/'){
return;
}
//update-end---author:scott ---date:2023-04-24 for【QQYUN-4713】登录代码调整逻辑有问题改造待观察--
redirectData.query = { redirectData.query = {
...redirectData.query, ...redirectData.query,
redirect: to.path, // update-begin-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
redirect: to.fullPath,
// update-end-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
}; };
} }
next(redirectData); next(redirectData);
return; return;
} }
//==============================【首次登录并且是企业微信或者钉钉的情况下才会调用】==================
//判断是免登录页面,如果页面包含/tenantId/,那么就直接前往主页
if(isOAuth2AppEnv() && to.path.indexOf("/tenantId/") != -1){
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
return;
}
//==============================【首次登录并且是企业微信或者钉钉的情况下才会调用】==================
// Jump to the 404 page after processing the login // Jump to the 404 page after processing the login
if (from.path === LOGIN_PATH && to.name === PAGE_NOT_FOUND_ROUTE.name && to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME)) { if (from.path === LOGIN_PATH && to.name === PAGE_NOT_FOUND_ROUTE.name && to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME)) {
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);

View File

@ -6,7 +6,7 @@ import { cloneDeep, omit } from 'lodash-es';
import { warn } from '/@/utils/log'; import { warn } from '/@/utils/log';
import { createRouter, createWebHashHistory } from 'vue-router'; import { createRouter, createWebHashHistory } from 'vue-router';
import { getTenantId, getToken } from "/@/utils/auth"; import { getTenantId, getToken } from "/@/utils/auth";
import { URL_HASH_TAB } from '/@/utils'; import { URL_HASH_TAB, _eval } from '/@/utils';
//引入online lib路由 //引入online lib路由
import { packageViews } from '/@/utils/monorepo/dynamicRouter'; import { packageViews } from '/@/utils/monorepo/dynamicRouter';
import {useI18n} from "/@/hooks/web/useI18n"; import {useI18n} from "/@/hooks/web/useI18n";
@ -39,11 +39,11 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
if (item?.meta?.title) { if (item?.meta?.title) {
const { t } = useI18n(); const { t } = useI18n();
if(item.meta.title.includes('t(\'') && t){ if(item.meta.title.includes('t(\'') && t){
item.meta.title = eval(item.meta.title); // update-begin--author:liaozhiyang---date:20230906---for【QQYUN-6390】eval替换成new Function解决build警告
//console.log('译后: ',item.meta.title) item.meta.title = new Function('t', `return ${item.meta.title}`)(t);
// update-end--author:liaozhiyang---date:20230906---for【QQYUN-6390】eval替换成new Function解决build警告
} }
} }
// update-begin--author:sunjianlei---date:20210918---for:适配旧版路由选项 -------- // update-begin--author:sunjianlei---date:20210918---for:适配旧版路由选项 --------
// @ts-ignore 适配隐藏路由 // @ts-ignore 适配隐藏路由
if (item?.hidden) { if (item?.hidden) {
@ -61,7 +61,7 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
let tenantId = getTenantId(); let tenantId = getTenantId();
// URL支持{{ window.xxx }}占位符变量 // URL支持{{ window.xxx }}占位符变量
//update-begin---author:wangshuai ---date:20220711 for[VUEN-1638]菜单tenantId需要动态生成------------ //update-begin---author:wangshuai ---date:20220711 for[VUEN-1638]菜单tenantId需要动态生成------------
item.component = (item.component || '').replace(/{{([^}}]+)?}}/g, (s1, s2) => eval(s2)).replace('${token}', token).replace('${tenantId}', tenantId); item.component = (item.component || '').replace(/{{([^}}]+)?}}/g, (s1, s2) => _eval(s2)).replace('${token}', token).replace('${tenantId}', tenantId);
//update-end---author:wangshuai ---date:20220711 for[VUEN-1638]菜单tenantId需要动态生成------------ //update-end---author:wangshuai ---date:20220711 for[VUEN-1638]菜单tenantId需要动态生成------------
// 适配 iframe // 适配 iframe
if (/^\/?http(s)?/.test(item.component as string)) { if (/^\/?http(s)?/.test(item.component as string)) {

View File

@ -21,6 +21,15 @@ export const router = createRouter({
scrollBehavior: () => ({ left: 0, top: 0 }), scrollBehavior: () => ({ left: 0, top: 0 }),
}); });
// TODO 【QQYUN-4517】【表单设计器】记录分享路由守卫测试
router.beforeEach(async (to, from, next) => {
//console.group('【QQYUN-4517】beforeEach');
//console.warn('from', from);
//console.warn('to', to);
//console.groupEnd();
next();
});
// reset router // reset router
export function resetRouter() { export function resetRouter() {
router.getRoutes().forEach((route) => { router.getRoutes().forEach((route) => {

View File

@ -39,7 +39,6 @@ export const LoginRoute: AppRouteRecordRaw = {
}, },
}; };
//update-begin---author:wangshuai ---date:20220629 forauth2登录页面路由------------
export const Oauth2LoginRoute: AppRouteRecordRaw = { export const Oauth2LoginRoute: AppRouteRecordRaw = {
path: '/oauth2-app/login', path: '/oauth2-app/login',
name: 'oauth2-app-login', name: 'oauth2-app-login',
@ -50,7 +49,6 @@ export const Oauth2LoginRoute: AppRouteRecordRaw = {
title: t('routes.oauth2.login'), title: t('routes.oauth2.login'),
}, },
}; };
//update-end---author:wangshuai ---date:20220629 forauth2登录页面路由------------
/** /**
* token * token

View File

@ -36,3 +36,18 @@ export const SIDE_BAR_BG_COLOR_LIST: string[] = [
'#344058', '#344058',
'#383f45', '#383f45',
]; ];
// sider logo line preset color [logo½¥±äÉ«]
export const SIDER_LOGO_BG_COLOR_LIST: string[] = [
'linear-gradient(180deg, #000000, #021d37)',
'linear-gradient(180deg, #000000, #282828)',
'linear-gradient(180deg, #1c253e, #2b385c)',
'linear-gradient(180deg, #ffffff, #faf8f8)',
'linear-gradient(180deg, #000000, #242735)',
'linear-gradient(180deg, #000000, #1d1f2a)',
'linear-gradient(180deg, #304156, #32455d)',
'linear-gradient(180deg, #000000, #001f39)',
'linear-gradient(180deg, #000000, #2b3743)',
'linear-gradient(180deg, #344058, #374560)',
'linear-gradient(180deg, #383f45, #3b434b)',
];

View File

@ -4,15 +4,13 @@ import { registerJVxeCustom } from '/@/components/JVxeCustom';
// 注册全局聊天表情包 // 注册全局聊天表情包
import { Picker } from 'emoji-mart-vue-fast/src'; import { Picker } from 'emoji-mart-vue-fast/src';
// import { EmojiIndex } from "emoji-mart-vue-fast/src";
// import data from "emoji-mart-vue-fast/data/apple.json";
// 注册全局dayjs // 注册全局dayjs
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime'; import relativeTime from 'dayjs/plugin/relativeTime';
import customParseFormat from 'dayjs/plugin/customParseFormat'; import customParseFormat from 'dayjs/plugin/customParseFormat';
export async function registerThirdComp(app: App) { export async function registerThirdComp(app: App) {
//---------------------------------------------------------------------
// 注册 JVxeTable 组件 // 注册 JVxeTable 组件
registerJVxeTable(app); registerJVxeTable(app);
// 注册 JVxeTable 自定义组件 // 注册 JVxeTable 自定义组件
@ -20,20 +18,13 @@ export async function registerThirdComp(app: App) {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// 注册全局聊天表情包 // 注册全局聊天表情包
app.component('Picker', Picker); app.component('Picker', Picker);
// let myEmojiIndex = new EmojiIndex(data, {
// function() {
// return true;
// },
// exclude:['recent','people','nature','foods','activity','places','objects','symbols','flags']
// });
// app.config.globalProperties.$globalEmojiIndex = myEmojiIndex;
// app.provide('$globalEmojiIndex', myEmojiIndex);
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// 注册全局dayjs // 注册全局dayjs
dayjs.locale('zh-cn'); dayjs.locale('zh-cn');
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
dayjs.extend(customParseFormat); dayjs.extend(customParseFormat);
app.config.globalProperties.$dayjs = dayjs; app.config.globalProperties.$dayjs = dayjs
app.provide('$dayjs', dayjs); app.provide('$dayjs', dayjs)
//--------------------------------------------------------------------- //---------------------------------------------------------------------
} }

View File

@ -1,5 +1,5 @@
// github repo url // github repo url
export const GITHUB_URL = 'https://github.com/jeecgboot/jeecgboot-vue3'; export const GITHUB_URL = 'https://github.com/jeecgboot/jeecg-boot';
// vue-Jeecg-admin-next-doc // vue-Jeecg-admin-next-doc
export const DOC_URL = 'http://help.jeecg.com'; export const DOC_URL = 'http://help.jeecg.com';

View File

@ -184,6 +184,7 @@ export const useMultipleTabStore = defineStore({
if (path !== tab.path) { if (path !== tab.path) {
// Closed is not the activation tab // Closed is not the activation tab
close(tab); close(tab);
this.updateCacheTab();
return; return;
} }

View File

@ -4,7 +4,7 @@ import { defineStore } from 'pinia';
import { store } from '/@/store'; import { store } from '/@/store';
import { RoleEnum } from '/@/enums/roleEnum'; import { RoleEnum } from '/@/enums/roleEnum';
import { PageEnum } from '/@/enums/pageEnum'; import { PageEnum } from '/@/enums/pageEnum';
import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY, LOGIN_INFO_KEY, DB_DICT_DATA_KEY, TENANT_ID } from '/@/enums/cacheEnum'; import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY, LOGIN_INFO_KEY, DB_DICT_DATA_KEY, TENANT_ID, OAUTH2_THIRD_LOGIN_TENANT_ID } from '/@/enums/cacheEnum';
import { getAuthCache, setAuthCache, removeAuthCache } from '/@/utils/auth'; import { getAuthCache, setAuthCache, removeAuthCache } from '/@/utils/auth';
import { GetUserInfoModel, LoginParams, ThirdLoginParams } from '/@/api/sys/model/userModel'; import { GetUserInfoModel, LoginParams, ThirdLoginParams } from '/@/api/sys/model/userModel';
import { doLogout, getUserInfo, loginApi, phoneLoginApi, thirdLogin } from '/@/api/sys/user'; import { doLogout, getUserInfo, loginApi, phoneLoginApi, thirdLogin } from '/@/api/sys/user';
@ -18,6 +18,7 @@ import { isArray } from '/@/utils/is';
import { useGlobSetting } from '/@/hooks/setting'; import { useGlobSetting } from '/@/hooks/setting';
import { JDragConfigEnum } from '/@/enums/jeecgEnum'; import { JDragConfigEnum } from '/@/enums/jeecgEnum';
import { useSso } from '/@/hooks/web/useSso'; import { useSso } from '/@/hooks/web/useSso';
import { isOAuth2AppEnv } from "/@/views/sys/login/useLogin";
interface UserState { interface UserState {
userInfo: Nullable<UserInfo>; userInfo: Nullable<UserInfo>;
token?: string; token?: string;
@ -26,6 +27,7 @@ interface UserState {
sessionTimeout?: boolean; sessionTimeout?: boolean;
lastUpdateTime: number; lastUpdateTime: number;
tenantid?: string | number; tenantid?: string | number;
shareTenantId?: Nullable<string | number>;
loginInfo?: Nullable<LoginInfo>; loginInfo?: Nullable<LoginInfo>;
} }
@ -46,6 +48,9 @@ export const useUserStore = defineStore({
lastUpdateTime: 0, lastUpdateTime: 0,
//租户id //租户id
tenantid: '', tenantid: '',
// 分享租户ID
// 用于分享页面所属租户与当前用户登录租户不一致的情况
shareTenantId: null,
//登录返回信息 //登录返回信息
loginInfo: null, loginInfo: null,
}), }),
@ -74,6 +79,10 @@ export const useUserStore = defineStore({
getTenant(): string | number { getTenant(): string | number {
return this.tenantid || getAuthCache<string | number>(TENANT_ID); return this.tenantid || getAuthCache<string | number>(TENANT_ID);
}, },
// 是否有分享租户id
hasShareTenantId(): boolean {
return this.shareTenantId != null && this.shareTenantId !== '';
},
}, },
actions: { actions: {
setToken(info: string | undefined) { setToken(info: string | undefined) {
@ -101,6 +110,9 @@ export const useUserStore = defineStore({
this.tenantid = id; this.tenantid = id;
setAuthCache(TENANT_ID, id); setAuthCache(TENANT_ID, id);
}, },
setShareTenantId(id: NonNullable<typeof this.shareTenantId>) {
this.shareTenantId = id;
},
setSessionTimeout(flag: boolean) { setSessionTimeout(flag: boolean) {
this.sessionTimeout = flag; this.sessionTimeout = flag;
}, },
@ -169,6 +181,19 @@ export const useUserStore = defineStore({
//update-begin-author:liusq date:2022-5-5 for:登录成功后缓存拖拽模块的接口前缀 //update-begin-author:liusq date:2022-5-5 for:登录成功后缓存拖拽模块的接口前缀
localStorage.setItem(JDragConfigEnum.DRAG_BASE_URL, useGlobSetting().domainUrl); localStorage.setItem(JDragConfigEnum.DRAG_BASE_URL, useGlobSetting().domainUrl);
//update-end-author:liusq date:2022-5-5 for: 登录成功后缓存拖拽模块的接口前缀 //update-end-author:liusq date:2022-5-5 for: 登录成功后缓存拖拽模块的接口前缀
// update-begin-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
let redirect = router.currentRoute.value?.query?.redirect as string;
// 判断是否有 redirect 重定向地址
//update-begin---author:wangshuai ---date:20230424 for【QQYUN-5195】登录之后直接刷新页面导致没有进入创建组织页面------------
if (redirect && goHome) {
//update-end---author:wangshuai ---date:20230424 for【QQYUN-5195】登录之后直接刷新页面导致没有进入创建组织页面------------
// 当前页面打开
window.open(redirect, '_self')
return;
}
// update-end-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
goHome && (await router.replace((userInfo && userInfo.homePath) || PageEnum.BASE_HOME)); goHome && (await router.replace((userInfo && userInfo.homePath) || PageEnum.BASE_HOME));
} }
return data; return data;
@ -257,8 +282,25 @@ export const useUserStore = defineStore({
if (openSso == 'true') { if (openSso == 'true') {
await useSso().ssoLoginOut(); await useSso().ssoLoginOut();
} }
//update-begin---author:wangshuai ---date:20230224 for[QQYUN-3440]新建企业微信和钉钉配置表,通过租户模式隔离------------
//退出登录的时候需要用的应用id
if(isOAuth2AppEnv()){
let tenantId = getAuthCache(OAUTH2_THIRD_LOGIN_TENANT_ID);
removeAuthCache(OAUTH2_THIRD_LOGIN_TENANT_ID);
goLogin && await router.push({ name:"Login",query:{ tenantId:tenantId }})
}else{
// update-begin-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
goLogin && (await router.push({
path: PageEnum.BASE_LOGIN,
query: {
// 传入当前的路由,登录成功后跳转到当前路由
redirect: router.currentRoute.value.fullPath,
}
}));
// update-end-author:sunjianlei date:20230306 for: 修复登录成功后,没有正确重定向的问题
goLogin && (await router.push(PageEnum.BASE_LOGIN)); }
//update-end---author:wangshuai ---date:20230224 for[QQYUN-3440]新建企业微信和钉钉配置表,通过租户模式隔离------------
}, },
/** /**
* *

View File

@ -16,6 +16,7 @@ import {
DB_DICT_DATA_KEY, DB_DICT_DATA_KEY,
TENANT_ID, TENANT_ID,
LOGIN_INFO_KEY, LOGIN_INFO_KEY,
OAUTH2_THIRD_LOGIN_TENANT_ID,
} from '/@/enums/cacheEnum'; } from '/@/enums/cacheEnum';
import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting'; import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting';
import { toRaw } from 'vue'; import { toRaw } from 'vue';
@ -31,6 +32,7 @@ interface BasicStore {
[DB_DICT_DATA_KEY]: string; [DB_DICT_DATA_KEY]: string;
[TENANT_ID]: string; [TENANT_ID]: string;
[LOGIN_INFO_KEY]: LoginInfo; [LOGIN_INFO_KEY]: LoginInfo;
[OAUTH2_THIRD_LOGIN_TENANT_ID]: string
} }
type LocalStore = BasicStore; type LocalStore = BasicStore;

View File

@ -2,6 +2,9 @@ import { useGlobSetting } from '/@/hooks/setting';
import { merge, random } from 'lodash-es'; import { merge, random } from 'lodash-es';
import { isArray } from '/@/utils/is'; import { isArray } from '/@/utils/is';
import { FormSchema } from '/@/components/Form'; import { FormSchema } from '/@/components/Form';
import { reactive } from "vue";
import { getTenantId, getToken } from "/@/utils/auth";
import { useUserStoreWithOut } from "/@/store/modules/user";
const globSetting = useGlobSetting(); const globSetting = useGlobSetting();
const baseApiUrl = globSetting.domainUrl; const baseApiUrl = globSetting.domainUrl;
@ -365,3 +368,94 @@ export function checkChildrenHidden(menuTreeItem){
} }
return menuTreeItem.children?.find((item) => item.hideMenu == false) != null; return menuTreeItem.children?.find((item) => item.hideMenu == false) != null;
} }
/**
*
* @param fileSize
* @param unit
* @return
*/
export function calculateFileSize(fileSize, unit?) {
let unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
if (unit && unit.length > 0) {
unitArr = unit;
}
let size = fileSize;
let unitIndex = 0;
while (size >= 1024 && unitIndex < unitArr.length - 1) {
size /= 1024;
unitIndex++;
}
//保留两位小数,四舍五入
size = Math.round(size * 100) / 100;
return size + unitArr[unitIndex];
}
/**
* header
*/
export function getHeaders() {
let tenantId = getTenantId();
return reactive({
'X-Access-Token': getToken(),
'X-Tenant-Id': tenantId ? tenantId : '0',
});
}
/** 根据表达式获取相应的用户信息 */
export function getUserInfoByExpression(expression) {
if (!expression) {
return expression;
}
const userStore = useUserStoreWithOut();
let userInfo = userStore.getUserInfo;
if (userInfo) {
switch (expression) {
case 'sysUserId':
return userInfo.id;
// 当前登录用户登录账号
case 'sysUserCode':
case 'sys_user_code':
return userInfo.username;
// 当前登录用户真实名称
case 'sysUserName':
return userInfo.realname;
// 当前登录用户部门编号
case 'sysOrgCode':
case 'sys_org_code':
return userInfo.orgCode;
}
}
return expression;
}
/**
* #{xxx}
* @param expression
*/
export function replaceUserInfoByExpression(expression: string | any[]) {
if (!expression) {
return expression;
}
const isString = typeof expression === 'string';
const isArray = Array.isArray(expression)
if (!isString && !isArray) {
return expression;
}
const reg = /#{(.*?)}/g;
const replace = (str) => {
if (typeof str !== 'string') {
return str;
}
let result = str.match(reg);
if (result && result.length > 0) {
result.forEach((item) => {
let userInfo = getUserInfoByExpression(item.substring(2, item.length - 1));
str = str.replace(item, userInfo);
});
}
return str;
};
// @ts-ignore
return isString ? replace(expression) : expression.map(replace);
}

View File

@ -1,5 +1,5 @@
import { h } from 'vue'; import { h } from 'vue';
import { Avatar, Tag, Tooltip } from 'ant-design-vue'; import { Avatar, Tag, Tooltip, Image } from 'ant-design-vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { Tinymce } from '/@/components/Tinymce'; import { Tinymce } from '/@/components/Tinymce';
import Icon from '/@/components/Icon'; import Icon from '/@/components/Icon';
@ -60,24 +60,26 @@ const render = {
*/ */
renderImage: ({ text }) => { renderImage: ({ text }) => {
if (!text) { if (!text) {
//update-begin-author:taoyan date:2022-5-24 for: VUEN-1084 【vue3】online表单测试发现的新问题 41、生成的代码树默认图大小未改 return h(Image, {
return h( width: 30,
Avatar, height: 30,
{ shape: 'square', size: 25 }, src: '',
{ fallback:
icon: () => h(Icon, { icon: 'ant-design:file-image-outlined', size: 25 }), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg==',
} });
);
} }
let avatarList = text.split(','); let avatarList = text.split(',');
return h( return h(
'span', 'span',
avatarList.map((item) => { avatarList.map((item) => {
return h(Avatar, { return h(Image, {
src: getFileAccessHttpUrl(item), src: getFileAccessHttpUrl(item),
shape: 'square', width: 30,
size: 25, height: 30,
style: { marginRight: '5px' }, style: { marginRight: '5px' },
previewMask: () => {
return h(Icon, { icon: 'ant-design:eye-outlined', size: 20 });
},
}); });
}) })
); );

View File

@ -0,0 +1,65 @@
const whiteColor = '#ffffff'
const blackColor = '#666666'
export const Colors = [
// 背景颜色,文字颜色
['#2196F3', whiteColor],
['#08C9C9', whiteColor],
['#00C345', whiteColor],
['#FAD714', whiteColor],
['#FF9300', whiteColor],
['#F52222', whiteColor],
['#EB2F96', whiteColor],
['#7500EA', whiteColor],
['#2D46C4', whiteColor],
['#484848', whiteColor],
// --------------------
['#C9E6FC', blackColor],
['#C3F2F2', blackColor],
['#C2F1D2', blackColor],
['#FEF6C6', blackColor],
['#FFE5C2', blackColor],
['#FDCACA', blackColor],
['#FACDE6', blackColor],
['#DEC2FA', blackColor],
['#CCD2F1', blackColor],
['#D3D3D3', blackColor],
]
export const NONE_COLOR = ['#e9e9e9', blackColor]
/**
* 返回一个颜色迭代器每次调用返回一个颜色当颜色用完后再从头开始
* @param {number} initIndex 初始颜色索引
* @returns {{getIndex: function, next: function}}
*/
export function getColorIterator(initIndex = 0) {
let index = initIndex;
if (index < 0 || index >= Colors.length) {
index = 0;
}
return {
getIndex: () => index,
next() {
const color = Colors[index];
index = (index + 1) % Colors.length;
return color;
},
}
}
/**
* 根据颜色获取当前坐标和颜色
*/
export function getItemColor(color) {
if(!color){
return NONE_COLOR[1];
}
let colorIndex = Colors.findIndex((value)=>{
return value[0] === color;
})
if(colorIndex === -1){
return NONE_COLOR[1];
}
return Colors[colorIndex][1];
}

View File

@ -33,6 +33,7 @@ export default class signMd5Utils {
let jsonObj = this.mergeObject(urlParams, requestParams); let jsonObj = this.mergeObject(urlParams, requestParams);
let requestBody = this.sortAsc(jsonObj); let requestBody = this.sortAsc(jsonObj);
delete requestBody._t; delete requestBody._t;
console.log('sign requestBody:', requestBody);
return md5(JSON.stringify(requestBody) + signatureSecret).toUpperCase(); return md5(JSON.stringify(requestBody) + signatureSecret).toUpperCase();
} }

View File

@ -139,7 +139,7 @@ const transform: AxiosTransform = {
requestInterceptors: (config: Recordable, options) => { requestInterceptors: (config: Recordable, options) => {
// 请求之前处理config // 请求之前处理config
const token = getToken(); const token = getToken();
let tenantid = getTenantId(); let tenantId: string | number = getTenantId();
if (token && (config as Recordable)?.requestOptions?.withToken !== false) { if (token && (config as Recordable)?.requestOptions?.withToken !== false) {
// jwt token // jwt token
config.headers.Authorization = options.authenticationScheme ? `${options.authenticationScheme} ${token}` : token; config.headers.Authorization = options.authenticationScheme ? `${options.authenticationScheme} ${token}` : token;
@ -153,10 +153,20 @@ const transform: AxiosTransform = {
config.headers[ConfigEnum.Sign] = signMd5Utils.getSign(config.url, config.params); config.headers[ConfigEnum.Sign] = signMd5Utils.getSign(config.url, config.params);
//--update-end--author:liusq---date:20210831---for:将签名和时间戳,添加在请求接口 Header //--update-end--author:liusq---date:20210831---for:将签名和时间戳,添加在请求接口 Header
//--update-begin--author:liusq---date:20211105---for: for:将多租户id添加在请求接口 Header //--update-begin--author:liusq---date:20211105---for: for:将多租户id添加在请求接口 Header
if (!tenantid) { if (!tenantId) {
tenantid = 0; tenantId = 0;
} }
config.headers[ConfigEnum.TENANT_ID] = tenantid;
// update-begin--author:sunjianlei---date:220230428---for【QQYUN-5279】修复分享的应用租户和当前登录租户不一致时提示404的问题
const userStore = useUserStoreWithOut();
// 判断是否有临时租户id
if (userStore.hasShareTenantId && userStore.shareTenantId !== 0) {
// 临时租户id存在使用临时租户id
tenantId = userStore.shareTenantId!;
}
// update-end--author:sunjianlei---date:220230428---for【QQYUN-5279】修复分享的应用租户和当前登录租户不一致时提示404的问题
config.headers[ConfigEnum.TENANT_ID] = tenantId;
//--update-begin--author:liusq---date:20220325---for: 增加vue3标记 //--update-begin--author:liusq---date:20220325---for: 增加vue3标记
config.headers[ConfigEnum.VERSION] = 'v3'; config.headers[ConfigEnum.VERSION] = 'v3';
//--update-end--author:liusq---date:20220325---for:增加vue3标记 //--update-end--author:liusq---date:20220325---for:增加vue3标记

View File

@ -104,6 +104,8 @@ export function cloneObject(obj) {
} }
export const withInstall = <T>(component: T, alias?: string) => { export const withInstall = <T>(component: T, alias?: string) => {
console.log("---初始化---", component)
const comp = component as any; const comp = component as any;
comp.install = (app: App) => { comp.install = (app: App) => {
app.component(comp.name || comp.displayName, component); app.component(comp.name || comp.displayName, component);

Some files were not shown because too many files have changed in this diff Show More