feat(creator-studio): multi-select category picker and creatable tag input

分类从平铺复选标签改为带搜索的多选下拉(触发器内是已选令牌),
标签改为令牌输入框:回车 / 逗号 / 顿号 / 分号 / 换行切分,输入时列出
站点已有标签作为建议,面板内可一键新建。

- 抽出 useAnchoredPanel,工具条下拉与新的选择器共用同一套 portal 定位
- bootstrap 的 tags 增加 suggestions(按使用量取前 200 个已有标签)
- 清理 .jio-creator-inline 与 chip 内的死样式

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-09 17:35:52 +08:00
1 parent 8bb4b98fc9
commit 330df53195
10 files changed
+888 -170

No files matched your search

@@ -477,6 +477,36 @@ test('writing surface is a centered paper card with a publish settings card belo
assert.doesNotMatch(drawer, /jio-creator-captcha/);
});
test('publish settings use a multi-select category picker and a creatable tag input', () => {
const settings = read('assets/creator-studio/src/components/publish-settings.tsx');
const category = read('assets/creator-studio/src/components/category-select.tsx');
const tag = read('assets/creator-studio/src/components/tag-input.tsx');
const styles = read('assets/creator-studio/src/styles/_publish-drawer.scss');
// 分类:带搜索的多选下拉,触发器里是已选令牌。
assert.match(settings, /<CategorySelect/);
assert.match(category, /createPortal/);
assert.match(category, /type="checkbox"/);
assert.match(category, /onChange\(/);
assert.match(category, /选择分类(可多选)/);
// 旧的分类平铺复选列表已移除(自定义分类法仍是复选标签,不受影响)。
assert.doesNotMatch(settings, /toggleCategory/);
assert.doesNotMatch(settings, /categories\.includes\(/);
// 标签:可直接新建,并展示站点已有标签作为建议。
assert.match(settings, /<TagInput/);
assert.match(tag, /新建标签/);
assert.match(tag, /站点已有标签/);
assert.match(tag, /SEPARATORS/);
assert.match(tag, /Backspace/);
assert.doesNotMatch(styles, /\.jio-creator-inline\s*\{/);
// 服务端把已有标签作为建议下发,前端只读。
assert.match(creatorRest, /'suggestions'\s*=>/);
assert.match(creatorRest, /'taxonomy'\s*=>\s*'post_tag'/);
assert.match(appSource, /suggestions: \(bootstrap\.tags && bootstrap\.tags\.suggestions\)/);
});
test('scheduled publishing is validated and applied server side', () => {
const save = read('src/Core/FrontSubmitSave.php');
const rest = read('src/Core/CreatorRest.php');