<template>
|
<GlobalWindow
|
:title="title"
|
:visible.sync="visible"
|
width="1000px"
|
:withFooter="false"
|
>
|
<div class="detail-container">
|
<div class="section">
|
<div class="section-header">
|
<span class="section-title">用户信息</span>
|
<span class="status-tag">
|
<el-tag type="success" v-if="detailInfo.telephone">已授权手机号</el-tag>
|
<el-tag type="warning" v-else>未授权手机号</el-tag>
|
</span>
|
</div>
|
<div class="info-grid">
|
<div class="info-item">
|
<span class="label">微信openid:</span>
|
<span class="value">{{ detailInfo.openid || '' }}</span>
|
</div>
|
<div class="info-item">
|
<span class="label">用户昵称:</span>
|
<span class="value">{{ detailInfo.nickName || ''}}</span>
|
</div>
|
<div class="info-item">
|
<span class="label">会员姓名:</span>
|
<span class="value">{{ detailInfo.name || ''}}</span>
|
</div>
|
<div class="info-item">
|
<span class="label">授权手机号:</span>
|
<span class="value">{{ detailInfo.telephone||'' }}</span>
|
</div>
|
<div class="info-item">
|
<span class="label">状态:</span>
|
<span class="value">{{ detailInfo.status === 0 ? '正常' : detailInfo.status === 1 ? '停用' : '已注销' }}</span>
|
</div>
|
</div>
|
</div>
|
|
<!-- 开票历史 -->
|
<div class="section">
|
<div class="section-header">
|
<span class="section-title">开票历史</span>
|
</div>
|
|
<!-- 查询表单 -->
|
<el-form :inline="true" :model="invoiceQuery" class="query-form" style="margin-bottom: 20px;">
|
<el-form-item label="开票编号">
|
<el-input v-model="invoiceQuery.invoiceNo" placeholder="请输入开票编号" style="width: 180px;"></el-input>
|
</el-form-item>
|
<el-form-item label="发票类型">
|
<el-select v-model="invoiceQuery.invoiceType" placeholder="请选择发票类型" style="width: 150px;">
|
<el-option label="电子普通发票" value="0"></el-option>
|
<el-option label="电子专用发票" value="1"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="抬头类型">
|
<el-select v-model="invoiceQuery.orgType" placeholder="请选择抬头类型" style="width: 150px;">
|
<el-option label="个人" value="1"></el-option>
|
<el-option label="企业" value="2"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="发票抬头">
|
<el-input v-model="invoiceQuery.name" placeholder="请输入发票抬头" style="width: 200px;"></el-input>
|
</el-form-item>
|
<el-form-item label="开票状态">
|
<el-select v-model="invoiceQuery.status" placeholder="请选择开票状态" style="width: 150px;">
|
<el-option label="申请中" value="0"></el-option>
|
<el-option label="开具成功" value="1"></el-option>
|
<el-option label="开具失败" value="99"></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="申请时间">
|
<el-date-picker
|
v-model="invoiceQuery.dateRange"
|
type="daterange"
|
range-separator="至"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
style="width: 250px;">
|
</el-date-picker>
|
</el-form-item>
|
<section>
|
<el-button type="primary" @click="queryInvoices">查询</el-button>
|
<el-button @click="resetQuery">重置</el-button>
|
</section>
|
</el-form>
|
|
<!-- 统计信息 -->
|
<div class="stats-row" style="margin-bottom: 20px;">
|
<div class="stat-item">
|
<span class="stat-label">开票数:</span>
|
<span class="stat-value">{{ invoicePage.total }}</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-label">开票总额:</span>
|
<span class="stat-value amount">¥{{ invoiceSummary.totalAmount }}</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-label">已开票总额:</span>
|
<span class="stat-value amount">¥{{ invoiceSummary.issuedAmount }}</span>
|
</div>
|
</div>
|
|
<!-- 开票历史表格 -->
|
<el-table :data="invoiceList" border style="width: 100%" :loading="invoiceLoading">
|
<el-table-column prop="orderNo" label="订单编号" min-width="120">
|
<template slot-scope="scope">
|
<a href="javascript:void(0)" @click="openInvoiceDetail(scope.row)">{{ scope.row.orderNo }}</a>
|
</template>
|
</el-table-column>
|
<el-table-column label="发票类型" min-width="120">
|
<template slot-scope="scope">
|
{{ scope.row.invoiceType === 1 ? '增值税普通发票' : '增值税专用发票' }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="orgType" label="抬头类型" min-width="100">
|
<template slot-scope="scope">
|
{{ scope.row.orgType === 0 ? '个人' : '企业' }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="name" label="发票抬头" min-width="150"></el-table-column>
|
<el-table-column prop="taxId" label="发票税号" min-width="150"></el-table-column>
|
<el-table-column label="开票金额(元)" min-width="120">
|
<template slot-scope="scope">
|
¥{{ ((scope.row.invoiceAmount || 0) / 100).toFixed(2) }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="createTime" label="申请时间" min-width="150"></el-table-column>
|
<el-table-column label="开票状态" min-width="120">
|
<template slot-scope="scope">
|
<el-tag :type="getStatusType(scope.row.status)">
|
{{ getStatusText(scope.row.status) }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<!-- 开票详情弹窗 -->
|
<OperaInvoiceDetail ref="operaInvoiceDetail" @close="handleClose" />
|
|
<!-- 分页 -->
|
<el-pagination
|
@size-change="handleSizeChange"
|
@current-change="handleCurrentChange"
|
:current-page="invoicePage.page"
|
:page-sizes="[10, 20, 50, 100]"
|
:page-size="invoicePage.size"
|
:total="invoicePage.total"
|
layout="total, sizes, prev, pager, next, jumper"
|
style="margin-top: 20px; text-align: right;">
|
</el-pagination>
|
</div>
|
</div>
|
</GlobalWindow>
|
</template>
|
|
<script>
|
import GlobalWindow from '@/components/common/GlobalWindow'
|
import { getById } from '@/api/business/memberManage'
|
import { fetchList, summary } from '@/api/business/invoiceRecord'
|
import BaseOpera from '@/components/base/BaseOpera'
|
import OperaInvoiceDetail from './OperaInvoiceDetail'
|
export default {
|
name: 'OperaMemberDetail',
|
extends: BaseOpera,
|
components: { GlobalWindow, BaseOpera, OperaInvoiceDetail },
|
data () {
|
return {
|
detailInfo: { },
|
invoiceQuery: {
|
invoiceNo: '',
|
invoiceType: '',
|
titleType: '',
|
invoiceTitle: '',
|
status: '',
|
dateRange: []
|
},
|
invoiceList: [],
|
invoiceLoading: false,
|
invoicePage: {
|
page: 1,
|
size: 10,
|
total: 10
|
},
|
invoiceSummary: {
|
issuedAmount: 0,
|
totalAmount: 0
|
}
|
}
|
},
|
methods: {
|
open (title, row) {
|
this.title = title
|
getById(row.id).then(res => {
|
this.detailInfo = res
|
this.visible = true
|
// 初始化开票历史数据
|
this.queryInvoices()
|
}).catch(e => {
|
this.$tip.apiFailed(e)
|
})
|
},
|
// 查询开票历史
|
async queryInvoices() {
|
this.invoiceLoading = true
|
try {
|
// 构建查询参数
|
const model = {
|
invoiceNo: this.invoiceQuery.invoiceNo,
|
invoiceType: this.invoiceQuery.invoiceType,
|
titleType: this.invoiceQuery.titleType,
|
invoiceTitle: this.invoiceQuery.invoiceTitle,
|
status: this.invoiceQuery.status,
|
memberId: this.detailInfo.id,
|
startDate: this.invoiceQuery.dateRange[0] ? this.invoiceQuery.dateRange[0].format('YYYY-MM-DD') : null,
|
endDate: this.invoiceQuery.dateRange[1] ? this.invoiceQuery.dateRange[1].format('YYYY-MM-DD') : null
|
}
|
// 同时查询列表数据和统计数据
|
const [listRes, summaryRes] = await Promise.all([
|
fetchList({
|
capacity: this.invoicePage.size,
|
page: this.invoicePage.page,
|
model: model
|
}),
|
summary({
|
capacity: this.invoicePage.size,
|
page: this.invoicePage.page,
|
model: model
|
})
|
])
|
this.invoiceList = listRes.records
|
this.invoicePage.total = listRes.total
|
this.invoiceSummary.issuedAmount = ((summaryRes.issuedAmount || 0) / 100).toFixed(2)
|
this.invoiceSummary.totalAmount = ((summaryRes.totalAmount || 0) / 100).toFixed(2)
|
} finally {
|
this.invoiceLoading = false
|
}
|
},
|
// 重置查询条件
|
resetQuery() {
|
this.invoiceQuery = {
|
invoiceNo: '',
|
invoiceType: '',
|
orgType: '',
|
invoiceTitle: '',
|
status: '',
|
dateRange: []
|
}
|
this.queryInvoices()
|
},
|
// 分页大小改变
|
handleSizeChange(val) {
|
this.invoicePage.size = val
|
this.queryInvoices()
|
},
|
// 当前页改变
|
handleCurrentChange(val) {
|
this.invoicePage.page = val
|
this.queryInvoices()
|
},
|
// 获取开票状态文本
|
getStatusText(status) {
|
switch(status) {
|
case 0:
|
return '申请中'
|
case 1:
|
return '开票成功'
|
case 2:
|
return '失败'
|
default:
|
return '未知'
|
}
|
},
|
// 获取开票状态标签类型
|
getStatusType(status) {
|
switch(status) {
|
case 0:
|
return 'warning'
|
case 1:
|
return 'success'
|
case 2:
|
return 'danger'
|
default:
|
return 'info'
|
}
|
},
|
// 打开开票详情
|
openInvoiceDetail(row) {
|
this.$refs.operaInvoiceDetail.open('开票详情', row)
|
},
|
// 关闭详情弹窗
|
handleClose() {
|
// 可以在这里添加关闭后的逻辑
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.section {
|
margin-bottom: 30px;
|
}
|
.section-header {
|
display: flex;
|
align-items: center;
|
gap: 15px;
|
margin-bottom: 15px;
|
}
|
.section-title {
|
font-size: 16px;
|
font-weight: bold;
|
color: #303133;
|
padding-left: 10px;
|
border-left: 4px solid #2E68EC;
|
}
|
.status-tag {
|
padding: 4px 12px;
|
border-radius: 4px;
|
font-size: 12px;
|
}
|
.status-pending {
|
background: #fdf6ec;
|
color: #E6A23C;
|
}
|
.status-success {
|
background: #f0f9eb;
|
color: #67C23A;
|
}
|
.status-reject {
|
background: #fef0f0;
|
color: #F56C6C;
|
}
|
.info-grid {
|
display: grid;
|
grid-template-columns: repeat(2, 1fr);
|
gap: 15px;
|
padding: 0 10px;
|
}
|
.info-item {
|
font-size: 14px;
|
}
|
.info-item .label {
|
color: #909399;
|
min-width: 90px;
|
}
|
.info-item .value {
|
color: #606266;
|
}
|
.info-item .amount {
|
color: #f56c6c;
|
font-weight: bold;
|
}
|
.query-form {
|
padding: 15px;
|
background: #f5f7fa;
|
border-radius: 4px;
|
}
|
.stats-row {
|
display: flex;
|
gap: 30px;
|
padding: 10px 15px;
|
background: #f5f7fa;
|
border-radius: 4px;
|
}
|
.stat-item {
|
font-size: 14px;
|
}
|
.stat-label {
|
color: #909399;
|
margin-right: 5px;
|
}
|
.stat-value {
|
color: #606266;
|
font-weight: bold;
|
}
|
.stat-value.amount {
|
color: #f56c6c;
|
}
|
.info-item.full-width {
|
grid-column: span 2;
|
}
|
.timeline-content {
|
padding: 10px;
|
background: #f5f7fa;
|
border-radius: 4px;
|
}
|
.timeline-title {
|
font-size: 14px;
|
font-weight: bold;
|
color: #303133;
|
margin-bottom: 8px;
|
}
|
.timeline-info {
|
display: flex;
|
gap: 20px;
|
font-size: 13px;
|
color: #606266;
|
margin-bottom: 5px;
|
}
|
.timeline-remark {
|
font-size: 13px;
|
color: #909399;
|
}
|
.approval-form {
|
padding: 20px;
|
background: #f5f7fa;
|
border-top: 1px solid #eee;
|
}
|
.approval-form /deep/ .el-form-item {
|
margin-bottom: 15px;
|
}
|
.approval-form /deep/ .el-form-item:last-child {
|
margin-bottom: 0;
|
}
|
.approval-buttons {
|
display: flex;
|
justify-content: flex-end;
|
gap: 10px;
|
margin-top: 15px;
|
}
|
</style>
|