fix: 修复 workbench 参考图 URL 上传与预览交互

This commit is contained in:
XianYuDaXian committed 2026-02-28 16:59:56 +08:00
1 parent 537514f78c
commit cc47603ca2
2 files changed
+90 -45

No files matched your search

+11 -2
View File
@@ -249,7 +249,12 @@ class UploadService:
lock_timeout = max(1, int(get_config("asset.upload_timeout")))
async with _file_lock(lock_name, timeout=lock_timeout):
session = await self.create()
response = await session.get(url, timeout=timeout, proxies=proxies)
response = await session.get(
url,
timeout=timeout,
proxies=proxies,
stream=True,
)
if response.status_code >= 400:
raise UpstreamException(
message=f"Failed to fetch: {response.status_code}",
@@ -263,7 +268,11 @@ class UploadService:
if not content_type:
content_type = self._infer_mime(filename)
if hasattr(response, "aiter_content"):
b64 = await self._encode_b64_stream(response.aiter_content())
try:
b64 = await self._encode_b64_stream(response.aiter_content())
except Exception:
# 某些响应对象虽存在 aiter_content,但底层未进入 stream 模式;回退读取 content。
b64 = base64.b64encode(response.content).decode()
else:
b64 = base64.b64encode(response.content).decode()
+79 -43
View File
@@ -199,6 +199,7 @@
function applyParentPostFromText(text, options = {}) {
const silent = Boolean(options.silent);
const addToReferences = Boolean(options.addToReferences);
const hit = resolveParentMemoryByText(text);
if (!hit || !hit.parentPostId) {
if (!silent) {
@@ -225,8 +226,43 @@
imageUrl: previewUrl,
origin: 'workbench_paste_apply',
});
if (addToReferences) {
const refUrl = String(sourceImageUrl || previewUrl || '').trim();
if (!refUrl) {
if (!silent) {
toast('该 parentPostId 未解析到可用参考图', 'warning');
}
} else if (state.referenceImages.length >= REFERENCE_LIMIT) {
if (!silent) {
toast(`最多支持 ${REFERENCE_LIMIT} 张参考图`, 'warning');
}
} else {
const exists = state.referenceImages.some((item) => (
(item.parentPostId && item.parentPostId === parentPostId)
|| String(item.data || '').trim() === refUrl
));
if (!exists) {
state.referenceImages.push({
id: buildRefId(),
name: `parent:${shortId(parentPostId)}`,
mime: '',
data: refUrl,
source: 'parent_post',
parentPostId,
sourceImageUrl: sourceImageUrl || refUrl,
isPrimary: false,
createdAt: Date.now(),
});
if (!state.referenceImages.some((item) => item.isPrimary)) {
state.referenceImages[0].isPrimary = true;
}
normalizeReferenceOrder();
renderReferenceStrip();
}
}
}
if (!silent) {
toast('已载入 parentPostId,可直接继续编辑', 'success');
toast(addToReferences ? '已载入 parentPostId,并加入参考图' : '已载入 parentPostId,可直接继续编辑', 'success');
}
return true;
}
@@ -324,20 +360,12 @@
function getPrimaryReference() {
if (!state.referenceImages.length) return null;
return state.referenceImages.find((item) => item.isPrimary) || state.referenceImages[0];
return state.referenceImages[0];
}
function normalizeReferenceOrder() {
if (!state.referenceImages.length) return;
const primary = getPrimaryReference();
const primaryId = primary ? primary.id : '';
state.referenceImages = state.referenceImages.map((item) => ({
...item,
isPrimary: item.id === primaryId,
}));
state.referenceImages.sort((a, b) => {
if (a.isPrimary && !b.isPrimary) return -1;
if (!a.isPrimary && b.isPrimary) return 1;
return a.createdAt - b.createdAt;
});
}
@@ -361,8 +389,8 @@
state.referenceImages.forEach((item) => {
const card = document.createElement('div');
card.className = `reference-item${item.isPrimary ? ' is-primary' : ''}`;
card.title = item.isPrimary ? `主图:${item.name}` : `设为主图:${item.name}`;
card.className = 'reference-item';
card.title = `预览:${item.name}`;
card.dataset.id = item.id;
card.setAttribute('role', 'button');
card.setAttribute('tabindex', '0');
@@ -374,13 +402,6 @@
img.loading = 'lazy';
card.appendChild(img);
if (item.isPrimary) {
const badge = document.createElement('div');
badge.className = 'reference-primary-badge';
badge.textContent = '主图';
card.appendChild(badge);
}
const removeBtn = document.createElement('button');
removeBtn.type = 'button';
removeBtn.className = 'reference-remove-btn';
@@ -395,12 +416,12 @@
card.appendChild(removeBtn);
card.addEventListener('click', () => {
setPrimaryReference(item.id);
previewReference(item.id);
});
card.addEventListener('keydown', (event) => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
setPrimaryReference(item.id);
previewReference(item.id);
}
});
referenceStrip.appendChild(card);
@@ -418,26 +439,44 @@
updateReferenceSummary();
}
function setPrimaryReference(id) {
function previewReference(id) {
if (!id) return;
let changed = false;
let primaryData = '';
state.referenceImages = state.referenceImages.map((item) => {
const isPrimary = item.id === id;
if (isPrimary) {
primaryData = String(item.data || '');
const hit = state.referenceImages.find((item) => item.id === id);
const previewData = String(hit && hit.data ? hit.data : '').trim();
if (!previewData) return;
// 仅存在这张 parentPostId 参考图时,点击即恢复到 parentPostId 编辑模式
if (
hit
&& hit.source === 'parent_post'
&& String(hit.parentPostId || '').trim()
&& state.referenceImages.length === 1
) {
state.currentParentPostId = String(hit.parentPostId || '').trim();
state.currentSourceImageUrl = String(hit.sourceImageUrl || previewData).trim();
state.currentModeValue = 'parent_post';
if (parentPostInput) {
parentPostInput.value = state.currentParentPostId;
}
const next = { ...item, isPrimary };
if (next.isPrimary !== item.isPrimary) changed = true;
return next;
});
if (!changed) return;
normalizeReferenceOrder();
renderReferenceStrip();
if (!state.currentParentPostId && primaryData) {
setPreview(primaryData);
setStatus('', '已切换主图');
updateMeta();
rememberParentPost({
parentPostId: state.currentParentPostId,
sourceImageUrl: state.currentSourceImageUrl,
imageUrl: previewData,
origin: 'workbench_reference_restore',
});
setPreview(previewData);
setStatus('done', `已恢复 parentPostId 模式:${shortId(state.currentParentPostId)}`);
return;
}
setPreview(previewData);
setStatus('', '已预览参考图');
}
function setPrimaryReference(id) {
// 兼容旧调用,点击行为仅预览,不再改变主图
previewReference(id);
}
function removeReferenceImage(id) {
@@ -510,9 +549,6 @@
});
added += 1;
}
if (added > 0 && !state.referenceImages.some((item) => item.isPrimary)) {
state.referenceImages[0].isPrimary = true;
}
normalizeReferenceOrder();
renderReferenceStrip();
@@ -1021,7 +1057,7 @@
if (applyParentBtn) {
applyParentBtn.addEventListener('click', () => {
applyParentPostFromText(parentPostInput ? parentPostInput.value : '');
applyParentPostFromText(parentPostInput ? parentPostInput.value : '', { addToReferences: true });
});
}
@@ -1029,7 +1065,7 @@
parentPostInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
event.preventDefault();
applyParentPostFromText(parentPostInput.value);
applyParentPostFromText(parentPostInput.value, { addToReferences: true });
}
});
parentPostInput.addEventListener('input', () => {