完善开放接口,完善开票历史

This commit is contained in:
BBIT-Kai
2026-05-21 10:53:08 +08:00
parent ccc164b176
commit 40f1c27e71
15 changed files with 1087 additions and 431 deletions
+1
View File
@@ -530,6 +530,7 @@ export interface InvoiceHistoryItem {
export const invoiceKindMap: Record<string, string> = {
'81': '数电专票',
'82': '数电普票',
'83': '数电机动车销售统一发票',
'87': '机动车发票',
'10': '电子普票',
'08': '电子专票',
@@ -44,6 +44,7 @@
<div class="card-body card-body-fill table-fill">
<n-data-table
remote
:columns="columns"
:data="dataSource"
:loading="loading"
@@ -100,9 +101,7 @@
<div class="detail-grid">
<div class="detail-item">
<span>发票种类</span>
<strong>{{
invoiceKindMap[detailItem.invoiceKindCode] || detailItem.invoiceKindCode
}}</strong>
<strong>{{ formatInvoiceKind(detailItem.invoiceKindCode) }}</strong>
</div>
<div class="detail-item">
<span>发票号码</span>
@@ -511,6 +510,7 @@ import type {
RedCreateRequest,
RedInvoiceInfo
} from '@/api/piaotong'
import { renderPagePrefix } from '@/utils/pagination'
import type { DataTableColumns } from 'naive-ui'
const invoiceTypeMap: Record<string, string> = {
@@ -533,6 +533,8 @@ const redFlagMap: Record<string, string> = {
PART_RED: '部分冲红'
}
const redInvoiceKindCodes = new Set(['81', '82', '83', '87'])
const invIssueChannelMap: Record<string, string> = {
'0': 'RPA电子税局',
'1': '乐企自用',
@@ -573,6 +575,19 @@ function statusTagType(status: string): 'warning' | 'info' | 'success' | 'error'
}
}
function formatInvoiceKind(invoiceKindCode?: string) {
return invoiceKindCode ? invoiceKindMap[invoiceKindCode] || invoiceKindCode : '-'
}
function canCreateRedInvoice(row: InvoiceHistoryItem) {
return (
activeTab.value === 'BLUE' &&
row.status === 'SUCCESS' &&
(!row.redFlag || row.redFlag === 'NOT_RED') &&
redInvoiceKindCodes.has(row.invoiceKindCode)
)
}
const activeTab = ref('BLUE')
const selectedStatus = ref<string | null>(null)
const selectedBatchNo = ref<string | null>(null)
@@ -665,7 +680,7 @@ const pagination = reactive({
showSizePicker: true,
pageSizes: [10, 20, 50, 100],
pageSlot: 7,
prefix: ({ itemCount }: { itemCount?: number }) => `${itemCount ?? 0}`
prefix: renderPagePrefix
})
async function fetchData() {
@@ -711,17 +726,29 @@ function getRowActions(row: InvoiceHistoryItem) {
actions.push({ label: '查看票样', icon: FileSearch, onClick: () => openSamplePreview(row) })
}
if (
activeTab.value === 'BLUE' &&
row.status === 'SUCCESS' &&
(!row.redFlag || row.redFlag === 'NOT_RED')
) {
if (canCreateRedInvoice(row)) {
actions.push({ label: '冲红', icon: RotateCcw, onClick: () => startRedTask(row) })
}
return actions
}
function getActionsColumnWidth() {
const buttonWidthMap: Record<string, number> = {
详情: 58,
刷新: 58,
查看票样: 86,
冲红: 58
}
const rowWidths = dataSource.value.map((row) => {
const actions = getRowActions(row)
const buttonWidth = actions.reduce((sum, action) => sum + (buttonWidthMap[action.label] || 64), 0)
const gapWidth = Math.max(0, actions.length - 1) * 6
return buttonWidth + gapWidth + 20
})
return Math.max(180, ...rowWidths)
}
async function openSamplePreview(item: InvoiceHistoryItem) {
showSamplePreview.value = true
sampleLoading.value = true
@@ -796,6 +823,16 @@ const columns = computed<DataTableColumns<InvoiceHistoryItem>>(() => {
() => invoiceStatusMap[row.status] || row.status
)
},
{
title: '失败原因',
key: 'msg',
width: 220,
ellipsis: { tooltip: true },
render: (row: InvoiceHistoryItem) =>
row.status === 'FAILED' && row.msg
? row.msg
: h('span', { style: 'color:#9ca3af' }, '-')
},
{
title: '冲红状态',
key: 'redFlag',
@@ -836,8 +873,9 @@ const columns = computed<DataTableColumns<InvoiceHistoryItem>>(() => {
{
title: '发票种类',
key: 'invoiceKindCode',
width: 110,
render: (row: InvoiceHistoryItem) => invoiceKindMap[row.invoiceKindCode] || row.invoiceKindCode
width: 150,
ellipsis: { tooltip: true },
render: (row: InvoiceHistoryItem) => formatInvoiceKind(row.invoiceKindCode)
},
{
title: '价税合计',
@@ -856,13 +894,14 @@ const columns = computed<DataTableColumns<InvoiceHistoryItem>>(() => {
{
title: '操作',
key: 'actions',
width: 180,
width: getActionsColumnWidth(),
minWidth: 180,
fixed: 'right' as const,
render: (row: InvoiceHistoryItem) => {
const actions = getRowActions(row)
return h(
'div',
{ style: 'display:flex;gap:6px;align-items:center;flex-wrap:wrap' },
{ class: 'table-actions' },
actions.map((btn) => {
const isLoading = btn.label === '刷新' && refreshingSet.has(row.invoiceReqSerialNo)
const Icon = btn.icon
@@ -1204,6 +1243,18 @@ onMounted(() => {
background: #fafafa !important;
}
.table-actions {
display: flex;
align-items: center;
gap: 6px;
flex-wrap: nowrap;
white-space: nowrap;
}
.table-actions :deep(.n-button) {
flex: 0 0 auto;
}
.sample-preview {
padding: 16px;
}