feat(bx): invoice wallet UI and reimburse apply invoice select

Add mine/admin wallet pages, select dialog, routes/icons, and switch
apply form from local invoice upload to optional wallet association with
balance gate; approve detail shows linked invoices.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-07-25 19:46:00 +08:00
1 parent 6092b685de
commit dadf903bff
8 files changed
+1000 -58

No files matched your search

@@ -0,0 +1,111 @@
<template>
<el-dialog
v-model="visible"
title="从发票夹选择"
width="720px"
class="dialog-form-layout"
align-center
destroy-on-close
append-to-body
@open="loadList"
>
<el-table
ref="tableRef"
v-loading="loading"
class="list-table"
:data="rows"
stripe
row-key="id"
max-height="420"
@selection-change="onSelectionChange"
>
<el-table-column type="selection" min-width="48" />
<el-table-column prop="amount" label="金额(元)" min-width="120" align="right">
<template #default="{ row }">{{ formatMoneyYuan(row.amount) }}</template>
</el-table-column>
<el-table-column prop="fileName" label="附件" min-width="160" show-overflow-tooltip>
<template #default="{ row }">{{ row.fileName || '-' }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip>
<template #default="{ row }">{{ row.remark || '-' }}</template>
</el-table-column>
<el-table-column prop="createTime" label="上传时间" min-width="160" />
</el-table>
<template #footer>
<el-button class="btn-ghost" @click="visible = false">
<el-icon><Close /></el-icon>取消
</el-button>
<el-button class="btn-main" type="primary" @click="confirm">
<el-icon><Check /></el-icon>确定
</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { nextTick, ref, watch } from 'vue'
import { Close, Check } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { invoiceApi } from '@/api/bx'
import { formatMoneyYuan } from '@/utils/bx/format'
import { pickBxPageResult } from '@/utils/http/bx'
const props = defineProps<{
modelValue: boolean
selectedIds?: string[]
}>()
const emit = defineEmits<{
(e: 'update:modelValue', v: boolean): void
(e: 'confirm', rows: any[]): void
}>()
const visible = ref(false)
const loading = ref(false)
const rows = ref<any[]>([])
const selected = ref<any[]>([])
const tableRef = ref<any>(null)
watch(
() => props.modelValue,
(v) => {
visible.value = v
},
{ immediate: true }
)
watch(visible, (v) => {
emit('update:modelValue', v)
})
async function loadList() {
loading.value = true
try {
const res: any = await invoiceApi.list({ page: 1, pageSize: 200 })
const page = pickBxPageResult<any>(res)
rows.value = page.list
await nextTick()
const idSet = new Set((props.selectedIds || []).map(String))
selected.value = []
rows.value.forEach((row) => {
if (idSet.has(String(row.id))) {
tableRef.value?.toggleRowSelection?.(row, true)
}
})
} catch (e: any) {
ElMessage.error(e?.message || '加载发票失败')
} finally {
loading.value = false
}
}
function onSelectionChange(list: any[]) {
selected.value = list
}
function confirm() {
emit('confirm', selected.value.slice())
visible.value = false
}
</script>