refactor: 系统和组织的用户组用splitbox重构

This commit is contained in:
RubyLiu 2023-10-25 15:24:23 +08:00 committed by Craftsman
parent 61e7c4d197
commit 6aef0347ae
5 changed files with 99 additions and 172 deletions

View File

@ -47,12 +47,23 @@
</template>
</a-table>
</div>
<div
class="fixed bottom-[16px] right-[16px] z-[999] flex justify-between bg-white p-[24px] shadow-[0_-1px_4px_rgba(2,2,2,0.1)]"
:style="{ width: props.width }"
>
<ms-button class="btn" :disabled="!canSave" @click="handleReset">{{ t('system.userGroup.reset') }}</ms-button>
<a-button class="btn" :disabled="!canSave" type="primary" @click="handleSave">{{
t('system.userGroup.save')
}}</a-button>
</div>
</template>
<script setup lang="ts">
import { computed, inject, ref, RenderFunction, VNodeChild, watchEffect } from 'vue';
import { Message, type TableColumnData, type TableData } from '@arco-design/web-vue';
import MsButton from '@/components/pure/ms-button/index.vue';
import { getAuthByUserGroup, saveProjectUGSetting } from '@/api/modules/project-management/usergroup';
import {
getGlobalUSetting,
@ -84,6 +95,7 @@
const props = defineProps<{
current: CurrentUserGroupItem;
width?: string;
}>();
const systemType = inject<AuthScopeEnum>('systemType');
@ -334,11 +346,6 @@
initData(props.current.id, props.current.internal);
}
});
defineExpose({
handleReset,
handleSave,
canSave,
});
</script>
<style scoped lang="less">

View File

@ -2,6 +2,7 @@
<router-view v-slot="{ Component, route }">
<transition name="fade" mode="out-in" appear>
<!-- transition内必须有且只有一个根元素不然会导致二级路由的组件无法渲染 -->
<!-- eslint-disable-next-line vue/require-toggle-inside-transition -->
<div class="page-content">
<component :is="Component" v-if="!route.meta.isCache" :key="route.fullPath" />
<keep-alive v-else>

View File

@ -0,0 +1,6 @@
export function addPixelValues(...values: string[]) {
const pixelValues = values.filter((v) => v.endsWith('px')).map((v) => parseInt(v, 10));
const totalValue = pixelValues.reduce((acc, val) => acc + val, 0);
return `${totalValue}px`;
}
export default {};

View File

