Files
qitongxue-admin/src/views/users/UserList.vue
2026-09-17 14:44:18 +08:00

97 lines
3.4 KiB
Vue

<script setup>
import { onMounted, reactive, ref } from 'vue'
import { message } from 'ant-design-vue'
import { userListApi, userSetLevelApi, userStatusApi } from '@/api/request/user'
import { levelListApi } from '@/api/request/level'
const loading = ref(false)
const list = ref([])
const total = ref(0)
const levels = ref([])
const query = reactive({ page: 1, pageSize: 20, keyword: '' })
const columns = [
{ title: '用户', key: 'name' },
{ title: 'openid', dataIndex: 'openid', key: 'openid', ellipsis: true },
{ title: '等级', key: 'level', width: 140 },
{ title: '使用次数', dataIndex: 'usageCount', key: 'usageCount', width: 100 },
{ title: '最近使用', dataIndex: 'lastUsedAt', key: 'lastUsedAt', width: 170 },
{ title: '注册时间', dataIndex: 'createdAt', key: 'createdAt', width: 170 },
{ title: '状态', key: 'status', width: 80 },
]
async function load() {
loading.value = true
try {
const res = await userListApi({ ...query, keyword: query.keyword || undefined })
list.value = res.list
total.value = res.total
} finally {
loading.value = false
}
}
async function loadLevels() {
const res = await levelListApi()
levels.value = res.list.filter((l) => l.isEnabled === 1)
}
onMounted(() => {
load()
loadLevels()
})
async function setLevel(record, levelKey) {
await userSetLevelApi({ userId: record.id, levelKey })
record.levelKey = levelKey
const target = levels.value.find((l) => l.levelKey === levelKey)
record.levelName = target?.name || levelKey
message.success(`已设为 ${record.levelName}`)
}
async function toggleStatus(record) {
await userStatusApi({ userId: record.id, status: record.status })
message.success(record.status === 1 ? '已启用' : '已禁用')
}
function onTableChange(pag) {
query.page = pag.current
query.pageSize = pag.pageSize
load()
}
</script>
<template>
<div class="flex flex-col gap-4">
<a-input-search v-model:value="query.keyword" placeholder="昵称 / openid" style="width: 280px" allowClear
@search="load" />
<a-table :columns="columns" :data-source="list" row-key="id" :loading="loading"
:pagination="{ current: query.page, pageSize: query.pageSize, total, showSizeChanger: false }"
@change="onTableChange">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'name'">
<div class="flex items-center gap-2">
<span class="inline-flex w-9 h-9 rounded-xl bg-[#FFF1E8] items-center justify-center text-[#E8531A]">
<template v-if="record.avatarUrl">
<img :src="record.avatarUrl" class="w-9 h-9 rounded-xl object-cover" alt="" />
</template>
<template v-else>{{ (record.nickname || '微').slice(0, 1) }}</template>
</span>
<span class="font-medium text-slate-700">{{ record.nickname }}</span>
</div>
</template>
<template v-else-if="column.key === 'level'">
<a-select :value="record.levelKey" size="small" style="width: 110px"
:options="levels.map((l) => ({ value: l.levelKey, label: l.name }))"
@change="(v) => setLevel(record, v)" />
</template>
<template v-else-if="column.key === 'status'">
<a-switch :checked="record.status === 1" size="small"
@change="(v) => { record.status = v ? 1 : 0; toggleStatus(record) }" />
</template>
</template>
</a-table>
</div>
</template>