fix(front-submit): let drafts save with partial content
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4a119358ca
commit
5f31c58df2
5 files changed
+29
-9
No files matched your search
@@ -1 +1 @@
|
||||
<?php return array('dependencies' => array('react', 'wp-element', 'wp-i18n'), 'version' => '5aca6e340eab7503b9b9');
|
||||
<?php return array('dependencies' => array('react', 'wp-element', 'wp-i18n'), 'version' => 'e6c1894c680db1bc0999');
|
||||
@@ -4,5 +4,5 @@
|
||||
(0,a.__)("%d小时前","jio"),Math.floor(o/N)):o<C?(0,a.sprintf)(/* translators: %d: days */ /* translators: %d: days */
|
||||
(0,a.__)("%d天前","jio"),Math.floor(o/w)):o<S?(0,a.sprintf)(/* translators: %d: months */ /* translators: %d: months */
|
||||
(0,a.__)("%d个月前","jio"),Math.floor(o/C)):(0,a.sprintf)(/* translators: %d: years */ /* translators: %d: years */
|
||||
(0,a.__)("%d年前","jio"),Math.floor(o/S))}(n.at):"",d=x[n.state]||x.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)(k,{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:l,disabled:r},(0,a.__)("保存草稿","jio")),(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-primary",onClick:c,disabled:r},o?(0,a.__)("提交改稿","jio"):(0,a.__)("发布","jio"))))}const $=e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""),q=[{value:"generic",label:(0,a.__)("通用","jio")},{value:"javascript",label:"JavaScript"},{value:"typescript",label:"TypeScript"},{value:"php",label:"PHP"},{value:"python",label:"Python"},{value:"java",label:"Java"},{value:"go",label:"Go"},{value:"rust",label:"Rust"},{value:"csharp",label:"C#"},{value:"cpp",label:"C++"},{value:"sql",label:"SQL"},{value:"json",label:"JSON"},{value:"bash",label:"Shell"},{value:"css",label:"CSS"},{value:"html",label:"HTML"},{value:"markdown",label:"Markdown"}];const L=(e,t,a)=>Math.min(a,Math.max(t,Number.isFinite(e)?Math.round(e):t)),I={table:(0,a.__)("插入表格","jio"),math:(0,a.__)("插入公式","jio"),footnote:(0,a.__)("插入注释","jio")};function R({kind:n,onSubmit:o,onClose:r}){const[l,i]=(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,g]=(0,t.useState)(!0),[h,j]=(0,t.useState)(""),y=(0,t.useRef)(null),E=(0,t.useRef)(null),v=(0,t.useRef)(null),k=(0,t.useRef)(null);(0,t.useEffect)(()=>{(E.current||v.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"},I[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:E,type:"number",min:1,max:20,value:l,onChange:e=>i(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:v,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"),Math.floor(o/S))}(n.at):"",d=x[n.state]||x.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)(k,{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:l,disabled:r},(0,a.__)("保存草稿","jio")),(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-primary",onClick:c,disabled:r},o?(0,a.__)("提交改稿","jio"):(0,a.__)("发布","jio"))))}const $=e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""),q=[{value:"generic",label:(0,a.__)("通用","jio")},{value:"javascript",label:"JavaScript"},{value:"typescript",label:"TypeScript"},{value:"php",label:"PHP"},{value:"python",label:"Python"},{value:"java",label:"Java"},{value:"go",label:"Go"},{value:"rust",label:"Rust"},{value:"csharp",label:"C#"},{value:"cpp",label:"C++"},{value:"sql",label:"SQL"},{value:"json",label:"JSON"},{value:"bash",label:"Shell"},{value:"css",label:"CSS"},{value:"html",label:"HTML"},{value:"markdown",label:"Markdown"}];const L=(e,t,a)=>Math.min(a,Math.max(t,Number.isFinite(e)?Math.round(e):t)),I={table:(0,a.__)("插入表格","jio"),math:(0,a.__)("插入公式","jio"),footnote:(0,a.__)("插入注释","jio")};function R({kind:n,onSubmit:o,onClose:r}){const[l,i]=(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,g]=(0,t.useState)(!0),[h,j]=(0,t.useState)(""),y=(0,t.useRef)(null),E=(0,t.useRef)(null),v=(0,t.useRef)(null),k=(0,t.useRef)(null);(0,t.useEffect)(()=>{(E.current||v.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"},I[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:E,type:"number",min:1,max:20,value:l,onChange:e=>i(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:v,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(ee.titleMax)||100),spellCheck:!1,maxLength:Number(ee.titleMax)||100})),(0,e.createElement)("div",{className:"jio-creator__editor","data-editor-ready":_?"true":"false"},(0,e.createElement)("textarea",{id:A,defaultValue:n.content,onChange:e=>oe(e.target.value),"aria-label":(0,a.__)("文章正文","jio")}))),(0,e.createElement)(b,{featured:n.featured,canEditCover:!!Z.canUploadImage,canSchedule:!!Z.canSchedule,scheduleEnabled:!!n.schedule.enabled,scheduleAt:n.schedule.at,onFeaturedChange:e=>ne({featured:e}),onScheduleChange:(e,t)=>ne({schedule:{enabled:e,at:t}})}),null!==I&&(0,e.createElement)("div",{className:"jio-creator-dialog",role:"dialog","aria-modal":"true","aria-labelledby":"jio-code-lang-title"},(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__backdrop","aria-label":(0,a.__)("关闭","jio"),onClick:()=>H(null)}),(0,e.createElement)("div",{className:"jio-creator-dialog__panel"},(0,e.createElement)("header",{className:"jio-creator-dialog__head"},(0,e.createElement)("h2",{id:"jio-code-lang-title"},(0,a.__)("代码语言","jio")),(0,e.createElement)("button",{type:"button",className:"jio-creator-dialog__close",onClick:()=>H(null),"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)("div",{className:"jio-creator__lang-grid"},q.map(t=>(0,e.createElement)("button",{key:t.value,type:"button",className:"jio-creator__lang-item"+(t.value===I?" is-active":""),onClick:()=>{const e=J.current;if(J.current=null,H(null),!e)return;e.setAttribute("data-enlighter-language",t.value);const a=e.querySelector("code");a&&a.setAttribute("data-enlighter-language",t.value),B(i.current),oe(j(i.current.getContent()))}},t.label)))))),x&&(0,e.createElement)(R,{kind:x,onSubmit:ve,onClose:()=>L(null)}),(0,e.createElement)(M,{charCount:ae,saveState:N,isPublishedEdit:te,saving:!_||"saving"===N.state||"submitting"===N.state,onSaveDraft:()=>{ce(!1)},onPreview:()=>{de()},onPublish:()=>S(!0)}),C&&(0,e.createElement)(s,{draft:n,setDraft:ne,capabilities:Z,limits:ee,taxonomy:{categories:D.categories&&D.categories.items||[],tags:!!D.tags?.enabled,customDefs:D.customDefs||[]},isPublishedEdit:te,onClose:()=>S(!1),onSaveDraft:()=>{ce(!1)},onSubmit:e=>{se(e)},privateStorage:!!D.privateStorage,privateUploads:D.privateUploads||[],captcha:!!D.captcha?.enabled,saving:"saving"===N.state||"submitting"===N.state}))}function J(){const a=document.getElementById("jio-creator-studio");a&&(a.classList.add("is-ready"),(0,t.createRoot)(a).render((0,e.createElement)(H,null)))}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",J):J()})();
|
||||
@@ -459,8 +459,10 @@ function Studio(): JSX.Element {
|
||||
return true;
|
||||
}
|
||||
const requestRevision = editRevisionRef.current;
|
||||
const hasDocument = current.title.trim() !== '' || plainText(current.content).trim() !== '';
|
||||
if (autosave && !hasDocument) {
|
||||
// 空文档(连块级内容都没有)不发请求:服务端会拒绝,前端也不该把它当失败。
|
||||
const hasDocument = current.title.trim() !== '' || plainText(current.content).trim() !== ''
|
||||
|| /<(?:img|table|pre|hr|iframe|video)/i.test(current.content);
|
||||
if (!hasDocument) {
|
||||
return true;
|
||||
}
|
||||
setSaveState({ state: 'saving', at: '' });
|
||||
|
||||
@@ -65,11 +65,16 @@ trait FrontSubmitSave {
|
||||
$content = (string) ($data['post_content'] ?? $data['content'] ?? '');
|
||||
$excerpt = sanitize_textarea_field((string) ($data['excerpt'] ?? $data['post_excerpt'] ?? ''));
|
||||
|
||||
if ($title === '') {
|
||||
return ['success' => false, 'message' => __('请填写文章标题', 'jio')];
|
||||
}
|
||||
if (trim(wp_strip_all_tags($content)) === '') {
|
||||
return ['success' => false, 'message' => __('还未填写任何内容', 'jio')];
|
||||
// 草稿只要有任何可保存的内容就落库;正式投稿才要求标题与正文齐备。
|
||||
if (!$is_draft) {
|
||||
if ($title === '') {
|
||||
return ['success' => false, 'message' => __('请填写文章标题', 'jio')];
|
||||
}
|
||||
if (trim(wp_strip_all_tags($content)) === '') {
|
||||
return ['success' => false, 'message' => __('还未填写任何内容', 'jio')];
|
||||
}
|
||||
} elseif ($title === '' && trim(wp_strip_all_tags($content)) === '') {
|
||||
return ['success' => false, 'message' => __('请先写点什么再保存', 'jio')];
|
||||
}
|
||||
|
||||
$categories = $this->normalize_category_ids($data);
|
||||
|
||||
@@ -66,6 +66,19 @@ test('stale autosave requests are rejected instead of overwriting', () => {
|
||||
assert.match(appSource, /status === 409/);
|
||||
});
|
||||
|
||||
test('drafts save with partial content instead of being rejected', () => {
|
||||
// 只写标题、或正文只有图片/表格/代码块时,也必须能存草稿。
|
||||
assert.match(saveTrait, /请先写点什么再保存/);
|
||||
const draftBranch = saveTrait.indexOf('if (!$is_draft) {');
|
||||
const titleGuard = saveTrait.indexOf("if ($title === '') {");
|
||||
assert.ok(draftBranch !== -1 && titleGuard !== -1, 'draft branch and title guard both exist');
|
||||
assert.ok(draftBranch < titleGuard, 'title/content requirements only apply to submit');
|
||||
// 前端空文档不再发保存请求。
|
||||
assert.match(appSource, /const hasDocument = /);
|
||||
assert.match(appSource, /if \(!hasDocument\) \{\s*return true;/);
|
||||
assert.match(appSource, /img\|table\|pre\|hr\|iframe\|video/);
|
||||
});
|
||||
|
||||
test('paid payload is validated before any post write', () => {
|
||||
const prepareAt = saveTrait.indexOf('prepare_pay_meta');
|
||||
const insertAt = saveTrait.indexOf('wp_insert_post');
|
||||
|
||||
Reference in new issue
Block a user