UnisKB/ui/src/views/system/workspace/index.vue

244 lines
8.1 KiB
Vue
Raw Normal View History

2025-06-13 03:02:03 +00:00
<template>
2025-06-26 08:36:08 +00:00
<div class="workspace-manage p-16-24">
2025-06-13 03:02:03 +00:00
<h2 class="mb-16">{{ $t('views.workspace.title') }}</h2>
2025-06-26 08:36:08 +00:00
<el-card style="--el-card-padding: 0">
2025-06-13 03:02:03 +00:00
<div class="flex h-full">
2025-06-26 08:36:08 +00:00
<div class="workspace-left border-r">
<div class="p-24 pb-0">
<div class="flex-between mb-12">
<h4 class="medium">{{ $t('views.workspace.list') }}</h4>
<el-tooltip
effect="dark"
:content="`${$t('common.create')}${$t('views.workspace.title')}`"
placement="top"
>
2025-06-26 08:36:08 +00:00
<el-button
type="primary"
text
@click="createOrUpdateWorkspace()"
v-hasPermission="[RoleConst.ADMIN, PermissionConst.WORKSPACE_CREATE]"
>
<el-icon :size="18"><Plus /></el-icon>
</el-button>
</el-tooltip>
</div>
<el-input
v-model="filterText"
:placeholder="$t('common.search')"
prefix-icon="Search"
clearable
/>
2025-06-13 03:02:03 +00:00
</div>
<div class="list-height-left">
<el-scrollbar v-loading="loading">
2025-06-26 08:36:08 +00:00
<div class="p-16">
<common-list
:data="filterList"
@click="clickWorkspace"
:default-active="currentWorkspace?.id"
@mouseenter="mouseenter"
@mouseleave="mouseId = ''"
>
<template #default="{ row }">
<div class="flex-between">
<span class="ellipsis">{{ row.name }}</span>
<div @click.stop v-show="mouseId === row.id">
<el-dropdown :teleported="false">
<el-button text>
<el-icon class="color-secondary">
<MoreFilled />
</el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu style="min-width: 80px">
<el-dropdown-item
@click.stop="createOrUpdateWorkspace(row)"
class="p-8"
v-if="
hasPermission(
[RoleConst.ADMIN, PermissionConst.WORKSPACE_EDIT],
'OR',
)
"
>
<el-icon><EditPen /></el-icon>
{{ $t('common.rename') }}
</el-dropdown-item>
<el-dropdown-item
@click.stop="deleteWorkspace(row)"
class="border-t p-8"
v-if="
row.id !== 'default' &&
hasPermission(
[RoleConst.ADMIN, PermissionConst.WORKSPACE_DELETE],
'OR',
)
"
>
<el-icon><Delete /></el-icon>
{{ $t('common.delete') }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
<template #empty>
<span></span>
</template>
</common-list>
</div>
2025-06-13 03:02:03 +00:00
</el-scrollbar>
</div>
</div>
<!-- 右边 -->
2025-06-26 08:36:08 +00:00
<div class="workspace-right p-24" v-loading="loading">
<div class="flex align-center mb-16">
2025-06-13 03:02:03 +00:00
<h4 class="medium">{{ currentWorkspace?.name }}</h4>
2025-06-26 08:36:08 +00:00
<el-divider direction="vertical" class="mr-8 ml-8" />
<AppIcon
iconName="app-workspace"
style="font-size: 16px"
class="color-input-placeholder"
></AppIcon>
2025-06-13 03:02:03 +00:00
<span class="color-input-placeholder ml-4">
2025-06-13 04:05:56 +00:00
{{ currentWorkspace?.user_count }}
2025-06-13 03:02:03 +00:00
</span>
</div>
2025-06-26 08:36:08 +00:00
<Member :currentWorkspace="currentWorkspace" />
2025-06-13 03:02:03 +00:00
</div>
</div>
</el-card>
2025-06-26 08:36:08 +00:00
<CreateOrUpdateWorkspaceDialog ref="createOrUpdateWorkspaceDialogRef" @refresh="refresh" />
2025-06-13 03:02:03 +00:00
</div>
</template>
<script lang="ts" setup>
2025-06-26 08:36:08 +00:00
import { onMounted, ref, watch } from 'vue'
2025-06-17 11:22:50 +00:00
import WorkspaceApi from '@/api/workspace/workspace'
2025-06-26 08:36:08 +00:00
import { t } from '@/locales'
2025-06-13 03:02:03 +00:00
import Member from './component/Member.vue'
import CreateOrUpdateWorkspaceDialog from './component/CreateOrUpdateWorkspaceDialog.vue'
2025-06-26 08:36:08 +00:00
import type { WorkspaceItem } from '@/api/type/workspace'
import { MsgSuccess, MsgConfirm } from '@/utils/message'
import { PermissionConst, RoleConst } from '@/utils/permission/data'
import { hasPermission } from '@/utils/permission/index'
2025-06-13 03:02:03 +00:00
const filterText = ref('')
const loading = ref(false)
const list = ref<WorkspaceItem[]>([])
const filterList = ref<WorkspaceItem[]>([]) // 搜索过滤后列表
const currentWorkspace = ref<WorkspaceItem>()
async function getWorkspace() {
try {
const res = await WorkspaceApi.getSystemWorkspaceList(loading)
list.value = res.data
filterList.value = filter(list.value, filterText.value)
} catch (error) {
console.error(error)
}
}
onMounted(async () => {
await getWorkspace()
currentWorkspace.value = list.value[0]
})
async function refresh(workspace?: WorkspaceItem) {
2025-06-26 08:36:08 +00:00
await getWorkspace()
2025-06-13 03:02:03 +00:00
// 创建角色后选中新建的角色
currentWorkspace.value = workspace ? workspace : currentWorkspace.value
}
function filter(list: WorkspaceItem[], filterText: string) {
if (!filterText.length) {
return list
}
2025-06-26 08:36:08 +00:00
return list.filter((v: WorkspaceItem) => v.name.toLowerCase().includes(filterText.toLowerCase()))
2025-06-13 03:02:03 +00:00
}
watch(filterText, (val: string) => {
filterList.value = filter(list.value, val)
})
function clickWorkspace(item: WorkspaceItem) {
currentWorkspace.value = item
}
const createOrUpdateWorkspaceDialogRef = ref<InstanceType<typeof CreateOrUpdateWorkspaceDialog>>()
2025-06-13 04:05:56 +00:00
2025-06-13 03:02:03 +00:00
function createOrUpdateWorkspace(item?: WorkspaceItem) {
2025-06-26 08:36:08 +00:00
createOrUpdateWorkspaceDialogRef.value?.open(item)
2025-06-13 03:02:03 +00:00
}
2025-06-13 09:38:37 +00:00
async function check(id: string) {
try {
2025-06-26 08:36:08 +00:00
return await WorkspaceApi.deleteWorkspaceCheck(id)
2025-06-13 09:38:37 +00:00
} catch (error) {
2025-06-26 08:36:08 +00:00
console.log(error)
2025-06-13 09:38:37 +00:00
}
}
async function deleteWorkspace(item: WorkspaceItem) {
// 判断是否能删除
2025-06-26 08:36:08 +00:00
const res = await check(item.id as string)
const canDelete = res ? res.data.can_delete : true
2025-06-13 09:38:37 +00:00
if (canDelete) {
MsgConfirm(
`${t('views.workspace.delete.confirmTitle')}${item.name} ?`,
t('views.workspace.delete.confirmContent'),
{
confirmButtonText: t('common.confirm'),
confirmButtonClass: 'danger',
},
2025-06-26 08:36:08 +00:00
).then(() => {
WorkspaceApi.deleteWorkspace(item.id as string, loading).then(async () => {
MsgSuccess(t('common.deleteSuccess'))
await getWorkspace()
currentWorkspace.value =
item.id === currentWorkspace.value?.id ? list.value[0] : currentWorkspace.value
2025-06-13 03:02:03 +00:00
})
2025-06-26 08:36:08 +00:00
})
2025-06-13 09:38:37 +00:00
} else {
MsgConfirm(
`${t('views.workspace.delete.confirmTitle')}${item.name} ?`,
res ? res.data.message : t('views.workspace.delete.confirmContent'),
2025-06-13 09:38:37 +00:00
{
showConfirmButton: false,
cancelButtonText: t('common.close'),
},
)
}
2025-06-13 03:02:03 +00:00
}
2025-06-26 08:36:08 +00:00
const mouseId = ref('')
function mouseenter(row: any) {
mouseId.value = row.id
}
2025-06-13 03:02:03 +00:00
</script>
<style lang="scss" scoped>
2025-06-26 08:36:08 +00:00
.workspace-manage {
2025-06-13 03:02:03 +00:00
.workspace-left {
box-sizing: border-box;
width: var(--setting-left-width);
min-width: var(--setting-left-width);
.list-height-left {
height: calc(100vh - 255px);
}
}
.workspace-right {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
}
}
</style>