style(系统设置): 用户组页面样式优化

This commit is contained in:
RubyLiu 2023-10-24 19:54:38 +08:00 committed by f2c-ci-robot[bot]
parent 097ca36387
commit e3fd24cdba
17 changed files with 353 additions and 168 deletions

View File

@ -1,5 +1,6 @@
<template>
<a-popover
ref="popoverRef"
:popup-visible="currentVisible"
position="bl"
trigger="click"
@ -7,44 +8,45 @@
:content-class="props.id ? 'move-left' : ''"
>
<template #content>
<div class="form">
<a-form
ref="formRef"
:model="form"
size="large"
layout="vertical"
:label-col-props="{ span: 0 }"
:wrapper-col-props="{ span: 24 }"
>
<a-form-item>
<div class="text-[14px] text-[var(--color-text-1)]">{{
<div v-outer="handleOutsideClick">
<div class="form">
<a-form
ref="formRef"
:model="form"
size="large"
layout="vertical"
:label-col-props="{ span: 0 }"
:wrapper-col-props="{ span: 24 }"
>
<div class="mb-[8px] text-[14px] font-medium text-[var(--color-text-1)]">{{
props.id ? t('system.userGroup.rename') : t('system.userGroup.createUserGroup')
}}</div>
</a-form-item>
<a-form-item field="name" :rules="[{ validator: validateName }]">
<a-input
v-model="form.name"
class="w-[243px]"
:placeholder="t('system.userGroup.pleaseInputUserGroupName')"
@press-enter="handleBeforeOk"
@keyup.esc="handleCancel"
/>
</a-form-item>
</a-form>
</div>
<div class="flex flex-row flex-nowrap justify-end gap-2">
<a-button type="secondary" size="mini" :disabled="loading" @click="handleCancel">
{{ t('common.cancel') }}
</a-button>
<a-button
type="primary"
size="mini"
:loading="loading"
:disabled="form.name.length === 0"
@click="handleBeforeOk"
>
{{ props.id ? t('common.rename') : t('common.create') }}
</a-button>
<a-form-item field="name" :rules="[{ validator: validateName }]">
<a-input
v-model="form.name"
class="w-[243px]"
:placeholder="t('system.userGroup.pleaseInputUserGroupName')"
allow-clear
@press-enter="handleBeforeOk"
@keyup.esc="handleCancel"
/>
</a-form-item>
</a-form>
</div>
<div class="flex flex-row flex-nowrap justify-end gap-2">
<a-button type="secondary" size="mini" :disabled="loading" @click="handleCancel">
{{ t('common.cancel') }}
</a-button>
<a-button
type="primary"
size="mini"
:loading="loading"
:disabled="form.name.length === 0"
@click="handleBeforeOk"
>
{{ props.id ? t('common.rename') : t('common.create') }}
</a-button>
</div>
</div>
</template>
<slot></slot>
@ -82,6 +84,7 @@
const formRef = ref<FormInstance>();
const currentVisible = ref(props.visible);
// trigger
const form = reactive({
name: '',
@ -154,6 +157,12 @@
currentVisible.value = props.visible;
form.name = props.defaultName || '';
});
const handleOutsideClick = () => {
if (currentVisible.value) {
handleCancel();
}
};
</script>
<style lang="less">

View File

@ -1,6 +1,6 @@
<template>
<div class="ms-ug-left flex h-full flex-col px-[24px] pb-[24px]">
<div class="sticky top-0 z-[999] w-[252px] bg-white pt-[24px]">
<div class="flex flex-col px-[24px] pb-[24px]">
<div class="sticky top-0 z-[999] bg-white pt-[24px]">
<a-input-search
:placeholder="t('system.userGroup.searchHolder')"
allow-clear
@ -8,7 +8,7 @@
@search="searchData"
/>
</div>
<div v-if="showSystem" class="mt-2 w-[252px]">
<div v-if="showSystem" class="mt-2">
<CreateUserGroupPopup
:list="systemUserGroupList"
:visible="systemUserGroupVisible"
@ -36,8 +36,8 @@
{{ t('system.userGroup.systemUserGroup') }}
</div>
</div>
<MsMoreAction :list="createSystemUGActionItem" @select="systemUserGroupVisible = true">
<icon-plus-circle-fill class="text-[rgb(var(--primary-7))]" size="20" />
<MsMoreAction :list="createSystemUGActionItem" @select="handleCreateUG(AuthScopeEnum.SYSTEM)">
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
</MsMoreAction>
</div>
</CreateUserGroupPopup>
@ -56,10 +56,10 @@
@cancel="handleRenameCancel(element)"
@submit="handleRenameCancel(element, element.id)"
>
<div class="flex grow flex-row items-center justify-between">
<div class="flex max-w-[100%] grow flex-row items-center justify-between">
<a-tooltip :content="element.name">
<div
class="one-line-text max-w-[156px] text-[var(--color-text-1)]"
class="one-line-text text-[var(--color-text-1)]"
:class="{ 'text-[rgb(var(--primary-7))]': element.id === currentId }"
>{{ element.name }}</div
>
@ -90,7 +90,7 @@
</div>
</Transition>
</div>
<div v-if="showOrg" class="mt-2 w-[252px]">
<div v-if="showOrg" class="mt-2">
<CreateUserGroupPopup
:list="orgUserGroupList"
:visible="orgUserGroupVisible"
@ -119,7 +119,7 @@
</div>
</div>
<MsMoreAction :list="createOrgUGActionItem" @select="orgUserGroupVisible = true">
<icon-plus-circle-fill class="text-[rgb(var(--primary-7))]" size="20" />
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
</MsMoreAction>
</div>
</CreateUserGroupPopup>
@ -138,10 +138,10 @@
@cancel="handleRenameCancel(element)"
@submit="handleRenameCancel(element, element.id)"
>
<div class="flex grow flex-row items-center justify-between">
<div class="flex max-w-[100%] grow flex-row items-center justify-between">
<a-tooltip :content="element.name">
<div
class="one-line-text max-w-[156px] text-[var(--color-text-1)]"
class="one-line-text text-[var(--color-text-1)]"
:class="{ 'text-[rgb(var(--primary-7))]': element.id === currentId }"
>{{ element.name }}</div
>
@ -172,7 +172,7 @@
</div>
</Transition>
</div>
<div v-if="showProject" class="mt-2 w-[252px]">
<div v-if="showProject" class="mt-2">
<CreateUserGroupPopup
:list="projectUserGroupList"
:visible="projectUserGroupVisible"
@ -201,7 +201,7 @@
</div>
</div>
<MsMoreAction :list="createProjectUGActionItem" @select="projectUserGroupVisible = true">
<icon-plus-circle-fill class="text-[rgb(var(--primary-7))]" size="20" />
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
</MsMoreAction>
</div>
</CreateUserGroupPopup>
@ -220,10 +220,10 @@
@cancel="handleRenameCancel(element)"
@submit="handleRenameCancel(element, element.id)"
>
<div class="flex grow flex-row items-center justify-between">
<div class="flex max-w-[100%] grow flex-row items-center justify-between">
<a-tooltip :content="element.name">
<div
class="one-line-text max-w-[156px] text-[var(--color-text-1)]"
class="one-line-text text-[var(--color-text-1)]"
:class="{ 'text-[rgb(var(--primary-7))]': element.id === currentId }"
>{{ element.name }}</div
>
@ -254,7 +254,7 @@
</Transition>
</div>
</div>
<AddUserModal :visible="userModalVisible" :current-id="currentItem.id" @cancel="userModalVisible = false" />
<AddUserModal :visible="userModalVisible" :current-id="currentItem.id" @cancel="handleAddUserCancel" />
</template>
<script setup lang="ts">
@ -286,6 +286,7 @@
const emit = defineEmits<{
(e: 'handleSelect', element: UserGroupItem): void;
(e: 'addUserSuccess', id: string): void;
}>();
const appStore = useAppStore();
const { openModal } = useModal();
@ -383,16 +384,13 @@
}
if (res.length > 0) {
userGroupList.value = res;
let tmpItem = res[0];
if (id) {
tmpItem = res.find((i) => i.id === id) || res[0];
}
if (isSelect) {
// leftCollapse
handleListItemClick(tmpItem);
} else {
// leftCollapse
currentId.value = id || '';
if (id) {
handleListItemClick(res.find((i) => i.id === id) || res[0]);
} else {
handleListItemClick(res[0]);
}
}
//
const tmpObj: PopVisible = {};
@ -452,7 +450,7 @@
function enterData(eve: Event) {
if (!(eve.target as HTMLInputElement).value) {
initData();
initData('', false);
return;
}
const keyword = (eve.target as HTMLInputElement).value;
@ -461,7 +459,7 @@
}
function searchData(value: string) {
if (!value) {
initData();
initData('', false);
return;
}
const keyword = value;
@ -480,6 +478,21 @@
defineExpose({
initData,
});
const handleCreateUG = (scoped: AuthScopeEnum) => {
if (scoped === AuthScopeEnum.SYSTEM) {
systemUserGroupVisible.value = true;
} else if (scoped === AuthScopeEnum.ORGANIZATION) {
orgUserGroupVisible.value = true;
} else if (scoped === AuthScopeEnum.PROJECT) {
projectUserGroupVisible.value = true;
}
};
const handleAddUserCancel = (shouldSearch: boolean) => {
userModalVisible.value = false;
if (shouldSearch) {
emit('addUserSuccess', currentId.value);
}
};
</script>
<style lang="less" scoped>

View File

@ -79,7 +79,7 @@
const { propsRes, propsEvent, loadList, setLoadListParams, setKeyword } = useTable(getRequestBySystemType(), {
columns: userGroupUsercolumns,
scroll: { x: '100%' },
scroll: { x: '100%', minWidth: 700 },
selectable: false,
noDisable: true,
showSetting: false,

View File

@ -7,6 +7,7 @@
:disabled="props.disabled"
:filter-option="false"
allow-clear
:loading="loading"
@change="change"
@search="debouncedSearch"
>
@ -97,6 +98,8 @@
// eslint-disable-next-line no-console
console.log(error);
allOptions.value = [];
} finally {
loading.value = false;
}
};

View File

@ -1,5 +1,3 @@
import { computed, defineComponent, reactive, ref, toRefs, watch } from 'vue';
import Pager from './page-item.vue';
import EllipsisPager from './page-item-ellipsis.vue';
import StepPager from './page-item-step.vue';

View File

@ -166,7 +166,9 @@
//
const titleClass = computed(() => {
return props.isDelete ? 'ml-2 font-semibold' : 'mb-[8px] font-medium text-[var(--color-text-1)] text-[14px]';
return props.isDelete
? 'ml-2 font-[14px] text-[var(--color-text-1)]'
: 'mb-[8px] font-medium text-[var(--color-text-1)] text-[14px]';
});
watch(

View File

@ -1,53 +1,55 @@
<script lang="ts" setup>
import '@halo-dev/richtext-editor/dist/style.css';
// import { unified } from 'unified';
// import rehypeParse from 'rehype-parse';
// import rehypeFormat from 'rehype-format';
// import rehypeStringify from 'rehype-stringify';
import { useLocalStorage } from '@vueuse/core';
import useLocale from '@/locale/useLocale';
import '@halo-dev/richtext-editor/dist/style.css';
import {
ExtensionAudio,
ExtensionBlockquote,
ExtensionBold,
ExtensionBulletList,
ExtensionCode,
ExtensionCodeBlock,
ExtensionColor,
ExtensionColumn,
ExtensionColumns,
ExtensionCommands,
ExtensionDocument,
ExtensionDraggable,
ExtensionDropcursor,
ExtensionFontSize,
ExtensionGapcursor,
ExtensionHardBreak,
ExtensionHeading,
ExtensionHighlight,
ExtensionHistory,
ExtensionHorizontalRule,
ExtensionItalic,
ExtensionOrderedList,
ExtensionStrike,
ExtensionText,
ExtensionIframe,
ExtensionImage,
ExtensionTaskList,
ExtensionIndent,
ExtensionItalic,
ExtensionLink,
ExtensionTextAlign,
ExtensionUnderline,
ExtensionTable,
ExtensionNodeSelected,
ExtensionOrderedList,
ExtensionPlaceholder,
ExtensionStrike,
ExtensionSubscript,
ExtensionSuperscript,
ExtensionPlaceholder,
ExtensionHighlight,
ExtensionCommands,
ExtensionIframe,
ExtensionTable,
ExtensionTaskList,
ExtensionText,
ExtensionTextAlign,
ExtensionTrailingNode,
ExtensionUnderline,
ExtensionVideo,
ExtensionAudio,
ExtensionCodeBlock,
ExtensionColor,
ExtensionFontSize,
lowlight,
RichTextEditor,
useEditor,
ExtensionIndent,
ExtensionDraggable,
ExtensionColumns,
ExtensionColumn,
ExtensionNodeSelected,
ExtensionTrailingNode,
} from '@halo-dev/richtext-editor';
const content = useLocalStorage('content', '');

View File

@ -43,7 +43,7 @@
}
);
const emit = defineEmits(['update:width']);
const emit = defineEmits(['update:width', 'expandChange']);
const innerWidth = ref(props.width || '300px');
@ -71,8 +71,10 @@
isExpandedLeft.value = !isExpandedLeft.value;
if (isExpandedLeft.value) {
innerWidth.value = props.width || '300px';
emit('expandChange', true);
} else {
innerWidth.value = '0px';
emit('expandChange', false);
}
//
setTimeout(() => {

View File

@ -33,5 +33,9 @@ export default {
modify: 'Modify{name}',
nameIsNotNull: 'Name cannot be empty',
nameIsExist: '{name} already exists',
empty: 'No Content',
loading: 'Loading, please wait',
errorStatus: 'Failed to load data, please',
retry: 'Retry',
},
};

View File

@ -1,5 +1,6 @@
import { App } from 'vue';
import outerClick from './outerClick';
import permission from './permission';
import validateLicense from './validateLicense';
@ -7,5 +8,6 @@ export default {
install(Vue: App) {
Vue.directive('permission', permission);
Vue.directive('xpack', validateLicense);
Vue.directive('outer', outerClick);
},
};

View File

@ -0,0 +1,104 @@
import { isServerRendering } from '@/utils/dom';
import type { ComponentPublicInstance, DirectiveBinding, ObjectDirective } from 'vue';
export const isElement = (e: unknown): e is Element => {
if (typeof Element === 'undefined') return false;
return e instanceof Element;
};
type DocumentHandler = <T extends MouseEvent>(mouseup: T, mousedown: T) => void;
type FlushList = Map<
HTMLElement,
{
documentHandler: DocumentHandler;
bindingFn: (...args: unknown[]) => unknown;
}[]
>;
const nodeList: FlushList = new Map();
let startClick: MouseEvent;
if (!isServerRendering) {
document.addEventListener('mousedown', (e: MouseEvent) => {
startClick = e;
});
document.addEventListener('mouseup', (e: MouseEvent) => {
nodeList.forEach((handlers) => {
handlers.forEach(({ documentHandler }) => {
documentHandler(e as MouseEvent, startClick);
});
});
});
}
function createDocumentHandler(el: HTMLElement, binding: DirectiveBinding): DocumentHandler {
let excludes: HTMLElement[] = [];
if (Array.isArray(binding.arg)) {
excludes = binding.arg;
} else if (isElement(binding.arg)) {
// due to current implementation on binding type is wrong the type casting is necessary here
excludes.push(binding.arg as unknown as HTMLElement);
}
return (mouseup, mousedown) => {
const { popperRef } = binding.instance as ComponentPublicInstance<{
popperRef: HTMLElement;
}>;
const mouseUpTarget = mouseup.target as Node;
const mouseDownTarget = mousedown?.target as Node;
const isBound = !binding || !binding.instance;
const isTargetExists = !mouseUpTarget || !mouseDownTarget;
const isContainedByEl = el.contains(mouseUpTarget) || el.contains(mouseDownTarget);
const isSelf = el === mouseUpTarget;
const isTargetExcluded =
(excludes.length && excludes.some((item) => item?.contains(mouseUpTarget))) ||
(excludes.length && excludes.includes(mouseDownTarget as HTMLElement));
const isContainedByPopper = popperRef && (popperRef.contains(mouseUpTarget) || popperRef.contains(mouseDownTarget));
if (isBound || isTargetExists || isContainedByEl || isSelf || isTargetExcluded || isContainedByPopper) {
return;
}
binding.value(mouseup, mousedown);
};
}
const ClickOutside: ObjectDirective = {
beforeMount(el: HTMLElement, binding: DirectiveBinding) {
// there could be multiple handlers on the element
if (!nodeList.has(el)) {
nodeList.set(el, []);
}
nodeList.get(el)?.push({
documentHandler: createDocumentHandler(el, binding),
bindingFn: binding.value,
});
},
updated(el: HTMLElement, binding: DirectiveBinding) {
let handlers = nodeList.get(el);
if (!handlers) {
handlers = [];
nodeList.set(el, handlers);
}
const oldHandlerIndex = handlers.findIndex((item) => item.bindingFn === binding.oldValue);
const newHandler = {
documentHandler: createDocumentHandler(el, binding),
bindingFn: binding.value,
};
if (oldHandlerIndex >= 0) {
// replace the old handler to the new handler
handlers.splice(oldHandlerIndex, 1, newHandler);
} else {
handlers.push(newHandler);
}
},
unmounted(el: HTMLElement) {
// remove all listeners when a component unmounted
nodeList.delete(el);
},
};
export default ClickOutside;

View File

@ -19,4 +19,16 @@ export enum MenuEnum {
uiTest = 'uiTest',
}
export default {};
export enum ShapeFlags {
ELEMENT = 1,
FUNCTIONAL_COMPONENT = 2,
STATEFUL_COMPONENT = 4,
COMPONENT = FUNCTIONAL_COMPONENT + STATEFUL_COMPONENT,
TEXT_CHILDREN = 8,
ARRAY_CHILDREN = 16,
SLOTS_CHILDREN = 32,
TELEPORT = 64,
SUSPENSE = 128,
COMPONENT_SHOULD_KEEP_ALIVE = 256,
COMPONENT_KEPT_ALIVE = 512,
}

View File

@ -18,3 +18,46 @@ export function scrollIntoView(targetRef: HTMLElement | Element | null, options:
targetRef?.scrollIntoView(scrollOptions);
}
export const NOOP = () => {
return undefined;
};
// 判断是否为服务端渲染
export const isServerRendering = (() => {
try {
return !(typeof window !== 'undefined' && document !== undefined);
} catch (e) {
return true;
}
})();
// 监听事件
export const on = (() => {
if (isServerRendering) {
return NOOP;
}
return <K extends keyof HTMLElementEventMap>(
element: HTMLElement | Window,
event: K,
handler: (ev: HTMLElementEventMap[K]) => void,
options: boolean | AddEventListenerOptions = false
) => {
element.addEventListener(event, handler as EventListenerOrEventListenerObject, options);
};
})();
// 移除监听事件
export const off = (() => {
if (isServerRendering) {
return NOOP;
}
return <K extends keyof HTMLElementEventMap>(
element: HTMLElement | Window,
type: K,
handler: (ev: HTMLElementEventMap[K]) => void,
options: boolean | EventListenerOptions = false
) => {
element.removeEventListener(type, handler as EventListenerOrEventListenerObject, options);
};
})();

View File

@ -143,7 +143,7 @@
description: '',
resourcePoolIds: [],
enable: true,
moduleIds: [],
moduleIds: ['workstation', 'testPlan', 'bugManagement', 'caseManagement', 'apiTest', 'uiTest', 'loadTest'],
});
const currentVisible = ref(props.visible);
@ -162,7 +162,7 @@
form.organizationId = currentOrgId.value;
form.description = '';
form.enable = true;
form.moduleIds = [];
form.moduleIds = ['workstation', 'testPlan', 'bugManagement', 'caseManagement', 'apiTest', 'uiTest', 'loadTest'];
form.resourcePoolIds = [];
};
const handleCancel = (shouldSearch: boolean) => {

View File

@ -1,17 +1,13 @@
<template>
<div class="card">
<div class="flex h-full flex-row">
<Transition>
<div v-if="leftCollapse" class="user-group-left ms-scroll-bar">
<UserGroupLeft ref="ugLeftRef" @handle-select="handleSelect" />
</div>
</Transition>
<Transition>
<div class="usergroup-collapse" :style="{ left: leftCollapse ? '300px' : '0' }" @click="handleCollapse">
<icon-double-left v-if="leftCollapse" class="text-[12px] text-[var(--color-text-brand)]" />
<icon-double-right v-else class="text-[12px] text-[var(--color-text-brand)]" />
</div>
</Transition>
<div v-if="leftCollapse" class="user-group-left ms-scroll-bar">
<UserGroupLeft ref="ugLeftRef" @handle-select="handleSelect" @add-user-success="handleAddMember" />
</div>
<div class="usergroup-collapse" :style="{ left: leftCollapse ? '300px' : '0' }" @click="handleCollapse">
<icon-double-left v-if="leftCollapse" class="text-[12px] text-[var(--color-text-brand)]" />
<icon-double-right v-else class="text-[12px] text-[var(--color-text-brand)]" />
</div>
<div class="p-[24px]" :style="{ width: leftCollapse ? 'calc(100% - 300px)' : '100%' }">
<div class="flex flex-row items-center justify-between">
<a-tooltip :content="currentUserGroupItem.name">
@ -125,7 +121,7 @@
leftCollapse.value = !leftCollapse.value;
if (leftCollapse.value) {
nextTick(() => {
ugLeftRef.value?.initData(currentUserGroupItem.value.id, false);
ugLeftRef.value?.initData(currentUserGroupItem.value.id);
});
}
};
@ -143,6 +139,11 @@
const handleSave = () => {
authRef.value?.handleSave();
};
const handleAddMember = (id: string) => {
if (id === currentUserGroupItem.value.id) {
tableSearch();
}
};
const canSave = computed(() => {
if (currentTable.value === 'auth') {
return authRef.value?.canSave;
@ -195,12 +196,4 @@
flex-shrink: 0;
cursor: pointer;
}
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>

View File

@ -141,7 +141,7 @@
organizationId: '',
description: '',
enable: true,
moduleIds: [],
moduleIds: ['workstation', 'testPlan', 'bugManagement', 'caseManagement', 'apiTest', 'uiTest', 'loadTest'],
resourcePoolIds: [],
});
@ -161,7 +161,7 @@
form.organizationId = '';
form.description = '';
form.enable = true;
form.moduleIds = [];
form.moduleIds = ['workstation', 'testPlan', 'bugManagement', 'caseManagement', 'apiTest', 'uiTest', 'loadTest'];
};
const handleCancel = (shouldSearch: boolean) => {
emit('cancel', shouldSearch);

View File

@ -1,48 +1,47 @@
<template>
<div class="card">
<div class="flex h-full flex-row">
<Transition>
<div v-if="leftCollapse" class="user-group-left ms-scroll-bar">
<UserGroupLeft ref="ugLeftRef" @handle-select="handleSelect" />
</div>
</Transition>
<Transition>
<div class="usergroup-collapse" :style="{ left: leftCollapse ? '300px' : '0' }" @click="handleCollapse">
<icon-double-left v-if="leftCollapse" class="text-[12px] text-[var(--color-text-brand)]" />
<icon-double-right v-if="!leftCollapse" class="text-[12px] text-[var(--color-text-brand)]" />
</div>
</Transition>
<div class="p-[24px]" :style="{ width: leftCollapse ? 'calc(100% - 300px)' : '100%' }">
<div class="flex flex-row items-center justify-between">
<a-tooltip :content="currentUserGroupItem.name">
<div class="one-line-text max-w-[300px]">{{ currentUserGroupItem.name }}</div>
</a-tooltip>
<div class="flex items-center">
<a-input-search
v-if="currentTable === 'user'"
:placeholder="t('system.user.searchUser')"
class="w-[240px]"
allow-clear
@press-enter="handleEnter"
@search="handleSearch"
></a-input-search>
<a-radio-group v-if="couldShowUser && couldShowAuth" v-model="currentTable" class="ml-[14px]" type="button">
<a-radio v-if="couldShowAuth" value="auth">{{ t('system.userGroup.auth') }}</a-radio>
<a-radio v-if="couldShowUser" value="user">{{ t('system.userGroup.user') }}</a-radio>
</a-radio-group>
<MsSplitBox @expand-change="handleCollapse">
<template #left>
<UserGroupLeft ref="ugLeftRef" @handle-select="handleSelect" @add-user-success="handleAddMember" />
</template>
<template #right>
<div class="p-[24px]">
<div class="flex flex-row items-center justify-between">
<a-tooltip :content="currentUserGroupItem.name">
<div class="one-line-text max-w-[300px]">{{ currentUserGroupItem.name }}</div>
</a-tooltip>
<div class="flex items-center">
<a-input-search
v-if="currentTable === 'user'"
:placeholder="t('system.user.searchUser')"
class="w-[240px]"
allow-clear
@press-enter="handleEnter"
@search="handleSearch"
></a-input-search>
<a-radio-group
v-if="couldShowUser && couldShowAuth"
v-model="currentTable"
class="ml-[14px]"
type="button"
>
<a-radio v-if="couldShowAuth" value="auth">{{ t('system.userGroup.auth') }}</a-radio>
<a-radio v-if="couldShowUser" value="user">{{ t('system.userGroup.user') }}</a-radio>
</a-radio-group>
</div>
</div>
<div class="mt-[16px]">
<UserTable
v-if="currentTable === 'user' && couldShowUser"
ref="userRef"
:keyword="currentKeyword"
:current="currentUserGroupItem"
/>
<AuthTable v-if="currentTable === 'auth' && couldShowAuth" ref="authRef" :current="currentUserGroupItem" />
</div>
</div>
<div class="mt-[16px]">
<UserTable
v-if="currentTable === 'user' && couldShowUser"
ref="userRef"
:keyword="currentKeyword"
:current="currentUserGroupItem"
/>
<AuthTable v-if="currentTable === 'auth' && couldShowAuth" ref="authRef" :current="currentUserGroupItem" />
</div>
</div>
</div>
</template>
</MsSplitBox>
</div>
<div
v-if="currentTable === 'auth'"
@ -63,6 +62,7 @@
import { computed, nextTick, onMounted, provide, ref, watchEffect } from 'vue';
import MsButton from '@/components/pure/ms-button/index.vue';
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
import AuthTable from '@/components/business/ms-user-group-comp/authTable.vue';
import UserGroupLeft from '@/components/business/ms-user-group-comp/msUserGroupLeft.vue';
import UserTable from '@/components/business/ms-user-group-comp/userTable.vue';
@ -119,13 +119,18 @@
currentUserGroupItem.value = item;
};
const handleAddMember = (id: string) => {
if (id === currentUserGroupItem.value.id) {
tableSearch();
}
};
const couldShowUser = computed(() => currentUserGroupItem.value.type === AuthScopeEnum.SYSTEM);
const couldShowAuth = computed(() => currentUserGroupItem.value.id !== 'admin');
const handleCollapse = () => {
leftCollapse.value = !leftCollapse.value;
if (leftCollapse.value) {
const handleCollapse = (collapse: boolean) => {
if (collapse) {
nextTick(() => {
ugLeftRef.value?.initData(currentUserGroupItem.value.id, false);
ugLeftRef.value?.initData(currentUserGroupItem.value.id);
});
}
};
@ -177,6 +182,7 @@
overflow-x: hidden;
overflow-y: auto;
padding-right: 6px;
padding-bottom: 24px;
width: 300px;
min-width: 300px;
height: 100%;
@ -195,12 +201,4 @@
flex-shrink: 0;
cursor: pointer;
}
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>