81 lines
2.7 KiB
Vue
81 lines
2.7 KiB
Vue
<script setup lang="ts">
|
||
// 最小用法:只喂 files + categories,上传 / 删除交给业务(组件不发请求)
|
||
import { ref } from 'vue'
|
||
import { G3Attachment } from '@g3soft/ui'
|
||
import type { AttachmentCategory, AttachmentItem, AttachmentUploadContext } from '@g3soft/ui'
|
||
|
||
// 分类(可选):不给 categories 就只渲染「列表 + 预览」两栏
|
||
const categories: AttachmentCategory[] = [
|
||
{ id: 'contract', name: '合同文件' },
|
||
{ id: 'invoice', name: '发票凭证' },
|
||
{ id: 'photo', name: '现场照片' },
|
||
]
|
||
|
||
// 内联 SVG,保证文档站离线也能看到图片预览
|
||
const PHOTO = `data:image/svg+xml;utf8,${encodeURIComponent(
|
||
'<svg xmlns="http://www.w3.org/2000/svg" width="320" height="200"><rect width="320" height="200" fill="#e5e7eb"/><text x="160" y="108" font-size="18" text-anchor="middle" fill="#6b7280">现场照片</text></svg>',
|
||
)}`
|
||
|
||
const files = ref<AttachmentItem[]>([
|
||
{ id: 1, name: '2026年度框架合同.pdf', size: 512_000, categoryId: 'contract' },
|
||
{ id: 2, name: '供应商报价明细.xlsx', size: 86_000, categoryId: 'invoice' },
|
||
{ id: 3, name: '现场照片.jpg', size: 1_240_000, categoryId: 'photo', url: PHOTO },
|
||
{ id: 4, name: '验收纪要.docx', size: 24_000, categoryId: 'contract' },
|
||
])
|
||
|
||
const lastEvent = ref('等待操作…')
|
||
|
||
// 没传 upload-request 时,组件把待上传文件抛出来,落库由业务决定
|
||
function onUpload(incoming: File[], context: AttachmentUploadContext) {
|
||
files.value = [
|
||
...files.value,
|
||
...incoming.map((file, index) => ({
|
||
id: `local-${Date.now()}-${index}`,
|
||
name: file.name,
|
||
size: file.size,
|
||
categoryId: context.categoryId,
|
||
// 真实项目换成接口返回的地址;示例用 blob 地址即时预览
|
||
url: URL.createObjectURL(file),
|
||
})),
|
||
]
|
||
lastEvent.value = `upload:${incoming.map((file) => file.name).join('、')}`
|
||
}
|
||
|
||
function onRemove(items: AttachmentItem[]) {
|
||
const removed = new Set(items.map((item) => item.id))
|
||
files.value = files.value.filter((file) => !removed.has(file.id))
|
||
lastEvent.value = `remove:${items.map((item) => item.name).join('、')}`
|
||
}
|
||
|
||
function onDownload(items: AttachmentItem[]) {
|
||
lastEvent.value = `download:${items.map((item) => item.name).join('、')}`
|
||
}
|
||
|
||
function onInvalid(info: { message: string }) {
|
||
lastEvent.value = `invalid:${info.message}`
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div>
|
||
<G3Attachment
|
||
v-model:files="files"
|
||
:categories="categories"
|
||
:height="560"
|
||
@upload="onUpload"
|
||
@remove="onRemove"
|
||
@download="onDownload"
|
||
@invalid="onInvalid"
|
||
/>
|
||
<p class="hint">{{ lastEvent }}</p>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.hint {
|
||
margin: 8px 0 0;
|
||
color: #8c8c8c;
|
||
font-size: 12px;
|
||
}
|
||
</style>
|