guzhi/web/src/views/user-management/user-list/UserDetailModal.vue
Wei_佳 09469888b4 feat: 完善用户管理功能,新增用户详情弹窗和审核页面优化
- 新增UserDetailModal组件,支持用户基础信息、发票抬头和操作记录查看
- 完善用户管理API数据结构,添加用户类型字段和模拟数据优化
- 实现用户详情查看功能,支持完整信息展示
- 优化估值审核详情页样式,改进标签页和区块视觉效果
- 修复审核详情页面布局问题,提升用户体验
2025-11-14 18:05:05 +08:00

223 lines
5.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { computed, ref, watch, h } from 'vue'
import { NModal, NButton, NTabs, NTabPane, NDataTable, NSpin } from 'naive-ui'
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
data: {
type: Object,
default: () => ({}),
},
loading: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:visible'])
const activeTab = ref('basic')
watch(
() => props.visible,
(show) => {
if (!show) {
activeTab.value = 'basic'
}
}
)
const baseInfo = computed(() => props.data?.baseInfo || {})
const invoiceHeaders = computed(() => props.data?.invoiceHeaders || [])
const operationLogs = computed(() => props.data?.operationLogs || [])
const invoiceColumns = [
{ title: '公司名称', key: 'company_name', ellipsis: { tooltip: true } },
{ title: '公司税号', key: 'tax_number', ellipsis: { tooltip: true } },
{ title: '注册地址', key: 'register_address', ellipsis: { tooltip: true } },
{ title: '注册电话', key: 'register_phone' },
{ title: '开户银行', key: 'bank_name' },
{ title: '银行账号', key: 'bank_account', ellipsis: { tooltip: true } },
{ title: '邮箱', key: 'email', ellipsis: { tooltip: true } },
]
const logColumns = [
{ title: '操作时间', key: 'time', width: 160 },
{ title: '操作人', key: 'operator', width: 100 },
{
title: '操作记录',
key: 'records',
render: (row) =>
h(
'div',
{ class: 'log-record' },
row.records?.map((item, idx) => h('div', { key: idx }, item))
),
},
]
function handleClose() {
emit('update:visible', false)
}
</script>
<template>
<NModal
:show="visible"
preset="card"
title="用户信息"
style="width: 780px"
:bordered="false"
size="huge"
:mask-closable="false"
@update:show="$emit('update:visible', $event)"
>
<NSpin :show="loading">
<div class="user-detail-modal">
<NTabs v-model:value="activeTab" type="card" size="large" class="detail-tabs">
<NTabPane name="basic" tab="基础信息">
<div class="basic-info">
<div class="info-row">
<span class="label">ID</span>
<span class="value">{{ baseInfo.id || '-' }}</span>
<span class="label">手机号</span>
<span class="value">{{ baseInfo.phone || '-' }}</span>
</div>
<div class="info-row">
<span class="label">微信号</span>
<span class="value">{{ baseInfo.wechat || '-' }}</span>
<span class="label">注册时间</span>
<span class="value">{{ baseInfo.register_time || '-' }}</span>
</div>
<div class="info-row">
<span class="label">剩余次数</span>
<span class="value">{{ baseInfo.remaining_count ?? '-' }}</span>
<span class="label">用户类型</span>
<span class="value">{{ baseInfo.user_type || '-' }}</span>
</div>
<div class="info-row notes">
<span class="label">备注</span>
<div class="notes-content">{{ baseInfo.notes || '暂无备注' }}</div>
</div>
</div>
</NTabPane>
<NTabPane name="invoice" tab="发票抬头">
<NDataTable
class="section-table"
:columns="invoiceColumns"
:data="invoiceHeaders"
:pagination="false"
:bordered="false"
:single-line="false"
>
<template #empty>
<div class="empty">暂无发票抬头信息</div>
</template>
</NDataTable>
</NTabPane>
<NTabPane name="logs" tab="操作记录">
<NDataTable
class="section-table"
:columns="logColumns"
:data="operationLogs"
:pagination="false"
:bordered="false"
:single-line="false"
>
<template #empty>
<div class="empty">暂无操作记录</div>
</template>
</NDataTable>
</NTabPane>
</NTabs>
<div class="action-buttons">
<NButton @click="handleClose">取消</NButton>
<NButton type="primary" @click="handleClose">确定</NButton>
</div>
</div>
</NSpin>
</NModal>
</template>
<style scoped>
.user-detail-modal {
padding: 12px 0 0;
}
.detail-tabs :deep(.n-tabs-nav-scroll-content) {
justify-content: flex-start;
}
.basic-info {
padding: 12px 8px;
}
.info-row {
display: flex;
align-items: center;
margin-bottom: 16px;
font-size: 14px;
color: #1f2329;
}
.info-row.notes {
align-items: flex-start;
}
.label {
min-width: 80px;
font-weight: 500;
}
.value {
flex: 1;
margin-right: 40px;
}
.notes-content {
flex: 1;
min-height: 60px;
padding: 12px;
border: 1px solid #ebedf0;
border-radius: 4px;
background: #fafafa;
}
.section-table {
width: 100%;
}
.section-table :deep(.n-data-table-th) {
background: #f6f7fb;
font-weight: 500;
}
.section-table :deep(.n-data-table-th),
.section-table :deep(.n-data-table-td) {
font-size: 14px;
padding: 12px;
color: #333;
}
.section-table .empty {
text-align: center;
color: #999;
padding: 24px 0;
}
.log-record div + div {
margin-top: 4px;
}
.action-buttons {
display: flex;
justify-content: center;
gap: 16px;
margin-top: 20px;
}
</style>