feat(miniprogram): show linked invoice thumbnails on reimburse detail.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
0c269b6e73
commit
d6fddc666c
1 file changed
+96
-3
@@ -133,6 +133,34 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-info-card">
|
||||
<view class="detail-info-card__title">关联发票</view>
|
||||
<view v-if="linkedInvoices.length" class="invoice-thumb-grid" style="margin-top: 0">
|
||||
<view
|
||||
v-for="pick in linkedInvoices"
|
||||
:key="pick.key"
|
||||
class="invoice-thumb"
|
||||
@click="previewInvoicePick(pick)"
|
||||
>
|
||||
<view class="invoice-thumb__media">
|
||||
<image
|
||||
v-if="isImageFileType(pick.fileType) && pick.previewUrl"
|
||||
:src="pick.previewUrl"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-else class="invoice-thumb__doc">
|
||||
<text class="invoice-thumb__doc-ext">{{ fileExtLabel(pick.fileName) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="invoice-thumb__meta">
|
||||
<text class="invoice-thumb__amt">¥{{ formatAmount(pick.amount) }}</text>
|
||||
<text class="invoice-thumb__date">{{ formatInvoiceDateYmd(pick.createTime) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="detail-section-empty">暂无关联发票</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-info-card">
|
||||
<view class="detail-info-card__title">申请附件</view>
|
||||
<view v-if="attachments.length" class="att-grid">
|
||||
@@ -187,6 +215,7 @@
|
||||
|
||||
<view v-if="showActions" class="bottom-action-bar">
|
||||
<template v-if="detail?.status === 'draft'">
|
||||
<button class="btn btn-primary" style="flex: 1" @click="handleEdit">编辑</button>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
style="flex: 1"
|
||||
@@ -205,8 +234,14 @@
|
||||
</button>
|
||||
</template>
|
||||
<template v-if="detail?.status === 'rejected'">
|
||||
<button class="btn btn-primary" style="flex: 1" @click="handleResubmit">
|
||||
重新提交
|
||||
<button class="btn btn-primary" style="flex: 1" @click="handleEdit">编辑</button>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
style="flex: 1"
|
||||
:disabled="actionLoading.submit"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
提交审批
|
||||
</button>
|
||||
</template>
|
||||
<template v-if="canWithdraw">
|
||||
@@ -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}`
|
||||
|
||||
Reference in new issue
Block a user