iter(g173): 上传图片显示缩略图
This commit is contained in:
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "ui-arch-registry-index/0.1",
|
"$schema": "ui-arch-registry-index/0.1",
|
||||||
"generatedAt": "2026-10-26T08:18:29.931Z",
|
"generatedAt": "2026-10-26T08:20:12.255Z",
|
||||||
"repoRoot": ".",
|
"repoRoot": ".",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
@@ -2432,7 +2432,8 @@
|
|||||||
"把 upload 放进表单,accept 限定类型、multiple 允许多选",
|
"把 upload 放进表单,accept 限定类型、multiple 允许多选",
|
||||||
"需要拦体积就给 maxSize(字节),限制数量给 maxCount",
|
"需要拦体积就给 maxSize(字节),限制数量给 maxCount",
|
||||||
"被拒的文件不会进清单,原因显示在下方提示行(拖拽与点选走同一套校验)",
|
"被拒的文件不会进清单,原因显示在下方提示行(拖拽与点选走同一套校验)",
|
||||||
"onChange 拿到的 File[] 是副本,自行发请求上传(组件不内置网络层)"
|
"onChange 拿到的 File[] 是副本,自行发请求上传(组件不内置网络层)",
|
||||||
|
"选中的图片会带 28px 缩略图(对象 URL,随文件离场即 revoke,不会泄漏);非图片只显示文件名与体积,点 × 移除"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||||
|
|
||||||
> 自动生成于 2026-10-26T08:18:29.931Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
> 自动生成于 2026-10-26T08:20:12.255Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||||
|
|
||||||
## 快速上手
|
## 快速上手
|
||||||
@@ -1247,6 +1247,7 @@ upload({ multiple: true, accept: 'image/*', hint: '拖拽图片到此处', onCha
|
|||||||
2. 需要拦体积就给 maxSize(字节),限制数量给 maxCount
|
2. 需要拦体积就给 maxSize(字节),限制数量给 maxCount
|
||||||
3. 被拒的文件不会进清单,原因显示在下方提示行(拖拽与点选走同一套校验)
|
3. 被拒的文件不会进清单,原因显示在下方提示行(拖拽与点选走同一套校验)
|
||||||
4. onChange 拿到的 File[] 是副本,自行发请求上传(组件不内置网络层)
|
4. onChange 拿到的 File[] 是副本,自行发请求上传(组件不内置网络层)
|
||||||
|
5. 选中的图片会带 28px 缩略图(对象 URL,随文件离场即 revoke,不会泄漏);非图片只显示文件名与体积,点 × 移除
|
||||||
|
|
||||||
现场演示:apps/docs/demo.html#sec-upload
|
现场演示:apps/docs/demo.html#sec-upload
|
||||||
|
|
||||||
|
|||||||
@@ -36,13 +36,24 @@ export function upload(props: UploadProps): HTMLElement {
|
|||||||
sync();
|
sync();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// —— 图片缩略图:对象 URL 按 File 缓存,文件离场即释放(否则整页存活期都在泄漏) ——
|
||||||
|
const urls = new Map<File, string>();
|
||||||
|
const thumbOf = (file: File): HTMLElement | null => {
|
||||||
|
if (!file.type.startsWith('image/')) return null; // 卫语句:非图片不缩略,只给文件名
|
||||||
|
let url = urls.get(file);
|
||||||
|
if (!url) { url = URL.createObjectURL(file); urls.set(file, url); }
|
||||||
|
return h('img', { class: 'ua-upload-thumb', src: url, alt: '', loading: 'lazy' });
|
||||||
|
};
|
||||||
|
|
||||||
/*** 重绘清单并回传(选择/拖拽/移除都走这里,保证单一出口) ***/
|
/*** 重绘清单并回传(选择/拖拽/移除都走这里,保证单一出口) ***/
|
||||||
const sync = (tip = '') => {
|
const sync = (tip = '') => {
|
||||||
|
for (const [file, url] of urls) if (!files.includes(file)) { URL.revokeObjectURL(url); urls.delete(file); } // 已离场的文件先释放
|
||||||
listEl.replaceChildren(
|
listEl.replaceChildren(
|
||||||
...files.map((file, i) =>
|
...files.map((file, i) =>
|
||||||
h(
|
h(
|
||||||
'div',
|
'div',
|
||||||
{ class: 'ua-upload-item' },
|
{ class: 'ua-upload-item' },
|
||||||
|
thumbOf(file),
|
||||||
h('span', { class: 'ua-upload-name' }, file.name),
|
h('span', { class: 'ua-upload-name' }, file.name),
|
||||||
h('span', { class: 'ua-upload-size' }, size(file.size)),
|
h('span', { class: 'ua-upload-size' }, size(file.size)),
|
||||||
h('button', { type: 'button', class: 'ua-upload-remove', 'aria-label': `移除 ${file.name}`, onclick: () => remove(i) }, '×'),
|
h('button', { type: 'button', class: 'ua-upload-remove', 'aria-label': `移除 ${file.name}`, onclick: () => remove(i) }, '×'),
|
||||||
|
|||||||
@@ -2303,7 +2303,8 @@
|
|||||||
"把 upload 放进表单,accept 限定类型、multiple 允许多选",
|
"把 upload 放进表单,accept 限定类型、multiple 允许多选",
|
||||||
"需要拦体积就给 maxSize(字节),限制数量给 maxCount",
|
"需要拦体积就给 maxSize(字节),限制数量给 maxCount",
|
||||||
"被拒的文件不会进清单,原因显示在下方提示行(拖拽与点选走同一套校验)",
|
"被拒的文件不会进清单,原因显示在下方提示行(拖拽与点选走同一套校验)",
|
||||||
"onChange 拿到的 File[] 是副本,自行发请求上传(组件不内置网络层)"
|
"onChange 拿到的 File[] 是副本,自行发请求上传(组件不内置网络层)",
|
||||||
|
"选中的图片会带 28px 缩略图(对象 URL,随文件离场即 revoke,不会泄漏);非图片只显示文件名与体积,点 × 移除"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2700,6 +2700,15 @@ button.ua-step-dot:hover {
|
|||||||
border-radius: var(--ua-radius-sm);
|
border-radius: var(--ua-radius-sm);
|
||||||
font-size: var(--ua-font-size-sm);
|
font-size: var(--ua-font-size-sm);
|
||||||
}
|
}
|
||||||
|
.ua-upload-thumb {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 1px solid var(--ua-color-border);
|
||||||
|
border-radius: var(--ua-radius-sm);
|
||||||
|
background: var(--ua-color-surface);
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
.ua-upload-name {
|
.ua-upload-name {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user