413 lines
12 KiB
Vue
413 lines
12 KiB
Vue
<template>
|
|
<div class="group p-16-24">
|
|
<div class="mb-16">
|
|
<h2>{{ $t('views.chatUser.title') }}</h2>
|
|
<div class="color-secondary">
|
|
{{
|
|
resource.resource_type === SourceTypeEnum.APPLICATION
|
|
? $t('views.chatUser.applicationTitleTip')
|
|
: $t('views.chatUser.knowledgeTitleTip')
|
|
}}
|
|
</div>
|
|
</div>
|
|
<el-card style="--el-card-padding: 0">
|
|
<div class="flex">
|
|
<div class="user-left border-r">
|
|
<div class="p-24 pb-0">
|
|
<h4 class="medium mb-12">{{ $t('views.chatUser.group.title') }}</h4>
|
|
<el-input
|
|
v-model="filterText"
|
|
:placeholder="$t('common.search')"
|
|
prefix-icon="Search"
|
|
clearable
|
|
/>
|
|
</div>
|
|
<div class="list-height-left">
|
|
<el-scrollbar v-loading="loading">
|
|
<div class="p-16">
|
|
<common-list
|
|
:data="filterList"
|
|
@click="clickUserGroup"
|
|
:default-active="current?.id"
|
|
>
|
|
<template #default="{ row }">
|
|
<span class="ellipsis-1" :title="row.name">{{ row.name }}</span>
|
|
</template>
|
|
<template #empty>
|
|
<span></span>
|
|
</template>
|
|
</common-list>
|
|
</div>
|
|
</el-scrollbar>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右边 -->
|
|
<div class="user-right" v-loading="rightLoading">
|
|
<div class="flex-between">
|
|
<div class="flex align-center">
|
|
<h4 class="medium ellipsis" :title="current?.name">{{ current?.name || '-' }}</h4>
|
|
<el-divider direction="vertical" class="mr-8 ml-8" />
|
|
|
|
<el-icon class="color-input-placeholder"><UserFilled /></el-icon>
|
|
<span class="color-input-placeholder ml-4">
|
|
{{ paginationConfig.total }}
|
|
</span>
|
|
</div>
|
|
<el-button
|
|
type="primary"
|
|
:disabled="current?.is_auth"
|
|
@click="handleSave"
|
|
v-if="
|
|
route.path.includes('share/')
|
|
? false
|
|
: hasPermission(
|
|
permissionObj[
|
|
route.path.includes('shared')
|
|
? 'SHAREDKNOWLEDGE'
|
|
: (route.meta?.resourceType as string)
|
|
],
|
|
'OR',
|
|
)
|
|
"
|
|
>
|
|
{{ t('common.save') }}
|
|
</el-button>
|
|
</div>
|
|
|
|
<div class="flex-between mb-16" style="margin-top: 18px">
|
|
<div class="flex complex-search">
|
|
<el-select class="complex-search__left" v-model="searchType" style="width: 120px">
|
|
<el-option :label="$t('views.login.loginForm.username.label')" value="name" />
|
|
</el-select>
|
|
<el-input
|
|
v-if="searchType === 'name'"
|
|
v-model="searchForm.name"
|
|
@change="getList"
|
|
:placeholder="$t('common.inputPlaceholder')"
|
|
style="width: 220px"
|
|
clearable
|
|
/>
|
|
</div>
|
|
<div
|
|
class="flex align-center"
|
|
v-if="
|
|
route.path.includes('share/')
|
|
? false
|
|
: hasPermission(
|
|
permissionObj[
|
|
route.path.includes('shared')
|
|
? 'SHAREDKNOWLEDGE'
|
|
: (route.meta?.resourceType as string)
|
|
],
|
|
'OR',
|
|
)
|
|
"
|
|
>
|
|
<div class="color-secondary mr-8">{{ $t('views.chatUser.autoAuthorization') }}</div>
|
|
<el-switch
|
|
size="small"
|
|
:model-value="current?.is_auth"
|
|
@click="changeAuth"
|
|
:loading="loading"
|
|
></el-switch>
|
|
</div>
|
|
</div>
|
|
|
|
<app-table
|
|
:data="tableData"
|
|
:pagination-config="paginationConfig"
|
|
@sizeChange="handleSizeChange"
|
|
@changePage="getList"
|
|
:maxTableHeight="350"
|
|
>
|
|
<el-table-column
|
|
prop="nick_name"
|
|
:label="$t('views.userManage.userForm.nick_name.label')"
|
|
show-overflow-tooltip
|
|
/>
|
|
<el-table-column prop="username" :label="$t('views.login.loginForm.username.label')" />
|
|
<el-table-column prop="source" :label="$t('views.userManage.source.label')">
|
|
<template #default="{ row }">
|
|
{{
|
|
row.source === 'LOCAL'
|
|
? $t('views.userManage.source.local')
|
|
: row.source === 'wecom'
|
|
? $t('views.userManage.source.wecom')
|
|
: row.source === 'lark'
|
|
? $t('views.userManage.source.lark')
|
|
: row.source === 'dingtalk'
|
|
? $t('views.userManage.source.dingtalk')
|
|
: row.source === 'OAUTH2' || row.source === 'OAuth2'
|
|
? 'OAuth2'
|
|
: row.source
|
|
}}
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column :width="140" align="center">
|
|
<template #header>
|
|
<el-checkbox
|
|
:model-value="allChecked"
|
|
:indeterminate="allIndeterminate"
|
|
:disabled="current?.is_auth"
|
|
@change="handleCheckAll"
|
|
>{{ $t('views.chatUser.authorization') }}</el-checkbox
|
|
>
|
|
</template>
|
|
<template #default="{ row }">
|
|
<el-checkbox
|
|
v-model="row.is_auth"
|
|
:indeterminate="row.indeterminate"
|
|
:disabled="current?.is_auth"
|
|
@change="(value: boolean) => handleRowChange(value, row)"
|
|
/>
|
|
</template>
|
|
</el-table-column>
|
|
</app-table>
|
|
</div>
|
|
</div>
|
|
</el-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, ref, watch, reactive, computed } from 'vue'
|
|
|
|
import { t } from '@/locales'
|
|
import type { ChatUserGroupItem, ChatUserGroupUserItem } from '@/api/type/workspaceChatUser'
|
|
import { useRoute } from 'vue-router'
|
|
import { SourceTypeEnum } from '@/enums/common'
|
|
import { MsgSuccess } from '@/utils/message'
|
|
import { ComplexPermission } from '@/utils/permission/type'
|
|
import { RoleConst, PermissionConst } from '@/utils/permission/data'
|
|
import { hasPermission } from '@/utils/permission/index'
|
|
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
|
|
|
|
const route = useRoute()
|
|
|
|
const {
|
|
params: { id, folderId },
|
|
} = route as any
|
|
|
|
const permissionObj = ref<any>({
|
|
APPLICATION: new ComplexPermission(
|
|
[RoleConst.ADMIN, RoleConst.WORKSPACE_MANAGE.getWorkspaceRole],
|
|
[
|
|
PermissionConst.APPLICATION_CHAT_USER_EDIT,
|
|
PermissionConst.APPLICATION_CHAT_USER_EDIT.getApplicationWorkspaceResourcePermission(id),
|
|
],
|
|
[],
|
|
'OR',
|
|
),
|
|
KNOWLEDGE: new ComplexPermission(
|
|
[RoleConst.ADMIN, RoleConst.WORKSPACE_MANAGE.getWorkspaceRole],
|
|
[
|
|
PermissionConst.KNOWLEDGE_CHAT_USER_EDIT,
|
|
PermissionConst.KNOWLEDGE_CHAT_USER_EDIT.getKnowledgeWorkspaceResourcePermission(id),
|
|
],
|
|
[],
|
|
'OR',
|
|
),
|
|
SHAREDKNOWLEDGE: new ComplexPermission(
|
|
[RoleConst.ADMIN],
|
|
[PermissionConst.SHARED_KNOWLEDGE_CHAT_USER_EDIT],
|
|
[],
|
|
'OR',
|
|
),
|
|
})
|
|
|
|
const resource = reactive({
|
|
resource_id: route.params.id as string,
|
|
resource_type: route.meta.resourceType as string,
|
|
})
|
|
|
|
const filterText = ref('')
|
|
const loading = ref(false)
|
|
const list = ref<ChatUserGroupItem[]>([])
|
|
const filterList = ref<ChatUserGroupItem[]>([]) // 搜索过滤后列表
|
|
const current = ref<ChatUserGroupItem>()
|
|
const apiType = computed(() => {
|
|
if (route.path.includes('shared')) {
|
|
return 'systemShare'
|
|
} else if (route.path.includes('resource-management')) {
|
|
return 'systemManage'
|
|
} else {
|
|
return 'workspace'
|
|
}
|
|
})
|
|
|
|
async function getUserGroupList() {
|
|
try {
|
|
const res = await loadSharedApi({
|
|
type: 'chatUser',
|
|
isShared: isShared.value,
|
|
systemType: apiType.value,
|
|
}).getUserGroupList(resource, loading)
|
|
list.value = res.data
|
|
filterList.value = filter(list.value, filterText.value)
|
|
} catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await getUserGroupList()
|
|
current.value = list.value[0]
|
|
})
|
|
|
|
function filter(list: ChatUserGroupItem[], filterText: string) {
|
|
if (!filterText.length) {
|
|
return list
|
|
}
|
|
return list.filter((v: ChatUserGroupItem) =>
|
|
v.name.toLowerCase().includes(filterText.toLowerCase()),
|
|
)
|
|
}
|
|
|
|
watch(filterText, (val: string) => {
|
|
filterList.value = filter(list.value, val)
|
|
})
|
|
|
|
const checkedMap = reactive<Record<string, boolean>>({}) // 选中的
|
|
|
|
function clickUserGroup(item: ChatUserGroupItem) {
|
|
// 清空跨组勾选缓存
|
|
for (const key in checkedMap) delete checkedMap[key]
|
|
current.value = item
|
|
}
|
|
|
|
async function changeAuth() {
|
|
const params = [{ user_group_id: current.value?.id as string, is_auth: !current.value?.is_auth }]
|
|
try {
|
|
await loadSharedApi({
|
|
type: 'chatUser',
|
|
systemType: apiType.value,
|
|
}).editUserGroupList(resource, params, loading)
|
|
await getUserGroupList()
|
|
current.value = {
|
|
name: current.value?.name as string,
|
|
id: current.value?.id as string,
|
|
is_auth: !current.value?.is_auth,
|
|
}
|
|
getList()
|
|
} catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|
|
|
|
const rightLoading = ref(false)
|
|
|
|
const searchType = ref('name')
|
|
const searchForm = ref<Record<string, any>>({
|
|
name: '',
|
|
})
|
|
const paginationConfig = reactive({
|
|
current_page: 1,
|
|
page_size: 20,
|
|
total: 0,
|
|
})
|
|
|
|
const tableData = ref<ChatUserGroupUserItem[]>([])
|
|
|
|
const isShared = computed(() => {
|
|
return folderId === 'share'
|
|
})
|
|
|
|
async function getList() {
|
|
if (!current.value?.id) return
|
|
try {
|
|
const res = await loadSharedApi({
|
|
type: 'chatUser',
|
|
isShared: isShared.value,
|
|
systemType: apiType.value,
|
|
}).getUserGroupUserList(
|
|
resource,
|
|
current.value?.id,
|
|
paginationConfig,
|
|
searchForm.value.name,
|
|
rightLoading,
|
|
)
|
|
// 更新缓存和回显状态
|
|
res.data.records.forEach((item: any) => {
|
|
if (checkedMap[item.id] === undefined) {
|
|
checkedMap[item.id] = item.is_auth
|
|
}
|
|
item.is_auth = checkedMap[item.id]
|
|
})
|
|
|
|
tableData.value = res.data.records
|
|
paginationConfig.total = res.data.total
|
|
} catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|
|
|
|
function handleSizeChange() {
|
|
paginationConfig.current_page = 1
|
|
getList()
|
|
}
|
|
|
|
watch(() => current.value?.id, () => {
|
|
paginationConfig.current_page = 1
|
|
getList()
|
|
})
|
|
|
|
const allChecked = computed(() =>
|
|
tableData.value.length > 0 &&
|
|
tableData.value.every(item => checkedMap[item.id])
|
|
)
|
|
|
|
const allIndeterminate = computed(() =>
|
|
!allChecked.value &&
|
|
tableData.value.some(item => checkedMap[item.id])
|
|
)
|
|
|
|
const handleCheckAll = (checked: boolean) => {
|
|
tableData.value.forEach(item => {
|
|
item.is_auth = checked
|
|
checkedMap[item.id] = checked
|
|
})
|
|
}
|
|
|
|
const handleRowChange = (value: boolean, row: ChatUserGroupUserItem) => {
|
|
row.is_auth = value
|
|
checkedMap[row.id] = value
|
|
}
|
|
|
|
async function handleSave() {
|
|
try {
|
|
const params = Object.entries(checkedMap).map(([id, is_auth]) => ({
|
|
chat_user_id: id,
|
|
is_auth,
|
|
}))
|
|
await loadSharedApi({
|
|
type: 'chatUser',
|
|
systemType: apiType.value,
|
|
}).putUserGroupUser(resource, current.value?.id as string, params, rightLoading)
|
|
MsgSuccess(t('common.saveSuccess'))
|
|
} catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.user-left {
|
|
box-sizing: border-box;
|
|
width: var(--setting-left-width);
|
|
min-width: var(--setting-left-width);
|
|
|
|
.list-height-left {
|
|
height: calc(100vh - 251px);
|
|
}
|
|
}
|
|
|
|
.user-right {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 24px;
|
|
}
|
|
</style>
|