This commit is contained in:
oneao committed 2026-10-11 22:14:13 +08:00
1 parent 32d423b759
commit 78eb811ff7
102 files changed
+12067 -209

No files matched your search

@@ -0,0 +1,80 @@
<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>