task-52(账号/权限页面): 实现用户列表加载/空/错状态
新增 user-list-state.ts 纯 phase 归一(loading>error>empty>ready)与空/错提示; UsersPage 显式 loadError 态 + 错误 el-alert(带重试)、加载/错误/空相位决策、 删除按钮对超管禁用。8 用例全过,379 单测 + build 绿。
This commit is contained in:
@@ -1,19 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import type { AdminUser } from '@/types/admin'
|
||||
import { deleteUser, fetchUserList } from '@/api/users'
|
||||
import { createUserFilterState, toUserListParams } from './users-filter'
|
||||
import { totalPageCount } from './user-pagination'
|
||||
import { deleteBlockReason } from './user-delete-model'
|
||||
import { listPhaseOf } from './user-list-state'
|
||||
|
||||
const loading = ref(false)
|
||||
const loadError = ref('')
|
||||
const rows = ref<AdminUser[]>([])
|
||||
const total = ref(0)
|
||||
const filters = reactive(createUserFilterState())
|
||||
const statePhase = computed(() => listPhaseOf({ loading: loading.value, error: loadError.value, items: rows.value, total: total.value }))
|
||||
|
||||
async function loadUsers() {
|
||||
loading.value = true
|
||||
loadError.value = ''
|
||||
try {
|
||||
const page = await fetchUserList(toUserListParams(filters))
|
||||
rows.value = page.items
|
||||
@@ -27,12 +31,18 @@ async function loadUsers() {
|
||||
total.value = retried.total
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : '用户列表加载失败')
|
||||
loadError.value = error instanceof Error ? error.message : '用户列表加载失败'
|
||||
ElMessage.error(loadError.value)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 错误态重试:重新拉取当前筛选列表。 */
|
||||
function retry() {
|
||||
void loadUsers()
|
||||
}
|
||||
|
||||
/** 提交新筛选条件:重置回第一页再查询。 */
|
||||
function search() {
|
||||
filters.page = 1
|
||||
@@ -83,6 +93,18 @@ onMounted(loadUsers)
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<el-alert
|
||||
v-if="statePhase === 'error' && loadError"
|
||||
:title="loadError"
|
||||
type="error"
|
||||
show-icon
|
||||
:closable="false"
|
||||
style="margin-bottom: 12px"
|
||||
>
|
||||
<template #default>
|
||||
<el-button link type="primary" @click="retry">重试</el-button>
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-table v-loading="loading" :data="rows" stripe>
|
||||
<el-table-column prop="id" label="ID" width="90" />
|
||||
<el-table-column prop="username" label="用户名" min-width="180" />
|
||||
@@ -91,7 +113,7 @@ onMounted(loadUsers)
|
||||
<el-table-column prop="createdAt" label="创建时间" width="180" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="danger" @click="removeUser(row)">删除</el-button>
|
||||
<el-button link type="danger" :disabled="deleteBlockReason(row) !== undefined" @click="removeUser(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/** 用户列表加载/空/错状态(任务 52):纯 phase 归一无 UI 依赖,供页面展示决策复用。 */
|
||||
|
||||
export type ListPhase = 'loading' | 'error' | 'empty' | 'ready'
|
||||
|
||||
export interface UserListPhaseInput {
|
||||
loading?: boolean
|
||||
error?: string
|
||||
items?: unknown[]
|
||||
total?: number
|
||||
}
|
||||
|
||||
/** 归一列表展示相位:loading 优先,其次 error,其次空,否则 ready。 */
|
||||
export function listPhaseOf(input: UserListPhaseInput): ListPhase {
|
||||
if (input.loading) return 'loading'
|
||||
if (typeof input.error === 'string' && input.error.trim()) return 'error'
|
||||
const items = Array.isArray(input.items) ? input.items : []
|
||||
const total = typeof input.total === 'number' ? input.total : items.length
|
||||
if (items.length === 0 || total === 0) return 'empty'
|
||||
return 'ready'
|
||||
}
|
||||
|
||||
/** 空态提示文案。 */
|
||||
export function userListEmptyHint(): string {
|
||||
return '暂无用户数据'
|
||||
}
|
||||
|
||||
/** 错误态可操作提示:带上具体原因,缺省给通用文案。 */
|
||||
export function userListErrorHint(message?: string | null): string {
|
||||
const text = (message || '').trim()
|
||||
return text ? `加载失败:${text}` : '加载失败,请稍后重试'
|
||||
}
|
||||
Reference in New Issue
Block a user