210 lines
5.3 KiB
Vue
210 lines
5.3 KiB
Vue
<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: 'operation_time', width: 180 },
|
||
{ title: '操作人', key: 'operator_name', width: 120 },
|
||
{ title: '操作记录', key: 'operation_detail', ellipsis: { tooltip: true } },
|
||
]
|
||
|
||
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;
|
||
}
|
||
|
||
.action-buttons {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 16px;
|
||
margin-top: 20px;
|
||
}
|
||
</style>
|