JeecgBoot 3.6.0大版本发布
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
9691
pnpm-lock.yaml
|
@ -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,
|
||||||
|
|
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 398 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 9.6 KiB |
|
@ -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;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import CodeMirrorEditor from './codemirror/CodeMirror.vue';
|
import CodeMirrorEditor from './codemirror/CodeMirror.vue';
|
||||||
import { isString } from '/@/utils/is';
|
import { isString } from '/@/utils/is';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
value: { type: [Object, String] as PropType<Record<string, any> | string> },
|
value: { type: [Object, String] as PropType<Record<string, any> | string> },
|
||||||
mode: { type: String, default: MODE.JSON },
|
mode: { type: String, default: MODE.JSON },
|
||||||
|
|
|
@ -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 },
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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---for:【QQYUN-6679】input去空格
|
||||||
|
let isTrim = false;
|
||||||
|
if (component === 'Input' && componentProps && componentProps.trim) {
|
||||||
|
isTrim = true;
|
||||||
|
}
|
||||||
|
// update-end--author:liaozhiyang---date:20231013---for:【QQYUN-6679】input去空格
|
||||||
const eventKey = `on${upperFirst(changeEvent)}`;
|
const eventKey = `on${upperFirst(changeEvent)}`;
|
||||||
// update-begin--author:liaozhiyang---date:20230922---for:【issues/752】表单校验dynamicRules 无法 使用失去焦点后校验 trigger: 'blur'
|
// update-begin--author:liaozhiyang---date:20230922---for:【issues/752】表单校验dynamicRules 无法 使用失去焦点后校验 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---for:【QQYUN-6679】input去空格
|
||||||
|
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---for:【QQYUN-6679】input去空格
|
||||||
props.setFormModel(field, value);
|
props.setFormModel(field, value);
|
||||||
//props.validateFields([field], { triggerName: 'change' }).catch((_) => {});
|
//props.validateFields([field], { triggerName: 'change' }).catch((_) => {});
|
||||||
},
|
},
|
||||||
|
|
|
@ -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),
|
||||||
//是否是全部
|
//是否是全部
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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---for:【QQYUN-5955】online js增强,加入代码提示
|
||||||
|
const { codeHintingMount, codeHintingRegistry } = useCodeHinting(CodeMirror, props.keywords, props.language);
|
||||||
|
codeHintingRegistry();
|
||||||
|
// update-end--author:liaozhiyang---date:20230904---for:【QQYUN-5955】online 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---for:【QQYUN-5955】online js增强,加入代码提示
|
||||||
|
codeHintingMount(coder);
|
||||||
|
// update-end--author:liaozhiyang---date:20230904---for:【QQYUN-5955】online js增强,加入代码提示
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换全屏状态
|
// 切换全屏状态
|
||||||
|
@ -205,7 +217,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//update-end-author:taoyan date:2022-10-18 for: VUEN-2480【严重bug】online vue3测试的问题 8、online js增强样式问题
|
//update-end-author:taoyan date:2022-10-18 for: VUEN-2480【严重bug】online vue3测试的问题 8、online 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>
|
||||||
|
|
|
@ -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),
|
||||||
});
|
});
|
||||||
//显示的文本
|
//显示的文本
|
||||||
|
|
|
@ -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);
|
||||||
//是否是初始化加载
|
//是否是初始化加载
|
||||||
|
|
|
@ -125,7 +125,9 @@
|
||||||
//传入赋值方法方式赋值
|
//传入赋值方法方式赋值
|
||||||
props.setFieldsValue && props.setFieldsValue(values);
|
props.setFieldsValue && props.setFieldsValue(values);
|
||||||
// update-begin--author:liaozhiyang---date:20230831---for:【issues/5288】popup弹框,无法将选择的数据填充到自身
|
// update-begin--author:liaozhiyang---date:20230831---for:【issues/5288】popup弹框,无法将选择的数据填充到自身
|
||||||
|
// update-begin--author:liaozhiyang---date:20230811---for:【issues/5213】JPopup抛出change事件
|
||||||
emit('popUpChange', values);
|
emit('popUpChange', values);
|
||||||
|
// update-end--author:liaozhiyang---date:20230811---for:【issues/5213】JPopup抛出change事件
|
||||||
// update-begin--author:liaozhiyang---date:20230831---for:【issues/5288】popup弹框,无法将选择的数据填充到自身
|
// update-begin--author:liaozhiyang---date:20230831---for:【issues/5288】popup弹框,无法将选择的数据填充到自身
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
},
|
},
|
||||||
rowKey: {
|
rowKey: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'code',
|
default: 'id',
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
|
@ -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 for:【QQYUN-5685】5、离职人员可以选自己------------
|
||||||
|
//排除用户id的集合
|
||||||
|
excludeUserIdList:{
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
}
|
||||||
|
//update-end---author:wangshuai ---date:20230703 for:【QQYUN-5685】5、离职人员可以选自己------------
|
||||||
},
|
},
|
||||||
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 for:【QQYUN-5685】5、离职人员可以选自己------------
|
||||||
|
const excludeUserIdList = ref<any>([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要监听一下excludeUserIdList,否则modal获取不到
|
||||||
|
*/
|
||||||
|
watch(()=>props.excludeUserIdList,(data)=>{
|
||||||
|
excludeUserIdList.value = data;
|
||||||
|
},{ immediate: true })
|
||||||
|
//update-end---author:wangshuai ---date:20230703 for:【QQYUN-5685】5、离职人员可以选自己------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打卡弹出框
|
* 打卡弹出框
|
||||||
*/
|
*/
|
||||||
|
@ -141,6 +159,7 @@
|
||||||
regModal,
|
regModal,
|
||||||
setValue,
|
setValue,
|
||||||
handleOpen,
|
handleOpen,
|
||||||
|
excludeUserIdList,
|
||||||
handleChange,
|
handleChange,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -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]Upload组件returnUrl为false时上传的字段值返回了一个'[object Object]' ------------
|
||||||
|
emitValue(JSON.stringify(newFileList));
|
||||||
|
//update-end---author:liusq ---date:20230914 for:[issues/5327]Upload组件returnUrl为false时上传的字段值返回了一个'[object Object]' ------------
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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([]);
|
||||||
//替换treeNode中key字段为treeData中对应的字段
|
//替换treeNode中key字段为treeData中对应的字段
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 for:【QQYUN-5685】5、离职人员可以选自己------------
|
||||||
|
//排除用户id的集合
|
||||||
|
excludeUserIdList: {
|
||||||
|
type: Array,
|
||||||
|
default: [],
|
||||||
|
},
|
||||||
|
//update-end---author:wangshuai ---date:20230703 for:【QQYUN-5685】5、离职人员可以选自己------------
|
||||||
},
|
},
|
||||||
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---for:【issues/657】右侧选中列表删除无效
|
||||||
|
watch(rowSelection.selectedRowKeys, (newVal) => {
|
||||||
|
//update-begin---author:wangshuai ---date: 20230829 for:null指针异常导致控制台报错页面不显示------------
|
||||||
|
if(tableRef.value){
|
||||||
|
tableRef.value.setSelectedRowKeys(newVal);
|
||||||
|
}
|
||||||
|
//update-end---author:wangshuai ---date: 20230829 for:null指针异常导致控制台报错页面不显示------------
|
||||||
|
});
|
||||||
|
// update-end--author:liaozhiyang---date:20230811---for:【issues/657】右侧选中列表删除无效
|
||||||
//查询form
|
//查询form
|
||||||
const formConfig = {
|
const formConfig = {
|
||||||
baseColProps: {
|
baseColProps: {
|
||||||
|
@ -209,6 +226,29 @@
|
||||||
closeModal();
|
closeModal();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//update-begin---author:wangshuai ---date:20230703 for:【QQYUN-5685】5、离职人员可以选自己------------
|
||||||
|
/**
|
||||||
|
* 用户返回结果逻辑查询
|
||||||
|
*/
|
||||||
|
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 for:【QQYUN-5685】5、离职人员可以选自己------------
|
||||||
|
|
||||||
return {
|
return {
|
||||||
//config,
|
//config,
|
||||||
|
@ -227,6 +267,7 @@
|
||||||
handleDeleteSelected,
|
handleDeleteSelected,
|
||||||
tableScroll,
|
tableScroll,
|
||||||
tableRef,
|
tableRef,
|
||||||
|
afterFetch,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"/>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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;
|
||||||
|
//如果排除的用户id的长度不为0,那么需要改变页数
|
||||||
|
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})
|
||||||
|
}
|
||||||
|
}
|
||||||
/*--------------加载数据---------------*/
|
/*--------------加载数据---------------*/
|
||||||
|
|
||||||
/*--------------选中/取消选中---------------*/
|
/*--------------选中/取消选中---------------*/
|
||||||
|
|
|
@ -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(() => {
|
||||||
|
|
|
@ -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)'
|
||||||
|
}
|
|
@ -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,
|
||||||
|
};
|
||||||
|
};
|
|
@ -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];
|
||||||
|
|
|
@ -147,6 +147,7 @@ export type ComponentType =
|
||||||
| 'LinkTableForQuery'
|
| 'LinkTableForQuery'
|
||||||
| 'CascaderPcaForQuery'
|
| 'CascaderPcaForQuery'
|
||||||
| 'UserSelect'
|
| 'UserSelect'
|
||||||
|
| 'RoleSelect'
|
||||||
| 'RangeDate'
|
| 'RangeDate'
|
||||||
| 'RangeNumber'
|
| 'RangeNumber'
|
||||||
| 'linkRecordSelect'
|
| 'linkRecordSelect'
|
||||||
|
|
|
@ -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 for:【issues/4947】菜单编辑页面菜单图标选择模板,每页显示数量切换无效------------
|
||||||
|
current.value = page;
|
||||||
|
pageSize.value = size;
|
||||||
|
setPageSize(size);
|
||||||
|
//update-end---author:wangshuai ---date:20230522 for:【issues/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 for:【issues/4947】菜单编辑页面菜单图标选择模板,每页显示数量切换无效------------
|
||||||
|
setCurrentPage(1);
|
||||||
|
current.value = 1;
|
||||||
|
//update-end---author:wangshuai ---date:20230522 for:【issues/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 for:【issues/4947】菜单编辑页面菜单图标选择模板,每页显示数量切换无效,输入框后面的图标点击之后清空数据------------
|
||||||
|
/**
|
||||||
|
* 图标点击重置页数
|
||||||
|
*/
|
||||||
|
function currentSelectClick() {
|
||||||
|
setCurrentPage(1);
|
||||||
|
setPageSize(140);
|
||||||
|
current.value = 1;
|
||||||
|
pageSize.value = 140;
|
||||||
|
currentList.value = icons;
|
||||||
|
searchIconValue.value = '';
|
||||||
|
}
|
||||||
|
//update-begin---author:wangshuai ---date:20230522 for:【issues/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;
|
||||||
|
|
|
@ -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---for:【issues/5371】一对多子表popup增加多选
|
||||||
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---for:【issues/5371】一对多子表popup增加多选
|
||||||
});
|
});
|
||||||
// update-begin--author:liaozhiyang---date:20230811---for:【issues/675】子表字段Popup弹框数据不更新
|
// update-begin--author:liaozhiyang---date:20230811---for:【issues/675】子表字段Popup弹框数据不更新
|
||||||
const handleFocus = () => {
|
const handleFocus = () => {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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---for:【QQYUN-5866】放大行数自适应
|
||||||
|
watch(fullScreenRef,(val)=>{
|
||||||
|
emit('fullScreen',val);
|
||||||
|
});
|
||||||
|
// update-begin--author:liaozhiyang---date:20230804---for:【QQYUN-5866】放大行数自适应
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleCancel,
|
handleCancel,
|
||||||
getBindValue,
|
getBindValue,
|
||||||
|
|
|
@ -31,7 +31,9 @@
|
||||||
<!-- 增加对antdv3.x兼容 -->
|
<!-- 增加对antdv3.x兼容 -->
|
||||||
<template #bodyCell="data">
|
<template #bodyCell="data">
|
||||||
<!-- update-begin--author:liaozhiyang---date:220230717---for:【issues-179】antd3 一些警告以及报错(针对表格) -->
|
<!-- update-begin--author:liaozhiyang---date:220230717---for:【issues-179】antd3 一些警告以及报错(针对表格) -->
|
||||||
|
<!-- update-begin--author:liusq---date:20230921---for:【issues/770】slotsBak异常报错的问题,增加判断column是否存在 -->
|
||||||
<template v-if="data.column?.slotsBak?.customRender">
|
<template v-if="data.column?.slotsBak?.customRender">
|
||||||
|
<!-- update-end--author:liusq---date:20230921---for:【issues/770】slotsBak异常报错的问题,增加判断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---for:【QQYUN-5571】自封装选择列,解决数据行选择卡顿问题
|
// update-end--author:sunjianlei---date:220230630---for:【QQYUN-5571】自封装选择列,解决数据行选择卡顿问题
|
||||||
|
|
||||||
|
// update-begin--author:liaozhiyang---date:20230919---for:【QQYUN-6387】展开写法(去掉报错)
|
||||||
|
!propsData.isTreeTable && delete propsData.expandIconColumnIndex;
|
||||||
|
propsData.expandedRowKeys === null && delete propsData.expandedRowKeys;
|
||||||
|
// update-end--author:liaozhiyang---date:20230919---for:【QQYUN-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---for:【issues/638】表格合计,列表table和合计table滚动联动
|
||||||
|
if (getProps.value.showSummary) {
|
||||||
|
let tableBody;
|
||||||
|
const handleSroll = function () {
|
||||||
|
const scrollLeft = this.scrollLeft;
|
||||||
|
tableBody.forEach((elem) => (elem.scrollLeft = scrollLeft));
|
||||||
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
const unwatch = watch(
|
||||||
|
getDataSourceRef,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal.length > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
unwatch();
|
||||||
|
tableBody = wrapRef.value.querySelectorAll('.ant-table-body');
|
||||||
|
tableBody.forEach((elem) => {
|
||||||
|
elem.addEventListener('scroll', handleSroll, false);
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
console.log("---表格合计滚动---")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (tableBody.length) {
|
||||||
|
tableBody.forEach((elem) => elem.removeEventListener('scroll', handleSroll));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// update-begin--author:liaozhiyang---date:20230804---for:【issues/638】表格合计,列表table和合计table滚动联动
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tableElRef,
|
tableElRef,
|
||||||
getBindValues,
|
getBindValues,
|
||||||
|
|
|
@ -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>
|
||||||
|
@ -152,7 +160,7 @@
|
||||||
/* update-begin-author:taoyan date:2022-11-18 for: 表格默认行高比官方示例多出2px*/
|
/* update-begin-author:taoyan date:2022-11-18 for: 表格默认行高比官方示例多出2px*/
|
||||||
height: 22px;
|
height: 22px;
|
||||||
/* update-end-author:taoyan date:2022-11-18 for: 表格默认行高比官方示例多出2px*/
|
/* update-end-author:taoyan date:2022-11-18 for: 表格默认行高比官方示例多出2px*/
|
||||||
|
|
||||||
.action-divider {
|
.action-divider {
|
||||||
display: table;
|
display: table;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
|
@ -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('');
|
||||||
|
@ -140,6 +139,19 @@
|
||||||
selectFileList.value = [];
|
selectFileList.value = [];
|
||||||
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,
|
||||||
|
@ -153,7 +165,11 @@
|
||||||
queding,
|
queding,
|
||||||
buttonLoading,
|
buttonLoading,
|
||||||
getImageAsBackground,
|
getImageAsBackground,
|
||||||
viewImage
|
viewImage,
|
||||||
|
registerModel,
|
||||||
|
showFileModal,
|
||||||
|
onSelectFileOk,
|
||||||
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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(() => {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -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";
|
||||||
|
@ -45,7 +46,7 @@ export function getGloablEmojiIndex(){
|
||||||
console.log("----走window['myEmojiIndex']缓存,不new新对象!")
|
console.log("----走window['myEmojiIndex']缓存,不new新对象!")
|
||||||
return window['myEmojiIndex'];
|
return window['myEmojiIndex'];
|
||||||
}
|
}
|
||||||
|
|
||||||
window['myEmojiIndex'] = new EmojiIndex(data, {
|
window['myEmojiIndex'] = new EmojiIndex(data, {
|
||||||
function() {
|
function() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -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);
|
||||||
|
@ -230,6 +249,10 @@ export function useFileList() {
|
||||||
return bg;
|
return bg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getImageTypeIcon() {
|
||||||
|
return typeMap['image'];
|
||||||
|
}
|
||||||
|
|
||||||
function getBase64(file, id){
|
function getBase64(file, id){
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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'
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
|
}
|
|
@ -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(() => {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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---for:【QQYUN-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---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
||||||
return {
|
return {
|
||||||
t,
|
t,
|
||||||
register,
|
register,
|
||||||
handleLock,
|
handleLock,
|
||||||
|
lockModalVisible,
|
||||||
|
modalRef,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
import md5 from 'crypto-js/md5';
|
import md5 from 'crypto-js/md5';
|
||||||
|
|
||||||
import SysMessageModal from '/@/views/system/message/components/SysMessageModal.vue'
|
import SysMessageModal from '/@/views/system/message/components/SysMessageModal.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
Popover,
|
Popover,
|
||||||
|
@ -155,7 +155,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
prefixCls,
|
prefixCls,
|
||||||
listData,
|
listData,
|
||||||
|
|
|
@ -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 });
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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']);
|
||||||
|
|
|
@ -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---for:【QQYUN-6333】空路由问题—首次访问资源太大
|
||||||
|
async function handleLock() {
|
||||||
|
await getRefPromise(lockActionRef);
|
||||||
openModal(true);
|
openModal(true);
|
||||||
}
|
}
|
||||||
|
// update-end--author:liaozhiyang---date:20230901---for:【QQYUN-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---for:【QQYUN-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---for:【QQYUN-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,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getIsMixMode, getMenuWidth, getIsMixSidebar } = useMenuSetting();
|
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getIsMixMode, getMenuWidth, getIsMixSidebar } = useMenuSetting();
|
||||||
const { getUseErrorHandle, getShowSettingButton, getSettingButtonPosition } = useRootSetting();
|
const { getUseErrorHandle, getShowSettingButton, getSettingButtonPosition } = useRootSetting();
|
||||||
const { title } = useGlobSetting();
|
const { title } = useGlobSetting();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getHeaderTheme,
|
getHeaderTheme,
|
||||||
getShowFullScreen,
|
getShowFullScreen,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -39,7 +39,6 @@ export const LoginRoute: AppRouteRecordRaw = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
//update-begin---author:wangshuai ---date:20220629 for:auth2登录页面路由------------
|
|
||||||
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 for:auth2登录页面路由------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【通过token直接静默登录】流程办理登录页面 中转跳转
|
* 【通过token直接静默登录】流程办理登录页面 中转跳转
|
||||||
|
|
|
@ -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)',
|
||||||
|
];
|
||||||
|
|
|
@ -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)
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]新建企业微信和钉钉配置表,通过租户模式隔离------------
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 登录事件
|
* 登录事件
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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 });
|
||||||
|
},
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -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];
|
||||||
|
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|