订单明细

This commit is contained in:
qiuyuan 2025-12-30 17:21:53 +08:00
parent 68d5b3bb14
commit 876358ea28

View File

@ -33,8 +33,31 @@
</a-col> </a-col>
<a-col :span="24"> <a-col :span="24">
<a-card> <a-card>
<a-table :dataSource="listData" :columns="columns" bordered :pagination="paginationState" <!-- 批量操作区域 -->
@change="onTableChange"> <div class="batch-operations" style="margin-bottom: 16px;">
<a-space>
<a-button
type="primary"
@click="handleBatchInvoice"
:disabled="selectedRowKeys.length === 0"
>
批量去开票
</a-button>
<span v-if="selectedRowKeys.length > 0">
已选择 {{ selectedRowKeys.length }} 条记录
</span>
</a-space>
</div>
<a-table
:dataSource="listData"
:columns="columns"
bordered
:pagination="paginationState"
:rowSelection="rowSelection"
@change="onTableChange"
:rowKey="record => record.id || record.serial_number"
>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'created_at'"> <template v-if="column.key === 'created_at'">
<div> <div>
@ -46,37 +69,129 @@
{{ dayjs(record.billing_start).format('YYYY-MM-DD HH:mm') +"~" +dayjs(record.billing_end).format('YYYY-MM-DD HH:mm') }} {{ dayjs(record.billing_start).format('YYYY-MM-DD HH:mm') +"~" +dayjs(record.billing_end).format('YYYY-MM-DD HH:mm') }}
</div> </div>
</template> </template>
<template v-if="column.key === 'price'">
<div>
¥{{ record.price || '0.00' }}
</div>
</template>
<template v-if="column.key === 'real_amount'">
<div style="color: #ff4d4f; font-weight: 500;">
-¥{{ record.real_amount || '0.00' }}
</div>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-button
type="link"
size="small"
@click="handleSingleInvoice(record)"
>
去开票
</a-button>
</a-space>
</template>
</template> </template>
</a-table> </a-table>
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
<!-- 单个开票确认模态框 -->
<a-modal
v-model:visible="singleInvoiceModalVisible"
title="开票确认"
@ok="handleSingleInvoiceConfirm"
@cancel="singleInvoiceModalVisible = false"
:confirm-loading="singleInvoiceLoading"
centered
>
<div class="invoice-confirm-content">
<div class="confirm-item">
<span class="confirm-label">流水号</span>
<span class="confirm-value">{{ currentInvoiceRecord?.serial_number || '-' }}</span>
</div>
<div class="confirm-item">
<span class="confirm-label">交易时间</span>
<span class="confirm-value">{{ currentInvoiceRecord?.created_at ? dayjs(currentInvoiceRecord.created_at).format('YYYY-MM-DD HH:mm') : '-' }}</span>
</div>
<div class="confirm-item">
<span class="confirm-label">交易金额</span>
<span class="confirm-value">¥{{ currentInvoiceRecord?.real_amount || '0.00' }}</span>
</div>
<div class="confirm-tips">
确认要为该订单申请发票吗
</div>
</div>
</a-modal>
<!-- 批量开票确认模态框 -->
<a-modal
v-model:visible="batchInvoiceModalVisible"
title="批量开票确认"
@ok="handleBatchInvoiceConfirm"
@cancel="batchInvoiceModalVisible = false"
:confirm-loading="batchInvoiceLoading"
centered
width="600px"
>
<div class="batch-invoice-content">
<div class="selected-count">
已选择 {{ selectedRowKeys.length }} 条记录进行批量开票
</div>
<div class="total-amount">
<span class="total-label">合计金额</span>
<span class="total-value">¥{{ selectedTotalAmount.toFixed(2) }}</span>
</div>
<div class="invoice-list" style="max-height: 300px; overflow-y: auto; margin-top: 16px;">
<a-table
:dataSource="selectedInvoiceRecords"
:columns="selectedColumns"
size="small"
:pagination="false"
bordered
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'created_at'">
{{ record.created_at ? dayjs(record.created_at).format('YYYY-MM-DD HH:mm') : '-' }}
</template>
<template v-if="column.key === 'real_amount'">
-¥{{ record.real_amount || '0.00' }}
</template>
</template>
</a-table>
</div>
<div class="batch-tips" style="margin-top: 16px; color: #ff4d4f;">
注意批量开票将为所有选中的订单统一生成一张发票
</div>
</div>
</a-modal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onBeforeMount } from 'vue' import { ref, onBeforeMount, computed } from 'vue'
import { usePagination } from '@/hooks' import { usePagination } from '@/hooks'
import { useList } from '@/apis/admin' import { useList } from '@/apis/admin'
import dayjs from 'dayjs' import dayjs from 'dayjs'
// const listData=ref([ {title:1}]) import { message } from 'ant-design-vue'
// const paginationState=ref({
// total: 0, //
// current: 1,
// pageSize: 10,
// showTotal: (total) => ` ${total} `,
// pageSizeOptions: ['10', '20', '30', '40'],
// })
const { listData, paginationState, resetPagination, searchFormData } = usePagination() const { listData, paginationState, resetPagination, searchFormData } = usePagination()
//
const selectedRowKeys = ref<string[]>([])
const selectedRows = ref<any[]>([])
//
const singleInvoiceModalVisible = ref(false)
const batchInvoiceModalVisible = ref(false)
const singleInvoiceLoading = ref(false)
const batchInvoiceLoading = ref(false)
//
const currentInvoiceRecord = ref<any>(null)
//
const columns = ref([ const columns = ref([
// { title: '', dataIndex: 'flowNum', key: 'flowNum' },
// { title: '', dataIndex: 'transactionTime', key: 'transactionTime' },
// { title: '', dataIndex: 'flowNum', key: 'flowNum' },
// { title: '', dataIndex: 'flowNum', key: 'flowNum' },
// { title: '', dataIndex: 'flowNum', key: 'flowNum' },
// { title: '', dataIndex: 'flowNum', key: 'flowNum' },
// { title: '', dataIndex: 'flowNum', key: 'flowNum' },
// { title: '', dataIndex: 'flowNum', key: 'flowNum' },
{ title: '流水号', dataIndex: 'serial_number', key: 'serial_number' }, { title: '流水号', dataIndex: 'serial_number', key: 'serial_number' },
{ title: '交易时间', dataIndex: 'created_at', key: 'created_at' }, { title: '交易时间', dataIndex: 'created_at', key: 'created_at' },
{ title: '主机ID', dataIndex: 'host_id', key: 'host_id' }, { title: '主机ID', dataIndex: 'host_id', key: 'host_id' },
@ -87,25 +202,62 @@ const columns = ref([
{ title: '计费时长', dataIndex: 'bill_time', key: 'bill_time' }, { title: '计费时长', dataIndex: 'bill_time', key: 'bill_time' },
{ title: '单价', dataIndex: 'price', key: 'price' }, { title: '单价', dataIndex: 'price', key: 'price' },
{ title: '交易金额', dataIndex: 'real_amount', key: 'real_amount' }, { title: '交易金额', dataIndex: 'real_amount', key: 'real_amount' },
{
title: '操作',
key: 'action',
width: 100,
align: 'center'
}
]) ])
//
const selectedColumns = ref([
{ title: '流水号', dataIndex: 'serial_number', key: 'serial_number', width: 120 },
{ title: '交易时间', dataIndex: 'created_at', key: 'created_at', width: 150 },
{ title: '交易金额', dataIndex: 'real_amount', key: 'real_amount', width: 100, align: 'right' }
])
//
const rowSelection = computed(() => ({
selectedRowKeys: selectedRowKeys.value,
onChange: (selectedKeys: string[], selectedRows: any[]) => {
selectedRowKeys.value = selectedKeys
selectedRows.value = selectedRows
},
getCheckboxProps: (record: any) => ({
disabled: record.status === '已开票' //
})
}))
//
const selectedTotalAmount = computed(() => {
return selectedRows.value.reduce((total, record) => {
const amount = parseFloat(record.real_amount) || 0
return total + amount
}, 0)
})
//
const selectedInvoiceRecords = computed(() => {
return selectedRows.value
})
onBeforeMount(() => { onBeforeMount(() => {
getPageList() getPageList()
}) })
const getPageList = async () => { const getPageList = async () => {
try { try {
const { pageSize, current } = paginationState const { pageSize, current } = paginationState
const res: any = await useList({ pageSize: pageSize, pageNum: current }); const res: any = await useList({ pageSize: pageSize, pageNum: current })
listData.value = res.list; listData.value = res.list
paginationState.total = res.count; paginationState.total = res.count
console.log('订单列表:', res); console.log('订单列表:', res)
// advantageList.value = list;
} catch (error: any) { } catch (error: any) {
console.error('产品优势请求失败:', error); console.error('产品优势请求失败:', error)
} }
} }
/** /**
* 分页 * 分页
*/ */
@ -114,19 +266,190 @@ function onTableChange({ current, pageSize }) {
paginationState.pageSize = pageSize paginationState.pageSize = pageSize
getPageList() getPageList()
} }
/** /**
* 搜索 * 搜索
*/ */
function handleSearch() { function handleSearch() {
resetPagination() resetPagination()
selectedRowKeys.value = [] //
selectedRows.value = []
getPageList() getPageList()
} }
/** /**
* 重置 * 重置
*/ */
function handleResetSearch() { function handleResetSearch() {
searchFormData.value = {} searchFormData.value = {}
resetPagination() resetPagination()
selectedRowKeys.value = [] //
selectedRows.value = []
getPageList() getPageList()
} }
</script>
/**
* 单个去开票
*/
function handleSingleInvoice(record: any) {
currentInvoiceRecord.value = record
singleInvoiceModalVisible.value = true
}
/**
* 确认单个开票
*/
async function handleSingleInvoiceConfirm() {
singleInvoiceLoading.value = true
try {
// API
// await invoiceApi.createSingleInvoice(currentInvoiceRecord.value.id)
// API
await new Promise(resolve => setTimeout(resolve, 1000))
message.success('开票申请已提交成功!')
singleInvoiceModalVisible.value = false
//
getPageList()
} catch (error) {
message.error('开票申请提交失败,请稍后重试')
} finally {
singleInvoiceLoading.value = false
}
}
/**
* 批量去开票
*/
function handleBatchInvoice() {
if (selectedRowKeys.value.length === 0) {
message.warning('请先选择要开票的记录')
return
}
batchInvoiceModalVisible.value = true
}
/**
* 确认批量开票
*/
async function handleBatchInvoiceConfirm() {
batchInvoiceLoading.value = true
try {
// API
// await invoiceApi.createBatchInvoice(selectedRowKeys.value)
// API
await new Promise(resolve => setTimeout(resolve, 1500))
message.success(`批量开票申请已提交成功,共 ${selectedRowKeys.value.length} 条记录`)
batchInvoiceModalVisible.value = false
//
selectedRowKeys.value = []
selectedRows.value = []
//
getPageList()
} catch (error) {
message.error('批量开票申请提交失败,请稍后重试')
} finally {
batchInvoiceLoading.value = false
}
}
</script>
<style scoped>
.batch-operations {
display: flex;
align-items: center;
justify-content: space-between;
}
.invoice-confirm-content {
padding: 8px 0;
}
.confirm-item {
display: flex;
justify-content: space-between;
margin-bottom: 12px;
padding-bottom: 12px;
border-bottom: 1px solid #f0f0f0;
}
.confirm-item:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.confirm-label {
color: #666;
font-weight: 500;
}
.confirm-value {
font-weight: 600;
color: #333;
}
.confirm-tips {
margin-top: 16px;
padding: 12px;
background-color: #f6ffed;
border-radius: 6px;
color: #52c41a;
text-align: center;
}
.batch-invoice-content .selected-count {
font-size: 16px;
font-weight: 600;
margin-bottom: 16px;
color: #1890ff;
}
.total-amount {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px;
background-color: #fafafa;
border-radius: 6px;
margin-bottom: 16px;
}
.total-label {
font-size: 16px;
font-weight: 600;
color: #333;
}
.total-value {
font-size: 20px;
font-weight: 700;
color: #ff4d4f;
}
.batch-tips {
font-size: 14px;
text-align: center;
}
/* 适配响应式 */
@media (max-width: 768px) {
.batch-operations {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.total-amount {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
}
</style>