refactor(creator-studio): move taxonomy to the settings card, slim the drawer to pay
Classification belongs next to everything else the author decides before publishing, and the drawer should only configure paid resources. - PublishSettings now renders categories, tags and custom taxonomy dimensions first, then cover, paid content and scheduling. Chips use a stacked row layout so long category lists wrap naturally. - PublishDrawer keeps only PayPanel: taxonomy, save/publish buttons and the now-unused props are gone, leaving a single 完成 button. - New PublishDialog takes over the publish action from the bottom bar, and with it the captcha mount point, so the gate still renders somewhere the author can see it. - Promotes .jio-creator-primary / .jio-creator-ghost out of the dialog-only rules (drawer and pay panel buttons had no styling), and drops the dead .jio-creator-field / .jio-creator-cover blocks. Contracts updated; 886 widget-system tests pass.
This commit is contained in:
1 parent
ac84e991d1
commit
f97fd72bd0
11 files changed
+448
-322
No files matched your search
@@ -1 +1 @@
|
||||
<?php return array('dependencies' => array('react', 'wp-element', 'wp-i18n'), 'version' => '099f95cc60dffc7455f7');
|
||||
<?php return array('dependencies' => array('react', 'wp-element', 'wp-i18n'), 'version' => '16333cda79ebcc6962cd');
|
||||
@@ -1 +1 @@
|
||||
.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-top:112px;--jc-status:52px;-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-bottom:var(--jc-status);padding-top:var(--jc-top)}.jio-creator *,.jio-creator :after,.jio-creator :before{box-sizing:border-box}.jio-creator button{color:inherit;font:inherit}.jio-creator__top{background:rgba(250,251,250,.98);box-shadow:0 2px 8px rgba(27,46,39,.035);left:0;position:fixed;right:0;top:0;z-index:300}.jio-creator__masthead{align-items:center;display:flex;gap:16px;height:56px;justify-content:space-between;padding:0 clamp(14px,2.4vw,30px)}.jio-creator__masthead-left{align-items:center;display:flex;gap:10px;min-width:0}.jio-creator__back{align-items:center;border-radius:7px;color:var(--jc-ink-soft);display:inline-flex;flex:0 0 auto;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__brand{align-items:center;color:inherit;display:inline-flex;min-width:0;text-decoration:none}.jio-creator__brand:focus-visible{outline:2px solid rgba(38,118,101,.35);outline-offset:4px}.jio-creator__brand-logo{display:block;height:30px;max-width:168px;-o-object-fit:contain;object-fit:contain;width:auto}.jio-creator__brand-text{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:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jio-creator__me{align-items:center;border-radius:50%;display:inline-flex;flex:0 0 auto;justify-content:center}.jio-creator__me:focus-visible{outline:2px solid rgba(38,118,101,.5);outline-offset:2px}.jio-creator__me-avatar{background:#eef1f0;border:1px solid rgba(24,39,34,.08);border-radius:50%;display:block;height:32px;-o-object-fit:cover;object-fit:cover;overflow:hidden;width:32px}.jio-creator__me-avatar.is-placeholder{align-items:center;color:#9aa2a0;display:inline-flex;font-size:13px;justify-content:center}.jio-creator__bar{align-items:center;border-bottom:1px solid var(--jc-line);border-top:1px solid var(--jc-line);display:flex;height:56px;justify-content:center;justify-content:safe center;padding:0 clamp(14px,2.4vw,30px)}.jio-creator__toolbar-tools{align-items:center;display:flex;gap:7px;max-width:100%;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:6px;color:#5f6664;cursor:pointer;display:inline-flex;flex:0 0 auto;flex-direction:column;font-size:11px;gap:2px;height:46px;justify-content:center;line-height:1.2;min-width:40px;padding:5px 6px;width:auto}.jio-creator__tool-btn i{font-size:14px;line-height:1}.jio-creator__tool-btn:focus-visible:not(:disabled),.jio-creator__tool-btn:hover:not(:disabled){background:#f0f2f1;color:var(--jc-accent-strong);outline:0}.jio-creator__tool-btn.is-active:not(:disabled),.jio-creator__tool-btn.is-open:not(:disabled){background:#e9f1ee;color:var(--jc-accent-strong)}.jio-creator__tool-btn:disabled{color:#c7d0cc;cursor:default}.jio-creator__tool-label{max-width:52px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jio-creator__tool-caret{bottom:4px;color:#b0b9b6;font-size:8px;line-height:1;position:absolute;right:3px}.jio-creator__tool-menu{display:inline-flex;flex:0 0 auto;position:relative}.jio-creator__tool-menu .jio-creator__tool-btn{position:relative}.jio-creator__menu{animation:jio-menu-in .12s ease-out;background:#fff;border:1px solid rgba(24,39,34,.06);border-radius:12px;box-shadow:0 14px 40px rgba(20,32,28,.16),0 2px 6px rgba(20,32,28,.06);display:flex;flex-direction:column;gap:2px;padding:6px;position:fixed;z-index:620}.jio-creator__menu.is-top{animation-name:jio-menu-in-up}@keyframes jio-menu-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes jio-menu-in-up{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.jio-creator__menu-item{align-items:center;background:transparent;border:0;border-radius:7px;color:#4Line truncated
|
||||
.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-top:112px;--jc-status:52px;-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-bottom:var(--jc-status);padding-top:var(--jc-top)}.jio-creator *,.jio-creator :after,.jio-creator :before{box-sizing:border-box}.jio-creator button{color:inherit;font:inherit}.jio-creator__top{background:rgba(250,251,250,.98);box-shadow:0 2px 8px rgba(27,46,39,.035);left:0;position:fixed;right:0;top:0;z-index:300}.jio-creator__masthead{align-items:center;display:flex;gap:16px;height:56px;justify-content:space-between;padding:0 clamp(14px,2.4vw,30px)}.jio-creator__masthead-left{align-items:center;display:flex;gap:10px;min-width:0}.jio-creator__back{align-items:center;border-radius:7px;color:var(--jc-ink-soft);display:inline-flex;flex:0 0 auto;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__brand{align-items:center;color:inherit;display:inline-flex;min-width:0;text-decoration:none}.jio-creator__brand:focus-visible{outline:2px solid rgba(38,118,101,.35);outline-offset:4px}.jio-creator__brand-logo{display:block;height:30px;max-width:168px;-o-object-fit:contain;object-fit:contain;width:auto}.jio-creator__brand-text{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:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jio-creator__me{align-items:center;border-radius:50%;display:inline-flex;flex:0 0 auto;justify-content:center}.jio-creator__me:focus-visible{outline:2px solid rgba(38,118,101,.5);outline-offset:2px}.jio-creator__me-avatar{background:#eef1f0;border:1px solid rgba(24,39,34,.08);border-radius:50%;display:block;height:32px;-o-object-fit:cover;object-fit:cover;overflow:hidden;width:32px}.jio-creator__me-avatar.is-placeholder{align-items:center;color:#9aa2a0;display:inline-flex;font-size:13px;justify-content:center}.jio-creator__bar{align-items:center;border-bottom:1px solid var(--jc-line);border-top:1px solid var(--jc-line);display:flex;height:56px;justify-content:center;justify-content:safe center;padding:0 clamp(14px,2.4vw,30px)}.jio-creator__toolbar-tools{align-items:center;display:flex;gap:7px;max-width:100%;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:6px;color:#5f6664;cursor:pointer;display:inline-flex;flex:0 0 auto;flex-direction:column;font-size:11px;gap:2px;height:46px;justify-content:center;line-height:1.2;min-width:40px;padding:5px 6px;width:auto}.jio-creator__tool-btn i{font-size:14px;line-height:1}.jio-creator__tool-btn:focus-visible:not(:disabled),.jio-creator__tool-btn:hover:not(:disabled){background:#f0f2f1;color:var(--jc-accent-strong);outline:0}.jio-creator__tool-btn.is-active:not(:disabled),.jio-creator__tool-btn.is-open:not(:disabled){background:#e9f1ee;color:var(--jc-accent-strong)}.jio-creator__tool-btn:disabled{color:#c7d0cc;cursor:default}.jio-creator__tool-label{max-width:52px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jio-creator__tool-caret{bottom:4px;color:#b0b9b6;font-size:8px;line-height:1;position:absolute;right:3px}.jio-creator__tool-menu{display:inline-flex;flex:0 0 auto;position:relative}.jio-creator__tool-menu .jio-creator__tool-btn{position:relative}.jio-creator__menu{animation:jio-menu-in .12s ease-out;background:#fff;border:1px solid rgba(24,39,34,.06);border-radius:12px;box-shadow:0 14px 40px rgba(20,32,28,.16),0 2px 6px rgba(20,32,28,.06);display:flex;flex-direction:column;gap:2px;padding:6px;position:fixed;z-index:620}.jio-creator__menu.is-top{animation-name:jio-menu-in-up}@keyframes jio-menu-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes jio-menu-in-up{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.jio-creator__menu-item{align-items:center;background:transparent;border:0;border-radius:7px;color:#4Line truncated
|
||||
@@ -1,10 +1,10 @@
|
||||
(()=>{"use strict";const e=window.React,t=window.wp.element,a=window.wp.i18n;function n(e,t){const a=e&&(e.message||e.error)||(401===t?"登录状态已失效,请刷新页面重新登录。":"请求失败,请稍后重试。"),n=new Error(String(a));return n.status=t,n.code=e&&e.code?String(e.code):"",n.data=e,n}async function o(e){try{return await e.json()}catch(e){return null}}async function r(e,t,a){const r=await fetch(e,{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","X-WP-Nonce":a},body:JSON.stringify(t)}),i=await o(r);if(!r.ok)throw n(i,r.status);return i}async function i(e,t,a,r={}){const i=new FormData;i.append("file",t),Object.entries(r).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 o(l);if(!l.ok)throw n(c,l.status);return c}const l={url:"",attachmentId:0,extractCode:"",copyKey:"",copyVal:"",label:"",class:""};function c({row:n,buttonClasses:o,onPickAttachment:r,onSubmit:i,onClose:c}){const[s,d]=(0,t.useState)(()=>n?{url:String(n.url||""),attachmentId:Number(n.attachmentId||0),extractCode:String(n.extractCode||""),copyKey:String(n.copyKey||""),copyVal:String(n.copyVal||""),label:String(n.label||""),class:String(n.class||"")}:{...l}),[u,m]=(0,t.useState)(""),p=(0,t.useRef)(null);(0,t.useEffect)(()=>{p.current?.focus();const e=e=>{"Escape"===e.key&&(e.preventDefault(),c())};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[c]);const _=e=>d(t=>({...t,...e}));return(0,e.createElement)("div",{className:"jio-creator-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"jio-creator-resource-title"},(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__backdrop","aria-label":(0,a.__)("关闭","jio"),onClick:c}),(0,e.createElement)("div",{className:"jio-creator-dialog__panel jio-creator-dialog__panel--wide"},(0,e.createElement)("header",{className:"jio-creator-dialog__head"},(0,e.createElement)("h2",{id:"jio-creator-resource-title"},n?(0,a.__)("编辑资源","jio"):(0,a.__)("添加资源","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__close",onClick:c,"aria-label":(0,a.__)("关闭","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))),(0,e.createElement)("div",{className:"jio-creator-dialog__body"},(0,e.createElement)("label",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("下载地址","jio")),(0,e.createElement)("div",{className:"jio-creator-dialog__url"},(0,e.createElement)("input",{ref:p,type:"url",value:s.url,placeholder:(0,a.__)("请输入资源下载地址","jio"),onChange:e=>_({url:e.target.value,attachmentId:0}),onPaste:e=>{const t=e.clipboardData?.getData("text")||"";if(!t)return;const n=t.match(/https?:\/\/\S+/i),o=t.match(/(?:提取码|密码)\s*[::]\s*([A-Za-z0-9]{4,8})/);if(!n&&!o)return;e.preventDefault();const r={attachmentId:0};n&&(r.url=n[0].replace(/[)\],。]+$/u,"")),o&&(r.extractCode=(0,a.sprintf)(/* translators: %s: extraction code */ /* translators: %s: extraction code */
|
||||
(0,a.__)("提取码:%s","jio"),o[1]),r.copyKey=(0,a.__)("提取码","jio"),r.copyVal=o[1]),_(r)}}),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__ghost",onClick:()=>r((e,t)=>_({url:e,attachmentId:t}))},(0,e.createElement)("i",{className:"fa fas fa-upload","aria-hidden":"true"})," ",(0,a.__)("上传附件","jio"))),(0,e.createElement)("span",{className:"jio-creator-dialog__hint"},(0,a.__)("支持直接粘贴网盘分享链接,会自动识别提取码。","jio"))),(0,e.createElement)("label",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("资源备注","jio")),(0,e.createElement)("input",{type:"text",value:s.extractCode,placeholder:(0,a.__)("例如提取码、解压密码等","jio"),onChange:e=>_({extractCode:e.target.value})})),(0,e.createElement)("div",{className:"jio-creator-dialog__row"},(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("复制名称","jio")),(0,e.createElement)("input",{type:"text",value:s.copyKey,placeholder:(0,a.__)("如:提取码","jio"),onChange:e=>_({copyKey:e.target.value})})),(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("复制内容","jio")),(0,e.createElement)("input",{type:"text",value:s.copyVal,placeholder:(0,a.__)("如:abcd","jio"),onChange:e=>_({copyVal:e.target.value})}))),(0,e.createElement)("span",{className:"jio-creator-dialog__hint"},(0,a.__)("填写后读者可点击按钮复制这段内容。","jio")),(0,e.createElement)("label",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("自定义按钮文案","jio")),(0,e.createElement)("input",{type:"text",value:s.label,placeholder:(0,a.__)("留空则按网盘自动识别","jio"),onChange:e=>_({label:e.target.value})})),(0,e.createElement)("div",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("按钮样式","jio")),(0,e.createElement)("div",{className:"jio-creator-swatches"},o.map(t=>(0,e.createElement)("button",{key:t||"default",type:"button",className:`jio-creator-swatch ${t||"b-theme"}${s.class===t?" is-active":""}`,onClick:()=>_({class:t}),title:t||(0,a.__)("默认样式","jio"),"aria-label":t||(0,a.__)("默认样式","jio"),"aria-pressed":s.class===t})))),u&&(0,e.createElement)("p",{className:"jio-creator-error"},u)),(0,e.createElement)("footer",{className:"jio-creator-dialog__foot"},(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__ghost",onClick:c},(0,a.__)("取消","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__primary",onClick:()=>{const e=function(e){const t=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""}}(s.url);if(!e)return void m((0,a.__)("请填写有效的下载地址","jio"));m("");const t=/pan\.baidu\.com|aliyundrive\.com|alipan\.com|pan\.quark\.cn|cloud\.189\.cn|115\.com|lanzou|weiyun|123pan/i.test(e);i({...n||{},type:t?"net_disk":"direct",url:e,attachmentId:Math.max(0,Number(s.attachmentId)||0),extractCode:s.extractCode.trim(),copyKey:s.copyKey.trim(),copyVal:s.copyVal.trim(),label:s.label.trim(),class:s.class})}},(0,a.__)("确认","jio")))))}const s=(e,t=0)=>{const a=Number(e);return Number.isFinite(a)?a:t};function d({pay:n,onChange:o,canDownload:r,privateStorage:i,privateUploads:l,bootstrap:d,onUploadPrivate:u,uploading:m,uploadError:p,onPickAttachment:_}){const[f,b]=(0,t.useState)(null),h=(0,t.useRef)(null),g=e=>o({...n,...e}),y="points"===n.modo,j=String(d.currencySymbol||"¥"),v=d.downloadClasses&&d.downloadClasses.length>0?d.downloadClasses:["","c-blue","b-blue","jb-blue"],E=n.downloads,k=e=>y?(0,a.sprintf)(/* translators: %s: VIP level name */ /* translators: %s: VIP level name */(0,a.__)("%s 积分","jio"),e):(0,a.sprintf)(/* translators: %s: VIP level name */ /* translators: %s: VIP level name */(0,a.__)("%s 价格","jio"),e),w=(t,a,n,o)=>{var r;return(0,e.createElement)("label",{className:"jio-creator-input"},(0,e.createElement)("span",null,t),(0,e.createElement)("span",{className:"jio-creator-price"},o.prefix&&(0,e.createElement)("em",null,o.prefix),(0,e.createElement)("input",{type:"number",min:null!==(r=o.min)&&void 0!==r?r:0,step:o.step,value:a,placeholder:o.placeholder,onChange:e=>n(e.target.value)}),o.suffix&&(0,e.createElement)("em",null,o.suffix)))};return(0,e.createElement)(e.Fragment,null,(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.enabled,onChange:e=>g({enabled:e.target.checked})}),(0,e.createElement)("span",{"aria-hidden":"true"}))),n.enabled&&(0Line truncated
|
||||
(0,a.__)("已开启,含 %d 个付费下载资源。","jio"),s.downloads.length):(0,a.__)("已开启,未购买读者只能看到免费部分。","jio"):(0,a.__)("开启后可以设置价格、会员价并添加付费下载资源。","jio")),s.enabled&&(0,e.createElement)("button",{type:"button",className:"jio-creator__setting-link",onClick:_},(0,e.createElement)("i",{className:"fa fas fa-coins","aria-hidden":"true"}),(0,a.__)("配置价格与付费资源","jio"))),(0,e.createElement)("label",{className:"jio-creator-toggle"},(0,e.createElement)("input",{type:"checkbox",checked:s.enabled,onChange:e=>{const t=e.target.checked;p(t),t&&_()}}),(0,e.createElement)("span",{"aria-hidden":"true"}))),(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"},r?(0,a.__)("开启后到点自动发布,发布前不会出现在文章列表。","jio"):(0,a.__)("当前账号提交后需要审核,审核通过后才会发布。","jio"))),(0,e.createElement)("label",{className:"jio-creator-toggle"},(0,e.createElement)("input",{type:"checkbox",checked:l,disabled:!r,onChange:e=>m(e.target.checked,c||E(new Date(Date.now()+36e5)))}),(0,e.createElement)("span",{"aria-hidden":"true"}))),r&&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:k,onChange:e=>m(!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(y.timezone||"UTC")))))}function w({centerUrl:t,site:n,viewer:o}){const r=String(n.name||""),i=String(o.avatar||""),l=t||"/";return(0,e.createElement)("header",{className:"jio-creator__masthead"},(0,e.createElement)("div",{className:"jio-creator__masthead-left"},(0,e.createElement)("a",{className:"jio-creator__back",href:t||"/","aria-label":(0,a.__)("返回作者中心","jio")},(0,e.createElement)("i",{className:"fa fas fa-angle-left","aria-hidden":"true"})),(0,e.createElement)("a",{className:"jio-creator__brand",href:String(n.home||"/"),"aria-label":r||(0,a.__)("返回首页","jio")},n.logo?(0,e.createElement)("img",{className:"jio-creator__brand-logo",src:String(n.logo),alt:r}):(0,e.createElement)("span",{className:"jio-creator__brand-text"},r))),(0,e.createElement)("a",{className:"jio-creator__me",href:l,"aria-label":(0,a.__)("返回作者中心","jio")},i?(0,e.createElement)("img",{className:"jio-creator__me-avatar",src:i,alt:"",width:32,height:32}):(0,e.createElement)("span",{className:"jio-creator__me-avatar is-placeholder","aria-hidden":"true"},(0,e.createElement)("i",{className:"fa fas fa-user"}))))}function N(e){const t=(e.downloads||[]).map(e=>{const t="string"==typeof e.label?e.label:"",a="string"==typeof e.assetKey?e.assetKey:"";if(a)return{type:"protected",asset_key:a,label:t};const n="string"==typeof e.url?e.url.trim():"";return n?{type:"net_disk"===e.type?"net_disk":"direct",url:n,label:t,extract_code:"string"==typeof e.extractCode?e.extractCode:"",copy_key:"string"==typeof e.copyKey?e.copyKey:"",copy_val:"string"==typeof e.copyVal?e.copyVal:"",class:"string"==typeof e.class?e.class:"",attachment_id:Math.max(0,Number(e.attachmentId)||0)}:null}).filter(Boolean),a="points"===e.modo;return{enabled:!!e.enabled,fields:{pay_type:e.enabled?t.length>0?"download":"reading":"no",pay_modo:a?"points":"0",price:a?"0.00":String(e.price||"0.00"),points_price:a?Math.max(0,Number(e.points)||0):0,vip1_price:a?"0.00":String(e.vip1Price||"0.00"),vip2_price:a?"0.00":String(e.vip2Price||"0.00"),vip1_points:a?Math.max(0,Number(e.vip1Points)||0):0,vip2_points:a?Math.max(0,Number(e.vip2Points)||0):0,pay_limit:Number(e.payLimit)||0,downloads:t}}}const C=e=>e.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">");function S(e){if(!e||-1===e.indexOf("data-jio-"))return e;const t=document.createElement("div");return t.innerHTML=e,t.querySelectorAll("[data-jio-math-source]").forEach(e=>{const t=e.getAttribute("data-jio-math-source")||"",a="0"!==e.getAttribute("data-jio-math-display"),n=`[jio_math display="${a?"1":"0"}"]${t}[/jio_math]`,o=e.closest("p");a&&o&&o.textContent?.trim()===e.textContent?.trim()?o.textContent=n:e.replaceWith(document.createTextNode(n))}),t.querySelectorAll("[data-jio-footnote]").forEach(e=>{const t=e.getAttribute("data-jio-footnote")||"";e.replaceWith(document.createTextNode(`[jio_footnote]${t}[/jio_footnote]`))}),t.innerHTML}function x(e){return e&&-1!==e.indexOf("[jio_")?e.replace(/\[jio_math display="([01])"\]([\s\S]*?)\[\/jio_math\]/g,(e,t,a)=>"0"===t?`<span class="jio-math" data-jio-math-source="${C(a)}" data-jio-math-display="0" contenteditable="false">${M(a)}</span>`:`<p><span class="jio-math jio-math--block" data-jio-math-source="${C(a)}" data-jio-math-display="1" contenteditable="false">${M(a)}</span></p>`).replace(/\[jio_footnote\]([\s\S]*?)\[\/jio_footnote\]/g,(e,t)=>`<sup class="jio-footnote-ref" data-jio-footnote="${C((e=>{const t=document.createElement("textarea");return t.innerHTML=e,t.value})(t))}" contenteditable="false">${t}</sup>`):e}const M=e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\^\{([^{}]*)\}|\^(\S)/gu,"<sup>$1$2</sup>").replace(/_\{([^{}]*)\}|_(\S)/gu,"<sub>$1$2</sub>"),$={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 L({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,$[t.state]||$.ready),"saved"===t.state&&t.at?(0,e.createElement)("time",null,t.at):null)}const P=36e5,q=24*P,I=30*q,R=365*q,D={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 z({charCount:t,saveState:n,isPublishedEdit:o,saving:r,onSaveDraft:i,onPreview:l,onPublish:c}){const s=n.at?function(e,t=Date.now()){const n=Date.parse(e);if(!Number.isFinite(n))return"";const o=Math.max(0,t-n);return o<6e4?(0,a.__)("刚刚","jio"):o<PLine truncated
|
||||
(0,a.__)("%d分钟前","jio"),Math.floor(o/6e4)):o<q?(0,a.sprintf)(/* translators: %d: hours */ /* translators: %d: hours */
|
||||
(0,a.__)("%d小时前","jio"),Math.floor(o/P)):o<I?(0,a.sprintf)(/* translators: %d: days */ /* translators: %d: days */
|
||||
(0,a.__)("%d天前","jio"),Math.floor(o/q)):o<R?(0,a.sprintf)(/* translators: %d: months */ /* translators: %d: months */
|
||||
(0,a.__)("%d个月前","jio"),Math.floor(o/I)):(0,a.sprintf)(/* translators: %d: years */ /* translators: %d: years */
|
||||
(0,a.__)("%d年前","jio"),Math.floor(o/R))}(n.at):"",d=D[n.state]||D.ready;return(0,e.createElement)("footer",{className:"jio-creator__status",role:"contentinfo"},(0,e.createElement)("div",{className:"jio-creator__status-left"},(0,e.createElement)("span",{className:"jio-creator__status-count"},(0,a.__)("字数","jio"),":",t),(0,e.createElement)("span",{className:"jio-creator__status-mode"},(0,a.__)("Markdown 语法输入中","jio"))),(0,e.createElement)("div",{className:"jio-creator__status-meta"},(0,e.createElement)(L,{value:n}),(0,e.createElement)("span",{className:"jio-creator__status-dot","aria-hidden":"true"},"·"),(0,e.createElement)("span",{className:"jio-creator__status-time"},s||d)),(0,e.createElement)("div",{className:"jio-creator__status-actions"},(0,e.createElement)("button",{type:"button",className:"jio-creator__status-ghost",onClick:i,disabled:r},(0,a.__)("保存草稿","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator__status-ghost",onClick:l,disabled:r},(0,a.__)("预览","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator__status-primary",onClick:c,disabled:r},o?(0,a.__)("提交改稿","jio"):(0,a.__)("发布","jio"))))}const A=e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""),U=/<(?:p|div|h[1-6]|ul|ol|li|blockquote|pre|table|figure|section)\b/i,V=e=>{const t=e.trim();return""===t?"<p></p>":U.test(t)?t:`<p>${t}</p>`};const B={reply:{open:"[reply]",close:"[/reply]",label:(0,a.__)("评论后可查看","jio")},login:{open:'[jio_hide mode="login"]',close:"[/jio_hide]",label:(0,a.__)("登录后可查看","jio")},vip:{open:"[vip]",close:"[/vip]",label:(0,a.__)("会员可查看","jio")},payshow:{open:"[payshow]",close:"[/payshow]",label:(0,a.__)("付费后可查看","jio")}},K=(e,t,a)=>Math.min(a,Math.max(t,Number.isFinite(e)?Math.round(e):t)),T={table:(0,a.__)("插入表格","jio"),math:(0,a.__)("插入公式","jio"),footnote:(0,a.__)("插入注释","jio")};function F({kind:n,onSubmit:o,onClose:r}){const[i,l]=(0,t.useState)(3),[c,s]=(0,t.useState)(3),[d,u]=(0,t.useState)(!0),[m,p]=(0,t.useState)(!1),[_,f]=(0,t.useState)("a^2 + b^2 = c^2"),[b,h]=(0,t.useState)(!0),[g,y]=(0,t.useState)(""),j=(0,t.useRef)(null),v=(0,t.useRef)(null),E=(0,t.useRef)(null),k=(0,t.useRef)(null);(0,t.useEffect)(()=>{(v.current||E.current||k.current)?.focus();const e=e=>{"Escape"===e.key&&(e.preventDefault(),r())};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[r]);const w=(0,t.useMemo)(()=>"footnote"===n?""!==g.trim():"math"!==n||""!==_.trim(),[n,g,_]);return(0,e.createElement)("div",{className:"jio-creator-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"jio-creator-dialog-title"},(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__backdrop","aria-label":(0,a.__)("关闭","jio"),onClick:r}),(0,e.createElement)("div",{className:"jio-creator-dialog__panel",ref:j},(0,e.createElement)("header",{className:"jio-creator-dialog__head"},(0,e.createElement)("h2",{id:"jio-creator-dialog-title"},T[n]),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__close",onClick:r,"aria-label":(0,a.__)("关闭","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))),(0,e.createElement)("div",{className:"jio-creator-dialog__body"},"table"===n&&(0,e.createElement)(e.Fragment,null,(0,e.createElement)("div",{className:"jio-creator-dialog__row"},(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("行数","jio")),(0,e.createElement)("input",{ref:v,type:"number",min:1,max:20,value:i,onChange:e=>l(Number(e.target.value))})),(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("列数","jio")),(0,e.createElement)("input",{type:"number",min:1,max:10,value:c,onChange:e=>s(Number(e.target.value))}))),(0,e.createElement)("label",{className:"jio-creator-dialog__check"},(0,e.createElement)("input",{type:"checkbox",checked:d,onChange:e=>u(e.target.checked)}),(0,e.createElement)("span",null,(0,a.__)("首行为表头","jio"))),(0,e.createElement)("label",{className:"jio-creator-dialog__check"},(0,e.createElement)("input",{type:"checkbox",checked:m,onChange:e=>p(e.target.checked)}),(0,e.createElement)("span",null,(0,a.__)("隔行变色","jio")))),"math"===n&&(0,e.createElement)(e.Fragment,null,(0,e.createElement)("label",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("公式","jio")),(0,e.createElement)("textarea",{ref:E,rows:3,value:_,onChange:e=>f(e.target.value),placeholder:"a^2 + b^2 = c^2"})),(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("支持上标 ^ 与下标 _,例如 x^2 与 a_n;暂不支持完整 LaTeX。","jio")),(0,e.createElement)("label",{className:"jio-creator-dialog__check"},(0,e.createElement)("input",{type:"checkbox",checked:b,onChange:e=>h(e.target.checked)}),(0,e.createElement)("span",null,(0,a.__)("独占一行显示","Line truncated
|
||||
(0,a.__)("请输入标题(最多 %d 个字)","jio"),Number(re.titleMax)||100),spellCheck:!1,maxLength:Number(re.titleMax)||100})),(0,e.createElement)("div",{className:"jio-creator__editor","data-editor-ready":m?"true":"false"},(0,e.createElement)("textarea",{id:Q,defaultValue:n.content,onChange:e=>se(e.target.value),"aria-label":(0,a.__)("文章正文","jio")}))),(0,e.createElement)(k,{featured:n.featured,canEditCover:!!oe.canUploadImage,canSchedule:!!oe.canSchedule,scheduleEnabled:!!n.schedule.enabled,scheduleAt:n.schedule.at,pay:n.pay,canPay:!!oe.canPay,onFeaturedChange:e=>ce({featured:e}),onScheduleChange:(e,t)=>ce({schedule:{enabled:e,at:t}}),onPayEnabledChange:e=>ce({pay:{...i.current.pay,enabled:e}}),onOpenPaySettings:()=>{I(!0),P(!0)}}),R&&(0,e.createElement)(F,{kind:R,onSubmit:$e,onClose:()=>D(null)}),(0,e.createElement)(z,{charCount:le,saveState:M,isPublishedEdit:ie,saving:!m||"saving"===M.state||"submitting"===M.state,onSaveDraft:()=>{_e(!1)},onPreview:()=>{be()},onPublish:()=>{I(!1),P(!0)}}),L&&(0,e.createElement)(p,{draft:n,setDraft:ce,capabilities:oe,limits:re,taxonomy:{categories:W.categories&&W.categories.items||[],tags:!!W.tags?.enabled,customDefs:W.customDefs||[]},isPublishedEdit:ie,focusPay:q,onClose:()=>{P(!1),I(!1)},onSaveDraft:()=>{_e(!1)},onSubmit:e=>{fe(e)},privateStorage:!!W.privateStorage,privateUploads:W.privateUploads||[],captcha:!!W.captcha?.enabled,saving:"saving"===M.state||"submitting"===M.state}))}function ae(){const a=document.getElementById("jio-creator-studio");a&&(a.classList.add("is-ready"),(0,t.createRoot)(a).render((0,e.createElement)(te,null)))}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",ae):ae()})();
|
||||
(()=>{"use strict";const e=window.React,t=window.wp.element,a=window.wp.i18n;function n(e,t){const a=e&&(e.message||e.error)||(401===t?"登录状态已失效,请刷新页面重新登录。":"请求失败,请稍后重试。"),n=new Error(String(a));return n.status=t,n.code=e&&e.code?String(e.code):"",n.data=e,n}async function o(e){try{return await e.json()}catch(e){return null}}async function r(e,t,a){const r=await fetch(e,{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json","X-WP-Nonce":a},body:JSON.stringify(t)}),i=await o(r);if(!r.ok)throw n(i,r.status);return i}async function i(e,t,a,r={}){const i=new FormData;i.append("file",t),Object.entries(r).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 o(l);if(!l.ok)throw n(c,l.status);return c}const l={url:"",attachmentId:0,extractCode:"",copyKey:"",copyVal:"",label:"",class:""};function c({row:n,buttonClasses:o,onPickAttachment:r,onSubmit:i,onClose:c}){const[s,d]=(0,t.useState)(()=>n?{url:String(n.url||""),attachmentId:Number(n.attachmentId||0),extractCode:String(n.extractCode||""),copyKey:String(n.copyKey||""),copyVal:String(n.copyVal||""),label:String(n.label||""),class:String(n.class||"")}:{...l}),[m,u]=(0,t.useState)(""),p=(0,t.useRef)(null);(0,t.useEffect)(()=>{p.current?.focus();const e=e=>{"Escape"===e.key&&(e.preventDefault(),c())};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[c]);const _=e=>d(t=>({...t,...e}));return(0,e.createElement)("div",{className:"jio-creator-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"jio-creator-resource-title"},(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__backdrop","aria-label":(0,a.__)("关闭","jio"),onClick:c}),(0,e.createElement)("div",{className:"jio-creator-dialog__panel jio-creator-dialog__panel--wide"},(0,e.createElement)("header",{className:"jio-creator-dialog__head"},(0,e.createElement)("h2",{id:"jio-creator-resource-title"},n?(0,a.__)("编辑资源","jio"):(0,a.__)("添加资源","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__close",onClick:c,"aria-label":(0,a.__)("关闭","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))),(0,e.createElement)("div",{className:"jio-creator-dialog__body"},(0,e.createElement)("label",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("下载地址","jio")),(0,e.createElement)("div",{className:"jio-creator-dialog__url"},(0,e.createElement)("input",{ref:p,type:"url",value:s.url,placeholder:(0,a.__)("请输入资源下载地址","jio"),onChange:e=>_({url:e.target.value,attachmentId:0}),onPaste:e=>{const t=e.clipboardData?.getData("text")||"";if(!t)return;const n=t.match(/https?:\/\/\S+/i),o=t.match(/(?:提取码|密码)\s*[::]\s*([A-Za-z0-9]{4,8})/);if(!n&&!o)return;e.preventDefault();const r={attachmentId:0};n&&(r.url=n[0].replace(/[)\],。]+$/u,"")),o&&(r.extractCode=(0,a.sprintf)(/* translators: %s: extraction code */ /* translators: %s: extraction code */
|
||||
(0,a.__)("提取码:%s","jio"),o[1]),r.copyKey=(0,a.__)("提取码","jio"),r.copyVal=o[1]),_(r)}}),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__ghost",onClick:()=>r((e,t)=>_({url:e,attachmentId:t}))},(0,e.createElement)("i",{className:"fa fas fa-upload","aria-hidden":"true"})," ",(0,a.__)("上传附件","jio"))),(0,e.createElement)("span",{className:"jio-creator-dialog__hint"},(0,a.__)("支持直接粘贴网盘分享链接,会自动识别提取码。","jio"))),(0,e.createElement)("label",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("资源备注","jio")),(0,e.createElement)("input",{type:"text",value:s.extractCode,placeholder:(0,a.__)("例如提取码、解压密码等","jio"),onChange:e=>_({extractCode:e.target.value})})),(0,e.createElement)("div",{className:"jio-creator-dialog__row"},(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("复制名称","jio")),(0,e.createElement)("input",{type:"text",value:s.copyKey,placeholder:(0,a.__)("如:提取码","jio"),onChange:e=>_({copyKey:e.target.value})})),(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("复制内容","jio")),(0,e.createElement)("input",{type:"text",value:s.copyVal,placeholder:(0,a.__)("如:abcd","jio"),onChange:e=>_({copyVal:e.target.value})}))),(0,e.createElement)("span",{className:"jio-creator-dialog__hint"},(0,a.__)("填写后读者可点击按钮复制这段内容。","jio")),(0,e.createElement)("label",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("自定义按钮文案","jio")),(0,e.createElement)("input",{type:"text",value:s.label,placeholder:(0,a.__)("留空则按网盘自动识别","jio"),onChange:e=>_({label:e.target.value})})),(0,e.createElement)("div",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("按钮样式","jio")),(0,e.createElement)("div",{className:"jio-creator-swatches"},o.map(t=>(0,e.createElement)("button",{key:t||"default",type:"button",className:`jio-creator-swatch ${t||"b-theme"}${s.class===t?" is-active":""}`,onClick:()=>_({class:t}),title:t||(0,a.__)("默认样式","jio"),"aria-label":t||(0,a.__)("默认样式","jio"),"aria-pressed":s.class===t})))),m&&(0,e.createElement)("p",{className:"jio-creator-error"},m)),(0,e.createElement)("footer",{className:"jio-creator-dialog__foot"},(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__ghost",onClick:c},(0,a.__)("取消","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__primary",onClick:()=>{const e=function(e){const t=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""}}(s.url);if(!e)return void u((0,a.__)("请填写有效的下载地址","jio"));u("");const t=/pan\.baidu\.com|aliyundrive\.com|alipan\.com|pan\.quark\.cn|cloud\.189\.cn|115\.com|lanzou|weiyun|123pan/i.test(e);i({...n||{},type:t?"net_disk":"direct",url:e,attachmentId:Math.max(0,Number(s.attachmentId)||0),extractCode:s.extractCode.trim(),copyKey:s.copyKey.trim(),copyVal:s.copyVal.trim(),label:s.label.trim(),class:s.class})}},(0,a.__)("确认","jio")))))}const s=(e,t=0)=>{const a=Number(e);return Number.isFinite(a)?a:t};function d({pay:n,onChange:o,canDownload:r,privateStorage:i,privateUploads:l,bootstrap:d,onUploadPrivate:m,uploading:u,uploadError:p,onPickAttachment:_}){const[f,b]=(0,t.useState)(null),g=(0,t.useRef)(null),h=e=>o({...n,...e}),j="points"===n.modo,y=String(d.currencySymbol||"¥"),v=d.downloadClasses&&d.downloadClasses.length>0?d.downloadClasses:["","c-blue","b-blue","jb-blue"],E=n.downloads,k=e=>j?(0,a.sprintf)(/* translators: %s: VIP level name */ /* translators: %s: VIP level name */(0,a.__)("%s 积分","jio"),e):(0,a.sprintf)(/* translators: %s: VIP level name */ /* translators: %s: VIP level name */(0,a.__)("%s 价格","jio"),e),N=(t,a,n,o)=>{var r;return(0,e.createElement)("label",{className:"jio-creator-input"},(0,e.createElement)("span",null,t),(0,e.createElement)("span",{className:"jio-creator-price"},o.prefix&&(0,e.createElement)("em",null,o.prefix),(0,e.createElement)("input",{type:"number",min:null!==(r=o.min)&&void 0!==r?r:0,step:o.step,value:a,placeholder:o.placeholder,onChange:e=>n(e.target.value)}),o.suffix&&(0,e.createElement)("em",null,o.suffix)))};return(0,e.createElement)(e.Fragment,null,(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.enabled,onChange:e=>h({enabled:e.target.checked})}),(0,e.createElement)("span",{"aria-hidden":"true"}))),n.enabled&&(0Line truncated
|
||||
(0,a.__)("已开启,含 %d 个付费下载资源。","jio"),s.downloads.length):(0,a.__)("已开启,未购买读者只能看到免费部分。","jio"):(0,a.__)("开启后可以设置价格、会员价并添加付费下载资源。","jio")),s.enabled&&(0,e.createElement)("button",{type:"button",className:"jio-creator__setting-link",onClick:N},(0,e.createElement)("i",{className:"fa fas fa-coins","aria-hidden":"true"}),(0,a.__)("配置价格与付费资源","jio"))),(0,e.createElement)("label",{className:"jio-creator-toggle"},(0,e.createElement)("input",{type:"checkbox",checked:s.enabled,onChange:e=>{const t=e.target.checked;g(t),t&&N()}}),(0,e.createElement)("span",{"aria-hidden":"true"}))),(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"},r?(0,a.__)("开启后到点自动发布,发布前不会出现在文章列表。","jio"):(0,a.__)("当前账号提交后需要审核,审核通过后才会发布。","jio"))),(0,e.createElement)("label",{className:"jio-creator-toggle"},(0,e.createElement)("input",{type:"checkbox",checked:l,disabled:!r,onChange:e=>b(e.target.checked,c||k(new Date(Date.now()+36e5)))}),(0,e.createElement)("span",{"aria-hidden":"true"}))),r&&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:P,onChange:e=>b(!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(y.timezone||"UTC")))))}function w({centerUrl:t,site:n,viewer:o}){const r=String(n.name||""),i=String(o.avatar||""),l=t||"/";return(0,e.createElement)("header",{className:"jio-creator__masthead"},(0,e.createElement)("div",{className:"jio-creator__masthead-left"},(0,e.createElement)("a",{className:"jio-creator__back",href:t||"/","aria-label":(0,a.__)("返回作者中心","jio")},(0,e.createElement)("i",{className:"fa fas fa-angle-left","aria-hidden":"true"})),(0,e.createElement)("a",{className:"jio-creator__brand",href:String(n.home||"/"),"aria-label":r||(0,a.__)("返回首页","jio")},n.logo?(0,e.createElement)("img",{className:"jio-creator__brand-logo",src:String(n.logo),alt:r}):(0,e.createElement)("span",{className:"jio-creator__brand-text"},r))),(0,e.createElement)("a",{className:"jio-creator__me",href:l,"aria-label":(0,a.__)("返回作者中心","jio")},i?(0,e.createElement)("img",{className:"jio-creator__me-avatar",src:i,alt:"",width:32,height:32}):(0,e.createElement)("span",{className:"jio-creator__me-avatar is-placeholder","aria-hidden":"true"},(0,e.createElement)("i",{className:"fa fas fa-user"}))))}function C(e){const t=(e.downloads||[]).map(e=>{const t="string"==typeof e.label?e.label:"",a="string"==typeof e.assetKey?e.assetKey:"";if(a)return{type:"protected",asset_key:a,label:t};const n="string"==typeof e.url?e.url.trim():"";return n?{type:"net_disk"===e.type?"net_disk":"direct",url:n,label:t,extract_code:"string"==typeof e.extractCode?e.extractCode:"",copy_key:"string"==typeof e.copyKey?e.copyKey:"",copy_val:"string"==typeof e.copyVal?e.copyVal:"",class:"string"==typeof e.class?e.class:"",attachment_id:Math.max(0,Number(e.attachmentId)||0)}:null}).filter(Boolean),a="points"===e.modo;return{enabled:!!e.enabled,fields:{pay_type:e.enabled?t.length>0?"download":"reading":"no",pay_modo:a?"points":"0",price:a?"0.00":String(e.price||"0.00"),points_price:a?Math.max(0,Number(e.points)||0):0,vip1_price:a?"0.00":String(e.vip1Price||"0.00"),vip2_price:a?"0.00":String(e.vip2Price||"0.00"),vip1_points:a?Math.max(0,Number(e.vip1Points)||0):0,vip2_points:a?Math.max(0,Number(e.vip2Points)||0):0,pay_limit:Number(e.payLimit)||0,downloads:t}}}const S=e=>e.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">");function x(e){if(!e||-1===e.indexOf("data-jio-"))return e;const t=document.createElement("div");return t.innerHTML=e,t.querySelectorAll("[data-jio-math-source]").forEach(e=>{const t=e.getAttribute("data-jio-math-source")||"",a="0"!==e.getAttribute("data-jio-math-display"),n=`[jio_math display="${a?"1":"0"}"]${t}[/jio_math]`,o=e.closest("p");a&&o&&o.textContent?.trim()===e.textContent?.trim()?o.textContent=n:e.replaceWith(document.createTextNode(n))}),t.querySelectorAll("[data-jio-footnote]").forEach(e=>{const t=e.getAttribute("data-jio-footnote")||"";e.replaceWith(document.createTextNode(`[jio_footnote]${t}[/jio_footnote]`))}),t.innerHTML}function M(e){return e&&-1!==e.indexOf("[jio_")?e.replace(/\[jio_math display="([01])"\]([\s\S]*?)\[\/jio_math\]/g,(e,t,a)=>"0"===t?`<span class="jio-math" data-jio-math-source="${S(a)}" data-jio-math-display="0" contenteditable="false">${L(a)}</span>`:`<p><span class="jio-math jio-math--block" data-jio-math-source="${S(a)}" data-jio-math-display="1" contenteditable="false">${L(a)}</span></p>`).replace(/\[jio_footnote\]([\s\S]*?)\[\/jio_footnote\]/g,(e,t)=>`<sup class="jio-footnote-ref" data-jio-footnote="${S((e=>{const t=document.createElement("textarea");return t.innerHTML=e,t.value})(t))}" contenteditable="false">${t}</sup>`):e}const L=e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\^\{([^{}]*)\}|\^(\S)/gu,"<sup>$1$2</sup>").replace(/_\{([^{}]*)\}|_(\S)/gu,"<sub>$1$2</sub>"),$={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 P({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,$[t.state]||$.ready),"saved"===t.state&&t.at?(0,e.createElement)("time",null,t.at):null)}const q=36e5,I=24*q,R=30*I,D=365*I,z={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 A({charCount:t,saveState:n,isPublishedEdit:o,saving:r,onSaveDraft:i,onPreview:l,onPublish:c}){const s=n.at?function(e,t=Date.now()){const n=Date.parse(e);if(!Number.isFinite(n))return"";const o=Math.max(0,t-n);return o<6e4?(0,a.__)("刚刚","jio"):o<qLine truncated
|
||||
(0,a.__)("%d分钟前","jio"),Math.floor(o/6e4)):o<I?(0,a.sprintf)(/* translators: %d: hours */ /* translators: %d: hours */
|
||||
(0,a.__)("%d小时前","jio"),Math.floor(o/q)):o<R?(0,a.sprintf)(/* translators: %d: days */ /* translators: %d: days */
|
||||
(0,a.__)("%d天前","jio"),Math.floor(o/I)):o<D?(0,a.sprintf)(/* translators: %d: months */ /* translators: %d: months */
|
||||
(0,a.__)("%d个月前","jio"),Math.floor(o/R)):(0,a.sprintf)(/* translators: %d: years */ /* translators: %d: years */
|
||||
(0,a.__)("%d年前","jio"),Math.floor(o/D))}(n.at):"",d=z[n.state]||z.ready;return(0,e.createElement)("footer",{className:"jio-creator__status",role:"contentinfo"},(0,e.createElement)("div",{className:"jio-creator__status-left"},(0,e.createElement)("span",{className:"jio-creator__status-count"},(0,a.__)("字数","jio"),":",t),(0,e.createElement)("span",{className:"jio-creator__status-mode"},(0,a.__)("Markdown 语法输入中","jio"))),(0,e.createElement)("div",{className:"jio-creator__status-meta"},(0,e.createElement)(P,{value:n}),(0,e.createElement)("span",{className:"jio-creator__status-dot","aria-hidden":"true"},"·"),(0,e.createElement)("span",{className:"jio-creator__status-time"},s||d)),(0,e.createElement)("div",{className:"jio-creator__status-actions"},(0,e.createElement)("button",{type:"button",className:"jio-creator__status-ghost",onClick:i,disabled:r},(0,a.__)("保存草稿","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator__status-ghost",onClick:l,disabled:r},(0,a.__)("预览","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator__status-primary",onClick:c,disabled:r},o?(0,a.__)("提交改稿","jio"):(0,a.__)("发布","jio"))))}const U=e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""),V=/<(?:p|div|h[1-6]|ul|ol|li|blockquote|pre|table|figure|section)\b/i,T=e=>{const t=e.trim();return""===t?"<p></p>":V.test(t)?t:`<p>${t}</p>`};const B={reply:{open:"[reply]",close:"[/reply]",label:(0,a.__)("评论后可查看","jio")},login:{open:'[jio_hide mode="login"]',close:"[/jio_hide]",label:(0,a.__)("登录后可查看","jio")},vip:{open:"[vip]",close:"[/vip]",label:(0,a.__)("会员可查看","jio")},payshow:{open:"[payshow]",close:"[/payshow]",label:(0,a.__)("付费后可查看","jio")}},K=(e,t,a)=>Math.min(a,Math.max(t,Number.isFinite(e)?Math.round(e):t)),F={table:(0,a.__)("插入表格","jio"),math:(0,a.__)("插入公式","jio"),footnote:(0,a.__)("插入注释","jio")};function O({kind:n,onSubmit:o,onClose:r}){const[i,l]=(0,t.useState)(3),[c,s]=(0,t.useState)(3),[d,m]=(0,t.useState)(!0),[u,p]=(0,t.useState)(!1),[_,f]=(0,t.useState)("a^2 + b^2 = c^2"),[b,g]=(0,t.useState)(!0),[h,j]=(0,t.useState)(""),y=(0,t.useRef)(null),v=(0,t.useRef)(null),E=(0,t.useRef)(null),k=(0,t.useRef)(null);(0,t.useEffect)(()=>{(v.current||E.current||k.current)?.focus();const e=e=>{"Escape"===e.key&&(e.preventDefault(),r())};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[r]);const N=(0,t.useMemo)(()=>"footnote"===n?""!==h.trim():"math"!==n||""!==_.trim(),[n,h,_]);return(0,e.createElement)("div",{className:"jio-creator-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"jio-creator-dialog-title"},(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__backdrop","aria-label":(0,a.__)("关闭","jio"),onClick:r}),(0,e.createElement)("div",{className:"jio-creator-dialog__panel",ref:y},(0,e.createElement)("header",{className:"jio-creator-dialog__head"},(0,e.createElement)("h2",{id:"jio-creator-dialog-title"},F[n]),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__close",onClick:r,"aria-label":(0,a.__)("关闭","jio")},(0,e.createElement)("i",{className:"fa fas fa-times","aria-hidden":"true"}))),(0,e.createElement)("div",{className:"jio-creator-dialog__body"},"table"===n&&(0,e.createElement)(e.Fragment,null,(0,e.createElement)("div",{className:"jio-creator-dialog__row"},(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("行数","jio")),(0,e.createElement)("input",{ref:v,type:"number",min:1,max:20,value:i,onChange:e=>l(Number(e.target.value))})),(0,e.createElement)("label",null,(0,e.createElement)("span",null,(0,a.__)("列数","jio")),(0,e.createElement)("input",{type:"number",min:1,max:10,value:c,onChange:e=>s(Number(e.target.value))}))),(0,e.createElement)("label",{className:"jio-creator-dialog__check"},(0,e.createElement)("input",{type:"checkbox",checked:d,onChange:e=>m(e.target.checked)}),(0,e.createElement)("span",null,(0,a.__)("首行为表头","jio"))),(0,e.createElement)("label",{className:"jio-creator-dialog__check"},(0,e.createElement)("input",{type:"checkbox",checked:u,onChange:e=>p(e.target.checked)}),(0,e.createElement)("span",null,(0,a.__)("隔行变色","jio")))),"math"===n&&(0,e.createElement)(e.Fragment,null,(0,e.createElement)("label",{className:"jio-creator-dialog__field"},(0,e.createElement)("span",null,(0,a.__)("公式","jio")),(0,e.createElement)("textarea",{ref:E,rows:3,value:_,onChange:e=>f(e.target.value),placeholder:"a^2 + b^2 = c^2"})),(0,e.createElement)("p",{className:"jio-creator-muted"},(0,a.__)("支持上标 ^ 与下标 _,例如 x^2 与 a_n;暂不支持完整 LaTeX。","jio")),(0,e.createElement)("label",{className:"jio-creator-dialog__check"},(0,e.createElement)("input",{type:"checkbox",checked:b,onChange:e=>g(e.target.checked)}),(0,e.createElement)("span",null,(0,a.__)("独占一行显示","Line truncated
|
||||
(0,a.__)("请输入标题(最多 %d 个字)","jio"),Number(ie.titleMax)||100),spellCheck:!1,maxLength:Number(ie.titleMax)||100})),(0,e.createElement)("div",{className:"jio-creator__editor","data-editor-ready":u?"true":"false"},(0,e.createElement)("textarea",{id:G,defaultValue:n.content,onChange:e=>de(e.target.value),"aria-label":(0,a.__)("文章正文","jio")}))),(0,e.createElement)(N,{featured:n.featured,canEditCover:!!re.canUploadImage,canSchedule:!!re.canSchedule,scheduleEnabled:!!n.schedule.enabled,scheduleAt:n.schedule.at,pay:n.pay,canPay:!!re.canPay,taxonomy:{categories:X.categories&&X.categories.items||[],tags:!!X.tags?.enabled,customDefs:X.customDefs||[]},categories:n.categories,tags:n.tags,custom:n.custom,onFeaturedChange:e=>se({featured:e}),onScheduleChange:(e,t)=>se({schedule:{enabled:e,at:t}}),onPayEnabledChange:e=>se({pay:{...i.current.pay,enabled:e}}),onCategoriesChange:e=>se({categories:e}),onTagsChange:e=>se({tags:e}),onCustomChange:e=>se({custom:e}),onOpenPaySettings:()=>q(!0)}),D&&(0,e.createElement)(O,{kind:D,onSubmit:$e,onClose:()=>z(null)}),(0,e.createElement)(A,{charCount:ce,saveState:L,isPublishedEdit:le,saving:!u||"saving"===L.state||"submitting"===L.state,onSaveDraft:()=>{fe(!1)},onPreview:()=>{ge()},onPublish:()=>R(!0)}),P&&(0,e.createElement)(p,{draft:n,setDraft:se,capabilities:re,isPublishedEdit:le,onClose:()=>q(!1),privateStorage:!!X.privateStorage,privateUploads:X.privateUploads||[]}),I&&(0,e.createElement)(_,{canPublishNow:!!re.canPublishNow,isPublishedEdit:le,captcha:!!X.captcha?.enabled,saving:"saving"===L.state||"submitting"===L.state,canSubmit:(n.title||"").trim().length>=Number(ie.titleMin||1),onClose:()=>R(!1),onSaveDraft:()=>{fe(!1)},onSubmit:e=>{be(e)}}))}function ne(){const a=document.getElementById("jio-creator-studio");a&&(a.classList.add("is-ready"),(0,t.createRoot)(a).render((0,e.createElement)(ae,null)))}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",ne):ne()})();
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 发布确认弹窗。
|
||||
*
|
||||
* 发布 / 提交审核是底部状态栏的动作,但人机验证需要一个真实挂载点,
|
||||
* 因此把验证控件与最终按钮放进这个轻量弹窗:分类、标签与付费配置在发布前
|
||||
* 就已经在「发布设置」卡片和付费抽屉里配置完毕。
|
||||
*
|
||||
* @package Jio
|
||||
*/
|
||||
|
||||
import { useEffect, useRef } from '@wordpress/element';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
type Props = {
|
||||
canPublishNow: boolean;
|
||||
isPublishedEdit: boolean;
|
||||
captcha: boolean;
|
||||
saving: boolean;
|
||||
canSubmit: boolean;
|
||||
onClose: () => void;
|
||||
onSaveDraft: () => void;
|
||||
onSubmit: (publishNow: boolean) => void;
|
||||
};
|
||||
|
||||
export function PublishDialog({
|
||||
canPublishNow,
|
||||
isPublishedEdit,
|
||||
captcha,
|
||||
saving,
|
||||
canSubmit,
|
||||
onClose,
|
||||
onSaveDraft,
|
||||
onSubmit,
|
||||
}: Props) {
|
||||
const captchaSlot = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
// 人机验证由 PHP 渲染(脚本按 uid 注册实例),这里只把挂载点移进弹窗,
|
||||
// 保证验证控件在用户提交时可见、可交互。
|
||||
useEffect(() => {
|
||||
const slot = captchaSlot.current;
|
||||
const mount = document.getElementById('jio-creator-captcha');
|
||||
if (!slot || !mount) {
|
||||
return undefined;
|
||||
}
|
||||
const previous = mount.parentElement;
|
||||
slot.appendChild(mount);
|
||||
mount.removeAttribute('hidden');
|
||||
return () => {
|
||||
if (previous) {
|
||||
previous.appendChild(mount);
|
||||
mount.setAttribute('hidden', '');
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape' && !saving) {
|
||||
event.preventDefault();
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', onKeyDown);
|
||||
return () => document.removeEventListener('keydown', onKeyDown);
|
||||
}, [onClose, saving]);
|
||||
|
||||
return (
|
||||
<div className="jio-creator-dialog" role="dialog" aria-modal="true" aria-labelledby="jio-creator-publish-title">
|
||||
<button type="button" className="jio-creator-dialog__backdrop" aria-label={__('关闭', 'jio')} onClick={onClose} />
|
||||
<div className="jio-creator-dialog__panel">
|
||||
<header className="jio-creator-dialog__head">
|
||||
<h2 id="jio-creator-publish-title">
|
||||
{isPublishedEdit ? __('提交改稿', 'jio') : __('发布文章', 'jio')}
|
||||
</h2>
|
||||
<button type="button" className="jio-creator-dialog__close" onClick={onClose} aria-label={__('关闭', 'jio')}>
|
||||
<i className="fa fas fa-times" aria-hidden="true" />
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<div className="jio-creator-dialog__body">
|
||||
{isPublishedEdit && (
|
||||
<p className="jio-creator-dialog__note">
|
||||
{__('审核通过前,读者看到的仍然是当前线上版本。', 'jio')}
|
||||
</p>
|
||||
)}
|
||||
{captcha ? (
|
||||
<div className="jio-creator-dialog__captcha" ref={captchaSlot} />
|
||||
) : (
|
||||
<p className="jio-creator-muted">
|
||||
{isPublishedEdit
|
||||
? __('确认后将提交这份改稿等待审核。', 'jio')
|
||||
: canPublishNow
|
||||
? __('确认后立即发布这篇文章。', 'jio')
|
||||
: __('确认后将提交审核,通过后才会发布。', 'jio')}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<footer className="jio-creator-dialog__foot">
|
||||
<button type="button" className="jio-creator-dialog__ghost" onClick={onSaveDraft} disabled={saving}>
|
||||
{__('保存草稿', 'jio')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="jio-creator-dialog__primary"
|
||||
onClick={() => onSubmit(false)}
|
||||
disabled={saving || !canSubmit}
|
||||
>
|
||||
{isPublishedEdit ? __('提交审核', 'jio') : canPublishNow ? __('发布', 'jio') : __('提交审核', 'jio')}
|
||||
</button>
|
||||
{canPublishNow && (
|
||||
<button
|
||||
type="button"
|
||||
className="jio-creator-link"
|
||||
onClick={() => onSubmit(true)}
|
||||
disabled={saving || !canSubmit}
|
||||
>
|
||||
{__('立即发布', 'jio')}
|
||||
</button>
|
||||
)}
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* 发布设置卡片(位于正文纸张下方)。
|
||||
*
|
||||
* 承载与"这篇会被怎样发布"有关的低频选项:封面、付费资源与定时发布。
|
||||
* 分类、标签等配置仍在发布抽屉里;服务端 bootstrap 决定每项是否可用。
|
||||
* 承载与"这篇会被怎样发布"有关的全部选项:分类、标签、自定义分类法、封面、
|
||||
* 付费资源与定时发布。发布抽屉只负责付费资源的细节配置。
|
||||
* 服务端 bootstrap 决定每项是否可用。
|
||||
*
|
||||
* @package Jio
|
||||
*/
|
||||
@@ -15,6 +16,12 @@ import type { PayState } from '../draft';
|
||||
|
||||
type Featured = { type: string; data: Record<string, any>; mediaId?: number };
|
||||
|
||||
export type TaxonomyDef = {
|
||||
categories: Array<{ id: number; name: string }>;
|
||||
tags: boolean;
|
||||
customDefs: Array<{ key: string; name: string; values: Array<{ key: string; name: string }> }>;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
featured: Featured;
|
||||
canEditCover: boolean;
|
||||
@@ -23,9 +30,16 @@ type Props = {
|
||||
scheduleAt: string;
|
||||
pay: PayState;
|
||||
canPay: boolean;
|
||||
taxonomy: TaxonomyDef;
|
||||
categories: number[];
|
||||
tags: string[];
|
||||
custom: Record<string, string[]>;
|
||||
onFeaturedChange: (featured: Featured) => void;
|
||||
onScheduleChange: (enabled: boolean, at: string) => void;
|
||||
onPayEnabledChange: (enabled: boolean) => void;
|
||||
onCategoriesChange: (categories: number[]) => void;
|
||||
onTagsChange: (tags: string[]) => void;
|
||||
onCustomChange: (custom: Record<string, string[]>) => void;
|
||||
/** 打开发布抽屉并直接定位到付费配置。 */
|
||||
onOpenPaySettings: () => void;
|
||||
};
|
||||
@@ -52,17 +66,52 @@ export function PublishSettings({
|
||||
scheduleAt,
|
||||
pay,
|
||||
canPay,
|
||||
taxonomy,
|
||||
categories,
|
||||
tags,
|
||||
custom,
|
||||
onFeaturedChange,
|
||||
onScheduleChange,
|
||||
onPayEnabledChange,
|
||||
onCategoriesChange,
|
||||
onTagsChange,
|
||||
onCustomChange,
|
||||
onOpenPaySettings,
|
||||
}: Props) {
|
||||
const coverInput = useRef<HTMLInputElement | null>(null);
|
||||
const [tagInput, setTagInput] = useState('');
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const minSchedule = useMemo(() => toLocalInput(new Date(Date.now() + 5 * 60 * 1000)), []);
|
||||
const coverUrl = typeof featured?.data?.url === 'string' ? featured.data.url : '';
|
||||
|
||||
const toggleCategory = (id: number) => {
|
||||
onCategoriesChange(
|
||||
categories.includes(id) ? categories.filter((value) => value !== id) : [...categories, id]
|
||||
);
|
||||
};
|
||||
|
||||
const addTag = () => {
|
||||
const value = tagInput.trim();
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
const next = value
|
||||
.split(/[,,\n]+/u)
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
onTagsChange(Array.from(new Set([...tags, ...next])));
|
||||
setTagInput('');
|
||||
};
|
||||
|
||||
const toggleCustom = (key: string, value: string) => {
|
||||
const current = custom[key] || [];
|
||||
onCustomChange({
|
||||
...custom,
|
||||
[key]: current.includes(value) ? current.filter((item) => item !== value) : [...current, value],
|
||||
});
|
||||
};
|
||||
|
||||
const uploadCover = async () => {
|
||||
const file = coverInput.current?.files?.[0];
|
||||
const uploadUrl = bootstrap.media?.uploadUrl?.image;
|
||||
@@ -93,6 +142,97 @@ export function PublishSettings({
|
||||
<section className="jio-creator__settings" aria-label={__('发布设置', 'jio')}>
|
||||
<h2 className="jio-creator__settings-title">{__('发布设置', 'jio')}</h2>
|
||||
|
||||
{/* 分类:卡片里的第一项,作者提交前一定会看到。 */}
|
||||
<div className="jio-creator__setting-row jio-creator__setting-row--stack">
|
||||
<div className="jio-creator__setting-copy">
|
||||
<span className="jio-creator__setting-label">{__('分类', 'jio')}</span>
|
||||
<p className="jio-creator__setting-help">{__('必选,决定文章出现在哪些栏目。', 'jio')}</p>
|
||||
</div>
|
||||
<div className="jio-creator-chips">
|
||||
{taxonomy.categories.length === 0 && (
|
||||
<span className="jio-creator-muted">{__('暂无可选分类', 'jio')}</span>
|
||||
)}
|
||||
{taxonomy.categories.map((category) => (
|
||||
<label
|
||||
key={category.id}
|
||||
className={`jio-creator-chip${categories.includes(category.id) ? ' is-active' : ''}`}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={categories.includes(category.id)}
|
||||
onChange={() => toggleCategory(category.id)}
|
||||
/>
|
||||
<span>{category.name}</span>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{taxonomy.tags && (
|
||||
<div className="jio-creator__setting-row jio-creator__setting-row--stack">
|
||||
<div className="jio-creator__setting-copy">
|
||||
<span className="jio-creator__setting-label">{__('标签', 'jio')}</span>
|
||||
<p className="jio-creator__setting-help">{__('多个标签用逗号分隔,回车即可添加。', 'jio')}</p>
|
||||
</div>
|
||||
<div>
|
||||
{tags.length > 0 && (
|
||||
<div className="jio-creator-chips">
|
||||
{tags.map((tag) => (
|
||||
<span key={tag} className="jio-creator-chip is-active">
|
||||
<span>{tag}</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onTagsChange(tags.filter((value) => value !== tag))}
|
||||
aria-label={sprintf(__('移除标签 %s', 'jio'), tag)}
|
||||
>
|
||||
<i className="fa fas fa-times" aria-hidden="true" />
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="jio-creator-inline">
|
||||
<input
|
||||
type="text"
|
||||
value={tagInput}
|
||||
placeholder={__('输入标签,逗号分隔', 'jio')}
|
||||
onChange={(event) => setTagInput(event.target.value)}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
addTag();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button type="button" onClick={addTag}>{__('添加', 'jio')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{taxonomy.customDefs.map((dimension) => (
|
||||
<div className="jio-creator__setting-row jio-creator__setting-row--stack" key={dimension.key}>
|
||||
<div className="jio-creator__setting-copy">
|
||||
<span className="jio-creator__setting-label">{dimension.name}</span>
|
||||
</div>
|
||||
<div className="jio-creator-chips">
|
||||
{dimension.values.map((value) => {
|
||||
const active = (custom[dimension.key] || []).includes(value.key);
|
||||
return (
|
||||
<label key={value.key} className={`jio-creator-chip${active ? ' is-active' : ''}`}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={active}
|
||||
onChange={() => toggleCustom(dimension.key, value.key)}
|
||||
/>
|
||||
<span>{value.name}</span>
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{canEditCover && (
|
||||
<div className="jio-creator__setting-row">
|
||||
<div className="jio-creator__setting-copy">
|
||||
|
||||
@@ -12,6 +12,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
import { apiPost } from './services/api';
|
||||
import { PublishDrawer } from './panels/publish-drawer';
|
||||
import { PublishDialog } from './components/publish-dialog';
|
||||
import { EditorToolbar } from './components/editor-toolbar';
|
||||
import { PublishSettings } from './components/publish-settings';
|
||||
import { StudioMasthead } from './components/studio-masthead';
|
||||
@@ -90,7 +91,7 @@ function Studio(): JSX.Element {
|
||||
at: '',
|
||||
}));
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
const [drawerFocusPay, setDrawerFocusPay] = useState(false);
|
||||
const [publishOpen, setPublishOpen] = useState(false);
|
||||
const [blockDialog, setBlockDialog] = useState<BlockDialogKind | null>(null);
|
||||
const [notice, setNotice] = useState<{ tone: 'ok' | 'error'; text: string } | null>(null);
|
||||
const [recovery, setRecovery] = useState<null | { savedAt: string }>(null);
|
||||
@@ -274,6 +275,7 @@ function Studio(): JSX.Element {
|
||||
dirtyRef.current = false;
|
||||
setSaveState({ state: 'submitted', at: '' });
|
||||
setNotice({ tone: 'ok', text: String(response.message || __('已提交', 'jio')) });
|
||||
setPublishOpen(false);
|
||||
setDrawerOpen(false);
|
||||
const target = response.url || response.goto || bootstrap.urls?.center;
|
||||
if (target) {
|
||||
@@ -768,13 +770,21 @@ function Studio(): JSX.Element {
|
||||
scheduleAt={draft.schedule.at}
|
||||
pay={draft.pay}
|
||||
canPay={!!capabilities.canPay}
|
||||
taxonomy={{
|
||||
categories: (bootstrap.categories && bootstrap.categories.items) || [],
|
||||
tags: !!bootstrap.tags?.enabled,
|
||||
customDefs: bootstrap.customDefs || [],
|
||||
}}
|
||||
categories={draft.categories}
|
||||
tags={draft.tags}
|
||||
custom={draft.custom}
|
||||
onFeaturedChange={(featured) => patchDraft({ featured })}
|
||||
onScheduleChange={(enabled, at) => patchDraft({ schedule: { enabled, at } })}
|
||||
onPayEnabledChange={(enabled) => patchDraft({ pay: { ...draftRef.current.pay, enabled } })}
|
||||
onOpenPaySettings={() => {
|
||||
setDrawerFocusPay(true);
|
||||
setDrawerOpen(true);
|
||||
}}
|
||||
onCategoriesChange={(categories) => patchDraft({ categories })}
|
||||
onTagsChange={(tags) => patchDraft({ tags })}
|
||||
onCustomChange={(custom) => patchDraft({ custom })}
|
||||
onOpenPaySettings={() => setDrawerOpen(true)}
|
||||
/>
|
||||
|
||||
{blockDialog && (
|
||||
@@ -792,10 +802,7 @@ function Studio(): JSX.Element {
|
||||
saving={!editorReady || saveState.state === 'saving' || saveState.state === 'submitting'}
|
||||
onSaveDraft={() => void save(false)}
|
||||
onPreview={() => void preview()}
|
||||
onPublish={() => {
|
||||
setDrawerFocusPay(false);
|
||||
setDrawerOpen(true);
|
||||
}}
|
||||
onPublish={() => setPublishOpen(true)}
|
||||
/>
|
||||
|
||||
{drawerOpen && (
|
||||
@@ -803,24 +810,23 @@ function Studio(): JSX.Element {
|
||||
draft={draft}
|
||||
setDraft={patchDraft}
|
||||
capabilities={capabilities}
|
||||
limits={limits}
|
||||
taxonomy={{
|
||||
categories: (bootstrap.categories && bootstrap.categories.items) || [],
|
||||
tags: !!bootstrap.tags?.enabled,
|
||||
customDefs: bootstrap.customDefs || [],
|
||||
}}
|
||||
isPublishedEdit={isPublishedEdit}
|
||||
focusPay={drawerFocusPay}
|
||||
onClose={() => {
|
||||
setDrawerOpen(false);
|
||||
setDrawerFocusPay(false);
|
||||
}}
|
||||
onSaveDraft={() => void save(false)}
|
||||
onSubmit={(publishNow: boolean) => void submit(publishNow)}
|
||||
onClose={() => setDrawerOpen(false)}
|
||||
privateStorage={!!bootstrap.privateStorage}
|
||||
privateUploads={bootstrap.privateUploads || []}
|
||||
/>
|
||||
)}
|
||||
|
||||
{publishOpen && (
|
||||
<PublishDialog
|
||||
canPublishNow={!!capabilities.canPublishNow}
|
||||
isPublishedEdit={isPublishedEdit}
|
||||
captcha={!!bootstrap.captcha?.enabled}
|
||||
saving={saveState.state === 'saving' || saveState.state === 'submitting'}
|
||||
canSubmit={(draft.title || '').trim().length >= Number(limits.titleMin || 1)}
|
||||
onClose={() => setPublishOpen(false)}
|
||||
onSaveDraft={() => void save(false)}
|
||||
onSubmit={(publishNow: boolean) => void submit(publishNow)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
/**
|
||||
* 发布配置抽屉。
|
||||
* 付费配置抽屉。
|
||||
*
|
||||
* 只承载付费相关内容:价格 / 会员价 / 付费下载资源。分类、标签、封面、
|
||||
* 定时发布与提交动作都在正文下方的「发布设置」卡片和底部状态栏里,
|
||||
* 抽屉不再重复这些入口。
|
||||
*
|
||||
* 分类、标签、付费与资料附件都在这里配置;封面与定时发布在正文下方的
|
||||
* 「发布设置」卡片里,避免把封面入口和正文挤在同一张纸上。
|
||||
* 手机端以全屏面板呈现。所有字段与权限来自服务端 bootstrap,前端不自行放大权限。
|
||||
*
|
||||
* @package Jio
|
||||
*/
|
||||
|
||||
import { useEffect, useMemo, useRef, useState } from '@wordpress/element';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { useRef, useState } from '@wordpress/element';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import { apiUpload } from '../services/api';
|
||||
import type { DownloadRow, Draft } from '../draft';
|
||||
@@ -17,63 +19,31 @@ import { PayPanel, type PayBootstrap } from './pay-panel';
|
||||
|
||||
type Capabilities = Record<string, boolean>;
|
||||
|
||||
type Limits = {
|
||||
titleMin?: number;
|
||||
titleMax?: number;
|
||||
priceMin?: number;
|
||||
priceMax?: number;
|
||||
pointsMin?: number;
|
||||
pointsMax?: number;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
draft: Draft;
|
||||
setDraft: (patch: Partial<Draft>) => void;
|
||||
capabilities: Capabilities;
|
||||
limits: Limits;
|
||||
captcha: boolean;
|
||||
taxonomy: {
|
||||
categories: Array<{ id: number; name: string }>;
|
||||
tags: boolean;
|
||||
customDefs: Array<{ key: string; name: string; values: Array<{ key: string; name: string }> }>;
|
||||
};
|
||||
isPublishedEdit: boolean;
|
||||
/** 打开时直接定位到付费配置(从正文下方的发布设置卡片进入)。 */
|
||||
focusPay?: boolean;
|
||||
onClose: () => void;
|
||||
onSaveDraft: () => void;
|
||||
onSubmit: (publishNow: boolean) => void;
|
||||
privateStorage: boolean;
|
||||
privateUploads: Array<Record<string, any>>;
|
||||
saving: boolean;
|
||||
};
|
||||
|
||||
const bootstrap: Record<string, any> = window['jioCreatorStudio'] || {};
|
||||
const nonce: string = bootstrap.nonce || '';
|
||||
|
||||
export function PublishDrawer(props: Props) {
|
||||
const {
|
||||
draft,
|
||||
setDraft,
|
||||
capabilities,
|
||||
limits,
|
||||
taxonomy,
|
||||
isPublishedEdit,
|
||||
focusPay,
|
||||
onClose,
|
||||
onSaveDraft,
|
||||
onSubmit,
|
||||
privateStorage,
|
||||
privateUploads,
|
||||
saving,
|
||||
captcha,
|
||||
} = props;
|
||||
|
||||
const [tagInput, setTagInput] = useState('');
|
||||
export function PublishDrawer({
|
||||
draft,
|
||||
setDraft,
|
||||
capabilities,
|
||||
isPublishedEdit,
|
||||
onClose,
|
||||
privateStorage,
|
||||
privateUploads,
|
||||
}: Props) {
|
||||
const [uploadError, setUploadError] = useState('');
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const captchaSlot = useRef<HTMLDivElement | null>(null);
|
||||
const paySection = useRef<HTMLElement | null>(null);
|
||||
const body = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const payBootstrap: PayBootstrap = {
|
||||
freeAllowed: !!bootstrap.pay?.freeAllowed,
|
||||
@@ -91,55 +61,6 @@ export function PublishDrawer(props: Props) {
|
||||
pointsMax: Number(bootstrap.pay?.pointsMax || 0),
|
||||
};
|
||||
|
||||
// 人机验证由 PHP 渲染(脚本在页面加载时按 uid 注册实例),这里只把挂载点
|
||||
// 移进抽屉,保证验证控件在用户提交时可见、可交互。
|
||||
useEffect(() => {
|
||||
const slot = captchaSlot.current;
|
||||
const mount = document.getElementById('jio-creator-captcha');
|
||||
if (!slot || !mount) {
|
||||
return undefined;
|
||||
}
|
||||
const previous = mount.parentElement;
|
||||
slot.appendChild(mount);
|
||||
mount.removeAttribute('hidden');
|
||||
return () => {
|
||||
if (previous) {
|
||||
previous.appendChild(mount);
|
||||
mount.setAttribute('hidden', '');
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 从发布设置卡片进入时,抽屉打开后直接滚到付费配置。
|
||||
useEffect(() => {
|
||||
if (focusPay) {
|
||||
paySection.current?.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
||||
}
|
||||
}, [focusPay]);
|
||||
|
||||
const titleLength = useMemo(() => (draft.title || '').trim().length, [draft.title]);
|
||||
const canSubmit = titleLength >= Number(limits.titleMin || 1);
|
||||
|
||||
const toggleCategory = (id: number) => {
|
||||
const has = draft.categories.includes(id);
|
||||
setDraft({
|
||||
categories: has ? draft.categories.filter((value) => value !== id) : [...draft.categories, id],
|
||||
});
|
||||
};
|
||||
|
||||
const addTag = () => {
|
||||
const value = tagInput.trim();
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
const next = value
|
||||
.split(/[,,\n]+/u)
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean);
|
||||
setDraft({ tags: Array.from(new Set([...draft.tags, ...next])) });
|
||||
setTagInput('');
|
||||
};
|
||||
|
||||
/** 上传一个受保护附件到私有存储,只保留 asset_key。 */
|
||||
const uploadPrivate = async (file: File): Promise<DownloadRow | null> => {
|
||||
setUploadError('');
|
||||
@@ -189,152 +110,51 @@ export function PublishDrawer(props: Props) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="jio-creator-drawer" role="dialog" aria-modal="true" aria-labelledby="jio-creator-publish-title">
|
||||
<div className="jio-creator-drawer" role="dialog" aria-modal="true" aria-labelledby="jio-creator-pay-title">
|
||||
<button type="button" className="jio-creator-drawer__backdrop" aria-label={__('关闭', 'jio')} onClick={onClose} />
|
||||
<div className="jio-creator-drawer__panel">
|
||||
<header className="jio-creator-drawer__head">
|
||||
<h2 id="jio-creator-publish-title">{isPublishedEdit ? __('提交改稿', 'jio') : __('发布文章', 'jio')}</h2>
|
||||
<div>
|
||||
<h2 id="jio-creator-pay-title">{__('付费资源', 'jio')}</h2>
|
||||
<p className="jio-creator-drawer__subtitle">
|
||||
{__('价格、会员价与付费下载资源', 'jio')}
|
||||
</p>
|
||||
</div>
|
||||
<button type="button" className="jio-creator-drawer__close" onClick={onClose} aria-label={__('关闭', 'jio')}>
|
||||
<i className="fa fas fa-times" aria-hidden="true" />
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<div className="jio-creator-drawer__body">
|
||||
<div className="jio-creator-drawer__body" ref={body}>
|
||||
{isPublishedEdit && (
|
||||
<p className="jio-creator-drawer__note">
|
||||
{__('审核通过前,读者看到的仍然是当前线上版本。', 'jio')}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<section className="jio-creator-field">
|
||||
<h3>{__('分类', 'jio')}</h3>
|
||||
<div className="jio-creator-chips">
|
||||
{taxonomy.categories.length === 0 && <span className="jio-creator-muted">{__('暂无可选分类', 'jio')}</span>}
|
||||
{taxonomy.categories.map((category) => (
|
||||
<label
|
||||
key={category.id}
|
||||
className={`jio-creator-chip${draft.categories.includes(category.id) ? ' is-active' : ''}`}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={draft.categories.includes(category.id)}
|
||||
onChange={() => toggleCategory(category.id)}
|
||||
/>
|
||||
<span>{category.name}</span>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{taxonomy.tags && (
|
||||
<section className="jio-creator-field">
|
||||
<h3>{__('标签', 'jio')}</h3>
|
||||
<div className="jio-creator-chips">
|
||||
{draft.tags.map((tag) => (
|
||||
<span key={tag} className="jio-creator-chip is-active">
|
||||
<span>{tag}</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setDraft({ tags: draft.tags.filter((value) => value !== tag) })}
|
||||
aria-label={sprintf(__('移除标签 %s', 'jio'), tag)}
|
||||
>
|
||||
<i className="fa fas fa-times" aria-hidden="true" />
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<div className="jio-creator-inline">
|
||||
<input
|
||||
type="text"
|
||||
value={tagInput}
|
||||
placeholder={__('输入标签,逗号分隔', 'jio')}
|
||||
onChange={(event) => setTagInput(event.target.value)}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
addTag();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button type="button" onClick={addTag}>{__('添加', 'jio')}</button>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{taxonomy.customDefs.map((dimension) => (
|
||||
<section className="jio-creator-field" key={dimension.key}>
|
||||
<h3>{dimension.name}</h3>
|
||||
<div className="jio-creator-chips">
|
||||
{dimension.values.map((value) => {
|
||||
const current = draft.custom[dimension.key] || [];
|
||||
const active = current.includes(value.key);
|
||||
return (
|
||||
<label key={value.key} className={`jio-creator-chip${active ? ' is-active' : ''}`}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={active}
|
||||
onChange={() =>
|
||||
setDraft({
|
||||
custom: {
|
||||
...draft.custom,
|
||||
[dimension.key]: active
|
||||
? current.filter((item) => item !== value.key)
|
||||
: [...current, value.key],
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
<span>{value.name}</span>
|
||||
</label>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
|
||||
{capabilities.canPay && (
|
||||
<section className="jio-creator-field" ref={paySection}>
|
||||
<PayPanel
|
||||
pay={draft.pay}
|
||||
onChange={(pay) => setDraft({ pay })}
|
||||
canDownload={!!capabilities.canPayDownload}
|
||||
privateStorage={privateStorage}
|
||||
privateUploads={privateUploads}
|
||||
bootstrap={payBootstrap}
|
||||
onUploadPrivate={uploadPrivate}
|
||||
uploading={uploading}
|
||||
uploadError={uploadError}
|
||||
onPickAttachment={pickAttachment}
|
||||
/>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{!capabilities.canPay && capabilities.canSaveDraft && (
|
||||
{capabilities.canPay ? (
|
||||
<PayPanel
|
||||
pay={draft.pay}
|
||||
onChange={(pay) => setDraft({ pay })}
|
||||
canDownload={!!capabilities.canPayDownload}
|
||||
privateStorage={privateStorage}
|
||||
privateUploads={privateUploads}
|
||||
bootstrap={payBootstrap}
|
||||
onUploadPrivate={uploadPrivate}
|
||||
uploading={uploading}
|
||||
uploadError={uploadError}
|
||||
onPickAttachment={pickAttachment}
|
||||
/>
|
||||
) : (
|
||||
<p className="jio-creator-muted">{__('当前账号不能设置付费内容。', 'jio')}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<footer className="jio-creator-drawer__foot">
|
||||
{captcha && (
|
||||
<div className="jio-creator-drawer__captcha" ref={captchaSlot} />
|
||||
)}
|
||||
<div className="jio-creator-drawer__actions">
|
||||
<button type="button" className="jio-creator-ghost" onClick={onSaveDraft} disabled={saving}>
|
||||
{__('保存草稿', 'jio')}
|
||||
<button type="button" className="jio-creator-primary" onClick={onClose}>
|
||||
{__('完成', 'jio')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="jio-creator-primary"
|
||||
onClick={() => onSubmit(false)}
|
||||
disabled={saving || !canSubmit}
|
||||
>
|
||||
{isPublishedEdit ? __('提交审核', 'jio') : capabilities.canPublishNow ? __('发布', 'jio') : __('提交审核', 'jio')}
|
||||
</button>
|
||||
{capabilities.canPublishNow && (
|
||||
<button type="button" className="jio-creator-link" onClick={() => onSubmit(true)} disabled={saving || !canSubmit}>
|
||||
{__('立即发布', 'jio')}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
@@ -161,6 +161,21 @@
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 发布确认弹窗里的人机验证挂载点:给一个最小高度,避免验证控件撑开时跳动。 */
|
||||
.jio-creator-dialog__captcha {
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.jio-creator-dialog__note {
|
||||
margin: 0;
|
||||
padding: 10px 12px;
|
||||
border-left: 3px solid var(--jc-accent);
|
||||
background: #f2f7f4;
|
||||
color: #7d8683;
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.jio-creator-dialog__url {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
@@ -72,10 +72,6 @@
|
||||
padding: 16px 24px calc(16px + env(safe-area-inset-bottom));
|
||||
border-top: 1px solid $line;
|
||||
background: #fff;
|
||||
|
||||
.jio-creator-primary {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.jio-creator-drawer__actions {
|
||||
@@ -84,21 +80,69 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.jio-creator-drawer__captcha {
|
||||
min-height: 40px;
|
||||
/* 抽屉只做付费配置,「完成」靠右,不承担发布动作。 */
|
||||
.jio-creator-drawer__actions .jio-creator-primary {
|
||||
flex: 0 0 auto;
|
||||
min-width: 96px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.jio-creator-field {
|
||||
margin-bottom: 26px;
|
||||
/* 抽屉 / 付费面板共用的按钮基础样式(此前只在弹窗里定义,抽屉按钮没有外观)。 */
|
||||
.jio-creator-ghost,
|
||||
.jio-creator-primary {
|
||||
display: inline-flex;
|
||||
min-height: 34px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
padding: 0 14px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
> h3 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: $ink;
|
||||
.jio-creator-ghost {
|
||||
border: 1px solid $line;
|
||||
background: #fff;
|
||||
color: #5f6664;
|
||||
|
||||
&:hover:not(:disabled),
|
||||
&:focus-visible:not(:disabled) {
|
||||
border-color: #b7cdc3;
|
||||
color: $accent-strong;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.jio-creator-primary {
|
||||
border: 1px solid transparent;
|
||||
background: $accent;
|
||||
color: #fff;
|
||||
|
||||
&:hover:not(:disabled),
|
||||
&:focus-visible:not(:disabled) {
|
||||
background: $accent-strong;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.55;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.jio-creator-drawer__head > div {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.jio-creator-drawer__subtitle {
|
||||
margin: 4px 0 0;
|
||||
color: $ink-soft;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.jio-creator-muted {
|
||||
margin: 0;
|
||||
color: $ink-soft;
|
||||
@@ -315,54 +359,6 @@
|
||||
border-top: 1px dashed $line;
|
||||
}
|
||||
|
||||
.jio-creator-cover {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
aspect-ratio: 2 / 1;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.jio-creator-cover-empty {
|
||||
display: flex;
|
||||
min-height: 120px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
border: 1px dashed $line;
|
||||
border-radius: 10px;
|
||||
background: #fafcfb;
|
||||
color: $ink-soft;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.jio-creator-attachments {
|
||||
margin-top: 18px;
|
||||
padding-top: 16px;
|
||||
|
||||
@@ -641,6 +641,13 @@ body.jio-page-submit.has-static-nav {
|
||||
}
|
||||
}
|
||||
|
||||
/* 分类 / 标签这类需要整行展开的选择器:说明在上,选项在下。 */
|
||||
.jio-creator__setting-row--stack {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.jio-creator__setting-copy {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -146,8 +146,12 @@ test('studio app uses TinyMCE while preserving autosave, recovery, and publishin
|
||||
assert.match(drawer, /canPayDownload/);
|
||||
assert.match(drawer, /<PayPanel/);
|
||||
assert.match(read('assets/creator-studio/src/panels/pay-panel.tsx'), /私有附件存储尚未配置/);
|
||||
assert.match(drawer, /onSubmit\(false\)/);
|
||||
assert.match(drawer, /立即发布/);
|
||||
// 发布动作在底部状态栏 + 确认弹窗里,抽屉只做付费配置。
|
||||
assert.doesNotMatch(drawer, /onSubmit\(/);
|
||||
assert.doesNotMatch(drawer, /立即发布/);
|
||||
assert.doesNotMatch(drawer, /保存草稿/);
|
||||
assert.match(read('assets/creator-studio/src/components/publish-dialog.tsx'), /onSubmit\(false\)/);
|
||||
assert.match(read('assets/creator-studio/src/components/publish-dialog.tsx'), /立即发布/);
|
||||
});
|
||||
|
||||
test('studio enqueues the WordPress editor and TinyMCE media tools', () => {
|
||||
@@ -436,8 +440,21 @@ test('writing surface is a centered paper card with a publish settings card belo
|
||||
assert.match(settings, /onOpenPaySettings/);
|
||||
assert.match(settings, /配置价格与付费资源/);
|
||||
assert.match(appSource, /onOpenPaySettings=\{/);
|
||||
assert.match(appSource, /focusPay=\{drawerFocusPay\}/);
|
||||
assert.match(read('assets/creator-studio/src/panels/publish-drawer.tsx'), /scrollIntoView/);
|
||||
|
||||
// 分类与标签已从抽屉移到发布设置卡片。
|
||||
assert.match(settings, /__\('分类', 'jio'\)/);
|
||||
assert.match(settings, /__\('标签', 'jio'\)/);
|
||||
assert.match(settings, /onCategoriesChange/);
|
||||
assert.match(settings, /onTagsChange/);
|
||||
assert.match(settings, /onCustomChange/);
|
||||
assert.match(appSource, /onCategoriesChange=\{/);
|
||||
assert.match(appSource, /onTagsChange=\{/);
|
||||
assert.doesNotMatch(read('assets/creator-studio/src/panels/publish-drawer.tsx'), /taxonomy/);
|
||||
|
||||
// 发布动作从抽屉移到确认弹窗,人机验证挂载点随之迁移。
|
||||
assert.match(appSource, /<PublishDialog/);
|
||||
assert.match(read('assets/creator-studio/src/components/publish-dialog.tsx'), /jio-creator-captcha/);
|
||||
assert.doesNotMatch(drawer, /jio-creator-captcha/);
|
||||
});
|
||||
|
||||
test('scheduled publishing is validated and applied server side', () => {
|
||||
|
||||
Reference in new issue
Block a user