fix(user): user manage

This commit is contained in:
dataeaseShu
2025-07-16 15:43:39 +08:00
parent 5865b5d36d
commit 6e97f7b7fa
12 changed files with 221 additions and 110 deletions
+1
View File
@@ -22,6 +22,7 @@ export const userApi = {
edit: (data: any) => request.put('/user', data),
clearErrorApi: (key: string) => request.get(`/user/clearErrorRecord/${key}`),
delete: (key: string) => request.delete(`/user/${key}`),
deleteBatch: (data: any) => request.delete(`/user`, { data }),
get: (key: string) => request.get(`/user/${key}`),
pwd: (data: any) => request.put('/user/pwd', data),
}
+9 -2
View File
@@ -3,7 +3,14 @@ import { request } from '@/utils/request'
export const workspaceUserList = (params: any, pageNum: number, pageSize: number) =>
request.get(`/system/workspace/uws/pager/${pageNum}/${pageSize}`, { params })
export const workspaceCreate = (data: any) => request.post('/system/workspace/uws', data)
export const workspaceDelete = (data: any) => request.delete('/system/workspace/uws', data)
export const workspaceOptionUserList = (params: any, pageNum: number, pageSize: number) =>
request.get(`/system/workspace/uws/option/pager/${pageNum}/${pageSize}`, { params })
export const workspaceUwsCreate = (data: any) => request.post('/system/workspace/uws', data)
export const workspaceUwsUpdate = (data: any) => request.put('/system/workspace/uws', data)
export const workspaceCreate = (data: any) => request.post('/system/workspace', data)
export const workspaceUpdate = (data: any) => request.put('/system/workspace', data)
export const workspaceUwsDelete = (data: any) => request.delete('/system/workspace/uws', { data })
export const workspaceDelete = (data: any) => request.delete('/system/workspace', { data })
export const workspaceList = () => request.get('/system/workspace')
export const workspaceDetail = (id: any) => request.get(`/system/workspace/${id}`)
@@ -0,0 +1,5 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="14" cy="14" r="14" fill="#1CBA90"/>
<path d="M15.75 14.5832H12.25C10.6392 14.5832 8.75 15.7099 8.75 17.7332V19.3082C8.75 19.5981 9.01117 19.8332 9.33333 19.8332H18.6667C18.9888 19.8332 19.25 19.5981 19.25 19.3082V17.7332C19.25 15.7082 17.3608 14.5832 15.75 14.5832Z" fill="white"/>
<path d="M11.0833 11.0832C11.0833 12.694 12.3892 13.9998 14 13.9998C15.6108 13.9998 16.9167 12.694 16.9167 11.0832C16.9167 9.47234 15.6108 8.1665 14 8.1665C12.3892 8.1665 11.0833 9.47234 11.0833 11.0832Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 617 B

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.99998 7.05718L12.4783 2.57883C12.6085 2.44866 12.8196 2.44866 12.9497 2.57883L13.4211 3.05024C13.5513 3.18041 13.5513 3.39147 13.4211 3.52164L8.94279 7.99998L13.4211 12.4783C13.5513 12.6085 13.5513 12.8196 13.4211 12.9497L12.9497 13.4211C12.8196 13.5513 12.6085 13.5513 12.4783 13.4211L7.99998 8.94279L3.52164 13.4211C3.39147 13.5513 3.18041 13.5513 3.05024 13.4211L2.57883 12.9497C2.44866 12.8196 2.44866 12.6085 2.57883 12.4783L7.05718 7.99998L2.57883 3.52164C2.44866 3.39147 2.44866 3.18041 2.57883 3.05024L3.05024 2.57883C3.18041 2.44866 3.39147 2.44866 3.52164 2.57883L7.99998 7.05718Z" fill="#8F959E"/>
</svg>

After

Width:  |  Height:  |  Size: 724 B

