diff --git a/miniprogram/pages/bx/reimburse/detail.vue b/miniprogram/pages/bx/reimburse/detail.vue
index 851afbb75..b9b9339e2 100644
--- a/miniprogram/pages/bx/reimburse/detail.vue
+++ b/miniprogram/pages/bx/reimburse/detail.vue
@@ -133,6 +133,34 @@
+
+ 关联发票
+
+
+
+
+
+ {{ fileExtLabel(pick.fileName) }}
+
+
+
+ ¥{{ formatAmount(pick.amount) }}
+ {{ formatInvoiceDateYmd(pick.createTime) }}
+
+
+
+ 暂无关联发票
+
+
申请附件
@@ -187,6 +215,7 @@
+
-
@@ -238,6 +273,11 @@ import {
flattenExpenseTree,
resolveExpenseDisplay
} from '@/utils/bxFormat'
+import {
+ isImageFileType,
+ fileExtLabel,
+ formatInvoiceDateYmd
+} from '@/utils/bxInvoiceThumb'
import { getSafeAreaStyle } from '@/utils/safeArea'
import { useUserStore } from '@/stores/user'
import { buildApplyAttachmentDisplayName } from '@/utils/bxAttachmentDisplayName'
@@ -250,6 +290,7 @@ const detail = ref(null)
const detailTab = ref(0)
const approvals = ref([])
const attachments = ref([])
+const linkedInvoices = ref([])
const flatList = ref([])
const actionLoading = reactive({ submit: false, delete: false, withdraw: false })
@@ -300,6 +341,26 @@ function previewAtt(file) {
uni.previewImage({ urls: [file.previewUrl], current: file.previewUrl })
}
+async function previewInvoicePick(pick) {
+ if (!isImageFileType(pick.fileType)) {
+ uni.showToast({ title: '非图片附件请在管理端查看', icon: 'none' })
+ return
+ }
+ let url = pick.previewUrl
+ if (!url && pick.attachmentId) {
+ try {
+ const pRes = await attachmentApi.preview(pick.attachmentId)
+ url = pRes?.data?.url || ''
+ if (url) pick.previewUrl = url
+ } catch (e) {
+ uni.showToast({ title: '暂无法预览', icon: 'none' })
+ return
+ }
+ }
+ if (url) uni.previewImage({ urls: [url], current: url })
+ else uni.showToast({ title: '暂无法预览', icon: 'none' })
+}
+
function attachmentDisplayName(file, index) {
return buildApplyAttachmentDisplayName({
remark: detail.value?.remark || '',
@@ -348,6 +409,38 @@ async function loadDetail() {
}
}
+ const invs = detail.value?.invoices || []
+ linkedInvoices.value = invs
+ .map((inv) => {
+ const attachmentId = String(inv.attachmentId || inv.attachment_id || '')
+ if (!attachmentId) return null
+ return {
+ key: `${inv.id || inv.invoiceId}:${attachmentId}`,
+ invoiceId: String(inv.id || inv.invoiceId || ''),
+ attachmentId,
+ amount: inv.amount,
+ createTime: inv.createTime || inv.create_time || '',
+ fileName: inv.fileName || inv.file_name || '发票附件',
+ fileType: inv.fileType || inv.file_type || '',
+ previewUrl: '',
+ previewLoading: false
+ }
+ })
+ .filter(Boolean)
+
+ for (const item of linkedInvoices.value) {
+ if (!isImageFileType(item.fileType)) continue
+ item.previewLoading = true
+ try {
+ const pRes = await attachmentApi.preview(item.attachmentId)
+ item.previewUrl = pRes?.data?.url || ''
+ } catch (e) {
+ // keep empty
+ } finally {
+ item.previewLoading = false
+ }
+ }
+
try {
const attRes = await attachmentApi.listByBiz('reimburse_apply', id)
const list = (attRes.data || []).map((a) => ({
@@ -410,7 +503,7 @@ function handleDelete() {
})
}
-function handleResubmit() {
+function handleEdit() {
if (!detail.value) return
uni.navigateTo({
url: `${PAGE_PATHS.bxReimburseApplyForm}?id=${detail.value.id}`