refactor(creator-studio): pick the cover from the toolbar image dialog

The cover row carried its own hidden file input and upload call, so authors
had two different image flows in one page.

- 添加封面 now opens window.JioSubmitMedia with type=image, the same dialog
  the toolbar's 图片 button uses (mine / upload / external link).
- The picked image is stored as the full-size URL plus its attachment id,
  matching FrontSubmitFeatured's image branch, which re-checks ownership
  and sets the post thumbnail.
- Removes the now-unused uploadCover path, apiUpload/nonce imports, and the
  .jio-creator__cover-input rule.

Contract added; 887 widget-system tests pass.
This commit is contained in:
kate522 committed 2026-11-09 15:57:30 +08:00
1 parent f97fd72bd0
commit 4cd296c066
6 files changed
+58 -61

No files matched your search

@@ -8,10 +8,9 @@
* @package Jio
*/
import { useMemo, useRef, useState } from '@wordpress/element';
import { useMemo, useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import { apiUpload } from '../services/api';
import type { PayState } from '../draft';
type Featured = { type: string; data: Record<string, any>; mediaId?: number };
@@ -78,9 +77,7 @@ export function PublishSettings({
onCustomChange,
onOpenPaySettings,
}: Props) {
const coverInput = useRef<HTMLInputElement | null>(null);
const [tagInput, setTagInput] = useState('');
const [uploading, setUploading] = useState(false);
const [error, setError] = useState('');
const minSchedule = useMemo(() => toLocalInput(new Date(Date.now() + 5 * 60 * 1000)), []);
const coverUrl = typeof featured?.data?.url === 'string' ? featured.data.url : '';
@@ -112,30 +109,37 @@ export function PublishSettings({
});
};
const uploadCover = async () => {
const file = coverInput.current?.files?.[0];
const uploadUrl = bootstrap.media?.uploadUrl?.image;
if (!file || !uploadUrl) {
/**
* 复用工具栏「图片」按钮的媒体弹窗选封面。
*
* 与正文插图走同一个 JioSubmitMedia:可以直接从「我的图片」挑,
* 也可以当场上传或填外链,作者不必在两套上传 UI 之间切换。
*/
const pickCover = () => {
const media = (window as any).JioSubmitMedia;
if (!media || typeof media.open !== 'function') {
setError(__('媒体选择器尚未加载,请刷新页面后重试。', 'jio'));
return;
}
setError('');
setUploading(true);
try {
const response = await apiUpload(uploadUrl, file, nonce);
const id = Number(response.attachment_id || response.id || 0);
const url = String(response.url || '');
if (!id || !url) {
throw new Error(__('上传后无法读取图片。', 'jio'));
}
onFeaturedChange({ type: 'image', mediaId: id, data: { id, url } });
} catch (uploadError: any) {
setError(String(uploadError?.message || __('上传失败', 'jio')));
} finally {
setUploading(false);
if (coverInput.current) {
coverInput.current.value = '';
}
}
media.open({
type: 'image',
multiple: false,
onSelect: (selected: any) => {
const item = Array.isArray(selected) ? selected[0] : selected;
if (!item) {
return;
}
// 封面按原图保存,预览才用缩略图,避免分享卡片被压成小图。
const url = String(item.url || item.large_url || '');
if (!url) {
setError(__('无法读取图片地址,请重新选择。', 'jio'));
return;
}
const id = Number(item.attachment_id || item.id || 0);
onFeaturedChange({ type: 'image', mediaId: id, data: { id, url } });
},
});
};
return (
@@ -245,7 +249,7 @@ export function PublishSettings({
<button
type="button"
className="jio-creator__cover-preview"
onClick={() => coverInput.current?.click()}
onClick={pickCover}
aria-label={__('更换封面', 'jio')}
>
<img src={coverUrl} alt="" />
@@ -260,23 +264,11 @@ export function PublishSettings({
</button>
</>
) : (
<button
type="button"
className="jio-creator__cover-add"
onClick={() => coverInput.current?.click()}
disabled={uploading}
>
<button type="button" className="jio-creator__cover-add" onClick={pickCover}>
<i className="fa fas fa-plus" aria-hidden="true" />
<span>{uploading ? __('上传中…', 'jio') : __('添加封面', 'jio')}</span>
<span>{__('添加封面', 'jio')}</span>
</button>
)}
<input
ref={coverInput}
type="file"
accept="image/*"
className="jio-creator__cover-input"
onChange={() => void uploadCover()}
/>
</div>
</div>
)}
@@ -699,15 +699,6 @@ body.jio-page-submit.has-static-nav {
gap: 8px;
}
.jio-creator__cover-input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
opacity: 0;
pointer-events: none;
}
.jio-creator__cover-add {
display: inline-flex;
align-items: center;