feat(forum): add quick publish, captcha and hidden content

Port the reference inline quick-publish composer to the forum home:
title/body inputs, image upload, plate/topic/access/hidden-content
dropdowns and save/publish actions. Wire the site captcha into forum
publishing through a new `forum_post` scene (admin + REST gate), and
turn the hidden-content box into the theme's own visibility shortcodes
(login/comment/vip/payshow) so the existing gate renderer unlocks them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Fable 5 committed 2026-11-11 16:37:31 +08:00
1 parent 5d3358d844
commit 7a59c65252
11 files changed
+204 -20

No files matched your search

+40
View File
@@ -61,3 +61,43 @@ test('compose page saves draft state and the cover through the REST contract', (
assert.ok(runtime.includes(token), `compose runtime missing ${token}`)
}
})
test('quick publish mirrors the reference inline composer', () => {
const quick = read('src/Forum/QuickPost.php')
for (const token of ['quick-posts-box', 'quick-input-group', 'edit-posts-title', 'line-form-input', 'edit-posts-content', 'quick-upload', 'quick-more-btns', 'plate-drop', 'topic-drop', 'allow-view-drop', 'hide-type-drop', 'quick-posts-submit', 'data-forum-draft']) {
assert.ok(quick.includes(token), `quick publish missing ${token}`)
}
// Guests get the login trigger instead of the editor actions.
assert.match(quick, /signin-loader/)
assert.match(quick, /登录后发布/)
})
test('forum publishing is gated by the site captcha scene', () => {
const rest = read('src/Forum/RestPosts.php')
const captcha = read('inc/modules/captcha.php')
const schema = read('src/Admin/Schema/SchemaPermissions.php')
const vue = read('assets/admin/src/schema/sections/permissions/index.js')
const quick = read('src/Forum/QuickPost.php')
const edit = read('src/Forum/EditView.php')
assert.match(captcha, /'forum_post'\s*=>\s*__\('论坛发帖'/)
assert.match(schema, /\['label' => '论坛发帖', 'value' => 'forum_post'\]/)
assert.match(vue, /\{ label: '论坛发帖', value: 'forum_post' \}/)
assert.match(rest, /jio_require_captcha\('forum_post'/)
assert.match(rest, /jio_captcha_proof/)
assert.match(quick, /jio_render_captcha\('forum_post'\)/)
assert.match(edit, /jio_render_captcha\('forum_post'\)/)
})
test('hidden content becomes the site visibility shortcode on save', () => {
const rest = read('src/Forum/Rest.php')
const posts = read('src/Forum/RestPosts.php')
const quick = read('src/Forum/QuickPost.php')
const edit = read('src/Forum/EditView.php')
assert.match(posts, /append_hidden_content\(\$content, \$input\)/)
assert.match(rest, /'logged' => 'login', 'reply' => 'comment', 'vip1' => 'vip', 'payshow' => 'payshow'/)
assert.match(rest, /hidecontent type="/)
assert.match(rest, /payshow/)
for (const token of ['hide_type', 'hide_content', '登录可见', '评论可见', '会员可见', '付费可见']) {
assert.ok(quick.includes(token) && edit.includes(token), `hidden content missing ${token}`)
}
})