From 7bdf7cf0183d8974d68bcebed64801ef19c3be15 Mon Sep 17 00:00:00 2001
From: unknown
Date: Fri, 6 Nov 2026 21:33:40 +0800
Subject: [PATCH] feat(creator-studio): centered paper layout and scheduled
publishing
Co-Authored-By: Claude Opus 5 (1M context)
---
.../src/schema/sections/post-list/submit.js | 8 +-
assets/creator-studio/build/index.asset.php | 2 +-
assets/creator-studio/build/index.css | 2 +-
assets/creator-studio/build/index.js | 4 +-
assets/creator-studio/scripts/preview.cjs | 4 +-
assets/creator-studio/scripts/shoot.cjs | 2 +-
.../src/components/cover-strip.tsx | 56 ---
.../src/components/publish-settings.tsx | 178 ++++++++++
assets/creator-studio/src/index.tsx | 65 ++--
.../src/panels/publish-drawer.tsx | 59 +---
assets/creator-studio/src/styles/_tokens.scss | 8 +-
assets/creator-studio/src/styles/studio.scss | 328 +++++++++++-------
src/Admin/Schema/SchemaPostList.php | 6 +-
src/Core/CreatorRest.php | 12 +-
src/Core/CreatorStudio.php | 2 +
src/Core/FrontSubmit.php | 6 +-
src/Core/FrontSubmitSave.php | 59 ++++
src/Settings/PostDisplay.php | 6 +-
...ubmit-settings-reference-contract.test.cjs | 10 +-
.../creator-studio-contract.test.cjs | 40 ++-
20 files changed, 549 insertions(+), 308 deletions(-)
delete mode 100644 assets/creator-studio/src/components/cover-strip.tsx
create mode 100644 assets/creator-studio/src/components/publish-settings.tsx
diff --git a/assets/admin/src/schema/sections/post-list/submit.js b/assets/admin/src/schema/sections/post-list/submit.js
index 111303f9..a80caa50 100644
--- a/assets/admin/src/schema/sections/post-list/submit.js
+++ b/assets/admin/src/schema/sections/post-list/submit.js
@@ -10,14 +10,14 @@ export const submitSchema = {
post_article_custom_filter_s: true,
post_article_tag: true,
post_article_user: 1,
- post_article_title_strlen_limit: { min: 5, max: 30 },
+ post_article_title_strlen_limit: { min: 5, max: 100 },
post_article_pay_free_s: true,
post_article_pay_price_limit: { price: { min: 0, max: 99999 }, points: { min: 0, max: 0 } },
post_article_pay_vip_price_s: true,
post_article_pay_vip_1_discount: 100,
post_article_pay_vip_2_discount: 100,
- post_t_placeholder: '请输入标题',
- post_c_placeholder: '请输入内容',
+ post_t_placeholder: '请输入标题(最多 100 个字)',
+ post_c_placeholder: '请输入正文',
},
groups: [
{
@@ -44,7 +44,7 @@ export const submitSchema = {
},
{ key: 'post_article_tag', label: '允许插入标签', type: 'switch', default: true, dependsOn: { key: 'post_article_s', value: true }, description: '前台投稿时候允许设置文章标签' },
{ key: 'post_article_user', label: '免登陆投稿发布用户', type: 'user_select', default: 1, dependsOn: { key: 'post_article_s', value: true }, description: '当选择投稿权限为无需登录就能投稿时,投稿文章的用户' },
- { key: 'post_article_title_strlen_limit', label: '标题字数限制', type: 'between_number', default: { min: 5, max: 30 }, unit: '字', description: '限制标题字数可有效的防止灌水等无意义内容(英文字符按0.5个字计算)' },
+ { key: 'post_article_title_strlen_limit', label: '标题字数限制', type: 'between_number', default: { min: 5, max: 100 }, unit: '字', description: '限制标题字数可有效的防止灌水等无意义内容(英文字符按0.5个字计算)' },
{ key: 'post_article_pay_free_s', label: '允许设置为免费资源', type: 'switch', default: true, dependsOn: { key: 'post_article_s', value: true }, description: '付费内容金额允许设置为 0' },
{
key: 'post_article_pay_price_limit',
diff --git a/assets/creator-studio/build/index.asset.php b/assets/creator-studio/build/index.asset.php
index a0efa170..f1c7cd40 100644
--- a/assets/creator-studio/build/index.asset.php
+++ b/assets/creator-studio/build/index.asset.php
@@ -1 +1 @@
- array('react', 'wp-element', 'wp-i18n'), 'version' => '7498c793a760249be02b');
+ array('react', 'wp-element', 'wp-i18n'), 'version' => 'ccaa65aec8e25f38d35c');
diff --git a/assets/creator-studio/build/index.css b/assets/creator-studio/build/index.css
index 455fe044..9fb67740 100644
--- a/assets/creator-studio/build/index.css
+++ b/assets/creator-studio/build/index.css
@@ -1 +1 @@
-.jio-page-submit{background:#fafbfa}body.jio-page-submit.has-static-nav,body.jio-page-submit.nav-fixed{padding-top:0!important}.jio-page-submit .float-btn,.jio-page-submit .footer,.jio-page-submit .footer-tabbar,.jio-page-submit .header,.jio-page-submit .jio-float-buttons{display:none!important}.jio-page-submit #main-content.container{max-width:none;padding:0}#jio-creator-studio.is-ready{display:block}.jio-creator{--jc-ink:#243330;--jc-ink-soft:#5c6b66;--jc-paper:#fafbfa;--jc-line:#e2e9e5;--jc-accent:#267665;--jc-accent-strong:#1d5f52;--jc-warn:#b4573f;--jc-bar:60px;-webkit-font-smoothing:antialiased;background:var(--jc-paper);color:var(--jc-ink);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans SC,PingFang SC,Microsoft YaHei,sans-serif;min-height:100vh;min-height:100dvh;padding-top:var(--jc-bar)}.jio-creator *,.jio-creator :after,.jio-creator :before{box-sizing:border-box}.jio-creator button{color:inherit;font:inherit}.jio-creator__bar{align-items:center;background:rgba(250,251,250,.98);border-bottom:1px solid var(--jc-line);box-shadow:0 2px 8px rgba(27,46,39,.035);display:flex;gap:clamp(10px,1.7vw,24px);height:var(--jc-bar);left:0;padding:0 clamp(14px,2.4vw,30px);position:fixed;right:0;top:0;z-index:300}.jio-creator__bar-actions,.jio-creator__bar-left{align-items:center;display:flex;flex:0 0 auto;gap:9px;min-width:0}.jio-creator__bar-left{border-right:1px solid var(--jc-line);padding-right:clamp(10px,1.5vw,20px)}.jio-creator__bar-actions{gap:7px;margin-left:auto}.jio-creator__bar-brand{color:var(--jc-accent-strong);font-family:Songti SC,"Noto Serif SC","Source Han Serif SC",serif;font-size:17px;font-weight:700;letter-spacing:-.04em}.jio-creator__bar-divider{background:var(--jc-line);height:18px;width:1px}.jio-creator__bar-mode{color:var(--jc-ink-soft);font-size:13px;white-space:nowrap}.jio-creator__back{align-items:center;border-radius:7px;color:var(--jc-ink-soft);display:inline-flex;height:30px;justify-content:center;text-decoration:none;width:30px}.jio-creator__back:focus-visible,.jio-creator__back:hover{background:#edf3f0;color:var(--jc-accent);outline:0}.jio-creator__toolbar-tools{align-items:center;display:flex;flex:1 1 auto;gap:7px;min-width:0;overflow-x:auto;scrollbar-width:none}.jio-creator__toolbar-tools::-webkit-scrollbar{display:none}.jio-creator__toolbar-group{align-items:center;display:inline-flex;flex:0 0 auto;gap:2px}.jio-creator__toolbar-divider{background:var(--jc-line);flex:0 0 auto;height:22px;width:1px}.jio-creator__tool-btn{align-items:center;background:transparent;border:0;border-radius:7px;color:var(--jc-ink-soft);cursor:pointer;display:inline-flex;flex:0 0 auto;font-size:13px;gap:7px;height:34px;justify-content:center;min-width:32px;padding:0 8px}.jio-creator__tool-btn:focus-visible:not(:disabled),.jio-creator__tool-btn:hover:not(:disabled){background:#edf3f0;color:var(--jc-accent-strong);outline:0}.jio-creator__tool-btn:disabled{color:#c7d0cc;cursor:default}.jio-creator__tool-labeled span{white-space:nowrap}.jio-creator__format-select{background:transparent;border:1px solid transparent;border-radius:7px;color:var(--jc-ink-soft);flex:0 0 auto;font:inherit;font-size:13px;height:34px;padding:0 8px;width:94px}.jio-creator__format-select:focus-visible,.jio-creator__format-select:hover{background:#fff;border-color:var(--jc-line);outline:0}.jio-creator__format-select:disabled{color:#aebbb5}.jio-creator__save-draft{align-items:center;background:#fff;border:1px solid var(--jc-line);border-radius:7px;color:var(--jc-ink-soft);cursor:pointer;display:inline-flex;flex:0 0 auto;font-size:13px;gap:7px;justify-content:center;min-height:34px;padding:0 10px;white-space:nowrap}.jio-creator__save-draft:focus-visible:not(:disabled),.jio-creator__save-draft:hover:not(:disabled){background:#f7faf8;border-color:#b7cdc3;color:var(--jc-accent-strong);outline:0}.jio-creator__save-draft:disabled{cursor:default;opacity:.55}.jio-creator__save{align-items:center;color:var(--jc-ink-soft);display:inline-flex;flex:0 0 auto;font-size:12px;gap:6px;white-space:nowrap}.jio-creator__save>i{color:var(--jc-line);font-size:7px}.jio-creator__save time{font-variant-numeric:tabular-nums;opacity:.7}.jio-creator__save.is-saved>i{color:var(--jc-accent)}.jio-creator__save.is-conflict,.jio-creator__save.is-conflict>i,.jio-creator__save.is-error,.jio-creator__save.is-error>i{color:var(--jc-warn)}.jio-creator__btn,.jio-creator__ghost,.jio-creator__primary{align-items:center;border:1px solid transparent;border-radius:7px;cursor:pointer;display:inline-flex;font-size:13px;justify-content:center;min-height:34px;padding:0 13px;transition:background .18s ease,border-color .18s ease,color .18s ease;white-space:nowrap}.jio-creator__ghost{background:transparent;border-color:var(--jc-line)}.jio-creator__ghost:focus-visible,.jio-creator__ghost:hover{border-color:var(--jc-accent);color:var(--jc-accent)}.jio-creator__primary{background:var(--jc-accent);color:#fff}.jio-creator__primary:focus-visible,.jio-creator__primary:hover{background:var(--jc-accent-strong)}.jio-creator__primary:disabled{cursor:not-allowed;opacity:.5}.jio-creator__notice{align-items:center;background:#f1f5f2;border-bottom:1px solid var(--jc-line);color:var(--jc-ink-soft);display:flex;font-size:13px;gap:12px;margin:0 auto;max-width:820px;padding:10px 16px}.jio-creator__notice>span{flex:1}.jio-creator__notice button{background:transparent;border:0;color:var(--jc-accent);cursor:pointer}.jio-creator__notice.is-error{background:#fdf2ee;color:var(--jc-warn)}.jio-creator__hint{color:var(--jc-ink-soft);font-size:13px;margin:18px auto 0;max-width:820px;padding:0 clamp(16px,4vw,40px)}.jio-creator__canvas{margin:0 auto;padding:clamp(20px,4vw,44px) clamp(20px,5vw,52px) 140px;width:min(720px,100%)}.jio-creator__title{display:block;margin-bottom:6px}.jio-creator__title textarea{background:transparent;border:0;color:var(--jc-ink);font-family:Songti SC,"Noto Serif SC","Source Han Serif SC",serif;font-size:clamp(23px,2.6vw,27px);font-weight:500;letter-spacing:.01em;line-height:1.4;min-height:50px;padding:0;resize:none;width:100%}.jio-creator__title textarea:focus{outline:0}.jio-creator__title textarea::-moz-placeholder{color:#b7c2bd}.jio-creator__title textarea::placeholder{color:#b7c2bd}.jio-creator__excerpt{display:block;margin-bottom:22px}.jio-creator__excerpt>span{color:#9aa8a2;display:block;font-size:12px;letter-spacing:.02em;margin-bottom:4px}.jio-creator__excerpt textarea{background:transparent;border:0;color:var(--jc-ink-soft);font-family:inherit;font-size:14px;line-height:1.7;padding:6px 0;resize:none;width:100%}.jio-creator__excerpt textarea:focus{outline:0}.jio-creator__editor{margin:12px 0 30px;min-height:50vh;position:relative}.jio-creator__editor .mce-top-part,.jio-creator__editor .quicktags-toolbar,.jio-creator__editor .wp-editor-tabs,.jio-creator__editor .wp-media-buttons{display:none!important}.jio-creator__editor .wp-editor-container,.jio-creator__editor .wp-editor-wrap{background:transparent;border:0;box-shadow:none}.jio-creator__editor .mce-top-part,.jio-creator__editor .tox .tox-editor-header,.jio-creator__editor .tox .tox-statusbar{display:none!important}.jio-creator__editor .mce-tinymce,.jio-creator__editor .tox-tinymce{background:transparent;border:0!important;box-shadow:none!important}.jio-creator__editor .mce-container-body,.jio-creator__editor .mce-edit-area,.jio-creator__editor .tox .tox-edit-area{background:transparent;border:0!important}.jio-creator__editor .mce-edit-area iframe,.jio-creator__editor .tox .tox-edit-area__iframe{min-height:55vh}.jio-creator__editor textarea{background:transparent;border:0;color:var(--jc-ink);font:inherit;font-size:16px;line-height:1.85;min-height:55vh;padding:0;resize:vertical;width:100%}.jio-creator__footer{border-top:1px solid var(--jc-line);color:var(--jc-ink-soft);display:flex;font-size:12px;justify-content:space-between;padding-top:20px}.jio-creator__cover{margin-bottom:18px;position:relative}.jio-creator__cover.is-empty{align-items:center;background:transparent;border:1px dashed #d3ded8;border-radius:8px;color:#8c9a94;cursor:pointer;display:inline-flex;font-size:12px;gap:7px;min-height:32px;padding:0 12px;transition:border-color .16s ease,color .16s ease}.jio-creator__cover.is-empty:focus-visible,.jio-creator__cover.is-empty:hover{border-color:var(--jc-accent);color:var(--jc-accent-strong);outline:0}.jio-creator__cover-thumb{background:#eef3f0;border:0;border-radius:10px;cursor:pointer;display:block;overflow:hidden;padding:0;position:relative;width:100%}.jio-creator__cover-thumb img{aspect-ratio:2.35/1;display:block;-o-object-fit:cover;object-fit:cover;width:100%}.jio-creator__cover-thumb:focus-visible{outline:2px solid var(--jc-accent);outline-offset:2px}.jio-creator__cover-edit{align-items:center;background:linear-gradient(0deg,rgba(15,25,22,.62),rgba(15,25,22,0));color:#fff;display:flex;font-size:12px;gap:6px;inset:auto 0 0 0;justify-content:center;opacity:0;padding:8px;position:absolute;transition:opacity .16s ease}.jio-creator__cover-thumb:focus-visible .jio-creator__cover-edit,.jio-creator__cover-thumb:hover .jio-creator__cover-edit{opacity:1}.jio-creator__cover-clear{background:rgba(15,25,22,.55);border:0;border-radius:50%;color:#fff;cursor:pointer;height:28px;position:absolute;right:8px;top:8px;width:28px}.jio-creator__cover-clear:focus-visible,.jio-creator__cover-clear:hover{background:rgba(15,25,22,.78);outline:0}.jio-creator__author{align-items:center;color:#8c9a94;display:flex;font-size:12px;gap:8px;margin:2px 0 20px}.jio-creator__author-avatar{border-radius:50%;flex:0 0 auto;height:24px;-o-object-fit:cover;object-fit:cover;width:24px}.jio-creator__author-avatar.is-placeholder{align-items:center;background:#e3ece7;color:#4a5f57;display:inline-flex;font-size:11px;font-weight:600;justify-content:center}.jio-creator__author-name{color:#4a5f57;font-weight:500}.jio-creator__author-meta{background:#eef5f2;border-radius:4px;color:#3c7d6c;font-size:11px;padding:1px 6px}.jio-creator__author-hint{color:#b0bcb7;margin-left:auto}.jio-creator-drawer{display:flex;inset:0;justify-content:flex-end;position:fixed;z-index:500}.jio-creator-drawer__backdrop{background:rgba(23,34,31,.32);border:0;cursor:default;inset:0;position:absolute}.jio-creator-drawer__panel{background:#fff;box-shadow:-20px 0 60px rgba(20,32,28,.16);display:flex;flex-direction:column;height:100%;position:relative;width:min(460px,100%)}.jio-creator-drawer__head{align-items:center;border-bottom:1px solid #e2e9e5;display:flex;justify-content:space-between;padding:20px 24px}.jio-creator-drawer__head h2{font-size:17px;font-weight:600;margin:0}.jio-creator-drawer__close{background:transparent;border:0;color:#5c6b66;cursor:pointer}.jio-creator-drawer__body{flex:1;overflow-y:auto;padding:20px 24px 32px}.jio-creator-drawer__note{background:#f2f7f4;border-left:3px solid #267665;color:#5c6b66;font-size:13px;line-height:1.6;margin:0 0 20px;padding:12px 14px}.jio-creator-drawer__foot{background:#fff;border-top:1px solid #e2e9e5;display:flex;flex-direction:column;gap:12px;padding:16px 24px calc(16px + env(safe-area-inset-bottom))}.jio-creator-drawer__foot .jio-creator-primary{flex:1}.jio-creator-drawer__actions{align-items:center;display:flex;gap:12px}.jio-creator-drawer__captcha{min-height:40px}.jio-creator-field{margin-bottom:26px}.jio-creator-field>h3{color:#243330;font-size:13px;font-weight:600;margin:0 0 10px}.jio-creator-muted{color:#5c6b66;font-size:12px;line-height:1.6;margin:0}.jio-creator-error{color:#b4573f;font-size:12px;margin:8px 0 0}.jio-creator-chips{display:flex;flex-wrap:wrap;gap:8px}.jio-creator-chip{align-items:center;border:1px solid #e2e9e5;border-radius:999px;color:#5c6b66;cursor:pointer;display:inline-flex;font-size:13px;gap:6px;padding:5px 12px}.jio-creator-chip input{clip:rect(0,0,0,0);height:1px;overflow:hidden;position:absolute;width:1px}.jio-creator-chip.is-active{background:#eef5f2;border-color:#267665;color:#1d5f52}.jio-creator-chip button{background:transparent;border:0;color:inherit;cursor:pointer}.jio-creator-inline{display:flex;gap:8px;margin-top:10px}.jio-creator-inline input:not([type]),.jio-creator-inline input[type=text]{border:1px solid #e2e9e5;border-radius:8px;flex:1;height:36px;min-width:0;padding:0 12px}.jio-creator-inline label{align-items:center;display:inline-flex;font-size:13px;gap:6px}.jio-creator-switch{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.jio-creator-switch h3{font-size:13px;margin:0 0 4px}.jio-creator-toggle{flex:0 0 auto;position:relative}.jio-creator-toggle input{height:1px;opacity:0;position:absolute;width:1px}.jio-creator-toggle span{background:#d6dfda;border-radius:999px;display:block;height:24px;transition:background .18s ease;width:42px}.jio-creator-toggle span:after{background:#fff;border-radius:50%;content:"";display:block;height:18px;margin:3px;transition:transform .18s ease;width:18px}.jio-creator-toggle input:checked+span{background:#267665}.jio-creator-toggle input:checked+span:after{transform:translateX(18px)}.jio-creator-toggle input:focus-visible+span{outline:2px solid #267665;outline-offset:2px}.jio-creator-pay{background:#fcfdfc;border:1px solid #e2e9e5;border-radius:10px;margin-top:16px;padding:16px}.jio-creator-input{align-items:center;display:flex;font-size:13px;gap:12px;justify-content:space-between;margin-top:12px}.jio-creator-input input{border:1px solid #e2e9e5;border-radius:8px;height:36px;padding:0 12px;text-align:right;width:140px}.jio-creator-cover{border-radius:10px;overflow:hidden;position:relative}.jio-creator-cover img{aspect-ratio:2/1;display:block;-o-object-fit:cover;object-fit:cover;width:100%}.jio-creator-cover button{background:rgba(0,0,0,.55);border:0;border-radius:50%;color:#fff;cursor:pointer;height:30px;position:absolute;right:8px;top:8px;width:30px}.jio-creator-cover-empty{align-items:center;background:#fafcfb;border:1px dashed #e2e9e5;border-radius:10px;color:#5c6b66;cursor:pointer;display:flex;flex-direction:column;font-size:13px;gap:8px;justify-content:center;min-height:120px}.jio-creator-cover-empty input{height:1px;opacity:0;position:absolute;width:1px}.jio-creator-attachments{border-top:1px solid #e2e9e5;margin-top:18px;padding-top:16px}.jio-creator-attachments__head{align-items:center;display:flex;gap:12px;justify-content:space-between}.jio-creator-attachments__head h4{font-size:13px;margin:0}.jio-creator-upload{align-items:center;border:1px solid #e2e9e5;border-radius:8px;color:#1d5f52;cursor:pointer;display:inline-flex;font-size:12px;min-height:32px;padding:0 12px}.jio-creator-upload input{height:1px;opacity:0;position:absolute;width:1px}.jio-creator-files{list-style:none;margin:12px 0 0;padding:0}.jio-creator-files li{align-items:center;border-bottom:1px solid #f0f4f1;display:flex;font-size:13px;gap:10px;padding:8px 0}.jio-creator-files button{background:transparent;border:0;color:#5c6b66;cursor:pointer;margin-left:auto}.jio-creator-files__name{align-items:center;display:inline-flex;gap:8px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jio-creator-files__name i{color:#267665}.jio-creator-reuse{font-size:13px;margin-top:14px}.jio-creator-reuse summary{color:#5c6b66;cursor:pointer}.jio-creator-reuse ul{list-style:none;margin:10px 0 0;padding:0}.jio-creator-reuse li{align-items:center;display:flex;gap:10px;padding:6px 0}.jio-creator-reuse button{background:#fff;border:1px solid #e2e9e5;border-radius:6px;cursor:pointer;margin-left:auto}.jio-creator-link{background:transparent;border:0;color:var(--jc-ink-soft,#5c6b66);cursor:pointer;font-size:13px;text-decoration:underline}@media(max-width:767px){.jio-creator{--jc-bar:56px}.jio-creator__bar{gap:7px;padding:0 8px}.jio-creator__bar-left{gap:5px;padding-right:7px}.jio-creator__bar-divider,.jio-creator__bar-mode{display:none}.jio-creator__bar-brand{font-size:15px}.jio-creator__bar-actions{gap:5px}.jio-creator__toolbar-tools{gap:4px}.jio-creator__toolbar-group{gap:0}.jio-creator__tool-btn{min-width:30px;padding:0 6px}.jio-creator__tool-labeled span{display:none}.jio-creator__format-select{padding:0 5px;width:82px}.jio-creator__bar-actions .jio-creator__save{display:none}.jio-creator__save-draft{font-size:0;min-width:34px;padding:0;width:34px}.jio-creator__save-draft i{font-size:13px}.jio-creator__preview{font-size:12px;min-height:32px;padding:0 8px}.jio-creator__primary{font-size:12px;min-height:32px;padding:0 10px}.jio-creator__ghost{padding:0 8px}.jio-creator__canvas{padding:20px 16px calc(120px + env(safe-area-inset-bottom))}.jio-creator__title textarea{font-size:24px}.jio-creator__editor .mce-edit-area iframe,.jio-creator__editor .tox .tox-edit-area__iframe{min-height:48vh}.jio-creator-drawer{display:block}.jio-creator-drawer__backdrop{display:none}.jio-creator-drawer__panel{border-radius:0;box-shadow:none;height:100dvh;width:100%}.jio-creator-drawer__foot{background:#fff;bottom:0;position:sticky}}@media(prefers-reduced-motion:reduce){.jio-creator *{animation:none!important;transition:none!important}}
+.jio-page-submit{background:#f6f6f6}body.jio-page-submit.has-static-nav,body.jio-page-submit.nav-fixed{padding-top:0!important}.jio-page-submit .float-btn,.jio-page-submit .footer,.jio-page-submit .footer-tabbar,.jio-page-submit .header,.jio-page-submit .jio-float-buttons{display:none!important}.jio-page-submit #main-content.container{max-width:none;padding:0}#jio-creator-studio.is-ready{display:block}.jio-creator{--jc-ink:#2b2b2b;--jc-ink-soft:#7d8683;--jc-paper:#f6f6f6;--jc-line:#e6e9e8;--jc-accent:#267665;--jc-accent-strong:#1d5f52;--jc-warn:#b4573f;--jc-bar:60px;-webkit-font-smoothing:antialiased;background:var(--jc-paper);color:var(--jc-ink);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans SC,PingFang SC,Microsoft YaHei,sans-serif;min-height:100vh;min-height:100dvh;padding-top:var(--jc-bar)}.jio-creator *,.jio-creator :after,.jio-creator :before{box-sizing:border-box}.jio-creator button{color:inherit;font:inherit}.jio-creator__bar{align-items:center;background:rgba(250,251,250,.98);border-bottom:1px solid var(--jc-line);box-shadow:0 2px 8px rgba(27,46,39,.035);display:flex;gap:clamp(10px,1.7vw,24px);height:var(--jc-bar);left:0;padding:0 clamp(14px,2.4vw,30px);position:fixed;right:0;top:0;z-index:300}.jio-creator__bar-actions,.jio-creator__bar-left{align-items:center;display:flex;flex:0 0 auto;gap:9px;min-width:0}.jio-creator__bar-left{border-right:1px solid var(--jc-line);padding-right:clamp(10px,1.5vw,20px)}.jio-creator__bar-actions{gap:7px;margin-left:auto}.jio-creator__bar-brand{color:var(--jc-accent-strong);font-family:Songti SC,"Noto Serif SC","Source Han Serif SC",serif;font-size:17px;font-weight:700;letter-spacing:-.04em}.jio-creator__bar-divider{background:var(--jc-line);height:18px;width:1px}.jio-creator__bar-mode{color:var(--jc-ink-soft);font-size:13px;white-space:nowrap}.jio-creator__back{align-items:center;border-radius:7px;color:var(--jc-ink-soft);display:inline-flex;height:30px;justify-content:center;text-decoration:none;width:30px}.jio-creator__back:focus-visible,.jio-creator__back:hover{background:#edf3f0;color:var(--jc-accent);outline:0}.jio-creator__toolbar-tools{align-items:center;display:flex;flex:1 1 auto;gap:7px;min-width:0;overflow-x:auto;scrollbar-width:none}.jio-creator__toolbar-tools::-webkit-scrollbar{display:none}.jio-creator__toolbar-group{align-items:center;display:inline-flex;flex:0 0 auto;gap:2px}.jio-creator__toolbar-divider{background:var(--jc-line);flex:0 0 auto;height:22px;width:1px}.jio-creator__tool-btn{align-items:center;background:transparent;border:0;border-radius:7px;color:var(--jc-ink-soft);cursor:pointer;display:inline-flex;flex:0 0 auto;font-size:13px;gap:7px;height:34px;justify-content:center;min-width:32px;padding:0 8px}.jio-creator__tool-btn:focus-visible:not(:disabled),.jio-creator__tool-btn:hover:not(:disabled){background:#edf3f0;color:var(--jc-accent-strong);outline:0}.jio-creator__tool-btn:disabled{color:#c7d0cc;cursor:default}.jio-creator__tool-labeled span{white-space:nowrap}.jio-creator__format-select{background:transparent;border:1px solid transparent;border-radius:7px;color:var(--jc-ink-soft);flex:0 0 auto;font:inherit;font-size:13px;height:34px;padding:0 8px;width:94px}.jio-creator__format-select:focus-visible,.jio-creator__format-select:hover{background:#fff;border-color:var(--jc-line);outline:0}.jio-creator__format-select:disabled{color:#aebbb5}.jio-creator__save-draft{align-items:center;background:#fff;border:1px solid var(--jc-line);border-radius:7px;color:var(--jc-ink-soft);cursor:pointer;display:inline-flex;flex:0 0 auto;font-size:13px;gap:7px;justify-content:center;min-height:34px;padding:0 10px;white-space:nowrap}.jio-creator__save-draft:focus-visible:not(:disabled),.jio-creator__save-draft:hover:not(:disabled){background:#f7faf8;border-color:#b7cdc3;color:var(--jc-accent-strong);outline:0}.jio-creator__save-draft:disabled{cursor:default;opacity:.55}.jio-creator__save{align-items:center;color:var(--jc-ink-soft);display:inline-flex;flex:0 0 auto;font-size:12px;gap:6px;white-space:nowrap}.jio-creator__save>i{color:var(--jc-line);font-size:7px}.jio-creator__save time{font-variant-numeric:tabular-nums;opacity:.7}.jio-creator__save.is-saved>i{color:var(--jc-accent)}.jio-creator__save.is-conflict,.jio-creator__save.is-conflict>i,.jio-creator__save.is-error,.jio-creator__save.is-error>i{color:var(--jc-warn)}.jio-creator__btn,.jio-creator__ghost,.jio-creator__primary{align-items:center;border:1px solid transparent;border-radius:7px;cursor:pointer;display:inline-flex;font-size:13px;justify-content:center;min-height:34px;padding:0 13px;transition:background .18s ease,border-color .18s ease,color .18s ease;white-space:nowrap}.jio-creator__ghost{background:transparent;border-color:var(--jc-line)}.jio-creator__ghost:focus-visible,.jio-creator__ghost:hover{border-color:var(--jc-accent);color:var(--jc-accent)}.jio-creator__primary{background:var(--jc-accent);color:#fff}.jio-creator__primary:focus-visible,.jio-creator__primary:hover{background:var(--jc-accent-strong)}.jio-creator__primary:disabled{cursor:not-allowed;opacity:.5}.jio-creator__notice{align-items:center;background:#f1f5f2;border-bottom:1px solid var(--jc-line);color:var(--jc-ink-soft);display:flex;font-size:13px;gap:12px;margin:0 auto;max-width:820px;padding:10px 16px}.jio-creator__notice>span{flex:1}.jio-creator__notice button{background:transparent;border:0;color:var(--jc-accent);cursor:pointer}.jio-creator__notice.is-error{background:#fdf2ee;color:var(--jc-warn)}.jio-creator__hint{color:var(--jc-ink-soft);font-size:13px;margin:18px auto 0;max-width:820px;padding:0 clamp(16px,4vw,40px)}.jio-creator__canvas{background:#fff;border-radius:4px;box-shadow:0 1px 2px rgba(24,39,34,.04),0 8px 28px rgba(24,39,34,.05);margin:40px auto 0;padding:clamp(30px,4vw,50px) clamp(28px,5vw,56px) clamp(36px,5vw,56px);width:min(900px,100% - clamp(24px,6vw,72px))}.jio-creator__title{display:block;margin-bottom:0}.jio-creator__title textarea{background:transparent;border:0;border-bottom:1px solid #eef0ef;color:#2b2b2b;font-family:inherit;font-size:clamp(26px,3vw,32px);font-weight:700;letter-spacing:.01em;line-height:1.35;min-height:46px;padding:0 0 16px;resize:none;width:100%}.jio-creator__title textarea:focus{border-bottom-color:#dfe3e1;outline:0}.jio-creator__title textarea::-moz-placeholder{color:#c3c7c5;font-weight:700}.jio-creator__title textarea::placeholder{color:#c3c7c5;font-weight:700}.jio-creator__editor{margin:22px 0 0;min-height:52vh;position:relative}.jio-creator__editor .mce-top-part,.jio-creator__editor .quicktags-toolbar,.jio-creator__editor .tox .tox-editor-header,.jio-creator__editor .tox .tox-statusbar,.jio-creator__editor .wp-editor-tabs,.jio-creator__editor .wp-media-buttons{display:none!important}.jio-creator__editor .wp-editor-container,.jio-creator__editor .wp-editor-wrap{background:transparent;border:0;box-shadow:none}.jio-creator__editor .mce-tinymce,.jio-creator__editor .tox-tinymce{background:transparent;border:0!important;box-shadow:none!important}.jio-creator__editor .mce-container-body,.jio-creator__editor .mce-edit-area,.jio-creator__editor .tox .tox-edit-area{background:transparent;border:0!important}.jio-creator__editor .mce-edit-area iframe,.jio-creator__editor .tox .tox-edit-area__iframe{min-height:52vh}.jio-creator__editor textarea{background:transparent;border:0;color:#2b2b2b;font:inherit;font-size:16px;line-height:1.8;min-height:52vh;padding:0;resize:vertical;width:100%}.jio-creator__editor textarea::-moz-placeholder{color:#b9bfbc}.jio-creator__editor textarea::placeholder{color:#b9bfbc}.jio-creator__settings{background:#fff;border-radius:4px;box-shadow:0 1px 2px rgba(24,39,34,.04),0 8px 28px rgba(24,39,34,.05);margin:20px auto 0;padding:clamp(20px,3vw,28px) clamp(24px,4vw,40px);width:min(900px,100% - clamp(24px,6vw,72px))}.jio-creator__settings-title{color:#2b2b2b;font-size:15px;font-weight:600;margin:0 0 4px}.jio-creator__setting-row{align-items:center;border-bottom:1px solid #f2f4f3;display:flex;gap:20px;justify-content:space-between;padding:16px 0}.jio-creator__setting-row:last-of-type{border-bottom:0}.jio-creator__setting-copy{min-width:0}.jio-creator__setting-label{color:#2b2b2b;display:block;font-size:14px;font-weight:500}.jio-creator__setting-help{color:#9aa2a0;font-size:12px;line-height:1.6;margin:4px 0 0}.jio-creator__cover-control{align-items:center;display:flex;flex:0 0 auto;gap:8px;position:relative}.jio-creator__cover-input{height:1px;opacity:0;overflow:hidden;pointer-events:none;position:absolute;width:1px}.jio-creator__cover-add{align-items:center;background:transparent;border:1px dashed #d8dedb;border-radius:6px;color:#7c8683;cursor:pointer;display:inline-flex;font-size:13px;gap:7px;min-height:34px;padding:0 14px}.jio-creator__cover-add:focus-visible:not(:disabled),.jio-creator__cover-add:hover:not(:disabled){border-color:var(--jc-accent);color:var(--jc-accent-strong);outline:0}.jio-creator__cover-add:disabled{cursor:default;opacity:.6}.jio-creator__cover-preview{background:#eef1f0;border:0;border-radius:6px;cursor:pointer;display:block;height:63px;overflow:hidden;padding:0;width:112px}.jio-creator__cover-preview img{display:block;height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.jio-creator__cover-preview:focus-visible{outline:2px solid var(--jc-accent);outline-offset:2px}.jio-creator__cover-clear{align-items:center;background:transparent;border:0;border-radius:50%;color:#98a19e;cursor:pointer;display:inline-flex;height:26px;justify-content:center;width:26px}.jio-creator__cover-clear:focus-visible,.jio-creator__cover-clear:hover{background:#f3f5f4;color:var(--jc-warn);outline:0}.jio-creator__schedule{align-items:center;display:flex;flex-wrap:wrap;gap:12px;padding:4px 0 18px}.jio-creator__schedule label{align-items:center;color:#6f7875;display:inline-flex;font-size:13px;gap:10px}.jio-creator__schedule input[type=datetime-local]{background:#fff;border:1px solid #e3e7e5;border-radius:6px;color:#2b2b2b;font:inherit;font-size:13px;height:36px;padding:0 10px}.jio-creator__schedule .jio-creator-muted{flex:1 1 100%}.jio-creator__footer{color:#98a19e;display:flex;font-size:12px;justify-content:space-between;margin:16px auto 0;padding:0 4px 140px;width:min(900px,100% - clamp(24px,6vw,72px))}.jio-creator__author{align-items:center;color:#8c9a94;display:flex;font-size:12px;gap:8px;margin:2px 0 20px}.jio-creator__author-avatar{border-radius:50%;flex:0 0 auto;height:24px;-o-object-fit:cover;object-fit:cover;width:24px}.jio-creator__author-avatar.is-placeholder{align-items:center;background:#e3ece7;color:#4a5f57;display:inline-flex;font-size:11px;font-weight:600;justify-content:center}.jio-creator__author-name{color:#4a5f57;font-weight:500}.jio-creator__author-meta{background:#eef5f2;border-radius:4px;color:#3c7d6c;font-size:11px;padding:1px 6px}.jio-creator__author-hint{color:#b0bcb7;margin-left:auto}.jio-creator-drawer{display:flex;inset:0;justify-content:flex-end;position:fixed;z-index:500}.jio-creator-drawer__backdrop{background:rgba(23,34,31,.32);border:0;cursor:default;inset:0;position:absolute}.jio-creator-drawer__panel{background:#fff;box-shadow:-20px 0 60px rgba(20,32,28,.16);display:flex;flex-direction:column;height:100%;position:relative;width:min(460px,100%)}.jio-creator-drawer__head{align-items:center;border-bottom:1px solid #e6e9e8;display:flex;justify-content:space-between;padding:20px 24px}.jio-creator-drawer__head h2{font-size:17px;font-weight:600;margin:0}.jio-creator-drawer__close{background:transparent;border:0;color:#7d8683;cursor:pointer}.jio-creator-drawer__body{flex:1;overflow-y:auto;padding:20px 24px 32px}.jio-creator-drawer__note{background:#f2f7f4;border-left:3px solid #267665;color:#7d8683;font-size:13px;line-height:1.6;margin:0 0 20px;padding:12px 14px}.jio-creator-drawer__foot{background:#fff;border-top:1px solid #e6e9e8;display:flex;flex-direction:column;gap:12px;padding:16px 24px calc(16px + env(safe-area-inset-bottom))}.jio-creator-drawer__foot .jio-creator-primary{flex:1}.jio-creator-drawer__actions{align-items:center;display:flex;gap:12px}.jio-creator-drawer__captcha{min-height:40px}.jio-creator-field{margin-bottom:26px}.jio-creator-field>h3{color:#2b2b2b;font-size:13px;font-weight:600;margin:0 0 10px}.jio-creator-muted{color:#7d8683;font-size:12px;line-height:1.6;margin:0}.jio-creator-error{color:#b4573f;font-size:12px;margin:8px 0 0}.jio-creator-chips{display:flex;flex-wrap:wrap;gap:8px}.jio-creator-chip{align-items:center;border:1px solid #e6e9e8;border-radius:999px;color:#7d8683;cursor:pointer;display:inline-flex;font-size:13px;gap:6px;padding:5px 12px}.jio-creator-chip input{clip:rect(0,0,0,0);height:1px;overflow:hidden;position:absolute;width:1px}.jio-creator-chip.is-active{background:#eef5f2;border-color:#267665;color:#1d5f52}.jio-creator-chip button{background:transparent;border:0;color:inherit;cursor:pointer}.jio-creator-inline{display:flex;gap:8px;margin-top:10px}.jio-creator-inline input:not([type]),.jio-creator-inline input[type=text]{border:1px solid #e6e9e8;border-radius:8px;flex:1;height:36px;min-width:0;padding:0 12px}.jio-creator-inline label{align-items:center;display:inline-flex;font-size:13px;gap:6px}.jio-creator-switch{align-items:flex-start;display:flex;gap:16px;justify-content:space-between}.jio-creator-switch h3{font-size:13px;margin:0 0 4px}.jio-creator-toggle{flex:0 0 auto;position:relative}.jio-creator-toggle input{height:1px;opacity:0;position:absolute;width:1px}.jio-creator-toggle span{background:#d6dfda;border-radius:999px;display:block;height:24px;transition:background .18s ease;width:42px}.jio-creator-toggle span:after{background:#fff;border-radius:50%;content:"";display:block;height:18px;margin:3px;transition:transform .18s ease;width:18px}.jio-creator-toggle input:checked+span{background:#267665}.jio-creator-toggle input:checked+span:after{transform:translateX(18px)}.jio-creator-toggle input:focus-visible+span{outline:2px solid #267665;outline-offset:2px}.jio-creator-pay{background:#fcfdfc;border:1px solid #e6e9e8;border-radius:10px;margin-top:16px;padding:16px}.jio-creator-input{align-items:center;display:flex;font-size:13px;gap:12px;justify-content:space-between;margin-top:12px}.jio-creator-input input{border:1px solid #e6e9e8;border-radius:8px;height:36px;padding:0 12px;text-align:right;width:140px}.jio-creator-cover{border-radius:10px;overflow:hidden;position:relative}.jio-creator-cover img{aspect-ratio:2/1;display:block;-o-object-fit:cover;object-fit:cover;width:100%}.jio-creator-cover button{background:rgba(0,0,0,.55);border:0;border-radius:50%;color:#fff;cursor:pointer;height:30px;position:absolute;right:8px;top:8px;width:30px}.jio-creator-cover-empty{align-items:center;background:#fafcfb;border:1px dashed #e6e9e8;border-radius:10px;color:#7d8683;cursor:pointer;display:flex;flex-direction:column;font-size:13px;gap:8px;justify-content:center;min-height:120px}.jio-creator-cover-empty input{height:1px;opacity:0;position:absolute;width:1px}.jio-creator-attachments{border-top:1px solid #e6e9e8;margin-top:18px;padding-top:16px}.jio-creator-attachments__head{align-items:center;display:flex;gap:12px;justify-content:space-between}.jio-creator-attachments__head h4{font-size:13px;margin:0}.jio-creator-upload{align-items:center;border:1px solid #e6e9e8;border-radius:8px;color:#1d5f52;cursor:pointer;display:inline-flex;font-size:12px;min-height:32px;padding:0 12px}.jio-creator-upload input{height:1px;opacity:0;position:absolute;width:1px}.jio-creator-files{list-style:none;margin:12px 0 0;padding:0}.jio-creator-files li{align-items:center;border-bottom:1px solid #f0f4f1;display:flex;font-size:13px;gap:10px;padding:8px 0}.jio-creator-files button{background:transparent;border:0;color:#7d8683;cursor:pointer;margin-left:auto}.jio-creator-files__name{align-items:center;display:inline-flex;gap:8px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jio-creator-files__name i{color:#267665}.jio-creator-reuse{font-size:13px;margin-top:14px}.jio-creator-reuse summary{color:#7d8683;cursor:pointer}.jio-creator-reuse ul{list-style:none;margin:10px 0 0;padding:0}.jio-creator-reuse li{align-items:center;display:flex;gap:10px;padding:6px 0}.jio-creator-reuse button{background:#fff;border:1px solid #e6e9e8;border-radius:6px;cursor:pointer;margin-left:auto}.jio-creator-link{background:transparent;border:0;color:var(--jc-ink-soft,#7d8683);cursor:pointer;font-size:13px;text-decoration:underline}@media(max-width:767px){.jio-creator{--jc-bar:56px}.jio-creator__bar{gap:7px;padding:0 8px}.jio-creator__bar-left{gap:5px;padding-right:7px}.jio-creator__bar-divider,.jio-creator__bar-mode{display:none}.jio-creator__bar-brand{font-size:15px}.jio-creator__bar-actions{gap:5px}.jio-creator__toolbar-tools{gap:4px}.jio-creator__toolbar-group{gap:0}.jio-creator__tool-btn{min-width:30px;padding:0 6px}.jio-creator__tool-labeled span{display:none}.jio-creator__format-select{padding:0 5px;width:82px}.jio-creator__bar-actions .jio-creator__save{display:none}.jio-creator__save-draft{font-size:0;min-width:34px;padding:0;width:34px}.jio-creator__save-draft i{font-size:13px}.jio-creator__preview{font-size:12px;min-height:32px;padding:0 8px}.jio-creator__primary{font-size:12px;min-height:32px;padding:0 10px}.jio-creator__ghost{padding:0 8px}.jio-creator__canvas{margin:14px auto 0;padding:22px 18px 28px;width:calc(100% - 20px)}.jio-creator__settings{margin-top:12px;padding:18px;width:calc(100% - 20px)}.jio-creator__setting-row{gap:12px}.jio-creator__title textarea{font-size:24px}.jio-creator__footer{padding-bottom:calc(120px + env(safe-area-inset-bottom));width:calc(100% - 20px)}.jio-creator__editor .mce-edit-area iframe,.jio-creator__editor .tox .tox-edit-area__iframe{min-height:48vh}.jio-creator-drawer{display:block}.jio-creator-drawer__backdrop{display:none}.jio-creator-drawer__panel{border-radius:0;box-shadow:none;height:100dvh;width:100%}.jio-creator-drawer__foot{background:#fff;bottom:0;position:sticky}}@media(prefers-reduced-motion:reduce){.jio-creator *{animation:none!important;transition:none!important}}
diff --git a/assets/creator-studio/build/index.js b/assets/creator-studio/build/index.js
index 17b062c7..532650e2 100644
--- a/assets/creator-studio/build/index.js
+++ b/assets/creator-studio/build/index.js
@@ -1 +1,3 @@
-(()=>{"use strict";const e=window.React,t=window.wp.element,a=window.wp.i18n;function r(e,t){const a=e&&(e.message||e.error)||(401===t?"登录状态已失效,请刷新页面重新登录。":"请求失败,请稍后重试。"),r=new Error(String(a));return r.status=t,r.code=e&&e.code?String(e.code):"",r.data=e,r}async function n(e){try{return await e.json()}catch(e){return null}}async function o(e,t,a){const o=await fetch(e,{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","X-WP-Nonce":a},body:JSON.stringify(t)}),i=await n(o);if(!o.ok)throw r(i,o.status);return i}async function i(e,t,a,o={}){const i=new FormData;i.append("file",t),Object.entries(o).forEach(([e,t])=>i.append(e,t));const l=await fetch(e,{method:"POST",credentials:"same-origin",headers:{"X-WP-Nonce":a},body:i}),c=await n(l);if(!l.ok)throw r(c,l.status);return c}const l=window.jioCreatorStudio||{},c=l.nonce||"";function s(r){const{draft:n,setDraft:o,capabilities:s,limits:u,taxonomy:m,isPublishedEdit:d,onClose:p,onSaveDraft:_,onSubmit:f,privateStorage:b,privateUploads:y,saving:j,captcha:E}=r,[g,h]=(0,t.useState)(""),[v,N]=(0,t.useState)(""),[w,k]=(0,t.useState)(!1),C=(0,t.useRef)(null),S=(0,t.useRef)(null),x=(0,t.useRef)(null);(0,t.useEffect)(()=>{const e=x.current,t=document.getElementById("jio-creator-captcha");if(!e||!t)return;const a=t.parentElement;return e.appendChild(t),t.removeAttribute("hidden"),()=>{a&&(a.appendChild(t),t.setAttribute("hidden",""))}},[]);const I=(0,t.useMemo)(()=>(n.title||"").trim().length,[n.title])>=Number(u.titleMin||1),M=()=>{const e=g.trim();if(!e)return;const t=e.split(/[,,\n]+/u).map(e=>e.trim()).filter(Boolean);o({tags:Array.from(new Set([...n.tags,...t]))}),h("")};return(0,e.createElement)("div",{className:"jio-creator-drawer",role:"dialog","aria-modal":"true","aria-labelledby":"jio-creator-publish-title"},(0,e.createElement)("button",{type:"button",className:"jio-creator-drawer__backdrop","aria-label":(0,a.__)("关闭","jio"),onClick:p}),(0,e.createElement)("div",{className:"jio-creator-drawer__panel"},(0,e.createElement)("header",{className:"jio-creator-drawer__head"},(0,e.createElement)("h2",{id:"jio-creator-publish-title"},d?(0,a.__)("提交改稿","jio"):(0,a.__)("发布文章","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-drawer__close",onClick:p,"aria-label":(0,a.__)("关闭","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))),(0,e.createElement)("div",{className:"jio-creator-drawer__body"},d&&(0,e.createElement)("p",{className:"jio-creator-drawer__note"},(0,a.__)("审核通过前,读者看到的仍然是当前线上版本。","jio")),(0,e.createElement)("section",{className:"jio-creator-field"},(0,e.createElement)("h3",null,(0,a.__)("封面","jio")),n.featured?.data?.url?(0,e.createElement)("div",{className:"jio-creator-cover"},(0,e.createElement)("img",{src:String(n.featured.data.url),alt:""}),(0,e.createElement)("button",{type:"button",onClick:()=>o({featured:{type:"",data:{}}}),"aria-label":(0,a.__)("移除封面","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))):s.canUploadImage?(0,e.createElement)("label",{className:"jio-creator-cover-empty"},(0,e.createElement)("input",{ref:C,type:"file",accept:"image/*",onChange:()=>{(async()=>{const e=C.current?.files?.[0];if(e&&l.media?.uploadUrl?.image){N(""),k(!0);try{const t=await i(l.media.uploadUrl.image,e,c),r=Number(t.attachment_id||t.id||0),n=String(t.url||"");if(!r||!n)throw new Error((0,a.__)("上传后无法读取图片。","jio"));o({featured:{type:"image",mediaId:r,data:{id:r,url:n}}})}catch(e){N(String(e?.message||(0,a.__)("上传失败","jio")))}finally{k(!1)}}})()},disabled:w}),(0,e.createElement)("i",{className:"fa fas fa-plus","aria-hidden":"true"}),(0,e.createElement)("span",null,w?(0,a.__)("上传中…","jio"):(0,a.__)("上传封面","jio"))):(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("当前账号不能设置封面。","jio"))),(0,e.createElement)("section",{className:"jio-creator-field"},(0,e.createElement)("h3",null,(0,a.__)("分类","jio")),(0,e.createElement)("div",{className:"jio-creator-chips"},0===m.categories.length&&(0,e.createElement)("span",{className:"jio-creator-muted"},(0,a.__)("暂无可选分类","jio")),m.categories.map(t=>(0,e.createElement)("label",{key:t.id,className:"jio-creator-chip"+(n.categories.includes(t.id)?" is-active":"")},(0,e.createElement)("input",{type:"checkbox",checked:n.categories.includes(t.id),onChange:()=>(e=>{const t=n.categories.includes(e);o({categories:t?n.categories.filter(t=>t!==e):[...n.categories,e]})})(t.id)}),(0,e.createElement)("span",null,t.name))))),m.tags&&(0,e.createElement)("section",{className:"jio-creator-field"},(0,e.createElement)("h3",null,(0,a.__)("标签","jio")),(0,e.createElement)("div",{className:"jio-creator-chips"},n.tags.map(t=>(0,e.createElement)("span",{key:t,className:"jio-creator-chip is-active"},(0,e.createElement)("span",null,t),(0,e.createElement)("button",{type:"button",onClick:()=>o({tags:n.tags.filter(e=>e!==t)}),"aria-label":(0,a.sprintf)((0,a.__)("移除标签 %s","jio"),t)},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))))),(0,e.createElement)("div",{className:"jio-creator-inline"},(0,e.createElement)("input",{type:"text",value:g,placeholder:(0,a.__)("输入标签,逗号分隔","jio"),onChange:e=>h(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),M())}}),(0,e.createElement)("button",{type:"button",onClick:M},(0,a.__)("添加","jio")))),m.customDefs.map(t=>(0,e.createElement)("section",{className:"jio-creator-field",key:t.key},(0,e.createElement)("h3",null,t.name),(0,e.createElement)("div",{className:"jio-creator-chips"},t.values.map(a=>{const r=n.custom[t.key]||[],i=r.includes(a.key);return(0,e.createElement)("label",{key:a.key,className:"jio-creator-chip"+(i?" is-active":"")},(0,e.createElement)("input",{type:"checkbox",checked:i,onChange:()=>o({custom:{...n.custom,[t.key]:i?r.filter(e=>e!==a.key):[...r,a.key]}})}),(0,e.createElement)("span",null,a.name))})))),s.canPay&&(0,e.createElement)("section",{className:"jio-creator-field"},(0,e.createElement)("div",{className:"jio-creator-switch"},(0,e.createElement)("div",null,(0,e.createElement)("h3",null,(0,a.__)("付费内容","jio")),(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("开启后,未购买读者只能看到免费部分。","jio"))),(0,e.createElement)("label",{className:"jio-creator-toggle"},(0,e.createElement)("input",{type:"checkbox",checked:n.pay.enabled,onChange:e=>o({pay:{...n.pay,enabled:e.target.checked}})}),(0,e.createElement)("span",{"aria-hidden":"true"}))),n.pay.enabled&&(0,e.createElement)("div",{className:"jio-creator-pay"},(0,e.createElement)("div",{className:"jio-creator-inline"},(0,e.createElement)("label",null,(0,e.createElement)("input",{type:"radio",checked:"cash"===n.pay.modo,onChange:()=>o({pay:{...n.pay,modo:"cash"}})}),(0,e.createElement)("span",null,(0,a.__)("现金","jio"))),(0,e.createElement)("label",null,(0,e.createElement)("input",{type:"radio",checked:"points"===n.pay.modo,onChange:()=>o({pay:{...n.pay,modo:"points"}})}),(0,e.createElement)("span",null,(0,a.__)("积分","jio")))),"cash"===n.pay.modo?(0,e.createElement)("label",{className:"jio-creator-input"},(0,e.createElement)("span",null,(0,a.__)("价格","jio")),(0,e.createElement)("input",{type:"number",min:Number(u.priceMin||0),step:"0.01",value:n.pay.price,onChange:e=>o({pay:{...n.pay,price:e.target.value}})})):(0,e.createElement)("label",{className:"jio-creator-input"},(0,e.createElement)("span",null,(0,a.__)("积分价格","jio")),(0,e.createElement)("input",{type:"number",min:0,step:"1",value:n.pay.points,onChange:e=>o({pay:{...n.pay,points:Number(e.target.value)||0}})})),s.canPayDownload&&(0,e.createElement)("div",{className:"jio-creator-attachments"},(0,e.createElement)("div",{className:"jio-creator-attachments__head"},(0,e.createElement)("h4",null,(0,a.__)("资料附件","jio")),b?(0,e.createElement)("label",{className:"jio-creator-upload"},(0,e.createElement)("input",{ref:S,type:"file",onChange:()=>{(async()=>{const e=S.current?.files?.[0];if(e){N(""),k(!0);try{const t=await i(l.creator.privateUrl,e,c,{post_id:String(n.postId||0)}),a={type:"protected",assetKey:String(t.asset_key||""),fileName:String(t.name||e.name),sizeBytes:Number(t.size||e.size),sizeLabel:String(t.size_label||""),label:""};o({pay:{...n.pay,enabled:!0,downloads:[...n.pay.downloads,a]}}),S.current&&(S.current.value="")}catch(e){N(String(e?.message||(0,a.__)("资料上传失败","jio")))}finally{k(!1)}}})()},disabled:w}),(0,e.createElement)("span",null,w?(0,a.__)("上传中…","jio"):(0,a.__)("添加 PDF / ZIP","jio"))):(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("私有附件存储尚未配置,暂时不能上传付费资料。","jio"))),v&&(0,e.createElement)("p",{className:"jio-creator-error"},v),n.pay.downloads.length>0&&(0,e.createElement)("ul",{className:"jio-creator-files"},n.pay.downloads.map((t,r)=>(0,e.createElement)("li",{key:`${t.assetKey||t.url}-${r}`},(0,e.createElement)("span",{className:"jio-creator-files__name"},t.assetKey?(0,e.createElement)(e.Fragment,null,(0,e.createElement)("i",{className:"fa fas fa-lock","aria-hidden":"true"}),t.fileName||t.label||(0,a.__)("受保护资料","jio")):(0,e.createElement)(e.Fragment,null,(0,e.createElement)("i",{className:"fa fas fa-link","aria-hidden":"true"}),t.label||t.url)),t.sizeLabel&&(0,e.createElement)("span",{className:"jio-creator-muted"},t.sizeLabel),(0,e.createElement)("button",{type:"button",onClick:()=>(e=>{o({pay:{...n.pay,downloads:n.pay.downloads.filter((t,a)=>a!==e)}})})(r),"aria-label":(0,a.__)("移除","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))))),y.length>0&&(0,e.createElement)("details",{className:"jio-creator-reuse"},(0,e.createElement)("summary",null,(0,a.__)("从已上传资料中选择","jio")),(0,e.createElement)("ul",null,y.filter(e=>!n.pay.downloads.some(t=>t.assetKey===e.assetKey)).map(t=>(0,e.createElement)("li",{key:t.assetKey},(0,e.createElement)("span",null,t.fileName),(0,e.createElement)("span",{className:"jio-creator-muted"},t.sizeLabel),(0,e.createElement)("button",{type:"button",onClick:()=>o({pay:{...n.pay,enabled:!0,downloads:[...n.pay.downloads,{...t,type:"protected"}]}})},(0,a.__)("使用","jio"))))))))),!s.canPay&&s.canSaveDraft&&(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("当前账号不能设置付费内容。","jio"))),(0,e.createElement)("footer",{className:"jio-creator-drawer__foot"},E&&(0,e.createElement)("div",{className:"jio-creator-drawer__captcha",ref:x}),(0,e.createElement)("div",{className:"jio-creator-drawer__actions"},(0,e.createElement)("button",{type:"button",className:"jio-creator-ghost",onClick:_,disabled:j},(0,a.__)("保存草稿","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-primary",onClick:()=>f(!1),disabled:j||!I},d?(0,a.__)("提交审核","jio"):s.canPublishNow?(0,a.__)("发布","jio"):(0,a.__)("提交审核","jio")),s.canPublishNow&&(0,e.createElement)("button",{type:"button",className:"jio-creator-link",onClick:()=>f(!0),disabled:j||!I},(0,a.__)("立即发布","jio"))))))}function u({featured:t,canEdit:r,onOpen:n,onClear:o}){const i="string"==typeof t?.data?.url?t.data.url:"";return r?i?(0,e.createElement)("div",{className:"jio-creator__cover"},(0,e.createElement)("button",{type:"button",className:"jio-creator__cover-thumb",onClick:n},(0,e.createElement)("img",{src:i,alt:""}),(0,e.createElement)("span",{className:"jio-creator__cover-edit"},(0,e.createElement)("i",{className:"fa fas fa-pen","aria-hidden":"true"}),(0,a.__)("更换封面","jio"))),(0,e.createElement)("button",{type:"button",className:"jio-creator__cover-clear",onClick:o,"aria-label":(0,a.__)("移除封面","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))):(0,e.createElement)("button",{type:"button",className:"jio-creator__cover is-empty",onClick:n},(0,e.createElement)("i",{className:"fa far fa-image","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("添加封面","jio"))):null}function m({author:t}){const r="string"==typeof t?.name?t.name.trim():"";if(""===r)return null;const n="string"==typeof t?.avatar?t.avatar:"",o="string"==typeof t?.meta?t.meta:"";return(0,e.createElement)("div",{className:"jio-creator__author"},""!==n?(0,e.createElement)("img",{className:"jio-creator__author-avatar",src:n,alt:"",width:24,height:24}):(0,e.createElement)("span",{className:"jio-creator__author-avatar is-placeholder","aria-hidden":"true"},r.slice(0,1)),(0,e.createElement)("span",{className:"jio-creator__author-name"},r),""!==o&&(0,e.createElement)("span",{className:"jio-creator__author-meta"},o),(0,e.createElement)("span",{className:"jio-creator__author-hint"},(0,a.__)("原创内容","jio")))}function d({ready:t,canUndo:r,canRedo:n,formatValue:o,onFormatChange:i,capabilities:l,onCommand:c,onRememberSelection:s,onOpenLink:u,onOpenMedia:m}){return(0,e.createElement)("div",{className:"jio-creator__toolbar-tools",role:"toolbar","aria-label":(0,a.__)("正文编辑工具","jio"),onMouseDown:e=>{s(),e.target.closest("button")&&e.preventDefault()}},(0,e.createElement)("div",{className:"jio-creator__toolbar-group",role:"group","aria-label":(0,a.__)("撤销和重做","jio")},(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!r,onClick:()=>c("undo"),title:(0,a.__)("撤销","jio"),"aria-label":(0,a.__)("撤销","jio")},(0,e.createElement)("i",{className:"fa fas fa-undo","aria-hidden":"true"})),(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!n,onClick:()=>c("redo"),title:(0,a.__)("重做","jio"),"aria-label":(0,a.__)("重做","jio")},(0,e.createElement)("i",{className:"fa fas fa-redo","aria-hidden":"true"}))),(0,e.createElement)("span",{className:"jio-creator__toolbar-divider","aria-hidden":"true"}),(0,e.createElement)("select",{className:"jio-creator__format-select","aria-label":(0,a.__)("段落样式","jio"),value:o,disabled:!t,onFocus:s,onChange:e=>{i(e.target.value),c("format",e.target.value)}},(0,e.createElement)("option",{value:"p"},(0,a.__)("正文","jio")),(0,e.createElement)("option",{value:"h1"},(0,a.__)("标题 1","jio")),(0,e.createElement)("option",{value:"h2"},(0,a.__)("标题 2","jio")),(0,e.createElement)("option",{value:"h3"},(0,a.__)("标题 3","jio")),(0,e.createElement)("option",{value:"blockquote"},(0,a.__)("引用","jio"))),(0,e.createElement)("span",{className:"jio-creator__toolbar-divider","aria-hidden":"true"}),(0,e.createElement)("div",{className:"jio-creator__toolbar-group",role:"group","aria-label":(0,a.__)("文字格式","jio")},(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!t,onClick:()=>c("Bold"),title:(0,a.__)("加粗","jio"),"aria-label":(0,a.__)("加粗","jio")},(0,e.createElement)("i",{className:"fa fas fa-bold","aria-hidden":"true"})),(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!t,onClick:()=>c("Italic"),title:(0,a.__)("斜体","jio"),"aria-label":(0,a.__)("斜体","jio")},(0,e.createElement)("i",{className:"fa fas fa-italic","aria-hidden":"true"})),(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!t,onClick:()=>c("Underline"),title:(0,a.__)("下划线","jio"),"aria-label":(0,a.__)("下划线","jio")},(0,e.createElement)("i",{className:"fa fas fa-underline","aria-hidden":"true"}))),(0,e.createElement)("span",{className:"jio-creator__toolbar-divider","aria-hidden":"true"}),(0,e.createElement)("div",{className:"jio-creator__toolbar-group",role:"group","aria-label":(0,a.__)("媒体和链接","jio")},l.canUploadImage&&(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn jio-creator__tool-labeled",disabled:!t,onClick:()=>m("image"),title:(0,a.__)("插入图片","jio")},(0,e.createElement)("i",{className:"fa far fa-image","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("图片","jio"))),(l.canUploadVideo||l.canEmbed)&&(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn jio-creator__tool-labeled",disabled:!t,onClick:()=>m("video"),title:(0,a.__)("插入视频","jio")},(0,e.createElement)("i",{className:"fa fas fa-video","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("视频","jio"))),(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn jio-creator__tool-labeled",disabled:!t,onClick:u,title:(0,a.__)("插入链接","jio")},(0,e.createElement)("i",{className:"fa fas fa-link","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("链接","jio")))))}const p={ready:(0,a.__)("尚未保存","jio"),saving:(0,a.__)("保存中…","jio"),saved:(0,a.__)("已保存","jio"),error:(0,a.__)("保存失败","jio"),conflict:(0,a.__)("内容已在别处更新","jio"),submitting:(0,a.__)("提交中…","jio"),submitted:(0,a.__)("已提交","jio")};function _({value:t}){return(0,e.createElement)("span",{className:`jio-creator__save is-${t.state}`,role:"status","aria-live":"polite"},(0,e.createElement)("i",{className:"fa fas fa-circle","aria-hidden":"true"}),(0,e.createElement)("span",null,p[t.state]||p.ready),"saved"===t.state&&t.at?(0,e.createElement)("time",null,t.at):null)}function f(e){const t=(e.downloads||[]).map(e=>{const t="string"==typeof e.assetKey?e.assetKey:"";if(t)return{type:"protected",asset_key:t,label:"string"==typeof e.label?e.label:""};const a="string"==typeof e.url?e.url.trim():"";return a?{type:"direct",url:a,label:"string"==typeof e.label?e.label:"",extract_code:"string"==typeof e.extractCode?e.extractCode:""}:null}).filter(Boolean);return{enabled:!!e.enabled,fields:{pay_type:e.enabled?t.length>0?"download":"reading":"no",pay_modo:"points"===e.modo?"points":"0",price:"points"===e.modo?"0.00":String(e.price||"0.00"),points_price:"points"===e.modo?Math.max(0,Number(e.points)||0):0,vip1_price:"points"===e.modo?"0.00":String(e.vip1Price||"0.00"),vip2_price:"points"===e.modo?"0.00":String(e.vip2Price||"0.00"),pay_limit:Number(e.payLimit)||0,downloads:t}}}const b=window.jioCreatorStudio||{},y=b.nonce||"",j=`jio-studio-${b.sourceId||0}`,E="jio-creator-content";function g(){const e=b.pay||{},t=b.categories&&b.categories.selected||[],a=b.tags&&b.tags.items||[];return{postId:Number(b.sourceId||0),versionId:Number(b.versionId||0),rev:Number(b.versionRev||0),title:String(b.title||""),excerpt:String(b.excerpt||""),content:String(b.content||""),categories:t.map(Number),tags:a.slice(),custom:b.custom||{},featured:b.featured||{type:"",data:{}},pay:{enabled:!!e.enabled,modo:"points"===e.payModo?"points":"cash",price:String(e.price||"0.00"),points:Number(e.points||0),vip1Price:String(e.vip1Price||"0.00"),vip2Price:String(e.vip2Price||"0.00"),payLimit:Number(e.payLimit||0),downloads:Array.isArray(e.downloads)?e.downloads:[]}}}function h(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(//g,">")}function v(e){const t=String(e||"").trim();if(!t)return"";try{const e=new URL(t,window.location.href);return"http:"===e.protocol||"https:"===e.protocol?e.href:""}catch(e){return""}}function N(e){const t=document.createElement("div");return t.innerHTML=e,(t.textContent||"").replace(/\s+/g,"")}function w(){const[r,n]=(0,t.useState)(g),i=(0,t.useRef)(r);i.current=r;const l=(0,t.useRef)(null),c=(0,t.useRef)(null),p=(0,t.useRef)(null),w=(0,t.useRef)(!1),k=(0,t.useRef)(()=>{}),[C,S]=(0,t.useState)(!1),[x,I]=(0,t.useState)({canUndo:!1,canRedo:!1}),[M,L]=(0,t.useState)("p"),[R,D]=(0,t.useState)(()=>({state:b.sourceId||b.versionId||b.content?"saved":"ready",at:""})),[P,U]=(0,t.useState)(!1),[O,$]=(0,t.useState)(null),[F,K]=(0,t.useState)(null),z=(0,t.useRef)(!1),T=(0,t.useRef)(0),A=b.capabilities||{},B={titleMin:Number(b.limits?.titleMin||1),titleMax:Number(b.limits?.titleMax||30),titlePlaceholder:String(b.limits?.titlePlaceholder||(0,a.__)("请输入标题","jio")),priceMin:Number(b.pay?.priceMin||0),priceMax:Number(b.pay?.priceMax||0),pointsMin:Number(b.pay?.pointsMin||0),pointsMax:Number(b.pay?.pointsMax||0)},J=!!b.isPublished,q=(0,t.useCallback)(e=>{z.current=!0,T.current+=1;const t={...i.current,...e};i.current=t,n(t)},[]),V=(0,t.useCallback)(e=>{if(e===i.current.content)return;z.current=!0,T.current+=1;const t={...i.current,content:e};i.current=t,n(t)},[]),H=(0,t.useCallback)(e=>{const t=e?.undoManager;t&&I({canUndo:"function"==typeof t.hasUndo&&t.hasUndo(),canRedo:"function"==typeof t.hasRedo&&t.hasRedo()})},[]),W=(0,t.useCallback)(e=>{const t=e?.selection?.getNode(),a=t?e.dom.getParent(t,"p,h1,h2,h3,blockquote")||t:null,r=a?.nodeName?.toLowerCase()||"p";L(["h1","h2","h3","blockquote"].includes(r)?r:"p")},[]),X=(0,t.useMemo)(()=>Array.from(N(r.content)).length,[r.content]),Y=(0,t.useCallback)((e={})=>{const t=i.current;return{post_id:t.postId,version_id:t.versionId,rev:t.rev,title:t.title,excerpt:t.excerpt,content:t.content,categories:t.categories,tags:t.tags,custom:t.custom,featured:t.featured,pay:f(t.pay),...e}},[]),Z=(0,t.useCallback)(async(e=!1)=>{const t=l.current;t&&!t.removed&&V(t.getContent());const a=i.current;if(!z.current&&(a.postId>0||a.versionId>0))return!0;const r=T.current,c=""!==a.title.trim()||""!==N(a.content).trim();if(e&&!c)return!0;D({state:"saving",at:""});try{const t=await o(b.creator.saveUrl,Y({autosave:e}),y),a={...i.current,postId:Number(t.post_id||i.current.postId||0),versionId:Number(t.version_id||i.current.versionId||0),rev:Number(t.rev||t.versionRev||i.current.rev||0)};window.jioSubmitData&&(window.jioSubmitData.postId=a.postId);const l=T.current===r;return z.current=!l,i.current=a,n(a),D({state:l?"saved":"saving",at:l?(new Date).toLocaleTimeString():""}),l}catch(e){return D({state:409===e?.status?"conflict":"error",at:""}),!1}},[Y]);k.current=()=>{Z(!1)};const G=(0,t.useCallback)(async e=>{if(await Z(!1)){D({state:"submitting",at:""});try{let t="";const r=window.JioCaptcha;if(b.captcha?.enabled&&r&&"function"==typeof r.run){const e=await r.run("front_submit");if(null===e)return D({state:"ready",at:""}),void $({tone:"error",text:(0,a.__)("请先完成人机验证","jio")});t=String(e?.jio_captcha_proof||"")}const n=await o(b.creator.submitUrl,Y({post_id:i.current.postId,version_id:i.current.versionId,rev:i.current.rev,publish_now:e,captcha_proof:t}),y);z.current=!1,D({state:"submitted",at:""}),$({tone:"ok",text:String(n.message||(0,a.__)("已提交","jio"))}),U(!1);const l=n.url||n.goto||b.urls?.center;l&&window.setTimeout(()=>{window.location.href=l},900)}catch(e){D({state:"error",at:""}),$({tone:"error",text:String(e?.message||(0,a.__)("提交失败","jio"))})}}else $({tone:"error",text:(0,a.__)("内容保存失败,请重试后再提交","jio")})},[Y,Z]),Q=(0,t.useCallback)(async()=>{if(await Z(!1))try{const e=await o(b.creator.previewUrl,{post_id:i.current.postId,version_id:i.current.versionId},y);e.url&&window.open(String(e.url),"_blank","noopener")}catch(e){$({tone:"error",text:String(e?.message||(0,a.__)("预览失败","jio"))})}},[Z]),{markLocalSaved:ee,clear:te}=function({key:e,snapshot:a,onFound:r}){const n=(0,t.useRef)(a);n.current=a;const o=(0,t.useRef)(!1);return(0,t.useEffect)(()=>{if(!o.current){o.current=!0;try{const t=window.localStorage.getItem(e);if(!t)return;const n=JSON.parse(t),o="string"==typeof n.at?Date.parse(n.at):NaN;if(!Number.isFinite(o)||Date.now()-o>6048e5)return void window.localStorage.removeItem(e);"string"==typeof n.content&&n.content!==a.content&&r(String(n.at))}catch(t){window.localStorage.removeItem(e)}}},[e,r,a.content]),{markLocalSaved:(0,t.useCallback)(()=>{try{window.localStorage.setItem(e,JSON.stringify(n.current))}catch(e){}},[e]),clear:(0,t.useCallback)(()=>{try{window.localStorage.removeItem(e)}catch(e){}},[e])}}({key:j,snapshot:{title:r.title,content:r.content,at:(new Date).toISOString()},onFound:e=>K({savedAt:e})}),ae=function({enabled:e,onSave:a,onLocal:r,remoteDelay:n=4e3,localDelay:o=1500}){const i=(0,t.useRef)(null),l=(0,t.useRef)(null),c=(0,t.useRef)(!1),s=(0,t.useRef)(a),u=(0,t.useRef)(r);s.current=a,u.current=r;const m=(0,t.useCallback)(()=>{i.current&&(window.clearTimeout(i.current),i.current=null),l.current&&(window.clearTimeout(l.current),l.current=null)},[]),d=(0,t.useCallback)(async()=>{if(!c.current){c.current=!0;try{await s.current()}finally{c.current=!1}}},[]),p=(0,t.useCallback)(()=>{m(),u.current(),e&&(l.current=window.setTimeout(()=>u.current(),o),i.current=window.setTimeout(()=>{d()},n))},[m,e,d,o,n]);return(0,t.useEffect)(()=>{if(!e)return;const t=()=>{"hidden"===document.visibilityState&&d()},a=()=>{d()};return document.addEventListener("visibilitychange",t),window.addEventListener("blur",a),()=>{document.removeEventListener("visibilitychange",t),window.removeEventListener("blur",a),m()}},[m,e,d]),(0,t.useMemo)(()=>({schedule:p,flush:d,cancel:m}),[m,d,p])}({enabled:!!A.isLoggedIn,onSave:async()=>{const e=await Z(!0);return e&&te(),e},onLocal:ee}).schedule;(0,t.useEffect)(()=>{z.current&&ae()},[r,ae]),(0,t.useEffect)(()=>{const e=e=>{z.current&&(e.preventDefault(),e.returnValue="")};return window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e)},[]),(0,t.useEffect)(()=>{const e=e=>{(e.metaKey||e.ctrlKey)&&"s"===e.key.toLowerCase()&&(e.preventDefault(),Z(!1))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[Z]),(0,t.useEffect)(()=>{const e=window.wp?.editor;if(!e||"function"!=typeof e.initialize)return void $({tone:"error",text:(0,a.__)("TinyMCE 加载失败,请刷新页面后重试。","jio")});const t={quicktags:!1,tinymce:{menubar:!1,statusbar:!1,resize:!1,toolbar1:"",toolbar2:"",toolbar3:"",plugins:"paste,link,lists,wordpress,wplink",wpautop:!0,body_class:"jio-creator__tinymce",content_css:b.creator?.contentCss||"",content_style:'body{margin:0;color:#243330;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans SC","PingFang SC","Microsoft YaHei",sans-serif;font-size:16px;line-height:1.85;letter-spacing:.01em}p{margin:0 0 1.1em}h1,h2,h3,h4,h5,h6{margin:1.5em 0 .65em;line-height:1.4}img,iframe{max-width:100%}img{height:auto}',height:650,placeholder:String(b.limits?.contentPlaceholder||""),setup:e=>{l.current=e,e.on("init",()=>{w.current=!0,S(!0),null!==p.current&&(e.setContent(p.current),p.current=null),H(e),W(e)}),e.on("NodeChange",()=>W(e)),e.on("input change Undo Redo AddUndo",()=>{V(e.getContent()),H(e)}),e.on("keydown",e=>{(e.metaKey||e.ctrlKey)&&83===e.keyCode&&(e.preventDefault(),k.current())})}}};return e.initialize(E,t),()=>{e.remove?.(E),w.current=!1,l.current=null}},[V]);const re=(0,t.useCallback)(()=>{try{const e=window.localStorage.getItem(j);if(e){const t=JSON.parse(e),a={};"string"==typeof t.title&&(a.title=t.title),"string"==typeof t.content&&(a.content=t.content),q(a),"string"==typeof t.content&&(w.current?l.current?.setContent(t.content):p.current=t.content)}}catch(e){}K(null)},[q]),ne=(0,t.useCallback)(()=>{const e=l.current;e&&!e.removed&&(c.current=e.selection.getBookmark(2,!0))},[]),oe=(0,t.useCallback)(()=>{const e=l.current;if(!e||e.removed)return null;if(e.focus(),c.current){try{e.selection.moveToBookmark(c.current)}catch(e){}c.current=null}return e},[]),ie=(0,t.useCallback)((e,t)=>{const a=oe();a&&("undo"===e?a.undoManager.undo():"redo"===e?a.undoManager.redo():"format"===e?("p"===t?a.execCommand("FormatBlock",!1,"p"):a.formatter.toggle(t||"h2"),W(a)):a.execCommand(e),a.nodeChanged())},[oe]),le=(0,t.useCallback)(()=>{const e=oe();if(!e)return;const t=window.wpLink;if(t&&"function"==typeof t.open)return void t.open(e.id);const r=window.prompt((0,a.__)("输入链接地址","jio"),"https://"),n=r?v(r):"";n&&e.execCommand("mceInsertLink",!1,{href:n})},[oe]),ce=(0,t.useCallback)(e=>{const t=l.current,r=window.JioSubmitMedia;t&&r&&"function"==typeof r.open?(ne(),r.open({type:e,multiple:"image"===e&&void 0,onSelect:t=>{const a=Array.isArray(t)?t:[t],r=oe();if(!r)return;const n=a.map(t=>{const a=v(t?.large_url||t?.url);if(!a)return"";const r=Number(t.attachment_id||t.id||0),n=r>0?` data-edit-file-id="${r}"`:"";if("image"===e){const e=v(t?.url||a),r=e?` data-full-url="${h(e)}"`:"";return`})
`}return``}).join("");n&&(r.insertContent(n),r.nodeChanged(),V(r.getContent()),H(r))},onEmbed:e=>{const t=oe();t&&(t.insertContent(`${e}`),t.nodeChanged(),V(t.getContent()),H(t))}})):$({tone:"error",text:(0,a.__)("媒体工具尚未加载,请刷新页面后重试。","jio")})},[oe,ne]);return(0,e.createElement)("div",{className:"jio-creator","data-status":b.status||"","data-editor-ready":C?"true":"false"},(0,e.createElement)("header",{className:"jio-creator__bar"},(0,e.createElement)("div",{className:"jio-creator__bar-left"},(0,e.createElement)("a",{className:"jio-creator__back",href:b.urls?.center||"/","aria-label":(0,a.__)("返回作者中心","jio")},(0,e.createElement)("i",{className:"fa fas fa-angle-left","aria-hidden":"true"})),(0,e.createElement)("span",{className:"jio-creator__bar-brand"},"Jio"),(0,e.createElement)("span",{className:"jio-creator__bar-divider","aria-hidden":"true"}),(0,e.createElement)("span",{className:"jio-creator__bar-mode"},J?(0,a.__)("修改文章","jio"):(0,a.__)("写文章","jio"))),(0,e.createElement)(d,{ready:C,formatValue:M,onFormatChange:L,canUndo:x.canUndo,canRedo:x.canRedo,capabilities:A,onCommand:ie,onRememberSelection:ne,onOpenLink:le,onOpenMedia:ce}),(0,e.createElement)("div",{className:"jio-creator__bar-actions jio-creator__toolbar-extension","data-toolbar-extension":!0,"aria-label":(0,a.__)("工具扩展区","jio")},(0,e.createElement)(_,{value:R}),(0,e.createElement)("button",{type:"button",className:"jio-creator__save-draft",onClick:()=>{Z(!1)},disabled:!C},(0,e.createElement)("i",{className:"fa fas fa-save","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("保存草稿","jio"))),(0,e.createElement)("button",{type:"button",className:"jio-creator__ghost jio-creator__preview",onClick:()=>{Q()}},(0,a.__)("预览","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator__primary",onClick:()=>U(!0)},J?(0,a.__)("提交改稿","jio"):(0,a.__)("发布","jio")))),F&&(0,e.createElement)("div",{className:"jio-creator__notice",role:"status"},(0,e.createElement)("span",null,(0,a.__)("发现本地未同步的草稿。","jio")),(0,e.createElement)("button",{type:"button",onClick:re},(0,a.__)("恢复","jio")),(0,e.createElement)("button",{type:"button",onClick:()=>K(null)},(0,a.__)("忽略","jio"))),O&&(0,e.createElement)("div",{className:`jio-creator__notice is-${O.tone}`,role:"status"},(0,e.createElement)("span",null,O.text),(0,e.createElement)("button",{type:"button",onClick:()=>$(null),"aria-label":(0,a.__)("关闭","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))),J&&(0,e.createElement)("p",{className:"jio-creator__hint"},(0,a.__)("这篇改稿不会立即覆盖线上文章;审核通过后才会替换。","jio")),(0,e.createElement)("main",{className:"jio-creator__canvas"},(0,e.createElement)(u,{featured:r.featured,canEdit:!!A.canUploadImage,onOpen:()=>U(!0),onClear:()=>q({featured:{type:"",data:{}}})}),(0,e.createElement)("label",{className:"jio-creator__title"},(0,e.createElement)("span",{className:"screen-reader-text"},(0,a.__)("文章标题","jio")),(0,e.createElement)("textarea",{value:r.title,onChange:e=>q({title:e.target.value}),rows:1,placeholder:B.titlePlaceholder||(0,a.__)("请输入标题","jio"),maxLength:4*(Number(B.titleMax)||30)})),(0,e.createElement)("label",{className:"jio-creator__excerpt"},(0,e.createElement)("span",null,(0,a.__)("摘要(可选)","jio")),(0,e.createElement)("textarea",{value:r.excerpt,onChange:e=>q({excerpt:e.target.value}),rows:2,placeholder:(0,a.__)("一句话概括这篇文章","jio")})),(0,e.createElement)(m,{author:b.author||{}}),(0,e.createElement)("div",{className:"jio-creator__editor","data-editor-ready":C?"true":"false"},(0,e.createElement)("textarea",{id:E,defaultValue:r.content,onChange:e=>V(e.target.value),"aria-label":(0,a.__)("文章正文","jio")})),(0,e.createElement)("footer",{className:"jio-creator__footer"},(0,e.createElement)("span",null,(0,a.__)("字数","jio"),":",X),(0,e.createElement)("span",null,(0,a.__)("约","jio")," ",Math.max(1,Math.round(X/400))," ",(0,a.__)("分钟阅读","jio")))),P&&(0,e.createElement)(s,{draft:r,setDraft:q,capabilities:A,limits:B,taxonomy:{categories:b.categories&&b.categories.items||[],tags:!!b.tags?.enabled,customDefs:b.customDefs||[]},isPublishedEdit:J,onClose:()=>U(!1),onSaveDraft:()=>{Z(!1)},onSubmit:e=>{G(e)},privateStorage:!!b.privateStorage,privateUploads:b.privateUploads||[],captcha:!!b.captcha?.enabled,saving:"saving"===R.state||"submitting"===R.state}))}function k(){const a=document.getElementById("jio-creator-studio");a&&(a.classList.add("is-ready"),(0,t.createRoot)(a).render((0,e.createElement)(w,null)))}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",k):k()})();
\ No newline at end of file
+(()=>{"use strict";const e=window.React,t=window.wp.element,a=window.wp.i18n;function r(e,t){const a=e&&(e.message||e.error)||(401===t?"登录状态已失效,请刷新页面重新登录。":"请求失败,请稍后重试。"),r=new Error(String(a));return r.status=t,r.code=e&&e.code?String(e.code):"",r.data=e,r}async function n(e){try{return await e.json()}catch(e){return null}}async function o(e,t,a){const o=await fetch(e,{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","X-WP-Nonce":a},body:JSON.stringify(t)}),i=await n(o);if(!o.ok)throw r(i,o.status);return i}async function i(e,t,a,o={}){const i=new FormData;i.append("file",t),Object.entries(o).forEach(([e,t])=>i.append(e,t));const l=await fetch(e,{method:"POST",credentials:"same-origin",headers:{"X-WP-Nonce":a},body:i}),c=await n(l);if(!l.ok)throw r(c,l.status);return c}const l=window.jioCreatorStudio||{},c=l.nonce||"";function s(r){const{draft:n,setDraft:o,capabilities:s,limits:u,taxonomy:m,isPublishedEdit:d,onClose:p,onSaveDraft:_,onSubmit:b,privateStorage:f,privateUploads:g,saving:j,captcha:h}=r,[E,y]=(0,t.useState)(""),[v,N]=(0,t.useState)(""),[w,k]=(0,t.useState)(!1),C=(0,t.useRef)(null),S=(0,t.useRef)(null);(0,t.useEffect)(()=>{const e=S.current,t=document.getElementById("jio-creator-captcha");if(!e||!t)return;const a=t.parentElement;return e.appendChild(t),t.removeAttribute("hidden"),()=>{a&&(a.appendChild(t),t.setAttribute("hidden",""))}},[]);const x=(0,t.useMemo)(()=>(n.title||"").trim().length,[n.title])>=Number(u.titleMin||1),I=()=>{const e=E.trim();if(!e)return;const t=e.split(/[,,\n]+/u).map(e=>e.trim()).filter(Boolean);o({tags:Array.from(new Set([...n.tags,...t]))}),y("")};return(0,e.createElement)("div",{className:"jio-creator-drawer",role:"dialog","aria-modal":"true","aria-labelledby":"jio-creator-publish-title"},(0,e.createElement)("button",{type:"button",className:"jio-creator-drawer__backdrop","aria-label":(0,a.__)("关闭","jio"),onClick:p}),(0,e.createElement)("div",{className:"jio-creator-drawer__panel"},(0,e.createElement)("header",{className:"jio-creator-drawer__head"},(0,e.createElement)("h2",{id:"jio-creator-publish-title"},d?(0,a.__)("提交改稿","jio"):(0,a.__)("发布文章","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-drawer__close",onClick:p,"aria-label":(0,a.__)("关闭","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))),(0,e.createElement)("div",{className:"jio-creator-drawer__body"},d&&(0,e.createElement)("p",{className:"jio-creator-drawer__note"},(0,a.__)("审核通过前,读者看到的仍然是当前线上版本。","jio")),(0,e.createElement)("section",{className:"jio-creator-field"},(0,e.createElement)("h3",null,(0,a.__)("分类","jio")),(0,e.createElement)("div",{className:"jio-creator-chips"},0===m.categories.length&&(0,e.createElement)("span",{className:"jio-creator-muted"},(0,a.__)("暂无可选分类","jio")),m.categories.map(t=>(0,e.createElement)("label",{key:t.id,className:"jio-creator-chip"+(n.categories.includes(t.id)?" is-active":"")},(0,e.createElement)("input",{type:"checkbox",checked:n.categories.includes(t.id),onChange:()=>(e=>{const t=n.categories.includes(e);o({categories:t?n.categories.filter(t=>t!==e):[...n.categories,e]})})(t.id)}),(0,e.createElement)("span",null,t.name))))),m.tags&&(0,e.createElement)("section",{className:"jio-creator-field"},(0,e.createElement)("h3",null,(0,a.__)("标签","jio")),(0,e.createElement)("div",{className:"jio-creator-chips"},n.tags.map(t=>(0,e.createElement)("span",{key:t,className:"jio-creator-chip is-active"},(0,e.createElement)("span",null,t),(0,e.createElement)("button",{type:"button",onClick:()=>o({tags:n.tags.filter(e=>e!==t)}),"aria-label":(0,a.sprintf)((0,a.__)("移除标签 %s","jio"),t)},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))))),(0,e.createElement)("div",{className:"jio-creator-inline"},(0,e.createElement)("input",{type:"text",value:E,placeholder:(0,a.__)("输入标签,逗号分隔","jio"),onChange:e=>y(e.target.value),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),I())}}),(0,e.createElement)("button",{type:"button",onClick:I},(0,a.__)("添加","jio")))),m.customDefs.map(t=>(0,e.createElement)("section",{className:"jio-creator-field",key:t.key},(0,e.createElement)("h3",null,t.name),(0,e.createElement)("div",{className:"jio-creator-chips"},t.values.map(a=>{const r=n.custom[t.key]||[],i=r.includes(a.key);return(0,e.createElement)("label",{key:a.key,className:"jio-creator-chip"+(i?" is-active":"")},(0,e.createElement)("input",{type:"checkbox",checked:i,onChange:()=>o({custom:{...n.custom,[t.key]:i?r.filter(e=>e!==a.key):[...r,a.key]}})}),(0,e.createElement)("span",null,a.name))})))),s.canPay&&(0,e.createElement)("section",{className:"jio-creator-field"},(0,e.createElement)("div",{className:"jio-creator-switch"},(0,e.createElement)("div",null,(0,e.createElement)("h3",null,(0,a.__)("付费内容","jio")),(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("开启后,未购买读者只能看到免费部分。","jio"))),(0,e.createElement)("label",{className:"jio-creator-toggle"},(0,e.createElement)("input",{type:"checkbox",checked:n.pay.enabled,onChange:e=>o({pay:{...n.pay,enabled:e.target.checked}})}),(0,e.createElement)("span",{"aria-hidden":"true"}))),n.pay.enabled&&(0,e.createElement)("div",{className:"jio-creator-pay"},(0,e.createElement)("div",{className:"jio-creator-inline"},(0,e.createElement)("label",null,(0,e.createElement)("input",{type:"radio",checked:"cash"===n.pay.modo,onChange:()=>o({pay:{...n.pay,modo:"cash"}})}),(0,e.createElement)("span",null,(0,a.__)("现金","jio"))),(0,e.createElement)("label",null,(0,e.createElement)("input",{type:"radio",checked:"points"===n.pay.modo,onChange:()=>o({pay:{...n.pay,modo:"points"}})}),(0,e.createElement)("span",null,(0,a.__)("积分","jio")))),"cash"===n.pay.modo?(0,e.createElement)("label",{className:"jio-creator-input"},(0,e.createElement)("span",null,(0,a.__)("价格","jio")),(0,e.createElement)("input",{type:"number",min:Number(u.priceMin||0),step:"0.01",value:n.pay.price,onChange:e=>o({pay:{...n.pay,price:e.target.value}})})):(0,e.createElement)("label",{className:"jio-creator-input"},(0,e.createElement)("span",null,(0,a.__)("积分价格","jio")),(0,e.createElement)("input",{type:"number",min:0,step:"1",value:n.pay.points,onChange:e=>o({pay:{...n.pay,points:Number(e.target.value)||0}})})),s.canPayDownload&&(0,e.createElement)("div",{className:"jio-creator-attachments"},(0,e.createElement)("div",{className:"jio-creator-attachments__head"},(0,e.createElement)("h4",null,(0,a.__)("资料附件","jio")),f?(0,e.createElement)("label",{className:"jio-creator-upload"},(0,e.createElement)("input",{ref:C,type:"file",onChange:()=>{(async()=>{const e=C.current?.files?.[0];if(e){N(""),k(!0);try{const t=await i(l.creator.privateUrl,e,c,{post_id:String(n.postId||0)}),a={type:"protected",assetKey:String(t.asset_key||""),fileName:String(t.name||e.name),sizeBytes:Number(t.size||e.size),sizeLabel:String(t.size_label||""),label:""};o({pay:{...n.pay,enabled:!0,downloads:[...n.pay.downloads,a]}}),C.current&&(C.current.value="")}catch(e){N(String(e?.message||(0,a.__)("资料上传失败","jio")))}finally{k(!1)}}})()},disabled:w}),(0,e.createElement)("span",null,w?(0,a.__)("上传中…","jio"):(0,a.__)("添加 PDF / ZIP","jio"))):(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("私有附件存储尚未配置,暂时不能上传付费资料。","jio"))),v&&(0,e.createElement)("p",{className:"jio-creator-error"},v),n.pay.downloads.length>0&&(0,e.createElement)("ul",{className:"jio-creator-files"},n.pay.downloads.map((t,r)=>(0,e.createElement)("li",{key:`${t.assetKey||t.url}-${r}`},(0,e.createElement)("span",{className:"jio-creator-files__name"},t.assetKey?(0,e.createElement)(e.Fragment,null,(0,e.createElement)("i",{className:"fa fas fa-lock","aria-hidden":"true"}),t.fileName||t.label||(0,a.__)("受保护资料","jio")):(0,e.createElement)(e.Fragment,null,(0,e.createElement)("i",{className:"fa fas fa-link","aria-hidden":"true"}),t.label||t.url)),t.sizeLabel&&(0,e.createElement)("span",{className:"jio-creator-muted"},t.sizeLabel),(0,e.createElement)("button",{type:"button",onClick:()=>(e=>{o({pay:{...n.pay,downloads:n.pay.downloads.filter((t,a)=>a!==e)}})})(r),"aria-label":(0,a.__)("移除","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))))),g.length>0&&(0,e.createElement)("details",{className:"jio-creator-reuse"},(0,e.createElement)("summary",null,(0,a.__)("从已上传资料中选择","jio")),(0,e.createElement)("ul",null,g.filter(e=>!n.pay.downloads.some(t=>t.assetKey===e.assetKey)).map(t=>(0,e.createElement)("li",{key:t.assetKey},(0,e.createElement)("span",null,t.fileName),(0,e.createElement)("span",{className:"jio-creator-muted"},t.sizeLabel),(0,e.createElement)("button",{type:"button",onClick:()=>o({pay:{...n.pay,enabled:!0,downloads:[...n.pay.downloads,{...t,type:"protected"}]}})},(0,a.__)("使用","jio"))))))))),!s.canPay&&s.canSaveDraft&&(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("当前账号不能设置付费内容。","jio"))),(0,e.createElement)("footer",{className:"jio-creator-drawer__foot"},h&&(0,e.createElement)("div",{className:"jio-creator-drawer__captcha",ref:S}),(0,e.createElement)("div",{className:"jio-creator-drawer__actions"},(0,e.createElement)("button",{type:"button",className:"jio-creator-ghost",onClick:_,disabled:j},(0,a.__)("保存草稿","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-primary",onClick:()=>b(!1),disabled:j||!x},d?(0,a.__)("提交审核","jio"):s.canPublishNow?(0,a.__)("发布","jio"):(0,a.__)("提交审核","jio")),s.canPublishNow&&(0,e.createElement)("button",{type:"button",className:"jio-creator-link",onClick:()=>b(!0),disabled:j||!x},(0,a.__)("立即发布","jio"))))))}function u({ready:t,canUndo:r,canRedo:n,formatValue:o,onFormatChange:i,capabilities:l,onCommand:c,onRememberSelection:s,onOpenLink:u,onOpenMedia:m}){return(0,e.createElement)("div",{className:"jio-creator__toolbar-tools",role:"toolbar","aria-label":(0,a.__)("正文编辑工具","jio"),onMouseDown:e=>{s(),e.target.closest("button")&&e.preventDefault()}},(0,e.createElement)("div",{className:"jio-creator__toolbar-group",role:"group","aria-label":(0,a.__)("撤销和重做","jio")},(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!r,onClick:()=>c("undo"),title:(0,a.__)("撤销","jio"),"aria-label":(0,a.__)("撤销","jio")},(0,e.createElement)("i",{className:"fa fas fa-undo","aria-hidden":"true"})),(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!n,onClick:()=>c("redo"),title:(0,a.__)("重做","jio"),"aria-label":(0,a.__)("重做","jio")},(0,e.createElement)("i",{className:"fa fas fa-redo","aria-hidden":"true"}))),(0,e.createElement)("span",{className:"jio-creator__toolbar-divider","aria-hidden":"true"}),(0,e.createElement)("select",{className:"jio-creator__format-select","aria-label":(0,a.__)("段落样式","jio"),value:o,disabled:!t,onFocus:s,onChange:e=>{i(e.target.value),c("format",e.target.value)}},(0,e.createElement)("option",{value:"p"},(0,a.__)("正文","jio")),(0,e.createElement)("option",{value:"h1"},(0,a.__)("标题 1","jio")),(0,e.createElement)("option",{value:"h2"},(0,a.__)("标题 2","jio")),(0,e.createElement)("option",{value:"h3"},(0,a.__)("标题 3","jio")),(0,e.createElement)("option",{value:"blockquote"},(0,a.__)("引用","jio"))),(0,e.createElement)("span",{className:"jio-creator__toolbar-divider","aria-hidden":"true"}),(0,e.createElement)("div",{className:"jio-creator__toolbar-group",role:"group","aria-label":(0,a.__)("文字格式","jio")},(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!t,onClick:()=>c("Bold"),title:(0,a.__)("加粗","jio"),"aria-label":(0,a.__)("加粗","jio")},(0,e.createElement)("i",{className:"fa fas fa-bold","aria-hidden":"true"})),(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!t,onClick:()=>c("Italic"),title:(0,a.__)("斜体","jio"),"aria-label":(0,a.__)("斜体","jio")},(0,e.createElement)("i",{className:"fa fas fa-italic","aria-hidden":"true"})),(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn",disabled:!t,onClick:()=>c("Underline"),title:(0,a.__)("下划线","jio"),"aria-label":(0,a.__)("下划线","jio")},(0,e.createElement)("i",{className:"fa fas fa-underline","aria-hidden":"true"}))),(0,e.createElement)("span",{className:"jio-creator__toolbar-divider","aria-hidden":"true"}),(0,e.createElement)("div",{className:"jio-creator__toolbar-group",role:"group","aria-label":(0,a.__)("媒体和链接","jio")},l.canUploadImage&&(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn jio-creator__tool-labeled",disabled:!t,onClick:()=>m("image"),title:(0,a.__)("插入图片","jio")},(0,e.createElement)("i",{className:"fa far fa-image","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("图片","jio"))),(l.canUploadVideo||l.canEmbed)&&(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn jio-creator__tool-labeled",disabled:!t,onClick:()=>m("video"),title:(0,a.__)("插入视频","jio")},(0,e.createElement)("i",{className:"fa fas fa-video","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("视频","jio"))),(0,e.createElement)("button",{type:"button",className:"jio-creator__tool-btn jio-creator__tool-labeled",disabled:!t,onClick:u,title:(0,a.__)("插入链接","jio")},(0,e.createElement)("i",{className:"fa fas fa-link","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("链接","jio")))))}const m=window.jioCreatorStudio||{},d=m.nonce||"",p=e=>String(e).padStart(2,"0");function _(e){return`${e.getFullYear()}-${p(e.getMonth()+1)}-${p(e.getDate())}T${p(e.getHours())}:${p(e.getMinutes())}`}function b({featured:r,canEditCover:n,canSchedule:o,scheduleEnabled:l,scheduleAt:c,onFeaturedChange:s,onScheduleChange:u}){const p=(0,t.useRef)(null),[b,f]=(0,t.useState)(!1),[g,j]=(0,t.useState)(""),h=(0,t.useMemo)(()=>_(new Date(Date.now()+3e5)),[]),E="string"==typeof r?.data?.url?r.data.url:"";return(0,e.createElement)("section",{className:"jio-creator__settings","aria-label":(0,a.__)("发布设置","jio")},(0,e.createElement)("h2",{className:"jio-creator__settings-title"},(0,a.__)("发布设置","jio")),n&&(0,e.createElement)("div",{className:"jio-creator__setting-row"},(0,e.createElement)("div",{className:"jio-creator__setting-copy"},(0,e.createElement)("span",{className:"jio-creator__setting-label"},(0,a.__)("添加封面","jio")),(0,e.createElement)("p",{className:"jio-creator__setting-help"},(0,a.__)("用于列表卡片、分享卡片;不设置时自动使用正文首图。","jio"))),(0,e.createElement)("div",{className:"jio-creator__cover-control"},E?(0,e.createElement)(e.Fragment,null,(0,e.createElement)("button",{type:"button",className:"jio-creator__cover-preview",onClick:()=>p.current?.click(),"aria-label":(0,a.__)("更换封面","jio")},(0,e.createElement)("img",{src:E,alt:""})),(0,e.createElement)("button",{type:"button",className:"jio-creator__cover-clear",onClick:()=>s({type:"",data:{}}),"aria-label":(0,a.__)("移除封面","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))):(0,e.createElement)("button",{type:"button",className:"jio-creator__cover-add",onClick:()=>p.current?.click(),disabled:b},(0,e.createElement)("i",{className:"fa fas fa-plus","aria-hidden":"true"}),(0,e.createElement)("span",null,b?(0,a.__)("上传中…","jio"):(0,a.__)("添加封面","jio"))),(0,e.createElement)("input",{ref:p,type:"file",accept:"image/*",className:"jio-creator__cover-input",onChange:()=>{(async()=>{const e=p.current?.files?.[0],t=m.media?.uploadUrl?.image;if(e&&t){j(""),f(!0);try{const r=await i(t,e,d),n=Number(r.attachment_id||r.id||0),o=String(r.url||"");if(!n||!o)throw new Error((0,a.__)("上传后无法读取图片。","jio"));s({type:"image",mediaId:n,data:{id:n,url:o}})}catch(e){j(String(e?.message||(0,a.__)("上传失败","jio")))}finally{f(!1),p.current&&(p.current.value="")}}})()}}))),g&&(0,e.createElement)("p",{className:"jio-creator-error"},g),(0,e.createElement)("div",{className:"jio-creator__setting-row"},(0,e.createElement)("div",{className:"jio-creator__setting-copy"},(0,e.createElement)("span",{className:"jio-creator__setting-label"},(0,a.__)("定时发布","jio")),(0,e.createElement)("p",{className:"jio-creator__setting-help"},o?(0,a.__)("开启后到点自动发布,发布前不会出现在文章列表。","jio"):(0,a.__)("当前账号提交后需要审核,审核通过后才会发布。","jio"))),(0,e.createElement)("label",{className:"jio-creator-toggle"},(0,e.createElement)("input",{type:"checkbox",checked:l,disabled:!o,onChange:e=>u(e.target.checked,c||_(new Date(Date.now()+36e5)))}),(0,e.createElement)("span",{"aria-hidden":"true"}))),o&&l&&(0,e.createElement)("div",{className:"jio-creator__schedule"},(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("发布时间","jio")),(0,e.createElement)("input",{type:"datetime-local",value:c,min:h,onChange:e=>u(!0,e.target.value)})),(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.sprintf)(/* translators: %s: site timezone */ /* translators: %s: site timezone */
+(0,a.__)("按站点时区(%s)发布,至少需要晚于当前时间 1 分钟。","jio"),String(m.timezone||"UTC")))))}function f({author:t}){const r="string"==typeof t?.name?t.name.trim():"";if(""===r)return null;const n="string"==typeof t?.avatar?t.avatar:"",o="string"==typeof t?.meta?t.meta:"";return(0,e.createElement)("div",{className:"jio-creator__author"},""!==n?(0,e.createElement)("img",{className:"jio-creator__author-avatar",src:n,alt:"",width:24,height:24}):(0,e.createElement)("span",{className:"jio-creator__author-avatar is-placeholder","aria-hidden":"true"},r.slice(0,1)),(0,e.createElement)("span",{className:"jio-creator__author-name"},r),""!==o&&(0,e.createElement)("span",{className:"jio-creator__author-meta"},o),(0,e.createElement)("span",{className:"jio-creator__author-hint"},(0,a.__)("原创内容","jio")))}const g={ready:(0,a.__)("尚未保存","jio"),saving:(0,a.__)("保存中…","jio"),saved:(0,a.__)("已保存","jio"),error:(0,a.__)("保存失败","jio"),conflict:(0,a.__)("内容已在别处更新","jio"),submitting:(0,a.__)("提交中…","jio"),submitted:(0,a.__)("已提交","jio")};function j({value:t}){return(0,e.createElement)("span",{className:`jio-creator__save is-${t.state}`,role:"status","aria-live":"polite"},(0,e.createElement)("i",{className:"fa fas fa-circle","aria-hidden":"true"}),(0,e.createElement)("span",null,g[t.state]||g.ready),"saved"===t.state&&t.at?(0,e.createElement)("time",null,t.at):null)}function h(e){const t=(e.downloads||[]).map(e=>{const t="string"==typeof e.assetKey?e.assetKey:"";if(t)return{type:"protected",asset_key:t,label:"string"==typeof e.label?e.label:""};const a="string"==typeof e.url?e.url.trim():"";return a?{type:"direct",url:a,label:"string"==typeof e.label?e.label:"",extract_code:"string"==typeof e.extractCode?e.extractCode:""}:null}).filter(Boolean);return{enabled:!!e.enabled,fields:{pay_type:e.enabled?t.length>0?"download":"reading":"no",pay_modo:"points"===e.modo?"points":"0",price:"points"===e.modo?"0.00":String(e.price||"0.00"),points_price:"points"===e.modo?Math.max(0,Number(e.points)||0):0,vip1_price:"points"===e.modo?"0.00":String(e.vip1Price||"0.00"),vip2_price:"points"===e.modo?"0.00":String(e.vip2Price||"0.00"),pay_limit:Number(e.payLimit)||0,downloads:t}}}const E=window.jioCreatorStudio||{},y=E.nonce||"",v=`jio-studio-${E.sourceId||0}`,N="jio-creator-content";function w(){const e=E.pay||{},t=E.categories&&E.categories.selected||[],a=E.tags&&E.tags.items||[];return{postId:Number(E.sourceId||0),versionId:Number(E.versionId||0),rev:Number(E.versionRev||0),title:String(E.title||""),content:String(E.content||""),schedule:{enabled:!1,at:""},categories:t.map(Number),tags:a.slice(),custom:E.custom||{},featured:E.featured||{type:"",data:{}},pay:{enabled:!!e.enabled,modo:"points"===e.payModo?"points":"cash",price:String(e.price||"0.00"),points:Number(e.points||0),vip1Price:String(e.vip1Price||"0.00"),vip2Price:String(e.vip2Price||"0.00"),payLimit:Number(e.payLimit||0),downloads:Array.isArray(e.downloads)?e.downloads:[]}}}function k(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(//g,">")}function C(e){const t=String(e||"").trim();if(!t)return"";try{const e=new URL(t,window.location.href);return"http:"===e.protocol||"https:"===e.protocol?e.href:""}catch(e){return""}}function S(e){const t=document.createElement("div");return t.innerHTML=e,(t.textContent||"").replace(/\s+/g,"")}function x(){const[r,n]=(0,t.useState)(w),i=(0,t.useRef)(r);i.current=r;const l=(0,t.useRef)(null),c=(0,t.useRef)(null),m=(0,t.useRef)(null),d=(0,t.useRef)(!1),p=(0,t.useRef)(()=>{}),[_,g]=(0,t.useState)(!1),[x,I]=(0,t.useState)({canUndo:!1,canRedo:!1}),[M,L]=(0,t.useState)("p"),[R,D]=(0,t.useState)(()=>({state:E.sourceId||E.versionId||E.content?"saved":"ready",at:""})),[P,U]=(0,t.useState)(!1),[$,F]=(0,t.useState)(null),[T,z]=(0,t.useState)(null),K=(0,t.useRef)(!1),O=(0,t.useRef)(0),A=E.capabilities||{},B={titleMin:Number(E.limits?.titleMin||1),titleMax:Number(E.limits?.titleMax||30),titlePlaceholder:String(E.limits?.titlePlaceholder||(0,a.__)("请输入标题","jio")),priceMin:Number(E.pay?.priceMin||0),priceMax:Number(E.pay?.priceMax||0),pointsMin:Number(E.pay?.pointsMin||0),pointsMax:Number(E.pay?.pointsMax||0)},J=!!E.isPublished,q=(0,t.useCallback)(e=>{K.current=!0,O.current+=1;const t={...i.current,...e};i.current=t,n(t)},[]),V=(0,t.useCallback)(e=>{if(e===i.current.content)return;K.current=!0,O.current+=1;const t={...i.current,content:e};i.current=t,n(t)},[]),H=(0,t.useCallback)(e=>{const t=e?.undoManager;t&&I({canUndo:"function"==typeof t.hasUndo&&t.hasUndo(),canRedo:"function"==typeof t.hasRedo&&t.hasRedo()})},[]),W=(0,t.useCallback)(e=>{const t=e?.selection?.getNode(),a=t?e.dom.getParent(t,"p,h1,h2,h3,blockquote")||t:null,r=a?.nodeName?.toLowerCase()||"p";L(["h1","h2","h3","blockquote"].includes(r)?r:"p")},[]),X=(0,t.useMemo)(()=>Array.from(S(r.content)).length,[r.content]),Y=(0,t.useCallback)((e={})=>{const t=i.current;return{post_id:t.postId,version_id:t.versionId,rev:t.rev,title:t.title,content:t.content,categories:t.categories,tags:t.tags,custom:t.custom,featured:t.featured,schedule:{enabled:!!t.schedule.enabled,at:t.schedule.enabled?t.schedule.at:""},pay:h(t.pay),...e}},[]),Z=(0,t.useCallback)(async(e=!1)=>{const t=l.current;t&&!t.removed&&V(t.getContent());const a=i.current;if(!K.current&&(a.postId>0||a.versionId>0))return!0;const r=O.current,c=""!==a.title.trim()||""!==S(a.content).trim();if(e&&!c)return!0;D({state:"saving",at:""});try{const t=await o(E.creator.saveUrl,Y({autosave:e}),y),a={...i.current,postId:Number(t.post_id||i.current.postId||0),versionId:Number(t.version_id||i.current.versionId||0),rev:Number(t.rev||t.versionRev||i.current.rev||0)};window.jioSubmitData&&(window.jioSubmitData.postId=a.postId);const l=O.current===r;return K.current=!l,i.current=a,n(a),D({state:l?"saved":"saving",at:l?(new Date).toLocaleTimeString():""}),l}catch(e){return D({state:409===e?.status?"conflict":"error",at:""}),!1}},[Y]);p.current=()=>{Z(!1)};const G=(0,t.useCallback)(async e=>{if(await Z(!1)){D({state:"submitting",at:""});try{let t="";const r=window.JioCaptcha;if(E.captcha?.enabled&&r&&"function"==typeof r.run){const e=await r.run("front_submit");if(null===e)return D({state:"ready",at:""}),void F({tone:"error",text:(0,a.__)("请先完成人机验证","jio")});t=String(e?.jio_captcha_proof||"")}const n=await o(E.creator.submitUrl,Y({post_id:i.current.postId,version_id:i.current.versionId,rev:i.current.rev,publish_now:e,captcha_proof:t}),y);K.current=!1,D({state:"submitted",at:""}),F({tone:"ok",text:String(n.message||(0,a.__)("已提交","jio"))}),U(!1);const l=n.url||n.goto||E.urls?.center;l&&window.setTimeout(()=>{window.location.href=l},900)}catch(e){D({state:"error",at:""}),F({tone:"error",text:String(e?.message||(0,a.__)("提交失败","jio"))})}}else F({tone:"error",text:(0,a.__)("内容保存失败,请重试后再提交","jio")})},[Y,Z]),Q=(0,t.useCallback)(async()=>{if(await Z(!1))try{const e=await o(E.creator.previewUrl,{post_id:i.current.postId,version_id:i.current.versionId},y);e.url&&window.open(String(e.url),"_blank","noopener")}catch(e){F({tone:"error",text:String(e?.message||(0,a.__)("预览失败","jio"))})}},[Z]),{markLocalSaved:ee,clear:te}=function({key:e,snapshot:a,onFound:r}){const n=(0,t.useRef)(a);n.current=a;const o=(0,t.useRef)(!1);return(0,t.useEffect)(()=>{if(!o.current){o.current=!0;try{const t=window.localStorage.getItem(e);if(!t)return;const n=JSON.parse(t),o="string"==typeof n.at?Date.parse(n.at):NaN;if(!Number.isFinite(o)||Date.now()-o>6048e5)return void window.localStorage.removeItem(e);"string"==typeof n.content&&n.content!==a.content&&r(String(n.at))}catch(t){window.localStorage.removeItem(e)}}},[e,r,a.content]),{markLocalSaved:(0,t.useCallback)(()=>{try{window.localStorage.setItem(e,JSON.stringify(n.current))}catch(e){}},[e]),clear:(0,t.useCallback)(()=>{try{window.localStorage.removeItem(e)}catch(e){}},[e])}}({key:v,snapshot:{title:r.title,content:r.content,at:(new Date).toISOString()},onFound:e=>z({savedAt:e})}),ae=function({enabled:e,onSave:a,onLocal:r,remoteDelay:n=4e3,localDelay:o=1500}){const i=(0,t.useRef)(null),l=(0,t.useRef)(null),c=(0,t.useRef)(!1),s=(0,t.useRef)(a),u=(0,t.useRef)(r);s.current=a,u.current=r;const m=(0,t.useCallback)(()=>{i.current&&(window.clearTimeout(i.current),i.current=null),l.current&&(window.clearTimeout(l.current),l.current=null)},[]),d=(0,t.useCallback)(async()=>{if(!c.current){c.current=!0;try{await s.current()}finally{c.current=!1}}},[]),p=(0,t.useCallback)(()=>{m(),u.current(),e&&(l.current=window.setTimeout(()=>u.current(),o),i.current=window.setTimeout(()=>{d()},n))},[m,e,d,o,n]);return(0,t.useEffect)(()=>{if(!e)return;const t=()=>{"hidden"===document.visibilityState&&d()},a=()=>{d()};return document.addEventListener("visibilitychange",t),window.addEventListener("blur",a),()=>{document.removeEventListener("visibilitychange",t),window.removeEventListener("blur",a),m()}},[m,e,d]),(0,t.useMemo)(()=>({schedule:p,flush:d,cancel:m}),[m,d,p])}({enabled:!!A.isLoggedIn,onSave:async()=>{const e=await Z(!0);return e&&te(),e},onLocal:ee}).schedule;(0,t.useEffect)(()=>{K.current&&ae()},[r,ae]),(0,t.useEffect)(()=>{const e=e=>{K.current&&(e.preventDefault(),e.returnValue="")};return window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e)},[]),(0,t.useEffect)(()=>{const e=e=>{(e.metaKey||e.ctrlKey)&&"s"===e.key.toLowerCase()&&(e.preventDefault(),Z(!1))};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[Z]),(0,t.useEffect)(()=>{const e=window.wp?.editor;if(!e||"function"!=typeof e.initialize)return void F({tone:"error",text:(0,a.__)("TinyMCE 加载失败,请刷新页面后重试。","jio")});const t={quicktags:!1,tinymce:{menubar:!1,statusbar:!1,resize:!1,toolbar1:"",toolbar2:"",toolbar3:"",plugins:"paste,link,lists,wordpress,wplink",wpautop:!0,body_class:"jio-creator__tinymce",content_css:E.creator?.contentCss||"",content_style:'body{margin:0;color:#243330;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans SC","PingFang SC","Microsoft YaHei",sans-serif;font-size:16px;line-height:1.85;letter-spacing:.01em}p{margin:0 0 1.1em}h1,h2,h3,h4,h5,h6{margin:1.5em 0 .65em;line-height:1.4}img,iframe{max-width:100%}img{height:auto}',height:650,placeholder:String(E.limits?.contentPlaceholder||""),setup:e=>{l.current=e,e.on("init",()=>{d.current=!0,g(!0),null!==m.current&&(e.setContent(m.current),m.current=null),H(e),W(e)}),e.on("NodeChange",()=>W(e)),e.on("input change Undo Redo AddUndo",()=>{V(e.getContent()),H(e)}),e.on("keydown",e=>{(e.metaKey||e.ctrlKey)&&83===e.keyCode&&(e.preventDefault(),p.current())})}}};return e.initialize(N,t),()=>{e.remove?.(N),d.current=!1,l.current=null}},[V]);const re=(0,t.useCallback)(()=>{try{const e=window.localStorage.getItem(v);if(e){const t=JSON.parse(e),a={};"string"==typeof t.title&&(a.title=t.title),"string"==typeof t.content&&(a.content=t.content),q(a),"string"==typeof t.content&&(d.current?l.current?.setContent(t.content):m.current=t.content)}}catch(e){}z(null)},[q]),ne=(0,t.useCallback)(()=>{const e=l.current;e&&!e.removed&&(c.current=e.selection.getBookmark(2,!0))},[]),oe=(0,t.useCallback)(()=>{const e=l.current;if(!e||e.removed)return null;if(e.focus(),c.current){try{e.selection.moveToBookmark(c.current)}catch(e){}c.current=null}return e},[]),ie=(0,t.useCallback)((e,t)=>{const a=oe();a&&("undo"===e?a.undoManager.undo():"redo"===e?a.undoManager.redo():"format"===e?("p"===t?a.execCommand("FormatBlock",!1,"p"):a.formatter.toggle(t||"h2"),W(a)):a.execCommand(e),a.nodeChanged())},[oe]),le=(0,t.useCallback)(()=>{const e=oe();if(!e)return;const t=window.wpLink;if(t&&"function"==typeof t.open)return void t.open(e.id);const r=window.prompt((0,a.__)("输入链接地址","jio"),"https://"),n=r?C(r):"";n&&e.execCommand("mceInsertLink",!1,{href:n})},[oe]),ce=(0,t.useCallback)(e=>{const t=l.current,r=window.JioSubmitMedia;t&&r&&"function"==typeof r.open?(ne(),r.open({type:e,multiple:"image"===e&&void 0,onSelect:t=>{const a=Array.isArray(t)?t:[t],r=oe();if(!r)return;const n=a.map(t=>{const a=C(t?.large_url||t?.url);if(!a)return"";const r=Number(t.attachment_id||t.id||0),n=r>0?` data-edit-file-id="${r}"`:"";if("image"===e){const e=C(t?.url||a),r=e?` data-full-url="${k(e)}"`:"";return`})
`}return``}).join("");n&&(r.insertContent(n),r.nodeChanged(),V(r.getContent()),H(r))},onEmbed:e=>{const t=oe();t&&(t.insertContent(`${e}`),t.nodeChanged(),V(t.getContent()),H(t))}})):F({tone:"error",text:(0,a.__)("媒体工具尚未加载,请刷新页面后重试。","jio")})},[oe,ne]);return(0,e.createElement)("div",{className:"jio-creator","data-status":E.status||"","data-editor-ready":_?"true":"false"},(0,e.createElement)("header",{className:"jio-creator__bar"},(0,e.createElement)("div",{className:"jio-creator__bar-left"},(0,e.createElement)("a",{className:"jio-creator__back",href:E.urls?.center||"/","aria-label":(0,a.__)("返回作者中心","jio")},(0,e.createElement)("i",{className:"fa fas fa-angle-left","aria-hidden":"true"})),(0,e.createElement)("span",{className:"jio-creator__bar-brand"},"Jio"),(0,e.createElement)("span",{className:"jio-creator__bar-divider","aria-hidden":"true"}),(0,e.createElement)("span",{className:"jio-creator__bar-mode"},J?(0,a.__)("修改文章","jio"):(0,a.__)("写文章","jio"))),(0,e.createElement)(u,{ready:_,formatValue:M,onFormatChange:L,canUndo:x.canUndo,canRedo:x.canRedo,capabilities:A,onCommand:ie,onRememberSelection:ne,onOpenLink:le,onOpenMedia:ce}),(0,e.createElement)("div",{className:"jio-creator__bar-actions jio-creator__toolbar-extension","data-toolbar-extension":!0,"aria-label":(0,a.__)("工具扩展区","jio")},(0,e.createElement)(j,{value:R}),(0,e.createElement)("button",{type:"button",className:"jio-creator__save-draft",onClick:()=>{Z(!1)},disabled:!_},(0,e.createElement)("i",{className:"fa fas fa-save","aria-hidden":"true"}),(0,e.createElement)("span",null,(0,a.__)("保存草稿","jio"))),(0,e.createElement)("button",{type:"button",className:"jio-creator__ghost jio-creator__preview",onClick:()=>{Q()}},(0,a.__)("预览","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator__primary",onClick:()=>U(!0)},J?(0,a.__)("提交改稿","jio"):(0,a.__)("发布","jio")))),T&&(0,e.createElement)("div",{className:"jio-creator__notice",role:"status"},(0,e.createElement)("span",null,(0,a.__)("发现本地未同步的草稿。","jio")),(0,e.createElement)("button",{type:"button",onClick:re},(0,a.__)("恢复","jio")),(0,e.createElement)("button",{type:"button",onClick:()=>z(null)},(0,a.__)("忽略","jio"))),$&&(0,e.createElement)("div",{className:`jio-creator__notice is-${$.tone}`,role:"status"},(0,e.createElement)("span",null,$.text),(0,e.createElement)("button",{type:"button",onClick:()=>F(null),"aria-label":(0,a.__)("关闭","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))),J&&(0,e.createElement)("p",{className:"jio-creator__hint"},(0,a.__)("这篇改稿不会立即覆盖线上文章;审核通过后才会替换。","jio")),(0,e.createElement)("main",{className:"jio-creator__canvas"},(0,e.createElement)(f,{author:E.author||{}}),(0,e.createElement)("label",{className:"jio-creator__title"},(0,e.createElement)("span",{className:"screen-reader-text"},(0,a.__)("文章标题","jio")),(0,e.createElement)("textarea",{value:r.title,onChange:e=>q({title:e.target.value}),rows:1,placeholder:(0,a.sprintf)(/* translators: %d: max title length */ /* translators: %d: max title length */
+(0,a.__)("请输入标题(最多 %d 个字)","jio"),Number(B.titleMax)||100),spellCheck:!1,maxLength:Number(B.titleMax)||100})),(0,e.createElement)("div",{className:"jio-creator__editor","data-editor-ready":_?"true":"false"},(0,e.createElement)("textarea",{id:N,defaultValue:r.content,onChange:e=>V(e.target.value),"aria-label":(0,a.__)("文章正文","jio")}))),(0,e.createElement)(b,{featured:r.featured,canEditCover:!!A.canUploadImage,canSchedule:!!A.canSchedule,scheduleEnabled:!!r.schedule.enabled,scheduleAt:r.schedule.at,onFeaturedChange:e=>q({featured:e}),onScheduleChange:(e,t)=>q({schedule:{enabled:e,at:t}})}),(0,e.createElement)("footer",{className:"jio-creator__footer"},(0,e.createElement)("span",null,(0,a.__)("字数","jio"),":",X),(0,e.createElement)("span",null,(0,a.__)("约","jio")," ",Math.max(1,Math.round(X/400))," ",(0,a.__)("分钟阅读","jio"))),P&&(0,e.createElement)(s,{draft:r,setDraft:q,capabilities:A,limits:B,taxonomy:{categories:E.categories&&E.categories.items||[],tags:!!E.tags?.enabled,customDefs:E.customDefs||[]},isPublishedEdit:J,onClose:()=>U(!1),onSaveDraft:()=>{Z(!1)},onSubmit:e=>{G(e)},privateStorage:!!E.privateStorage,privateUploads:E.privateUploads||[],captcha:!!E.captcha?.enabled,saving:"saving"===R.state||"submitting"===R.state}))}function I(){const a=document.getElementById("jio-creator-studio");a&&(a.classList.add("is-ready"),(0,t.createRoot)(a).render((0,e.createElement)(x,null)))}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",I):I()})();
\ No newline at end of file
diff --git a/assets/creator-studio/scripts/preview.cjs b/assets/creator-studio/scripts/preview.cjs
index 953d71fc..d92fdd2a 100644
--- a/assets/creator-studio/scripts/preview.cjs
+++ b/assets/creator-studio/scripts/preview.cjs
@@ -63,10 +63,11 @@ const mockBootstrap = {
canPay: true,
canPayDownload: true,
canPublishNow: true,
+ canSchedule: true,
canEdit: true,
isLoggedIn: true,
},
- limits: { titleMin: 5, titleMax: 30, titlePlaceholder: '请输入标题', contentPlaceholder: '开始写作…' },
+ limits: { titleMin: 5, titleMax: 100, titlePlaceholder: '请输入标题', contentPlaceholder: '请输入正文' },
author: { name: '预览作者', avatar: '', meta: '' },
privateUploads: [],
privateStorage: false,
@@ -82,6 +83,7 @@ const mockBootstrap = {
bootstrapUrl: '#',
},
nonce: 'preview',
+ timezone: 'Asia/Shanghai',
};
// 换成模拟数据。WP 的 wp_add_inline_script 会在结尾追加 sourceURL 注释,
diff --git a/assets/creator-studio/scripts/shoot.cjs b/assets/creator-studio/scripts/shoot.cjs
index 6c290114..209e0bb6 100644
--- a/assets/creator-studio/scripts/shoot.cjs
+++ b/assets/creator-studio/scripts/shoot.cjs
@@ -57,7 +57,7 @@ const PREFIX = process.argv[3] || 'C:/Users/Xing/Desktop/WP-Date/data/wordpress/
return {
bar: pick('.jio-creator__bar'),
title: pick('.jio-creator__title textarea'),
- excerpt: pick('.jio-creator__excerpt textarea'),
+ settings: pick('.jio-creator__settings'),
canvas: pick('.jio-creator__canvas'),
toolbar: pick('.jio-creator__toolbar-tools'),
editor: pick('.jio-creator__editor .mce-edit-area'),
diff --git a/assets/creator-studio/src/components/cover-strip.tsx b/assets/creator-studio/src/components/cover-strip.tsx
deleted file mode 100644
index 3c614458..00000000
--- a/assets/creator-studio/src/components/cover-strip.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * 封面预览条(公众号式)。
- *
- * 位于标题上方一行:有封面时显示缩略图,点击回到发布抽屉的封面区;
- * 无封面时给一个低调的入口。封面能力由服务端 bootstrap 决定,前端不放大权限。
- *
- * @package Jio
- */
-
-import { __ } from '@wordpress/i18n';
-
-type Featured = { type: string; data: Record; mediaId?: number };
-
-type Props = {
- featured: Featured;
- canEdit: boolean;
- onOpen: () => void;
- onClear: () => void;
-};
-
-export function CoverStrip({ featured, canEdit, onOpen, onClear }: Props) {
- const url = typeof featured?.data?.url === 'string' ? featured.data.url : '';
-
- if (!canEdit) {
- return null;
- }
-
- if (!url) {
- return (
-
- );
- }
-
- return (
-
-
-
-
- );
-}
diff --git a/assets/creator-studio/src/components/publish-settings.tsx b/assets/creator-studio/src/components/publish-settings.tsx
new file mode 100644
index 00000000..aaaa00e5
--- /dev/null
+++ b/assets/creator-studio/src/components/publish-settings.tsx
@@ -0,0 +1,178 @@
+/**
+ * 发布设置卡片(位于正文纸张下方)。
+ *
+ * 只承载与"这篇会被怎样发布"有关的低频选项:封面与定时发布。
+ * 分类、标签、付费等配置仍在发布抽屉里;服务端 bootstrap 决定每项是否可用。
+ *
+ * @package Jio
+ */
+
+import { useMemo, useRef, useState } from '@wordpress/element';
+import { __, sprintf } from '@wordpress/i18n';
+
+import { apiUpload } from '../services/api';
+
+type Featured = { type: string; data: Record; mediaId?: number };
+
+type Props = {
+ featured: Featured;
+ canEditCover: boolean;
+ canSchedule: boolean;
+ scheduleEnabled: boolean;
+ scheduleAt: string;
+ onFeaturedChange: (featured: Featured) => void;
+ onScheduleChange: (enabled: boolean, at: string) => void;
+};
+
+const bootstrap: Record = window['jioCreatorStudio'] || {};
+const nonce: string = bootstrap.nonce || '';
+
+const pad = (value: number): string => String(value).padStart(2, '0');
+
+function toLocalInput(date: Date): string {
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
+}
+
+export function defaultScheduleTime(): string {
+ // 默认给一小时后,避免用户点开开关就看到一个"已经过去"的时间。
+ return toLocalInput(new Date(Date.now() + 60 * 60 * 1000));
+}
+
+export function PublishSettings({
+ featured,
+ canEditCover,
+ canSchedule,
+ scheduleEnabled,
+ scheduleAt,
+ onFeaturedChange,
+ onScheduleChange,
+}: Props) {
+ const coverInput = useRef(null);
+ 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 : '';
+
+ const uploadCover = async () => {
+ const file = coverInput.current?.files?.[0];
+ const uploadUrl = bootstrap.media?.uploadUrl?.image;
+ if (!file || !uploadUrl) {
+ 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 = '';
+ }
+ }
+ };
+
+ return (
+
+ {__('发布设置', 'jio')}
+
+ {canEditCover && (
+
+
+
{__('添加封面', 'jio')}
+
{__('用于列表卡片、分享卡片;不设置时自动使用正文首图。', 'jio')}
+
+
+ {coverUrl ? (
+ <>
+
+
+ >
+ ) : (
+
+ )}
+
void uploadCover()}
+ />
+
+
+ )}
+
+ {error && {error}
}
+
+
+
+
{__('定时发布', 'jio')}
+
+ {canSchedule
+ ? __('开启后到点自动发布,发布前不会出现在文章列表。', 'jio')
+ : __('当前账号提交后需要审核,审核通过后才会发布。', 'jio')}
+
+
+
+
+
+ {canSchedule && scheduleEnabled && (
+
+
+
+ {sprintf(
+ /* translators: %s: site timezone */
+ __('按站点时区(%s)发布,至少需要晚于当前时间 1 分钟。', 'jio'),
+ String(bootstrap.timezone || 'UTC')
+ )}
+
+
+ )}
+
+ );
+}
diff --git a/assets/creator-studio/src/index.tsx b/assets/creator-studio/src/index.tsx
index 8d9a22a6..2f237bcd 100644
--- a/assets/creator-studio/src/index.tsx
+++ b/assets/creator-studio/src/index.tsx
@@ -8,13 +8,13 @@
*/
import { createRoot, useCallback, useEffect, useMemo, useRef, useState } from '@wordpress/element';
-import { __ } from '@wordpress/i18n';
+import { __, sprintf } from '@wordpress/i18n';
import { apiPost } from './services/api';
import { PublishDrawer } from './panels/publish-drawer';
-import { CoverStrip } from './components/cover-strip';
-import { AuthorRow } from './components/author-row';
import { EditorToolbar } from './components/editor-toolbar';
+import { PublishSettings } from './components/publish-settings';
+import { AuthorRow } from './components/author-row';
import { SaveState, type SaveStateValue } from './components/save-state';
import { useAutosave } from './hooks/use-autosave';
import { useLocalRecovery } from './hooks/use-local-recovery';
@@ -48,13 +48,15 @@ type Limits = {
pointsMax?: number;
};
+type Schedule = { enabled: boolean; at: string };
+
type Draft = {
postId: number;
versionId: number;
rev: number;
title: string;
- excerpt: string;
content: string;
+ schedule: Schedule;
categories: number[];
tags: string[];
custom: Record;
@@ -71,8 +73,8 @@ function initialDraft(): Draft {
versionId: Number(bootstrap.versionId || 0),
rev: Number(bootstrap.versionRev || 0),
title: String(bootstrap.title || ''),
- excerpt: String(bootstrap.excerpt || ''),
content: String(bootstrap.content || ''),
+ schedule: { enabled: false, at: '' },
categories: selected.map(Number),
tags: tags.slice(),
custom: bootstrap.custom || {},
@@ -191,12 +193,15 @@ function Studio(): JSX.Element {
version_id: current.versionId,
rev: current.rev,
title: current.title,
- excerpt: current.excerpt,
content: current.content,
categories: current.categories,
tags: current.tags,
custom: current.custom,
featured: current.featured,
+ schedule: {
+ enabled: !!current.schedule.enabled,
+ at: current.schedule.enabled ? current.schedule.at : '',
+ },
pay: normalizePayForRequest(current.pay),
...extra,
};
@@ -613,12 +618,7 @@ function Studio(): JSX.Element {
)}
- setDrawerOpen(true)}
- onClear={() => patchDraft({ featured: { type: '', data: {} } })}
- />
+
-
-
-
-
-
-
+ patchDraft({ featured })}
+ onScheduleChange={(enabled, at) => patchDraft({ schedule: { enabled, at } })}
+ />
+
+
+
{drawerOpen && (
; 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;
- 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(null);
const fileInput = useRef(null);
const captchaSlot = useRef(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) {
)}
-
- {__('封面', 'jio')}
- {draft.featured?.data?.url ? (
-
-
})
-
-
- ) : capabilities.canUploadImage ? (
-
- ) : (
- {__('当前账号不能设置封面。', 'jio')}
- )}
-
-
{__('分类', 'jio')}
diff --git a/assets/creator-studio/src/styles/_tokens.scss b/assets/creator-studio/src/styles/_tokens.scss
index 0d594525..67f2a025 100644
--- a/assets/creator-studio/src/styles/_tokens.scss
+++ b/assets/creator-studio/src/styles/_tokens.scss
@@ -1,7 +1,7 @@
-$ink: #243330;
-$ink-soft: #5c6b66;
-$paper: #fafbfa;
-$line: #e2e9e5;
+$ink: #2b2b2b;
+$ink-soft: #7d8683;
+$paper: #f6f6f6;
+$line: #e6e9e8;
$accent: #267665;
$accent-strong: #1d5f52;
$warn: #b4573f;
diff --git a/assets/creator-studio/src/styles/studio.scss b/assets/creator-studio/src/styles/studio.scss
index 86fa4440..2d6029b6 100644
--- a/assets/creator-studio/src/styles/studio.scss
+++ b/assets/creator-studio/src/styles/studio.scss
@@ -1,8 +1,8 @@
/**
* Jio Creator Studio — 沉浸式写作工作台。
*
- * 视觉方向:纸面写作而不是后台配置。单一深青绿用于“保存/发布”这类推进动作,
- * 其余保持低对比;发布设置全部收进抽屉,正文区域只有标题、摘要与画布。
+ * 视觉方向:浅灰页面 + 居中白纸。写作卡片居中并承担主要视觉重量,
+ * 高频操作固定在顶栏,封面与定时发布收在正文下方的「发布设置」卡片里。
*/
@use './tokens' as *;
@@ -14,7 +14,7 @@
* 只在投稿模板的 body class 下生效,不影响其他页面。
*/
.jio-page-submit {
- background: $paper;
+ background: #f6f6f6;
}
/* 主题固定导航会给 body.nav-fixed 预留 88px;工作台隐藏了导航,不应保留空位。 */
@@ -43,7 +43,7 @@ body.jio-page-submit.has-static-nav {
.jio-creator {
--jc-ink: #{$ink};
--jc-ink-soft: #{$ink-soft};
- --jc-paper: #{$paper};
+ --jc-paper: #f6f6f6;
--jc-line: #{$line};
--jc-accent: #{$accent};
--jc-accent-strong: #{$accent-strong};
@@ -373,78 +373,57 @@ body.jio-page-submit.has-static-nav {
}
.jio-creator__canvas {
- /* 公众号式阅读宽度:正文行宽控制在约 40 个汉字,留白优先。 */
- width: min(720px, 100%);
- margin: 0 auto;
- padding: clamp(20px, 4vw, 44px) clamp(20px, 5vw, 52px) 140px;
+ /* 居中白纸:正文行宽固定,页面底色是浅灰,卡片本身承担视觉重量。 */
+ width: min(900px, calc(100% - clamp(24px, 6vw, 72px)));
+ margin: 40px auto 0;
+ padding: clamp(30px, 4vw, 50px) clamp(28px, 5vw, 56px) clamp(36px, 5vw, 56px);
+ border-radius: 4px;
+ background: #fff;
+ box-shadow: 0 1px 2px rgba(24, 39, 34, 0.04), 0 8px 28px rgba(24, 39, 34, 0.05);
}
.jio-creator__title {
display: block;
- margin-bottom: 6px;
+ margin-bottom: 0;
textarea {
width: 100%;
- min-height: 50px;
- padding: 0;
+ min-height: 46px;
+ padding: 0 0 16px;
border: 0;
+ border-bottom: 1px solid #eef0ef;
background: transparent;
- color: var(--jc-ink);
- font-family: "Songti SC", "Noto Serif SC", "Source Han Serif SC", serif;
- font-size: clamp(23px, 2.6vw, 27px);
- font-weight: 500;
+ color: #2b2b2b;
+ font-family: inherit;
+ font-size: clamp(26px, 3vw, 32px);
+ font-weight: 700;
letter-spacing: 0.01em;
- line-height: 1.4;
+ line-height: 1.35;
resize: none;
&:focus {
outline: 0;
+ border-bottom-color: #dfe3e1;
}
&::placeholder {
- color: #b7c2bd;
- }
- }
-}
-
-.jio-creator__excerpt {
- display: block;
- margin-bottom: 22px;
-
- > span {
- display: block;
- margin-bottom: 4px;
- color: #9aa8a2;
- font-size: 12px;
- letter-spacing: 0.02em;
- }
-
- textarea {
- width: 100%;
- padding: 6px 0;
- border: 0;
- background: transparent;
- color: var(--jc-ink-soft);
- font-family: inherit;
- font-size: 14px;
- line-height: 1.7;
- resize: none;
-
- &:focus {
- outline: 0;
+ color: #c3c7c5;
+ font-weight: 700;
}
}
}
.jio-creator__editor {
position: relative;
- min-height: 50vh;
- margin: 12px 0 30px;
+ min-height: 52vh;
+ margin: 22px 0 0;
.wp-editor-tabs,
.wp-media-buttons,
.quicktags-toolbar,
- .mce-top-part {
+ .mce-top-part,
+ .tox .tox-editor-header,
+ .tox .tox-statusbar {
display: none !important;
}
@@ -455,12 +434,6 @@ body.jio-page-submit.has-static-nav {
box-shadow: none;
}
- .mce-top-part,
- .tox .tox-editor-header,
- .tox .tox-statusbar {
- display: none !important;
- }
-
.mce-tinymce,
.tox-tinymce {
border: 0 !important;
@@ -477,76 +450,134 @@ body.jio-page-submit.has-static-nav {
.mce-edit-area iframe,
.tox .tox-edit-area__iframe {
- min-height: 55vh;
+ min-height: 52vh;
}
textarea {
width: 100%;
- min-height: 55vh;
+ min-height: 52vh;
padding: 0;
border: 0;
background: transparent;
- color: var(--jc-ink);
+ color: #2b2b2b;
font: inherit;
font-size: 16px;
- line-height: 1.85;
+ line-height: 1.8;
resize: vertical;
- }
-}
-.jio-creator__footer {
- display: flex;
- justify-content: space-between;
- padding-top: 20px;
- border-top: 1px solid var(--jc-line);
- color: var(--jc-ink-soft);
- font-size: 12px;
-}
-
-/* ---------- 封面预览条 ---------- */
-
-.jio-creator__cover {
- position: relative;
- margin-bottom: 18px;
-
- &.is-empty {
- display: inline-flex;
- align-items: center;
- gap: 7px;
- min-height: 32px;
- padding: 0 12px;
- border: 1px dashed #d3ded8;
- border-radius: 8px;
- background: transparent;
- color: #8c9a94;
- font-size: 12px;
- cursor: pointer;
- transition: border-color 0.16s ease, color 0.16s ease;
-
- &:hover,
- &:focus-visible {
- border-color: var(--jc-accent);
- color: var(--jc-accent-strong);
- outline: 0;
+ &::placeholder {
+ color: #b9bfbc;
}
}
}
-.jio-creator__cover-thumb {
- position: relative;
+/* ---------- 发布设置卡片 ---------- */
+
+.jio-creator__settings {
+ width: min(900px, calc(100% - clamp(24px, 6vw, 72px)));
+ margin: 20px auto 0;
+ padding: clamp(20px, 3vw, 28px) clamp(24px, 4vw, 40px);
+ border-radius: 4px;
+ background: #fff;
+ box-shadow: 0 1px 2px rgba(24, 39, 34, 0.04), 0 8px 28px rgba(24, 39, 34, 0.05);
+}
+
+.jio-creator__settings-title {
+ margin: 0 0 4px;
+ color: #2b2b2b;
+ font-size: 15px;
+ font-weight: 600;
+}
+
+.jio-creator__setting-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 20px;
+ padding: 16px 0;
+ border-bottom: 1px solid #f2f4f3;
+
+ &:last-of-type {
+ border-bottom: 0;
+ }
+}
+
+.jio-creator__setting-copy {
+ min-width: 0;
+}
+
+.jio-creator__setting-label {
display: block;
- width: 100%;
+ color: #2b2b2b;
+ font-size: 14px;
+ font-weight: 500;
+}
+
+.jio-creator__setting-help {
+ margin: 4px 0 0;
+ color: #9aa2a0;
+ font-size: 12px;
+ line-height: 1.6;
+}
+
+.jio-creator__cover-control {
+ position: relative;
+ display: flex;
+ flex: 0 0 auto;
+ align-items: center;
+ 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;
+ gap: 7px;
+ min-height: 34px;
+ padding: 0 14px;
+ border: 1px dashed #d8dedb;
+ border-radius: 6px;
+ background: transparent;
+ color: #7c8683;
+ font-size: 13px;
+ cursor: pointer;
+
+ &:hover:not(:disabled),
+ &:focus-visible:not(:disabled) {
+ border-color: var(--jc-accent);
+ color: var(--jc-accent-strong);
+ outline: 0;
+ }
+
+ &:disabled {
+ opacity: 0.6;
+ cursor: default;
+ }
+}
+
+.jio-creator__cover-preview {
+ display: block;
+ width: 112px;
+ height: 63px;
padding: 0;
overflow: hidden;
border: 0;
- border-radius: 10px;
- background: #eef3f0;
+ border-radius: 6px;
+ background: #eef1f0;
cursor: pointer;
img {
display: block;
width: 100%;
- aspect-ratio: 2.35 / 1;
+ height: 100%;
object-fit: cover;
}
@@ -556,45 +587,67 @@ body.jio-page-submit.has-static-nav {
}
}
-.jio-creator__cover-edit {
- position: absolute;
- inset: auto 0 0 0;
- display: flex;
+.jio-creator__cover-clear {
+ display: inline-flex;
+ width: 26px;
+ height: 26px;
align-items: center;
justify-content: center;
- gap: 6px;
- padding: 8px;
- background: linear-gradient(to top, rgba(15, 25, 22, 0.62), rgba(15, 25, 22, 0));
- color: #fff;
- font-size: 12px;
- opacity: 0;
- transition: opacity 0.16s ease;
-}
-
-.jio-creator__cover-thumb:hover .jio-creator__cover-edit,
-.jio-creator__cover-thumb:focus-visible .jio-creator__cover-edit {
- opacity: 1;
-}
-
-.jio-creator__cover-clear {
- position: absolute;
- top: 8px;
- right: 8px;
- width: 28px;
- height: 28px;
border: 0;
border-radius: 50%;
- background: rgba(15, 25, 22, 0.55);
- color: #fff;
+ background: transparent;
+ color: #98a19e;
cursor: pointer;
&:hover,
&:focus-visible {
- background: rgba(15, 25, 22, 0.78);
+ background: #f3f5f4;
+ color: var(--jc-warn);
outline: 0;
}
}
+.jio-creator__schedule {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 12px;
+ padding: 4px 0 18px;
+
+ label {
+ display: inline-flex;
+ align-items: center;
+ gap: 10px;
+ color: #6f7875;
+ font-size: 13px;
+ }
+
+ input[type="datetime-local"] {
+ height: 36px;
+ padding: 0 10px;
+ border: 1px solid #e3e7e5;
+ border-radius: 6px;
+ background: #fff;
+ color: #2b2b2b;
+ font: inherit;
+ font-size: 13px;
+ }
+
+ .jio-creator-muted {
+ flex: 1 1 100%;
+ }
+}
+
+.jio-creator__footer {
+ display: flex;
+ justify-content: space-between;
+ width: min(900px, calc(100% - clamp(24px, 6vw, 72px)));
+ margin: 16px auto 0;
+ padding: 0 4px 140px;
+ color: #98a19e;
+ font-size: 12px;
+}
+
/* ---------- 作者行 ---------- */
.jio-creator__author {
@@ -728,13 +781,30 @@ body.jio-page-submit.has-static-nav {
}
.jio-creator__canvas {
- padding: 20px 16px calc(120px + env(safe-area-inset-bottom));
+ width: calc(100% - 20px);
+ margin: 14px auto 0;
+ padding: 22px 18px 28px;
+ }
+
+ .jio-creator__settings {
+ width: calc(100% - 20px);
+ margin-top: 12px;
+ padding: 18px;
+ }
+
+ .jio-creator__setting-row {
+ gap: 12px;
}
.jio-creator__title textarea {
font-size: 24px;
}
+ .jio-creator__footer {
+ width: calc(100% - 20px);
+ padding-bottom: calc(120px + env(safe-area-inset-bottom));
+ }
+
.jio-creator__editor .mce-edit-area iframe,
.jio-creator__editor .tox .tox-edit-area__iframe {
min-height: 48vh;
diff --git a/src/Admin/Schema/SchemaPostList.php b/src/Admin/Schema/SchemaPostList.php
index 4cdc77b5..5cb8c30f 100644
--- a/src/Admin/Schema/SchemaPostList.php
+++ b/src/Admin/Schema/SchemaPostList.php
@@ -267,7 +267,7 @@ class SchemaPostList {
['key' => 'post_article_custom_filter_s', 'label' => '允许选择高级筛选', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'post_article_s', 'value' => true], 'description' => '此功能启用后,请先在文章列表/高级筛选中添加高级筛选明细'],
['key' => 'post_article_tag', 'label' => '允许插入标签', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'post_article_s', 'value' => true], 'description' => '前台投稿时候允许设置文章标签'],
['key' => 'post_article_user', 'label' => '免登陆投稿发布用户', 'type' => 'user_select', 'default' => 1, 'dependsOn' => ['key' => 'post_article_s', 'value' => true], 'description' => '当选择投稿权限为无需登录就能投稿时,投稿文章的用户'],
- ['key' => 'post_article_title_strlen_limit', 'label' => '标题字数限制', 'type' => 'between_number', 'default' => ['min' => 5, 'max' => 30], 'unit' => '字', 'description' => '限制标题字数可有效的防止灌水等无意义内容(英文字符按0.5个字计算)'],
+ ['key' => 'post_article_title_strlen_limit', 'label' => '标题字数限制', 'type' => 'between_number', 'default' => ['min' => 5, 'max' => 100], 'unit' => '字', 'description' => '限制标题字数可有效的防止灌水等无意义内容(英文字符按0.5个字计算)'],
['key' => 'post_article_pay_free_s', 'label' => '允许设置为免费资源', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'post_article_s', 'value' => true], 'description' => '付费内容金额允许设置为 0'],
['key' => 'post_article_pay_price_limit', 'label' => '付费内容金额限制', 'type' => 'fieldset', 'default' => ['price' => ['min' => 0, 'max' => 99999], 'points' => ['min' => 0, 'max' => 0]], 'description' => '限制用户允许设置的金额,防止金额过高不合理(填0为不限制)', 'fields' => [
['key' => 'price', 'label' => '现金金额限制', 'type' => 'between_number', 'default' => ['min' => 0, 'max' => 99999]],
@@ -276,8 +276,8 @@ class SchemaPostList {
['key' => 'post_article_pay_vip_price_s', 'label' => '付费内容允许设置会员价', 'type' => 'switcher', 'default' => true, 'dependsOn' => ['key' => 'post_article_s', 'value' => true], 'description' => '前台投稿时对拥有设置付费内容权限的用户,是否开启设置会员价格。开启此项,会直接在前台显示设置会员价的选项;关闭此项,则用户只能设置普通价格,会员价则按照下方设置的折扣自动计算'],
['key' => 'post_article_pay_vip_1_discount', 'label' => '一级会员折扣', 'type' => 'number', 'default' => 100, 'min' => 0, 'max' => 100, 'unit' => '%', 'dependsOn' => ['all' => [['key' => 'post_article_s', 'value' => true], ['key' => 'post_article_pay_vip_price_s', 'value' => false]]]],
['key' => 'post_article_pay_vip_2_discount', 'label' => '二级会员折扣', 'type' => 'number', 'default' => 100, 'min' => 0, 'max' => 100, 'unit' => '%', 'dependsOn' => ['all' => [['key' => 'post_article_s', 'value' => true], ['key' => 'post_article_pay_vip_price_s', 'value' => false]]], 'description' => '执行价的百分之多少,0为免费,100为没有折扣,不能高于100'],
- ['key' => 'post_t_placeholder', 'label' => '投稿标题占位符', 'type' => 'input', 'default' => '请输入标题'],
- ['key' => 'post_c_placeholder', 'label' => '投稿内容占位符', 'type' => 'input', 'default' => '请输入内容'],
+ ['key' => 'post_t_placeholder', 'label' => '投稿标题占位符', 'type' => 'input', 'default' => '请输入标题(最多 100 个字)'],
+ ['key' => 'post_c_placeholder', 'label' => '投稿内容占位符', 'type' => 'input', 'default' => '请输入正文'],
]],
],
],
diff --git a/src/Core/CreatorRest.php b/src/Core/CreatorRest.php
index 4eca3e6a..18d75251 100644
--- a/src/Core/CreatorRest.php
+++ b/src/Core/CreatorRest.php
@@ -187,11 +187,11 @@ final class CreatorRest {
$payload = [
'title' => (string) $request->get_param('title'),
'content' => (string) $request->get_param('content'),
- 'excerpt' => (string) $request->get_param('excerpt'),
'categories' => (array) $request->get_param('categories'),
'tags' => (array) $request->get_param('tags'),
'custom' => (array) $request->get_param('custom'),
'featured' => (array) $request->get_param('featured'),
+ 'schedule' => (array) $request->get_param('schedule'),
'pay' => (array) $request->get_param('pay'),
];
@@ -199,7 +199,6 @@ final class CreatorRest {
$result = SubmissionVersion::get_instance()->save_working($post_id, $user_id, [
'title' => $payload['title'] !== '' ? $payload['title'] : null,
'content' => $payload['content'],
- 'excerpt' => $payload['excerpt'],
'base_rev' => absint($request->get_param('rev')),
'snapshot' => $this->snapshot_from_payload($payload),
], false);
@@ -215,10 +214,10 @@ final class CreatorRest {
'posts_id' => $post_id,
'post_title' => $payload['title'],
'post_content' => $payload['content'],
- 'excerpt' => $payload['excerpt'],
'category' => $payload['categories'],
'tags' => implode(',', array_map('strval', $payload['tags'])),
'featured_data'=> $payload['featured'],
+ 'schedule' => $payload['schedule'],
];
foreach ($payload['custom'] as $key => $value) {
$data['cf_' . sanitize_key((string) $key)] = $value;
@@ -259,11 +258,11 @@ final class CreatorRest {
$payload = [
'title' => (string) $request->get_param('title'),
'content' => (string) $request->get_param('content'),
- 'excerpt' => (string) $request->get_param('excerpt'),
'categories' => (array) $request->get_param('categories'),
'tags' => (array) $request->get_param('tags'),
'custom' => (array) $request->get_param('custom'),
'featured' => (array) $request->get_param('featured'),
+ 'schedule' => (array) $request->get_param('schedule'),
'pay' => (array) $request->get_param('pay'),
];
@@ -275,7 +274,6 @@ final class CreatorRest {
$version = SubmissionVersion::get_instance()->save_working($post_id, $user_id, [
'title' => $payload['title'],
'content' => $payload['content'],
- 'excerpt' => $payload['excerpt'],
'base_rev' => absint($request->get_param('rev')),
'snapshot' => $this->snapshot_from_payload($payload),
], true);
@@ -299,10 +297,10 @@ final class CreatorRest {
'posts_id' => $post_id,
'post_title' => $payload['title'],
'post_content' => $payload['content'],
- 'excerpt' => $payload['excerpt'],
'category' => $payload['categories'],
'tags' => implode(',', array_map('strval', $payload['tags'])),
'featured_data' => $payload['featured'],
+ 'schedule' => $payload['schedule'],
];
foreach ($payload['custom'] as $key => $value) {
$data['cf_' . sanitize_key((string) $key)] = $value;
@@ -691,6 +689,8 @@ final class CreatorRest {
'canPay' => $cap('new_post_pay'),
'canPayDownload' => $cap('new_post_pay_download'),
'canPublishNow' => $cap('new_post_audit_no'),
+ // 定时发布只有能直接发布的账号可用;其余账号提交后仍走审核队列。
+ 'canSchedule' => $cap('new_post_audit_no'),
'canEdit' => $post_id > 0 ? $front->can_edit_post($post_id, $user_id) : $front->can_submit($user_id),
'isLoggedIn' => $user_id > 0,
];
diff --git a/src/Core/CreatorStudio.php b/src/Core/CreatorStudio.php
index 3bf7f6f8..a5ab5296 100644
--- a/src/Core/CreatorStudio.php
+++ b/src/Core/CreatorStudio.php
@@ -215,6 +215,8 @@ final class CreatorStudio {
'root' => rest_url(),
'ajax' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wp_rest'),
+ // 定时发布按站点时区解释;文案里显示给作者,避免 UTC 误解。
+ 'timezone' => (string) wp_timezone_string(),
'captcha' => [
'enabled' => function_exists('jio_is_captcha_enabled_for') && jio_is_captcha_enabled_for('front_submit'),
],
diff --git a/src/Core/FrontSubmit.php b/src/Core/FrontSubmit.php
index 88ebf4be..186857a6 100644
--- a/src/Core/FrontSubmit.php
+++ b/src/Core/FrontSubmit.php
@@ -245,9 +245,9 @@ class FrontSubmit {
'enabled' => true,
'btn_text' => '发布文章',
'title_min' => 5,
- 'title_max' => 30,
- 'title_placeholder' => '请输入标题',
- 'content_placeholder' => '请输入内容',
+ 'title_max' => 100,
+ 'title_placeholder' => '请输入标题(最多 100 个字)',
+ 'content_placeholder' => '请输入正文',
'allowed_cat_ids' => [],
'default_user_id' => 1,
'allow_tags' => true,
diff --git a/src/Core/FrontSubmitSave.php b/src/Core/FrontSubmitSave.php
index aed3bba2..b295169a 100644
--- a/src/Core/FrontSubmitSave.php
+++ b/src/Core/FrontSubmitSave.php
@@ -134,8 +134,17 @@ trait FrontSubmitSave {
}
$status = 'draft';
+ $schedule_at = '';
if (!$is_draft) {
$status = $this->resolve_publish_status($user_id);
+ if ($status === 'publish') {
+ // 定时发布:只有能直接发布的账号才排期,否则仍走审核队列。
+ $schedule = $this->normalize_schedule($data);
+ if ($schedule !== '') {
+ $schedule_at = $schedule;
+ $status = 'future';
+ }
+ }
}
// Paid fields are validated before anything is written, so an invalid
@@ -161,6 +170,11 @@ trait FrontSubmitSave {
'post_status' => $status,
'comment_status' => 'open',
];
+ if ($schedule_at !== '') {
+ // WordPress 按 post_date 到点把 future 转成 publish。
+ $postarr['post_date'] = $schedule_at;
+ $postarr['post_date_gmt'] = get_gmt_from_date($schedule_at);
+ }
if ($excerpt !== '' || array_key_exists('excerpt', $data) || array_key_exists('post_excerpt', $data)) {
$postarr['post_excerpt'] = $excerpt;
}
@@ -223,6 +237,18 @@ trait FrontSubmitSave {
];
switch ($status) {
+ case 'future':
+ $send['message'] = sprintf(
+ /* translators: %s: scheduled publish time */
+ __('文章已排期,将在 %s 发布', 'jio'),
+ $schedule_at
+ );
+ $send['scheduled_at'] = $schedule_at;
+ if ($user_id > 0 && function_exists('jio_get_user_home_url')) {
+ $send['reload'] = true;
+ $send['goto'] = jio_get_user_home_url($user_id);
+ }
+ break;
case 'pending':
$send['message'] = __('内容已提交,正在等待审核', 'jio');
if ($user_id > 0 && function_exists('jio_get_user_home_url')) {
@@ -247,6 +273,39 @@ trait FrontSubmitSave {
return $send;
}
+ /**
+ * 解析定时发布时间(站点本地时间 Y-m-d H:i:s);未开启或不合法时返回空串。
+ *
+ * @param array
$data
+ */
+ private function normalize_schedule(array $data): string {
+ $schedule = $data['schedule'] ?? null;
+ if (!is_array($schedule) || empty($schedule['enabled'])) {
+ return '';
+ }
+ $raw = trim((string) ($schedule['at'] ?? ''));
+ if ($raw === '') {
+ return '';
+ }
+ // datetime-local 提交 Y-m-d\TH:i(部分浏览器带秒);统一成站点本地时间。
+ $normalized = str_replace('T', ' ', $raw);
+ if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $normalized) === 1) {
+ $normalized .= ':00';
+ }
+ $timezone = wp_timezone();
+ $scheduled = \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $normalized, $timezone);
+ $errors = \DateTimeImmutable::getLastErrors();
+ if (!$scheduled instanceof \DateTimeImmutable || (is_array($errors) && (int) $errors['warning_count'] > 0)) {
+ return '';
+ }
+ // 至少晚于当前时间 1 分钟,避免"排期到过去"被 WordPress 立即发布。
+ $threshold = new \DateTimeImmutable('now', $timezone);
+ if ($scheduled->getTimestamp() < $threshold->getTimestamp() + MINUTE_IN_SECONDS) {
+ return '';
+ }
+ return $scheduled->format('Y-m-d H:i:s');
+ }
+
/**
* Publish status for a non-draft submission.
*
diff --git a/src/Settings/PostDisplay.php b/src/Settings/PostDisplay.php
index 658af72c..9c3af265 100644
--- a/src/Settings/PostDisplay.php
+++ b/src/Settings/PostDisplay.php
@@ -351,7 +351,7 @@ class PostDisplay {
? $settings['post_article_title_strlen_limit']
: [];
$title_min = max(1, min(100, (int) ($title_limit['min'] ?? 5)));
- $title_max = max(5, min(200, (int) ($title_limit['max'] ?? 30)));
+ $title_max = max(5, min(200, (int) ($title_limit['max'] ?? 100)));
if ($title_max < $title_min) {
$title_max = $title_min;
}
@@ -368,8 +368,8 @@ class PostDisplay {
'btn_text' => sanitize_text_field((string) ($settings['post_article_btn_txte'] ?? '')) ?: __('发布文章', 'jio'),
'title_min' => $title_min,
'title_max' => $title_max,
- 'title_placeholder' => sanitize_text_field((string) ($settings['post_t_placeholder'] ?? '')) ?: __('请输入标题', 'jio'),
- 'content_placeholder' => sanitize_textarea_field((string) ($settings['post_c_placeholder'] ?? '')) ?: __('请输入内容', 'jio'),
+ 'title_placeholder' => sanitize_text_field((string) ($settings['post_t_placeholder'] ?? '')) ?: __('请输入标题(最多 100 个字)', 'jio'),
+ 'content_placeholder' => sanitize_textarea_field((string) ($settings['post_c_placeholder'] ?? '')) ?: __('请输入正文', 'jio'),
'allowed_cat_ids' => is_array($settings['post_article_cat'] ?? null) ? array_values(array_filter(array_map('intval', $settings['post_article_cat']))) : [],
'default_user_id' => max(0, (int) ($settings['post_article_user'] ?? 1)),
'allow_tags' => !isset($settings['post_article_tag']) || !empty($settings['post_article_tag']),
diff --git a/tests/admin/submit-settings-reference-contract.test.cjs b/tests/admin/submit-settings-reference-contract.test.cjs
index b1937ddb..a3881a73 100644
--- a/tests/admin/submit-settings-reference-contract.test.cjs
+++ b/tests/admin/submit-settings-reference-contract.test.cjs
@@ -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*\}/);
});
diff --git a/tests/widget-system/creator-studio-contract.test.cjs b/tests/widget-system/creator-studio-contract.test.cjs
index c836673d..35aae6f2 100644
--- a/tests/widget-system/creator-studio-contract.test.cjs
+++ b/tests/widget-system/creator-studio-contract.test.cjs
@@ -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, / {
+ 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, / {
+ 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', () => {