feat(bx-mobile): show attachment grid picker on reimburse apply
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
9f92012e43
commit
0e8cefe89f
1 file changed
+226
-35
@@ -161,37 +161,82 @@
|
||||
<button type="button" class="btn btn-primary btn-sm" @click="openInvoicePicker">
|
||||
从发票夹选择
|
||||
</button>
|
||||
<div v-if="selectedInvoicePicksSorted.length" class="invoice-picked">
|
||||
<div v-if="selectedInvoicePicksSorted.length" class="invoice-picked-row">
|
||||
<div
|
||||
v-for="pick in selectedInvoicePicksSorted"
|
||||
:key="pick.key"
|
||||
class="invoice-picked__item"
|
||||
class="invoice-picked-card"
|
||||
>
|
||||
<span>¥{{ money(pick.amount) }} · {{ pick.fileName }}</span>
|
||||
<button type="button" class="del" @click="removeInvoicePick(pick.key)">×</button>
|
||||
<button
|
||||
type="button"
|
||||
class="invoice-picked-card__remove"
|
||||
aria-label="移除"
|
||||
@click="removeInvoicePick(pick.key)"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<div class="invoice-picked-card__preview">
|
||||
<img
|
||||
v-if="isImageFileType(pick.fileType) && pick.previewUrl"
|
||||
:src="pick.previewUrl"
|
||||
:alt="pick.fileName"
|
||||
/>
|
||||
<div v-else class="invoice-picked-card__icon">
|
||||
{{ isImageFileType(pick.fileType) ? '图片' : 'PDF' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-picked-card__meta">
|
||||
<span class="invoice-picked-card__name">{{ pick.fileName }}</span>
|
||||
<div class="invoice-picked-card__amount">¥{{ money(pick.amount) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="form-tip">请先在「我的发票夹」上传发票;提交时按合计扣减余额。选择对象为附件文件。</p>
|
||||
</div>
|
||||
|
||||
<van-popup v-model:show="showInvoicePicker" position="bottom" round :style="{ height: '70%' }">
|
||||
<van-popup v-model:show="showInvoicePicker" position="bottom" round :style="{ height: '72%' }">
|
||||
<div class="invoice-picker">
|
||||
<div class="invoice-picker__title">选择发票附件</div>
|
||||
<van-cell-group>
|
||||
<van-cell
|
||||
v-for="item in attachItems"
|
||||
:key="item.key"
|
||||
clickable
|
||||
@click="togglePickerKey(item.key)"
|
||||
<div class="invoice-picker__body">
|
||||
<p v-if="!pickerMonthGroups.length" class="invoice-picker__empty">暂无发票附件</p>
|
||||
<section
|
||||
v-for="group in pickerMonthGroups"
|
||||
:key="group.monthKey"
|
||||
class="invoice-month"
|
||||
>
|
||||
<template #title>
|
||||
¥{{ money(item.amount) }} · {{ item.fileName }}
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<span v-if="pickerDraftKeys.includes(item.key)">✓</span>
|
||||
</template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
<h4 class="invoice-month__title">{{ group.monthLabel }}</h4>
|
||||
<div class="invoice-attach-grid">
|
||||
<button
|
||||
v-for="item in group.items"
|
||||
:key="item.key"
|
||||
type="button"
|
||||
class="invoice-attach-card"
|
||||
:class="{ 'is-selected': pickerDraftKeys.includes(item.key) }"
|
||||
@click="togglePickerKey(item.key)"
|
||||
>
|
||||
<span class="invoice-attach-card__index">{{ item.serial }}</span>
|
||||
<span
|
||||
v-if="pickerDraftKeys.includes(item.key)"
|
||||
class="invoice-attach-card__check"
|
||||
>✓</span>
|
||||
<div class="invoice-attach-card__preview">
|
||||
<img
|
||||
v-if="isImageFileType(item.fileType) && item.previewUrl"
|
||||
:src="item.previewUrl"
|
||||
:alt="item.fileName"
|
||||
/>
|
||||
<div v-else class="invoice-attach-card__doc">
|
||||
{{ isImageFileType(item.fileType) ? '图片' : 'PDF' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-attach-card__meta">
|
||||
<span class="invoice-attach-card__name">{{ item.fileName }}</span>
|
||||
<div class="invoice-attach-card__amount">¥{{ money(item.amount) }}</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="invoice-picker__footer">
|
||||
<button type="button" class="btn btn-primary btn-block" @click="confirmInvoicePicker">
|
||||
确定(已选 {{ pickerDraftKeys.length }})
|
||||
@@ -569,7 +614,8 @@ function confirmInvoicePicker() {
|
||||
const set = new Set(pickerDraftKeys.value)
|
||||
selectedInvoicePicks.value = attachItems.value
|
||||
.filter((i) => set.has(i.key))
|
||||
.map((i) => ({ ...i }))
|
||||
.map((i) => ({ ...i, previewUrl: i.previewUrl }))
|
||||
kickAttachPreviews(selectedInvoicePicks.value)
|
||||
showInvoicePicker.value = false
|
||||
}
|
||||
|
||||
@@ -919,26 +965,69 @@ onMounted(async () => {
|
||||
color: #dc2626;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.invoice-picked {
|
||||
margin-top: 10px;
|
||||
.invoice-picked-row {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 4px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.invoice-picked__item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 10px;
|
||||
background: #f8fafc;
|
||||
.invoice-picked-card {
|
||||
position: relative;
|
||||
flex: 0 0 120px;
|
||||
width: 120px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
.invoice-picked__item .del {
|
||||
.invoice-picked-card__remove {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
z-index: 2;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 18px;
|
||||
color: #94a3b8;
|
||||
border-radius: 50%;
|
||||
background: rgba(15, 23, 42, 0.55);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
}
|
||||
.invoice-picked-card__preview {
|
||||
height: 80px;
|
||||
background: #f1f5f9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
.invoice-picked-card__preview img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.invoice-picked-card__icon {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.invoice-picked-card__meta {
|
||||
padding: 8px;
|
||||
}
|
||||
.invoice-picked-card__name {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.invoice-picked-card__amount {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
.form-tip {
|
||||
margin-top: 8px;
|
||||
@@ -956,6 +1045,108 @@ onMounted(async () => {
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
.invoice-picker__body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.invoice-picker__empty {
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
padding: 40px 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.invoice-month {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.invoice-month__title {
|
||||
margin: 0 0 10px 4px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.invoice-attach-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px;
|
||||
}
|
||||
.invoice-attach-card {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
border: 1.5px solid var(--border);
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
.invoice-attach-card.is-selected {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 1px var(--primary);
|
||||
}
|
||||
.invoice-attach-card__index {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
z-index: 1;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
padding: 0 4px;
|
||||
border-radius: 9px;
|
||||
background: rgba(15, 23, 42, 0.5);
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.invoice-attach-card__check {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
z-index: 1;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary);
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.invoice-attach-card__preview {
|
||||
height: 72px;
|
||||
background: #f1f5f9;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
.invoice-attach-card__preview img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.invoice-attach-card__doc {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.invoice-attach-card__meta {
|
||||
padding: 6px 8px 8px;
|
||||
}
|
||||
.invoice-attach-card__name {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.invoice-attach-card__amount {
|
||||
margin-top: 2px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
.invoice-picker__footer {
|
||||
margin-top: auto;
|
||||
padding: 12px 16px;
|
||||
|
||||
Reference in new issue
Block a user