fix(creator-studio): caret overlap in toolbar and hidden sub-categories

工具条下拉触发器的下三角原本绝对定位在按钮右下角,按钮宽度不够时会压到
居中的文字上。改为文字 + 三角同行排版(.jio-creator__tool-meta),宽度不足
时只压缩文字。

分类只查询 parent=0,导致二级 / 三级分类在投稿页完全不可选。新增
SubmitCategories 统一解析:
- 取全部分类并按父子关系深度优先展平,带上 depth / path;
- 白名单按"选了上级即包含其全部子级"展开,未配置白名单时不做额外过滤;
- 创作者工作台、经典投稿表单、保存校验与审核应用共用同一份结果。

选择器按 depth 缩进,搜索同时匹配完整路径。

同时把 assets/creator-studio/build 与 assets/admin/build 统一为整目录忽略
(不再跟踪 .gitkeep),避免构建产物反复被误提交。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-09 18:10:19 +08:00
1 parent 330df53195
commit beb898b1ab
12 files changed
+291 -53

No files matched your search

@@ -380,7 +380,6 @@ test('quote, hidden content, and block math render like the live article', () =>
test('creator studio build artifacts and contracts exist', () => {
assert.ok(exists('assets/creator-studio/package.json'));
assert.ok(exists('assets/creator-studio/package-lock.json'));
assert.ok(exists('assets/creator-studio/build/.gitkeep'));
// build/ is gitignored and deploy-only (same as assets/admin/build); when a
// local build is present, all three entry artifacts must be there together.
const built = ['index.asset.php', 'index.js', 'index.css'];
@@ -507,6 +506,30 @@ test('publish settings use a multi-select category picker and a creatable tag in
assert.match(appSource, /suggestions: \(bootstrap\.tags && bootstrap\.tags\.suggestions\)/);
});
// 二级 / 三级分类必须出现在投稿页:列表是完整层级树,白名单向下展开到子分类。
test('submit categories resolve the full hierarchy and expand the whitelist', () => {
const categories = read('src/Core/SubmitCategories.php');
const submitContext = read('templates/parts/submit/context.php');
const save = read('src/Core/FrontSubmitSave.php');
// 不再用 parent=0 过滤,改为取全部分类后按父子关系展平。
assert.doesNotMatch(categories, /'parent'\s*=>\s*0/);
assert.match(categories, /get_term_children\(\$id, 'category'\)/);
assert.match(categories, /'number'\s*=>\s*0/);
assert.match(categories, /'depth'\s*=>\s*\$depth/);
// 父级不在集合里时,子分类仍作为根节点出现,不会被静默丢弃。
assert.match(categories, /if \(!isset\(\$present\[\$parent\]\)\) \{/);
// 创作者工作台与经典投稿表单共用同一份分类数据。
assert.match(creatorRest, /SubmitCategories::tree\(\$settings\)/);
assert.match(submitContext, /SubmitCategories::tree\(\$settings\)/);
assert.doesNotMatch(submitContext, /\$cat_args\['parent'\]\s*=\s*0/);
// 白名单与审核应用都走同一套"含后代"的过滤。
assert.match(save, /SubmitCategories::filter_ids\(\$categories, \$settings\)/);
assert.match(versions, /SubmitCategories::filter_ids\(\$cats, \$settings\)/);
});
test('scheduled publishing is validated and applied server side', () => {
const save = read('src/Core/FrontSubmitSave.php');
const rest = read('src/Core/CreatorRest.php');
@@ -34,10 +34,21 @@ namespace {
}
}
class WP_Term {
public int $term_id;
public string $name;
public int $parent;
public function __construct(int $term_id, string $name, int $parent = 0) {
$this->term_id = $term_id;
$this->name = $name;
$this->parent = $parent;
}
}
class WP_Error {
private string $code;
private string $message;
public function __construct($code = '', $message = '', $data = null) {
$this->code = (string) $code;
$this->message = (string) $message;
@@ -185,6 +196,13 @@ namespace {
function do_action($tag, ...$args): void { $GLOBALS['front_pending_state']['actions'][] = $tag; }
function current_time($type): string { return '2026-10-30 12:00:00'; }
function wp_set_post_categories($post_id, $categories): void {}
function get_terms($args = []) {
// 投稿分类解析需要一张分类表;本 harness 只关心上传生命周期,
// 给一个单层分类即可让白名单校验通过。
$term = new WP_Term(1, 'uncategorized', 0);
return [$term];
}
function get_term_children($term_id, $taxonomy) { return []; }
function wp_set_post_tags($post_id, $tags): void {}
function get_permalink($post_id): string { return 'https://example.test/?p=' . (int) $post_id; }
function clean_post_cache($post_id): void {}
@@ -334,6 +352,7 @@ namespace {
}
fp_reset();
require_once dirname(__DIR__, 2) . '/src/Core/SubmitCategories.php';
require_once dirname(__DIR__, 2) . '/src/Attachment/PendingUploads.php';
require_once dirname(__DIR__, 2) . '/src/Core/FrontSubmitSave.php';
require_once dirname(__DIR__, 2) . '/src/Core/FrontSubmitPay.php';