feat(yxe-reimburse): 凭证图片超过 3 张折叠为前 2 张并支持查看更多弹窗

This commit is contained in:
2026-10-29 16:59:19 +08:00
parent f723279a95
commit e98387418d
+96 -6
View File
@@ -23,16 +23,23 @@
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'images'"> <template v-if="column.key === 'images'">
<a-space> <div class="voucher-cell">
<a-image <a-image
:src="item" :src="item"
:width="50" :width="50"
:height="50" :height="50"
v-for="(item, index) in JSON.parse(record.images)" v-for="(item, index) in visibleImages(record)"
style="object-fit: cover; width: 50px; height: 50px" style="object-fit: cover; width: 50px; height: 50px"
:key="index" :key="index"
/> />
</a-space> <a
v-if="hasMoreImages(record)"
class="voucher-more"
@click="openPreview(record)"
>
查看更多({{ imageCount(record) }})
</a>
</div>
</template> </template>
<template v-else-if="column.key === 'status'"> <template v-else-if="column.key === 'status'">
<a-select <a-select
@@ -78,6 +85,24 @@
:data="current" :data="current"
@done="reload" @done="reload"
/> />
<!-- 凭证图片查看弹窗 -->
<a-modal
v-model:visible="voucherVisible"
:title="`凭证图片(共 ${voucherImages.length} 张)`"
:footer="null"
:width="640"
destroy-on-close
>
<div class="voucher-preview">
<a-image
v-for="(item, index) in voucherImages"
:key="index"
:src="item"
style="object-fit: cover; width: 120px; height: 120px"
/>
</div>
</a-modal>
</div> </div>
</div> </div>
</template> </template>
@@ -107,6 +132,9 @@
} from '@/api/yxe/yxeReimburse/model'; } from '@/api/yxe/yxeReimburse/model';
import { openExportFile } from '@/utils/export-file'; import { openExportFile } from '@/utils/export-file';
// 列表行:附带解析后的凭证图片数组
type ReimburseRow = YxeReimburse & { imageList: string[] };
// 表格实例 // 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null); const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
@@ -120,6 +148,41 @@
const showMove = ref(false); const showMove = ref(false);
// 加载状态 // 加载状态
const loading = ref(true); const loading = ref(true);
// 凭证图片查看弹窗可见性
const voucherVisible = ref(false);
// 凭证图片查看弹窗中的图片
const voucherImages = ref<string[]>([]);
// 解析凭证图片字段,null 或非法 JSON 返回空数组
const parseImages = (images?: string | null): string[] => {
if (!images) {
return [];
}
try {
const list = JSON.parse(images);
return Array.isArray(list)
? list.filter((item) => typeof item === 'string' && item)
: [];
} catch (e) {
return [];
}
};
// 凭证图片总数
const imageCount = (record: ReimburseRow) => record.imageList?.length ?? 0;
// 单元格展示的凭证:不超过 3 张时全部展示,超过 3 张时只展示前 2 张
const visibleImages = (record: ReimburseRow) =>
record.imageList?.slice(0, imageCount(record) > 3 ? 2 : 3) ?? [];
// 凭证是否被折叠
const hasMoreImages = (record: ReimburseRow) => imageCount(record) > 3;
// 打开凭证图片查看弹窗
const openPreview = (record: ReimburseRow) => {
voucherImages.value = record.imageList ?? [];
voucherVisible.value = true;
};
// 表格数据源 // 表格数据源
const datasource: DatasourceFunction = ({ const datasource: DatasourceFunction = ({
@@ -137,7 +200,13 @@
...orders, ...orders,
page, page,
limit limit
}); }).then((res) => ({
...res,
list: (res.list || []).map((row) => ({
...row,
imageList: parseImages(row.images)
}))
}));
}; };
// 表格列配置 // 表格列配置
@@ -199,7 +268,8 @@
title: '凭证', title: '凭证',
dataIndex: 'images', dataIndex: 'images',
key: 'images', key: 'images',
align: 'center' align: 'center',
width: 200
}, },
{ {
title: '用户备注', title: '用户备注',
@@ -350,4 +420,24 @@
}; };
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped>
.voucher-cell {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
white-space: nowrap;
}
.voucher-more {
font-size: 12px;
}
.voucher-preview {
display: flex;
flex-wrap: wrap;
gap: 12px;
max-height: 60vh;
overflow-y: auto;
}
</style>