This commit is contained in:
zlwu committed 2026-08-21 09:35:11 +08:00
1 parent b9ff9c9d67
commit 44749ae716
87 files changed
+35089 -21918

No files matched your search

File diff suppressed because it is too large. Load diff
+106 -27
View File
@@ -45,7 +45,11 @@
<el-button class="btn-ghost" :loading="loading" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" :loading="loading" @click="handleSearch"
<el-button
class="btn-main"
type="primary"
:loading="loading"
@click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
@@ -55,7 +59,7 @@
<div class="list-toolbar">
<div class="list-toolbar-row">
<ListQuickSearchInput
<ListQuickSearchInput
v-model="quickSearchKeyword"
placeholder="账号/姓名/手机号"
@search="handleQuickSearch"
@@ -105,7 +109,8 @@
</div>
<div class="list-body list-wrap">
<ListTable table-key="system-user"
<ListTable
table-key="system-user"
class="list-table"
:data="tableData"
v-loading="loading"
@@ -114,7 +119,12 @@
@selection-change="handleSelectionChange"
@row-dblclick="handleView"
>
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
<el-table-column
type="selection"
min-width="55"
align="center"
header-align="center"
/>
<el-table-column
type="index"
label="序号"
@@ -151,7 +161,27 @@
header-align="center"
>
<template #default="{ row }">
{{ formatUserDeptDisplay(row) }}
{{ row.deptName || '—' }}
</template>
</el-table-column>
<el-table-column
v-if="isColumnVisible('roles')"
prop="roles"
label="角色"
min-width="180"
align="center"
header-align="center"
>
<template #default="{ row }">
<template v-if="resolveUserRoles(row).length">
<template v-for="(role, idx) in resolveUserRoles(row)" :key="role.id">
<span v-if="idx > 0" class="user-role-sep">、</span>
<el-link type="primary" @click.stop="handleOpenRole(role.id)">{{
role.label
}}</el-link>
</template>
</template>
<span v-else>—</span>
</template>
</el-table-column>
<el-table-column
@@ -191,9 +221,9 @@
</ListTable>
<div class="pagination list-pager-bar">
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<div class="list-pager-selected">
已选 <span class="sel-num">{{ selectedRows.length }}</span> 项
</div>
<el-pagination
:current-page="pagination.page"
@@ -324,14 +354,38 @@
删除
</el-button>
</template>
<template #userRoles>
<div class="user-view-roles">
<template v-if="viewRow && resolveUserRoles(viewRow).length">
<el-tag
v-for="role in resolveUserRoles(viewRow)"
:key="role.id"
type="info"
size="small"
class="user-role-tag"
@click="handleOpenRole(role.id)"
>
{{ role.label }}
</el-tag>
</template>
<span v-else>—</span>
</div>
</template>
</SystemViewDialog>
<RoleManageDialogs ref="roleDialogsRef" />
</section>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
import {
canDeleteByCreator,
filterDeletableByCreator,
allRowsDeletableByCreator,
CREATOR_DELETE_TIP
} from '@/utils/creator-delete'
import { syncViewRowFromFlatList } from '@/utils/view-dialog-refresh'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
@@ -346,6 +400,7 @@
Delete
} from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import RoleManageDialogs from '@/components/business/role-manage-dialogs/index.vue'
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
@@ -359,12 +414,12 @@
fetchDeptTree,
fetchRoleOptions
} from '@/api/admin'
import { buildPathLabelMapFromTreeRoots } from '@/utils/tree-path'
import { useDictStore } from '@/store/modules/dict'
import { buildPathLabelMapFromTreeRoots } from '@/utils/tree-path'
import { useDictStore } from '@/store/modules/dict'
defineOptions({ name: 'SystemUser' })
defineOptions({ name: 'SystemUser' })
const dictStore = useDictStore()
const dictStore = useDictStore()
const roleOptions = ref<Array<{ label: string; value: string }>>([])
@@ -396,13 +451,20 @@ const dictStore = useDictStore()
return deptPathLabelMap.value.get(id) || row.deptName || '—'
}
function formatUserRoleDisplay(row: Api.User.UserItem) {
function resolveUserRoles(row: Api.User.UserItem) {
const ids = row.roleIds || []
if (!ids.length) return '—'
const labels = ids
.map((id) => roleOptions.value.find((o) => o.value === id)?.label)
.filter((name): name is string => Boolean(name))
return labels.length ? labels.join('、') : '—'
return ids
.map((id) => {
const label = roleOptions.value.find((o) => o.value === id)?.label
return label ? { id, label } : null
})
.filter((item): item is { id: string; label: string } => Boolean(item))
}
const roleDialogsRef = ref<InstanceType<typeof RoleManageDialogs> | null>(null)
function handleOpenRole(roleId: string) {
roleDialogsRef.value?.openView(roleId)
}
const searchForm = reactive<{ keyword: string; status: string }>({ keyword: '', status: '' })
@@ -415,18 +477,14 @@ const dictStore = useDictStore()
const listColumnDefs = [
{ prop: 'userNo', label: '用户账号' },
{ prop: 'deptName', label: '所属组织' },
{ prop: 'roles', label: '角色' },
{ prop: 'phoneNo', label: '手机号' },
{ prop: 'status', label: '状态' },
{ prop: 'createTime', label: '创建时间', defaultVisible: false }
]
const {
visibleColumns,
checkAll,
isIndeterminate,
isColumnVisible,
resetToDefault
} = usePersistedListColumns('system-user-list-columns', listColumnDefs)
const { visibleColumns, checkAll, isIndeterminate, isColumnVisible, resetToDefault } =
usePersistedListColumns('system-user-list-columns', listColumnDefs)
const dialogVisible = ref(false)
const dialogTitle = ref('新增用户')
@@ -722,9 +780,14 @@ const dictStore = useDictStore()
long: false
},
{ label: '创建时间', value: row.createTime, long: false },
{ label: '角色', value: formatUserRoleDisplay(row), long: false },
{ label: '备注', value: row.remark, long: false }
]
},
{
title: '角色',
titleStyle: 'field' as const,
fields: [],
slot: 'userRoles'
}
]
})
@@ -823,4 +886,20 @@ const dictStore = useDictStore()
margin-bottom: 0;
}
}
.user-role-tag {
margin: 2px 4px;
cursor: pointer;
}
.user-role-sep {
color: var(--mint-text-muted, var(--el-text-color-secondary));
}
.user-view-roles {
display: flex;
flex-wrap: wrap;
gap: 4px;
align-items: center;
}
</style>