feat(creator-studio): centered paper layout and scheduled publishing

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-06 21:33:40 +08:00
1 parent 384d2b7aa0
commit 7bdf7cf018
20 files changed
+549 -308

No files matched your search

@@ -1,7 +1,8 @@
/**
* 发布配置抽屉。
*
* 封面、分类、摘要、付费与资料附件都只在这里出现,正文画布保持干净;
* 分类、标签、付费与资料附件都在这里配置;封面与定时发布在正文下方的
* 「发布设置」卡片里,避免把封面入口和正文挤在同一张纸上。
* 手机端以全屏面板呈现。所有字段与权限来自服务端 bootstrap,前端不自行放大权限。
*
* @package Jio
@@ -12,7 +13,6 @@ import { __, sprintf } from '@wordpress/i18n';
import { apiUpload } from '../services/api';
type Featured = { type: string; data: Record<string, any>; mediaId?: number };
type PayState = {
enabled: boolean;
modo: 'cash' | 'points';
@@ -27,11 +27,9 @@ type PayState = {
type Draft = {
postId: number;
title: string;
excerpt: string;
categories: number[];
tags: string[];
custom: Record<string, string[]>;
featured: Featured;
pay: PayState;
};
@@ -89,7 +87,6 @@ export function PublishDrawer(props: Props) {
const [tagInput, setTagInput] = useState('');
const [uploadError, setUploadError] = useState('');
const [uploading, setUploading] = useState(false);
const coverInput = useRef<HTMLInputElement | null>(null);
const fileInput = useRef<HTMLInputElement | null>(null);
const captchaSlot = useRef<HTMLDivElement | null>(null);
@@ -135,28 +132,6 @@ export function PublishDrawer(props: Props) {
setTagInput('');
};
const uploadCover = async () => {
const file = coverInput.current?.files?.[0];
if (!file || !bootstrap.media?.uploadUrl?.image) {
return;
}
setUploadError('');
setUploading(true);
try {
const response = await apiUpload(bootstrap.media.uploadUrl.image, file, nonce);
const id = Number(response.attachment_id || response.id || 0);
const url = String(response.url || '');
if (!id || !url) {
throw new Error(__('上传后无法读取图片。', 'jio'));
}
setDraft({ featured: { type: 'image', mediaId: id, data: { id, url } } });
} catch (error: any) {
setUploadError(String(error?.message || __('上传失败', 'jio')));
} finally {
setUploading(false);
}
};
const uploadAttachment = async () => {
const file = fileInput.current?.files?.[0];
if (!file) {
@@ -213,36 +188,6 @@ export function PublishDrawer(props: Props) {
</p>
)}
<section className="jio-creator-field">
<h3>{__('封面', 'jio')}</h3>
{draft.featured?.data?.url ? (
<div className="jio-creator-cover">
<img src={String(draft.featured.data.url)} alt="" />
<button
type="button"
onClick={() => setDraft({ featured: { type: '', data: {} } })}
aria-label={__('移除封面', 'jio')}
>
<i className="fa fas fa-times" aria-hidden="true" />
</button>
</div>
) : capabilities.canUploadImage ? (
<label className="jio-creator-cover-empty">
<input
ref={coverInput}
type="file"
accept="image/*"
onChange={() => void uploadCover()}
disabled={uploading}
/>
<i className="fa fas fa-plus" aria-hidden="true" />
<span>{uploading ? __('上传中…', 'jio') : __('上传封面', 'jio')}</span>
</label>
) : (
<p className="jio-creator-muted">{__('当前账号不能设置封面。', 'jio')}</p>
)}
</section>
<section className="jio-creator-field">
<h3>{__('分类', 'jio')}</h3>
<div className="jio-creator-chips">