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

@@ -123,11 +123,11 @@ test('PHP submit section 默认值对齐参考主题', () => {
assert.match(submitPhp, /'post_article_s',\s*'label'\s*=>\s*'启用前台投稿',\s*'type'\s*=>\s*'switcher',\s*'default'\s*=>\s*true/);
assert.match(submitPhp, /'post_article_btn_txte',\s*'label'\s*=>\s*'按钮文字',\s*'type'\s*=>\s*'input',\s*'default'\s*=>\s*'发布文章'/);
assert.match(submitPhp, /'post_article_user',\s*'label'\s*=>\s*'免登陆投稿发布用户',\s*'type'\s*=>\s*'user_select',\s*'default'\s*=>\s*1/);
assert.match(submitPhp, /'post_article_title_strlen_limit',\s*'label'\s*=>\s*'标题字数限制',\s*'type'\s*=>\s*'between_number',\s*'default'\s*=>\s*\['min'\s*=>\s*5,\s*'max'\s*=>\s*30\]/);
assert.match(submitPhp, /'post_article_title_strlen_limit',\s*'label'\s*=>\s*'标题字数限制',\s*'type'\s*=>\s*'between_number',\s*'default'\s*=>\s*\['min'\s*=>\s*5,\s*'max'\s*=>\s*100\]/);
assert.match(submitPhp, /'post_article_pay_vip_1_discount',\s*'label'\s*=>\s*'一级会员折扣',\s*'type'\s*=>\s*'number',\s*'default'\s*=>\s*100/);
assert.match(submitPhp, /'post_article_pay_vip_2_discount',\s*'label'\s*=>\s*'二级会员折扣',\s*'type'\s*=>\s*'number',\s*'default'\s*=>\s*100/);
assert.match(submitPhp, /'post_t_placeholder',\s*'label'\s*=>\s*'投稿标题占位符',\s*'type'\s*=>\s*'input',\s*'default'\s*=>\s*'请输入标题'/);
assert.match(submitPhp, /'post_c_placeholder',\s*'label'\s*=>\s*'投稿内容占位符',\s*'type'\s*=>\s*'input',\s*'default'\s*=>\s*'请输入内容'/);
assert.match(submitPhp, /'post_t_placeholder',\s*'label'\s*=>\s*'投稿标题占位符',\s*'type'\s*=>\s*'input',\s*'default'\s*=>\s*'请输入标题(最多 100 个字)'/);
assert.match(submitPhp, /'post_c_placeholder',\s*'label'\s*=>\s*'投稿内容占位符',\s*'type'\s*=>\s*'input',\s*'default'\s*=>\s*'请输入正文'/);
assert.match(submitPhp, /'price',\s*'label'\s*=>\s*'现金金额限制'/);
assert.match(submitPhp, /'points',\s*'label'\s*=>\s*'积分金额限制'/);
});
@@ -164,8 +164,8 @@ test('JS schema 默认值对齐参考主题', () => {
assert.match(js, /post_article_user:\s*1\b/);
assert.match(js, /post_article_pay_vip_1_discount:\s*100\b/);
assert.match(js, /post_article_pay_vip_2_discount:\s*100\b/);
assert.match(js, /post_t_placeholder:\s*'请输入标题'/);
assert.match(js, /post_c_placeholder:\s*'请输入内容'/);
assert.match(js, /post_t_placeholder:\s*'请输入标题(最多 100 个字)'/);
assert.match(js, /post_c_placeholder:\s*'请输入正文'/);
assert.match(js, /price:\s*\{\s*min:\s*0,\s*max:\s*99999\s*\}/);
});
@@ -197,8 +197,44 @@ test('TinyMCE media buttons reuse Jio uploads and preserve bookmarks', () => {
assert.match(appSource, /data-video-url/);
assert.match(read('src/Core/CreatorStudio.php'), /front-submit\/upload\/image/);
assert.match(read('assets/css/frontend/pages/submit.css'), /\.jio-editor-media\s*\{/);
assert.match(read('assets/creator-studio/src/components/cover-strip.tsx'), /添加封面/);
assert.match(appSource, /<CoverStrip/);
assert.match(read('assets/creator-studio/src/components/publish-settings.tsx'), /添加封面/);
assert.match(appSource, /<PublishSettings/);
});
test('writing surface is a centered paper card with a publish settings card below', () => {
const styles = read('assets/creator-studio/src/styles/studio.scss');
const settings = read('assets/creator-studio/src/components/publish-settings.tsx');
assert.doesNotMatch(appSource, /jio-creator__excerpt/);
assert.match(appSource, /请输入标题(最多 %d 个字)/, 'title placeholder must state the character limit');
assert.match(appSource, /className="jio-creator__title"/);
assert.match(appSource, /<PublishSettings/);
assert.match(styles, /\.jio-creator__canvas\s*\{[^}]*background:\s*#fff/);
assert.match(styles, /\.jio-creator__canvas\s*\{[^}]*width:\s*min\(900px/);
assert.match(styles, /\.jio-creator__canvas\s*\{[^}]*margin:\s*40px auto 0/);
assert.match(styles, /\.jio-page-submit\s*\{[^}]*background:\s*#f6f6f6/);
assert.match(styles, /\.jio-creator__settings\s*\{[^}]*background:\s*#fff/);
assert.match(styles, /\.jio-creator__title\s*\{[\s\S]*?font-size:\s*clamp\(26px, 3vw, 32px\)/);
assert.match(styles, /\.jio-creator__title\s*\{[\s\S]*?border-bottom:\s*1px solid/);
assert.match(settings, /定时发布/);
assert.match(settings, /type="datetime-local"/);
assert.match(settings, /canSchedule/);
assert.match(appSource, /scheduleEnabled=\{!!draft\.schedule\.enabled\}/);
});
test('scheduled publishing is validated and applied server side', () => {
const save = read('src/Core/FrontSubmitSave.php');
const rest = read('src/Core/CreatorRest.php');
assert.match(save, /private function normalize_schedule\(array \$data\): string/);
assert.match(save, /\$status\s*=\s*'future';/);
assert.match(save, /\$postarr\['post_date'\]\s*=\s*\$schedule_at;/);
assert.match(save, /get_gmt_from_date\(\$schedule_at\)/);
assert.match(save, /case 'future':/);
assert.match(rest, /'schedule'\s*=>\s*\(array\) \$request->get_param\('schedule'\)/);
assert.match(rest, /'canSchedule'\s*=>\s*\$cap\('new_post_audit_no'\)/);
});
test('Chinese character count strips markup and counts visible text', () => {