+1 -1
View File
@@ -80,7 +80,7 @@
"type": "Data Source Type",
"status": "Status",
"actions": "Actions",
"pieces_in_total": "Showing {ms} records out of {msg}",
"pieces_in_total": "Showing {ms} records",
"test_connection": "Test Connection",
"check": "check",
"connection_success": "Connection Successful",
+1 -1
View File
@@ -87,7 +87,7 @@
"name": "数据源名称",
"type": "数据源类型",
"status": "状态",
"pieces_in_total": "显示 {ms} 条数据,共 {msg} 条",
"pieces_in_total": "显示 {ms} 条数据",
"actions": "操作",
"test_connection": "测试连接",
"check": "校验",
+6 -6
View File
@@ -6,16 +6,16 @@ import { computed } from 'vue'
const props = withDefaults(
defineProps<{
name: string
modleType: string
baseModle: string
modelType: string
baseModel: string
id?: string
isDefault?: boolean
supplier?: number
}>(),
{
name: '-',
modleType: '-',
baseModle: '-',
modelType: '-',
baseModel: '-',
id: '-',
isDefault: false,
supplier: 0,
@@ -47,11 +47,11 @@ const handleDel = () => {
</div>
<div class="type-value">
<span class="type">{{ $t('model.model_type') }}</span>
<span class="value"> {{ modleType }}</span>
<span class="value"> {{ modelType }}</span>
</div>
<div class="type-value">
<span class="type">{{ $t('model.basic_model') }}</span>
<span class="value"> {{ baseModle }}</span>
<span class="value"> {{ baseModel }}</span>
</div>
<div class="methods">
<el-tooltip :offset="14" effect="dark" :content="$t('datasource.edit')" placement="top">
+3 -3
View File
@@ -172,7 +172,7 @@ const preStep = () => {
}
const saveModel = () => {
modelFormRef.value.submitModle()
modelFormRef.value.submitModel()
}
const search = () => {
@@ -287,8 +287,8 @@ const submit = (item: any) => {
:key="ele.id"
:name="ele.name"
:supplier="ele.supplier"
:modle-type="getModelTypeName(ele['model_type'])"
:base-modle="ele['base_model']"
:model-type="getModelTypeName(ele['model_type'])"
:base-model="ele['base_model']"
:is-default="ele['default_model']"
@edit="handleEditModel(ele)"
@del="deleteHandler"
@@ -147,7 +147,7 @@ const initForm = (item?: any) => {
}
const emits = defineEmits(['submit'])
const submitModle = () => {
const submitModel = () => {
modelRef.value.validate((res: any) => {
if (res) {
emits('submit', {
@@ -160,7 +160,7 @@ const submitModle = () => {
defineExpose({
initForm,
submitModle,
submitModel,
supplierChang,
})
</script>
+10 -4
View File
@@ -504,6 +504,7 @@ const statusHandler = (row: any) => {
}
const cancelDelete = () => {
handleToggleRowSelection(false)
multipleSelectionAll.value = []
checkAll.value = false
isIndeterminate.value = false
@@ -515,9 +516,14 @@ const deleteBatchUser = () => {
cancelButtonText: t('common.cancel'),
customClass: 'confirm-no_icon',
autofocus: false,
callback: (val: string) => {
console.log(val)
},
}).then(() => {
userApi.deleteBatch(multipleSelectionAll.value.map((ele) => ele.id)).then(() => {
ElMessage({
type: 'success',
message: t('dashboard.delete_success'),
})
search()
})
})
}
const deleteHandler = (row: any) => {
@@ -532,7 +538,7 @@ const deleteHandler = (row: any) => {
userApi.delete(row.id).then(() => {
ElMessage({
type: 'success',
message: 'Delete completed',
message: t('dashboard.delete_success'),
})
search()
})
@@ -7,8 +7,8 @@
>
<p class="mb-8 lighter">{{ $t('workspace.member_type') }}</p>
<el-radio-group v-model="listType">
<el-radio value="0">{{ $t('workspace.ordinary_member') }}</el-radio>
<el-radio value="1">{{ $t('workspace.administrator') }}</el-radio>
<el-radio :value="0">{{ $t('workspace.ordinary_member') }}</el-radio>
<el-radio :value="1">{{ $t('workspace.administrator') }}</el-radio>
</el-radio-group>
<p class="mb-8 lighter mt-16">{{ $t('workspace.select_member') }}</p>
<div v-loading="loading" class="flex border" style="height: 428px; border-radius: 6px">
@@ -48,8 +48,11 @@
:value="space"
>
<div class="flex">
<img :src="avatar_personal" width="28px" height="28px" />
<el-icon size="28">
<avatar_personal></avatar_personal>
</el-icon>
<span class="ml-4"> {{ space.name }}</span>
<span class="account">({{ space.account }})</span>
</div>
</el-checkbox>
</el-checkbox-group>
@@ -67,11 +70,14 @@
</div>
<div v-for="ele in checkedWorkspace" :key="ele.name" class="flex-between">
<div class="flex align-center">
<img :src="avatar_personal" width="28px" height="28px" />
<el-icon size="28">
<avatar_personal></avatar_personal>
</el-icon>
<span class="ml-4 lighter">{{ ele.name }}</span>
<span class="account">({{ ele.account }})</span>
</div>
<el-button text>
<el-icon :size="18" @click="clearWorkspace(ele)"><Close /></el-icon>
<el-icon size="16" @click="clearWorkspace(ele)"><Close /></el-icon>
</el-button>
</div>
</div>
@@ -89,16 +95,16 @@
<script lang="ts" setup>
import { ref, computed } from 'vue'
import avatar_personal from '@/assets/workspace/avatar_personal.png'
import Close from '@/assets/svg/icon_close_outlined.svg'
import { workspaceOptionUserList, workspaceUwsCreate } from '@/api/workspace'
import avatar_personal from '@/assets/svg/avatar_personal.svg'
import Close from '@/assets/svg/icon_close_outlined_w.svg'
import Search from '@/assets/svg/icon_search-outline_outlined.svg'
import type { CheckboxValueType } from 'element-plus-secondary'
const checkAll = ref(false)
const isIndeterminate = ref(true)
const isIndeterminate = ref(false)
const checkedWorkspace = ref<any[]>([])
const workspace = ref<any[]>([])
const listType = ref('0')
const listType = ref(0)
const search = ref('')
const loading = ref(false)
const centerDialogVisible = ref(false)
@@ -118,29 +124,26 @@ const handleCheckedWorkspaceChange = (value: CheckboxValueType[]) => {
checkAll.value = checkedCount === workspace.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < workspace.value.length
}
let oid: any = null
const open = async () => {
const open = async (id: any) => {
loading.value = true
// const [authList, systemWorkspaceList] = await Promise.all([
// authorizationApi[`getSharedAuthorization${type}`](id),
// workspaceApi.getSystemWorkspaceList(),
// ])
// workspace.value = systemWorkspaceList.data as any
// listType.value = (authList.data || {}).authentication_type || 'WHITE_LIST'
// let workspace_id_list = (authList.data || {}).workspace_id_list || []
// checkedWorkspace.value = workspace.value.filter((ele) => workspace_id_list.includes(ele.id))
// handleCheckedWorkspaceChange(checkedWorkspace.value)
// loading.value = false
// centerDialogVisible.value = true
oid = id
const systemWorkspaceList = await workspaceOptionUserList({ oid }, 1, 1000)
workspace.value = systemWorkspaceList.items as any
loading.value = false
centerDialogVisible.value = true
}
const emits = defineEmits(['refresh'])
const handleConfirm = () => {
// authorizationApi[`postSharedAuthorization${currentType}`](knowledge_id, {
// workspace_id_list: checkedWorkspace.value.map((ele: any) => ele.id),
// authentication_type: listType.value,
// }).then(() => {
// centerDialogVisible.value = false
// })
workspaceUwsCreate({
uid_list: checkedWorkspace.value.map((ele: any) => ele.id),
oid,
weight: listType.value,
}).then(() => {
centerDialogVisible.value = false
emits('refresh')
})
}
const clearWorkspace = (val: any) => {
@@ -176,12 +179,32 @@ defineExpose({
line-height: 22px;
}
.checkbox-group-block {
.ed-checkbox,
.ed-checkbox__label,
.flex {
width: 100%;
height: 44px;
}
.flex {
align-items: center;
.account {
color: #8f959e;
}
}
}
.border {
border: 1px solid #dee0e3;
}
.w-full {
width: 100%;
.flex-between {
height: 44px;
}
}
.mt-8 {
+128 -62
View File
@@ -1,6 +1,14 @@
<script lang="ts" setup>
import { ref, computed, onMounted, reactive } from 'vue'
import { workspaceList, workspaceUserList } from '@/api/workspace'
import {
workspaceList,
workspaceUserList,
workspaceDelete,
workspaceUwsDelete,
workspaceCreate,
workspaceUpdate,
workspaceUwsUpdate,
} from '@/api/workspace'
import icon_add_outlined from '@/assets/svg/icon_add_outlined.svg'
import arrow_down from '@/assets/svg/arrow-down.svg'
import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlined.svg'
@@ -20,14 +28,14 @@ import icon_done_outlined from '@/assets/svg/icon_done_outlined.svg'
const { t } = useI18n()
const multipleSelectionAll = ref<any[]>([])
const tableList = ref([] as any[])
const keywords = ref('')
const keyword = ref('')
const keywordsMember = ref('')
const workspaceFormRef = ref()
const authorizedWorkspaceDialog = ref()
const tableListWithSearch = computed(() => {
if (!keywords.value) return tableList.value
if (!keyword.value) return tableList.value
return tableList.value.filter((ele) =>
ele.name.toLowerCase().includes(keywords.value.toLowerCase())
ele.name.toLowerCase().includes(keyword.value.toLowerCase())
)
})
const workspaceForm = reactive({
@@ -38,16 +46,26 @@ const workspaceForm = reactive({
const userTypeList = [
{
name: t('workspace.administrator'),
value: '0',
value: 1,
},
{
name: t('workspace.ordinary_member'),
value: '1',
value: 0,
},
]
const handleUserTypeChange = (val: any, row: any) => {
row.user_source = val
workspaceUwsUpdate({
uid: row.id,
oid: currentTable.value.id,
weight: val,
}).then(() => {
ElMessage({
type: 'success',
message: t('common.save_success'),
})
search()
})
}
const rules = {
@@ -60,7 +78,7 @@ const rules = {
],
}
const fieldListWithSearch = computed(() => {
if (!keywords.value) return fieldList.value
if (!keyword.value) return fieldList.value
return fieldList.value.filter((ele: any) =>
ele.name.toLowerCase().includes(keywordsMember.value.toLowerCase())
)
@@ -81,7 +99,7 @@ const checkAll = ref(false)
const fieldList = ref<any>([])
const pageInfo = reactive({
currentPage: 1,
pageSize: 1,
pageSize: 10,
total: 0,
})
@@ -91,6 +109,7 @@ const clickTable = (table: any) => {
search()
}
const cancelDelete = () => {
handleToggleRowSelection(false)
multipleSelectionAll.value = []
checkAll.value = false
isIndeterminate.value = false
@@ -104,11 +123,20 @@ const deleteBatchUser = () => {
cancelButtonText: t('common.cancel'),
customClass: 'confirm-no_icon',
autofocus: false,
callback: (val: string) => {
console.log(val)
},
}
)
).then(() => {
workspaceUwsDelete({
uid_list: multipleSelectionAll.value.map((ele) => ele.id),
oid: currentTable.value.id,
}).then(() => {
ElMessage({
type: 'success',
message: t('dashboard.delete_success'),
})
multipleSelectionAll.value = []
search()
})
})
}
const deleteHandler = (row: any) => {
ElMessageBox.confirm(t('workspace.member_feng_yibudao', { msg: row.name }), {
@@ -117,25 +145,18 @@ const deleteHandler = (row: any) => {
cancelButtonText: t('common.cancel'),
customClass: 'confirm-no_icon',
autofocus: false,
callback: (val: string) => {
console.log(val)
},
})
.then(() => {
/* userApi.delete(id).then(() => {
ElMessage({
type: 'success',
message: 'Delete completed',
})
search()
}) */
})
.catch(() => {
}).then(() => {
workspaceUwsDelete({
uid_list: [row.id],
oid: currentTable.value.id,
}).then(() => {
ElMessage({
type: 'info',
message: 'Delete canceled',
type: 'success',
message: t('dashboard.delete_success'),
})
search()
})
})
}
const handleSelectionChange = (val: any[]) => {
const ids = fieldList.value.map((ele: any) => ele.id)
@@ -170,18 +191,21 @@ const handleToggleRowSelection = (check: boolean = true) => {
}
const handleAddMember = () => {
authorizedWorkspaceDialog.value.open(1)
authorizedWorkspaceDialog.value.open(currentTable.value.id)
}
const refresh = () => {
search()
}
const search = () => {
workspaceUserList({ oid: currentTable.value.id }, pageInfo.currentPage, pageInfo.pageSize).then(
(res) => {
fieldList.value = res.items
fieldList.value = [{ id: 0, user_source: '管理员' }]
// datasourceApi.previewData(props.info.id, buildData()).then((res) => {
// previewData.value = res
// })
}
)
workspaceUserList(
{ oid: currentTable.value.id, keyword: keywordsMember.value },
pageInfo.currentPage,
pageInfo.pageSize
).then((res) => {
fieldList.value = res.items
pageInfo.total = res.total
})
}
const closeField = () => {
@@ -191,7 +215,15 @@ const closeField = () => {
const saveField = () => {
workspaceFormRef.value.validate((res: any) => {
if (res) {
console.log(res)
const req = workspaceForm.id ? workspaceUpdate : workspaceCreate
req(workspaceForm).then(() => {
ElMessage({
type: 'success',
message: t('common.save_success'),
})
init()
fieldDialog.value = false
})
}
})
}
@@ -203,25 +235,17 @@ const delWorkspace = (row: any) => {
cancelButtonText: t('common.cancel'),
customClass: 'confirm-no_icon',
autofocus: false,
callback: (val: string) => {
console.log(val)
},
})
.then(() => {
/* userApi.delete(id).then(() => {
ElMessage({
type: 'success',
message: 'Delete completed',
})
search()
}) */
})
.catch(() => {
}).then(() => {
workspaceDelete({
id: row.id,
}).then(() => {
ElMessage({
type: 'info',
message: 'Delete canceled',
type: 'success',
message: t('dashboard.delete_success'),
})
init()
})
})
}
const addWorkspace = (row: any) => {
@@ -258,7 +282,7 @@ const handleCurrentChange = (val: number) => {
</el-tooltip>
</div>
<el-input
v-model="keywords"
v-model="keyword"
clearable
style="width: 232px"
:placeholder="$t('datasource.search')"
@@ -311,7 +335,7 @@ const handleCurrentChange = (val: number) => {
</div>
</el-popover>
</div>
<div v-if="!!keywords && !tableListWithSearch.length" class="no-result">
<div v-if="!!keyword && !tableListWithSearch.length" class="no-result">
{{ $t('workspace.historical_dialogue') }}
</div>
</div>
@@ -338,6 +362,8 @@ const handleCurrentChange = (val: number) => {
v-model="keywordsMember"
clearable
style="width: 232px"
@blur="search"
@keyup.enter="search"
:placeholder="$t('workspace.name_username_email')"
>
<template #prefix>
@@ -376,15 +402,19 @@ const handleCurrentChange = (val: number) => {
<el-table-column prop="email" :label="$t('user.email')" width="204" />
<el-table-column
class-name="user-source"
prop="user_source"
:label="$t('user.user_source')"
prop="weight"
:label="$t('workspace.member_type')"
width="120"
>
<template #default="scope">
<el-popover popper-class="system-workspace_user" placement="bottom">
<template #reference>
<div style="display: flex; align-items: center; justify-content: space-between">
<span>{{ scope.row.user_source }}</span>
<span>{{
scope.row.weight === 1
? t('workspace.administrator')
: t('workspace.ordinary_member')
}}</span>
<el-icon size="16">
<arrow_down></arrow_down>
</el-icon>
@@ -474,7 +504,10 @@ const handleCurrentChange = (val: number) => {
</div>
</div>
</div>
<AuthorizedWorkspaceDialog ref="authorizedWorkspaceDialog"></AuthorizedWorkspaceDialog>
<AuthorizedWorkspaceDialog
@refresh="refresh"
ref="authorizedWorkspaceDialog"
></AuthorizedWorkspaceDialog>
<el-dialog
v-model="fieldDialog"
:title="$t(workspaceForm.id ? 'workspace.rename_a_workspace' : 'workspace.add_workspace')"
@@ -728,6 +761,39 @@ const handleCurrentChange = (val: number) => {
}
}
}
.bottom-select {
position: absolute;
height: 64px;
width: 100%;
left: 0;
bottom: 0;
border-top: 1px solid #1f232926;
display: flex;
align-items: center;
padding-left: 24px;
.danger-button {
border: 1px solid var(--ed-color-danger);
color: var(--ed-color-danger);
border-radius: var(--ed-border-radius-base);
min-width: 80px;
height: 32px;
line-height: 32px;
text-align: center;
cursor: pointer;
margin: 0 16px;
background-color: transparent;
}
.selected {
font-weight: 400;
font-size: 14px;
line-height: 22px;
color: #646a73;
margin-right: 12px;
}
}
}
}
</style>