|
|
@@ -0,0 +1,94 @@
|
|
|
+export function isImageFileType(fileType) {
|
|
|
+ return !!(fileType && String(fileType).startsWith('image/'))
|
|
|
+}
|
|
|
+
|
|
|
+export function fileExtLabel(name) {
|
|
|
+ const ext = String(name || '').split('.').pop()
|
|
|
+ return ext ? ext.toUpperCase() : 'FILE'
|
|
|
+}
|
|
|
+
|
|
|
+/** 展示用 YYYY-MM-DD;无有效日期返回 — */
|
|
|
+export function formatInvoiceDateYmd(value) {
|
|
|
+ if (value == null || value === '') return '—'
|
|
|
+ const s = String(value).trim()
|
|
|
+ const m = s.match(/^(\d{4}-\d{2}-\d{2})/)
|
|
|
+ if (m) return m[1]
|
|
|
+ const d = new Date(s)
|
|
|
+ if (Number.isNaN(d.getTime())) return '—'
|
|
|
+ const y = d.getFullYear()
|
|
|
+ const mo = String(d.getMonth() + 1).padStart(2, '0')
|
|
|
+ const day = String(d.getDate()).padStart(2, '0')
|
|
|
+ return `${y}-${mo}-${day}`
|
|
|
+}
|
|
|
+
|
|
|
+function invoiceFileList(inv) {
|
|
|
+ const raw = Array.isArray(inv?.attachments) ? inv.attachments : []
|
|
|
+ if (raw.length) {
|
|
|
+ return raw.map((a) => ({
|
|
|
+ id: String(a.id || a.attachmentId || ''),
|
|
|
+ fileName: a.fileName || a.file_name || '发票附件',
|
|
|
+ fileType: a.fileType || a.file_type || ''
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ const aid = inv?.attachmentId || inv?.attachment_id
|
|
|
+ if (aid) {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ id: String(aid),
|
|
|
+ fileName: inv.fileName || inv.file_name || '发票附件',
|
|
|
+ fileType: inv.fileType || inv.file_type || ''
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ return []
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 发票列表行 → 附件粒度选项
|
|
|
+ * @returns {{ key, invoiceId, attachmentId, amount, createTime, fileName, fileType, previewUrl, previewLoading }[]}
|
|
|
+ */
|
|
|
+export function buildAttachItemsFromInvoiceRows(rows) {
|
|
|
+ const items = []
|
|
|
+ for (const row of rows || []) {
|
|
|
+ const createTime = row.createTime || row.create_time || ''
|
|
|
+ for (const file of invoiceFileList(row)) {
|
|
|
+ if (!file.id) continue
|
|
|
+ items.push({
|
|
|
+ key: `${row.id}:${file.id}`,
|
|
|
+ invoiceId: String(row.id),
|
|
|
+ attachmentId: file.id,
|
|
|
+ amount: row.amount,
|
|
|
+ createTime,
|
|
|
+ fileName: file.fileName,
|
|
|
+ fileType: file.fileType,
|
|
|
+ previewUrl: '',
|
|
|
+ previewLoading: false
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return items
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 确定勾选:已加载项优先;draft 中仍勾选但不在已加载列表的旧已选项保留(防分页冲掉)
|
|
|
+ */
|
|
|
+export function mergeInvoicePicksByDraftKeys(draftKeys, attachItems, previousPicks) {
|
|
|
+ const set = new Set(draftKeys || [])
|
|
|
+ const fromLoaded = (attachItems || []).filter((i) => set.has(i.key))
|
|
|
+ const loadedKeys = new Set(fromLoaded.map((i) => i.key))
|
|
|
+ const fromPrev = (previousPicks || []).filter(
|
|
|
+ (p) => set.has(p.key) && !loadedKeys.has(p.key)
|
|
|
+ )
|
|
|
+ const byKey = new Map()
|
|
|
+ for (const p of fromPrev) byKey.set(p.key, { ...p })
|
|
|
+ for (const i of fromLoaded) {
|
|
|
+ const prev = byKey.get(i.key)
|
|
|
+ byKey.set(i.key, {
|
|
|
+ ...i,
|
|
|
+ previewUrl: i.previewUrl || prev?.previewUrl || ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return Array.from(set)
|
|
|
+ .map((k) => byKey.get(k))
|
|
|
+ .filter(Boolean)
|
|
|
+}
|