Files
X-Financial/web/src/views/scripts/receiptFolderDetailFields.js

225 lines
7.1 KiB
JavaScript
Raw Normal View History

import { computed } from 'vue'
const TRAIN_KEY_FIELD_DEFINITIONS = [
{
id: 'invoice_number',
label: '发票号码',
placeholder: '待识别',
keys: ['invoice_number', 'ticket_number'],
labels: ['发票号码', '票据号码', '票号']
},
{
id: 'invoice_date',
label: '开票日期',
placeholder: 'YYYY-MM-DD',
keys: ['invoice_date', 'issue_date'],
labels: ['开票日期', '发票日期']
},
{
id: 'fare',
label: '票价',
placeholder: '待识别',
keys: ['fare', 'amount'],
labels: ['票价', '金额']
},
{
id: 'passenger_name',
label: '姓名',
placeholder: '待识别',
keys: ['passenger_name'],
labels: ['乘车人', '旅客姓名', '姓名']
}
]
const DEFAULT_KEY_FIELD_DEFINITIONS = [
{
id: 'invoice_number',
label: '发票号码',
placeholder: '待识别',
keys: ['invoice_number', 'ticket_number'],
labels: ['发票号码', '票据号码', '票号']
},
{
id: 'invoice_date',
label: '开票日期',
placeholder: 'YYYY-MM-DD',
keys: ['invoice_date', 'issue_date'],
labels: ['开票日期', '发票日期']
},
{
id: 'amount',
label: '金额',
placeholder: '待识别',
keys: ['amount', 'fare'],
labels: ['金额', '价税合计', '合计金额', '票价']
},
{
id: 'merchant_name',
label: '商户',
placeholder: '待识别',
keys: ['merchant_name'],
labels: ['商户', '销售方', '开票方']
}
]
const RECEIPT_META_FIELD_DEFINITIONS = [
{
id: 'document_type_label',
label: '票据类型',
placeholder: '待识别',
keys: ['document_type_label'],
labels: ['票据类型', '识别类型']
},
{
id: 'scene_label',
label: '费用场景',
placeholder: '待识别',
keys: ['scene_label'],
labels: ['费用场景', '场景']
},
{
id: 'merchant_name',
label: '商户',
placeholder: '待识别',
keys: ['merchant_name'],
labels: ['商户', '销售方', '开票方']
}
]
export function createReceiptDetailFieldModel({ detailForm, isTrainTicket }) {
const activeKeyFieldDefinitions = computed(() => (
isTrainTicket.value ? TRAIN_KEY_FIELD_DEFINITIONS : DEFAULT_KEY_FIELD_DEFINITIONS
))
const keyReceiptFields = computed(() => (
activeKeyFieldDefinitions.value.map((definition) => ({
...definition,
value: getReceiptFieldValue(definition)
}))
))
const keyReceiptFieldTokens = computed(() => {
const tokens = new Set()
activeKeyFieldDefinitions.value.forEach((definition) => {
for (const token of [definition.id, ...(definition.keys || []), ...(definition.labels || [])]) {
const normalized = normalizeReceiptFieldToken(token)
if (normalized) tokens.add(normalized)
}
})
return tokens
})
const editableOtherFields = computed(() => (
detailForm.fields.filter((field) => {
const key = normalizeReceiptFieldToken(field?.key)
const label = normalizeReceiptFieldToken(field?.label)
return !keyReceiptFieldTokens.value.has(key) && !keyReceiptFieldTokens.value.has(label)
})
))
function findReceiptFieldForDefinition(definition) {
const keys = (definition.keys || []).map(normalizeReceiptFieldToken).filter(Boolean)
const labels = (definition.labels || []).map(normalizeReceiptFieldToken).filter(Boolean)
return detailForm.fields.find((field) => keys.includes(normalizeReceiptFieldToken(field?.key)))
|| detailForm.fields.find((field) => labels.includes(normalizeReceiptFieldToken(field?.label)))
|| null
}
function getReceiptFieldFallback(definition) {
if (definition.id === 'invoice_date') return detailForm.document_date
if (definition.id === 'fare' || definition.id === 'amount') return detailForm.amount
if (definition.id === 'merchant_name') return detailForm.merchant_name
if (definition.id === 'document_type_label') return detailForm.document_type_label
if (definition.id === 'scene_label') return detailForm.scene_label
return ''
}
function getReceiptFieldValue(definition) {
const field = findReceiptFieldForDefinition(definition)
return String(field?.value || getReceiptFieldFallback(definition) || '')
}
function ensureReceiptField(definition) {
const field = findReceiptFieldForDefinition(definition)
if (field) {
field.key = field.key || definition.keys?.[0] || definition.id
field.label = field.label || definition.label
return field
}
const created = {
key: definition.keys?.[0] || definition.id,
label: definition.label,
value: getReceiptFieldFallback(definition)
}
detailForm.fields.push(created)
return created
}
function ensureEditableReceiptFields() {
for (const definition of [...activeKeyFieldDefinitions.value, ...RECEIPT_META_FIELD_DEFINITIONS]) {
const field = ensureReceiptField(definition)
const fallback = getReceiptFieldFallback(definition)
if (!String(field.value || '').trim() && fallback) {
field.value = fallback
}
}
}
function updateReceiptField(definition, value) {
const field = ensureReceiptField(definition)
field.value = value
syncEditableFieldsToTopLevel()
}
function readFieldValue(definition) {
return String(findReceiptFieldForDefinition(definition)?.value || '').trim()
}
function syncEditableFieldsToTopLevel() {
const invoiceDate = readFieldValue(TRAIN_KEY_FIELD_DEFINITIONS[1]) || readFieldValue(DEFAULT_KEY_FIELD_DEFINITIONS[1])
const amount = readFieldValue(TRAIN_KEY_FIELD_DEFINITIONS[2]) || readFieldValue(DEFAULT_KEY_FIELD_DEFINITIONS[2])
const merchant = readFieldValue(RECEIPT_META_FIELD_DEFINITIONS[2]) || readFieldValue(DEFAULT_KEY_FIELD_DEFINITIONS[3])
const documentTypeLabel = readFieldValue(RECEIPT_META_FIELD_DEFINITIONS[0])
const sceneLabel = readFieldValue(RECEIPT_META_FIELD_DEFINITIONS[1])
if (invoiceDate) detailForm.document_date = invoiceDate
if (amount) detailForm.amount = amount
if (merchant) detailForm.merchant_name = merchant
if (documentTypeLabel) detailForm.document_type_label = documentTypeLabel
if (sceneLabel) detailForm.scene_label = sceneLabel
}
function buildDetailPayload() {
syncEditableFieldsToTopLevel()
return {
document_type: detailForm.document_type,
document_type_label: detailForm.document_type_label,
scene_code: detailForm.scene_code,
scene_label: detailForm.scene_label,
summary: detailForm.summary,
amount: detailForm.amount,
document_date: detailForm.document_date,
merchant_name: detailForm.merchant_name,
fields: detailForm.fields
.map((field) => ({
key: String(field?.key || '').trim(),
label: String(field?.label || '').trim(),
value: String(field?.value || '').trim()
}))
.filter((field) => field.key || field.label || field.value)
}
}
return {
buildDetailPayload,
editableOtherFields,
ensureEditableReceiptFields,
keyReceiptFields,
syncEditableFieldsToTopLevel,
updateReceiptField
}
}
function normalizeReceiptFieldToken(value) {
return String(value || '').trim().toLowerCase().replace(/\s+/g, '')
}