fix(creator-studio): 修复白屏与前台 REST 鉴权

白屏根因:CreatorRest / SubmissionVersion 位于 Jio\Core 命名空间,
但调用 Jio\Content\PrivateAssets 时缺少 use 导入,PHP 就近解析为不存在的
Jio\Core\PrivateAssets,在 wp_head 中抛致命错误导致页面输出截断。

- 为 CreatorRest、SubmissionVersion 补上 use Jio\Content\PrivateAssets
- 新增前台 api-fetch nonce 中间件:WordPress 只在后台注入 wpApiSettings,
  前台工作台里 Gutenberg core-data 请求(/wp/v2/users/me)因此全部 403
- 提交前先落一次草稿,避免自动保存未触发时发布到旧内容
- 新增 tools/check-class-refs.php:静态检测命名空间内未导入的裸类引用
- 新增 assets/creator-studio/scripts/smoke.cjs:浏览器冒烟脚本,
  抓控制台错误、失败请求与未捕获的 Promise 拒绝

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-06 15:39:10 +08:00
1 parent fac4a714e0
commit 2c7262770b
10 files changed
+262 -36

No files matched your search

+10 -1
View File
@@ -17,6 +17,7 @@ import { count as countWords } from '@wordpress/wordcount';
import { __ } from '@wordpress/i18n';
import { apiPost } from './services/api';
import { installApiFetchNonce } from './services/api-fetch';
import { installMediaUploadBridge } from './services/media';
import { PublishDrawer } from './panels/publish-drawer';
import { SaveState, type SaveStateValue } from './components/save-state';
@@ -183,6 +184,13 @@ function Studio(): JSX.Element {
const submit = useCallback(
async (publishNow: boolean): Promise<void> => {
// 提交前先落一次草稿:审核 / 立即发布都以服务端最终保存的内容为准,
// 避免自动保存尚未触发时提交到旧内容。
const persisted = await save(false);
if (!persisted) {
setNotice({ tone: 'error', text: __('内容保存失败,请重试后再提交', 'jio') });
return;
}
setSaveState({ state: 'submitting', at: '' });
try {
// 站点启用「前台投稿」人机验证时,先完成挑战再提交;
@@ -218,7 +226,7 @@ function Studio(): JSX.Element {
setNotice({ tone: 'error', text: String(error?.message || __('提交失败', 'jio')) });
}
},
[buildPayload]
[buildPayload, save]
);
const preview = useCallback(async (): Promise<void> => {
@@ -436,6 +444,7 @@ function mount() {
if (!target) {
return;
}
installApiFetchNonce(nonce);
installMediaUploadBridge(bootstrap, nonce);
target.classList.add('is-ready');
createRoot(target).render(<Studio />);
@@ -0,0 +1,33 @@
/**
* 给 @wordpress/api-fetch 注入 REST nonce。
*
* WordPress 仅在后台为 wp-api 注入 wpApiSettings(含 nonce),前台工作台里
* Gutenberg 的 core-data 请求(如 /wp/v2/users/me)因此全部 403。这里统一挂一个
* nonce 中间件,让区块编辑器的数据请求与 Jio REST 使用同一次页面加载的 nonce。
*
* @package Jio
*/
import apiFetch from '@wordpress/api-fetch';
export function installApiFetchNonce(nonce: string): void {
if (!nonce || typeof apiFetch.use !== 'function') {
return;
}
if ((window as any).__jioApiFetchNonceInstalled) {
return;
}
(window as any).__jioApiFetchNonceInstalled = true;
// createNonceMiddleware 在收到 rest_cookie_invalid_nonce 时会带着 nonce 重试,
// 比在每次请求上手工加 header 更稳妥。
const factory = (apiFetch as any).createNonceMiddleware;
if (typeof factory === 'function') {
apiFetch.use(factory(nonce));
return;
}
apiFetch.use((options: any, next: any) => {
options.headers = { ...(options.headers || {}), 'X-WP-Nonce': nonce };
return next(options);
});
}