@ -1,54 +1,51 @@
<template>
<div class="card">
<div class="flex h-full flex-row">
<div v-if="leftCollapse" class="user-group-left ms-scroll-bar">
<MsSplitBox v-model:width="leftWidth" @expand-change="handleCollapse">
<template #left>
<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">
<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>
</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"
:current="currentUserGroupItem"
:width="bottomWidth"
/>
</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>
</div>
<div
v-if="currentTable === 'auth'"
class="fixed bottom-[16px] right-[16px] z-[999] flex justify-between bg-white p-[24px] shadow-[0_-1px_4px_rgba(2,2,2,0.1)]"
:style="{ width: `calc(100% - ${menuWidth + 16}px)` }"
>
<ms-button class="btn" :disabled="!canSave" @click="handleReset">{{ t('system.userGroup.reset') }}</ms-button>
<a-button class="btn" :disabled="!canSave" type="primary" @click="handleSave">{{
t('system.userGroup.save')
}}</a-button>
</template>
</MsSplitBox>
</div>
</template>
@ -58,13 +55,14 @@
*/
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';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import { addPixelValues } from '@/utils/css';
import { CurrentUserGroupItem } from '@/models/setting/usergroup';
import { AuthScopeEnum } from '@/enums/commonEnum';
@ -72,7 +70,6 @@
//
provide('systemType', AuthScopeEnum.ORGANIZATION);
const currentTable = ref('user');
const leftCollapse = ref(true);
const { t } = useI18n();
const currentKeyword = ref('');
@ -83,13 +80,17 @@
type: AuthScopeEnum.ORGANIZATION,
internal: true,
});
const authRef = ref<{
handleReset: () => void;
handleSave: () => void;
canSave: boolean;
}>();
const userRef = ref();
const appStore = useAppStore();
const leftCollapse = ref(true);
const leftWidth = ref('300px');
const bottomWidth = computed(() => {
const width = appStore.menuCollapse ? '86px' : `${appStore.menuWidth}px`;
if (leftCollapse.value) {
return `calc(100% - ${addPixelValues(width, leftWidth.value, '20px')})`;
}
return `calc(100% - ${addPixelValues(width, '16px')})`;
});
const tableSearch = () => {
if (currentTable.value === 'user' && userRef.value) {
@ -112,44 +113,24 @@
const couldShowUser = computed(() => currentUserGroupItem.value.type === AuthScopeEnum.ORGANIZATION);
const couldShowAuth = computed(() => currentUserGroupItem.value.id !== 'admin');
const handleSelect = (item: CurrentUserGroupItem) => {
currentUserGroupItem.value = item;
};
const handleCollapse = () => {
leftCollapse.value = !leftCollapse.value;
if (leftCollapse.value) {
const handleCollapse = (collapse: boolean) => {
leftCollapse.value = collapse;
if (collapse) {
leftWidth.value = '300px';
nextTick(() => {
ugLeftRef.value?.initData(currentUserGroupItem.value.id);
});
}
};
const menuWidth = computed(() => {
const width = appStore.menuCollapse ? 86 : appStore.menuWidth;
if (leftCollapse.value) {
return width + 300;
}
return width;
});
const handleSelect = (item: CurrentUserGroupItem) => {
currentUserGroupItem.value = item;
};
const handleReset = () => {
authRef.value?.handleReset();
};
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;
}
return true;
});
watchEffect(() => {
if (!couldShowAuth.value) {
currentTable.value = 'user';
@ -173,27 +154,4 @@
border-radius: var(--border-radius-large);
box-shadow: 0 0 10px rgb(120 56 135 / 5%);
}
.user-group-left {
position: relative;
overflow-x: hidden;
overflow-y: auto;
padding-right: 6px;
width: 300px;
min-width: 300px;
height: 100%;
border-right: 1px solid var(--color-border-1);
}
.usergroup-collapse {
position: absolute;
top: 50%;
z-index: 101;
display: flex;
justify-content: center;
align-items: center;
width: 16px;
height: 36px;
background-color: var(--color-text-n8);
flex-shrink: 0;
cursor: pointer;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="card">
<MsSplitBox @expand-change="handleCollapse">
<MsSplitBox v-model:width="leftWidth" @expand-change="handleCollapse">
<template #left>
<UserGroupLeft ref="ugLeftRef" @handle-select="handleSelect" @add-user-success="handleAddMember" />
</template>
@ -37,22 +37,16 @@
:keyword="currentKeyword"
:current="currentUserGroupItem"
/>
<AuthTable v-if="currentTable === 'auth' && couldShowAuth" ref="authRef" :current="currentUserGroupItem" />
<AuthTable
v-if="currentTable === 'auth' && couldShowAuth"
:current="currentUserGroupItem"
:width="bottomWidth"
/>
</div>
</div>
</template>
</MsSplitBox>
</div>
<div
v-if="currentTable === 'auth'"
class="fixed bottom-[16px] right-[16px] z-[999] flex justify-between bg-white p-[24px] shadow-[0_-1px_4px_rgba(2,2,2,0.1)]"
:style="{ width: `calc(100% - ${menuWidth + 16}px)` }"
>
<ms-button class="btn" :disabled="!canSave" @click="handleReset">{{ t('system.userGroup.reset') }}</ms-button>
<a-button class="btn" :disabled="!canSave" type="primary" @click="handleSave">{{
t('system.userGroup.save')
}}</a-button>
</div>
</template>
<script lang="ts" setup>
@ -61,7 +55,6 @@
*/
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';
@ -69,6 +62,7 @@
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import { addPixelValues } from '@/utils/css';
import { CurrentUserGroupItem } from '@/models/setting/usergroup';
import { AuthScopeEnum } from '@/enums/commonEnum';
@ -79,6 +73,7 @@
const { t } = useI18n();
const currentKeyword = ref('');
const ugLeftRef = ref();
const currentUserGroupItem = ref<CurrentUserGroupItem>({
id: '',
name: '',
@ -86,15 +81,17 @@
internal: true,
});
const leftCollapse = ref(true);
const authRef = ref<{
handleReset: () => void;
handleSave: () => void;
canSave: boolean;
}>();
const userRef = ref();
const appStore = useAppStore();
const leftCollapse = ref(true);
const leftWidth = ref('300px');
const bottomWidth = computed(() => {
const width = appStore.menuCollapse ? '86px' : `${appStore.menuWidth}px`;
if (leftCollapse.value) {
return `calc(100% - ${addPixelValues(width, leftWidth.value, '20px')})`;
}
return `calc(100% - ${addPixelValues(width, '16px')})`;
});
const tableSearch = () => {
if (currentTable.value === 'user' && userRef.value) {
@ -128,32 +125,14 @@
const couldShowUser = computed(() => currentUserGroupItem.value.type === AuthScopeEnum.SYSTEM);
const couldShowAuth = computed(() => currentUserGroupItem.value.id !== 'admin');
const handleCollapse = (collapse: boolean) => {
leftCollapse.value = collapse;
if (collapse) {
leftWidth.value = '300px';
nextTick(() => {
ugLeftRef.value?.initData(currentUserGroupItem.value.id);
});
}
};
const menuWidth = computed(() => {
const width = appStore.menuCollapse ? 86 : appStore.menuWidth;
if (leftCollapse.value) {
return width + 300;
}
return width;
});
const handleReset = () => {
authRef.value?.handleReset();
};
const handleSave = () => {
authRef.value?.handleSave();
};
const canSave = computed(() => {
if (currentTable.value === 'auth') {
return authRef.value?.canSave;
}
return true;
});
watchEffect(() => {
if (!couldShowAuth.value) {
currentTable.value = 'user';
@ -177,28 +156,4 @@
border-radius: var(--border-radius-large);
box-shadow: 0 0 10px rgb(120 56 135 / 5%);
}
.user-group-left {
position: relative;
overflow-x: hidden;
overflow-y: auto;
padding-right: 6px;
padding-bottom: 24px;
width: 300px;
min-width: 300px;
height: 100%;
border-right: 1px solid var(--color-border-1);
}
.usergroup-collapse {
position: absolute;
top: 50%;
z-index: 101;
display: flex;
justify-content: center;
align-items: center;
width: 16px;
height: 36px;
background-color: var(--color-text-n8);
flex-shrink: 0;
cursor: pointer;
}
</style>