Merge pull request 'feat(admin): expose shop/forum CPTs on native WP sidebar (Phase 0–1)' (#140) from worktree-zibll-native-admin-menus into main

Reviewed-on: CYL/wordpress-theme-aksrt#140
This commit is contained in:
2026-07-15 01:45:07 +08:00
6 changed files with 388 additions and 60 deletions
+150
View File
@@ -0,0 +1,150 @@
# Admin IA Map — zibll-aligned native ops + SPA config
> Living blueprint for AKSRT admin information architecture after the zibll 1:1 ops-menu migration.
> Source of truth for *where* a surface lives; field-level schema remains in Vue schema / PHP schema provider.
## Split rule (locked)
| Layer | Surface | Purpose |
|-------|---------|---------|
| **WP native sidebar** | CPT menus, `aksrt_pay` top menu, `users.php` submenus | Day-to-day **operations** (content CRUD, orders, tickets) |
| **AKSRT SPA** (`admin.php?page=aksrt-settings#/...`) | Schema-driven pages only | **Configuration** (switches, layout, gateways, policies) |
Do **not** reintroduce operational workbenches into the SPA once native pages ship.
---
## Native sidebar tree (target)
```
[pos ~34 separator]
商城 (aksrt_product) pos 35, dashicons-store
├─ 所有商品 / 新增商品
├─ 商品分类 (aksrt_product_cat)
├─ 特色标签 (aksrt_product_tag)
└─ 优惠活动 (shop_discount)
支付中心 (aksrt_pay) pos ~36–38, dashicons-cart
├─ 概览 aksrt_pay
├─ 订单 aksrt_orders
├─ 发货及物流 aksrt_shipping
├─ 售后管理 aksrt_after_sale
├─ 优惠码 aksrt_coupons
├─ 卡密管理 aksrt_charge_cards
├─ 创作分成 aksrt_income
├─ 推广返佣 aksrt_rebate
└─ 提现审核 aksrt_withdraw
[pos ~39 separator]
论坛版块 (aksrt_forum_plate) pos 40, dashicons-buddicons-forums
├─ 所有版块 / 添加版块
└─ 分区 (aksrt_plate_cat)
论坛帖子 (aksrt_forum_topic) pos 40, dashicons-buddicons-topics
├─ 所有帖子 / 添加帖子
├─ 话题 (aksrt_forum_topic_cat)
└─ 标签 (aksrt_forum_tag)
用户 (WP core users.php)
├─ 消息管理 users.php?page=aksrt_messages
├─ 邀请码管理 users.php?page=aksrt_invite_codes
├─ 身份认证 users.php?page=aksrt_user_auth
└─ 举报&禁封 users.php?page=aksrt_user_ban
AKSRT (SPA shell) pos 58, dashicons-admin-generic
└─ hash routes: config-only sections
```
### Feature gates
| Surface | Settings key | Notes |
|---------|--------------|-------|
| 商城 CPT/tax | `shop_s` → `AKSRT_Settings::get_shop_settings()['enabled']` | Hide menu when shop off |
| 论坛 CPT/tax | `bbs_s` → `get_forum_settings()['enabled']` | Front skips registration when off; admin still registers but may hide menu |
| 支付中心子项 | payment/shop/rebate switches | Per-submenu |
| 用户子菜单 | message / invite / verify / ban flags | Align SPA users schema |
Capability baseline: `manage_options` (later may tighten toward super-admin like zibll).
---
## SPA config tree (retained)
### 支付&付费 `/payment`
| Route | Type | Notes |
|-------|------|-------|
| `/payment/paid` | custom/schema | Download / paid-content **policy** |
| `/payment/recharge` | schema | Balance recharge |
| `/payment/vip` | schema | VIP plans |
| `/payment/gateway` | custom | Gateway credentials |
| `/payment/order` | schema | Order display settings (not order list) |
| `/payment/affiliate` | schema | Rebate **rules** |
| `/payment/card-pass` | schema | Card rules/copy |
| `/payment/withdrawal` | schema | Withdraw **policy** (tickets → native) |
**Removed from SPA (ops):** charge-card workbench, revenue table, rebate table.
### 商城&商品 `/shop`
| Route | Type |
|-------|------|
| `/shop/basic` | schema |
| `/shop/list` | schema |
| `/shop/single` | schema |
| `/shop/product-defaults` | schema |
| `/shop/contact` | schema |
| `/shop/shipping-config` | schema |
| `/shop/timing` | schema |
**Removed from SPA (ops):** products, orders, after-sale, shipping, coupons, withdrawals, dashboard.
Default SPA entry after strip: `/shop/basic`.
### 社区&论坛 `/forum`
| Route | Type |
|-------|------|
| `/forum/settings` | schema basic |
| `/forum/settings/names` | schema |
| `/forum/settings/homepage` | schema |
| `/forum/settings/board-page` | schema |
| `/forum/settings/post-page` | schema |
| `/forum/settings/reply` | schema |
| `/forum/settings/permissions` | schema |
| `/forum/settings/other` | schema |
| `/forum/settings/upload` | schema |
| `/forum/settings/credits` | schema |
**Removed from SPA (ops):** boards, topics, moderators, moderator-applications, dashboard.
Default SPA entry after strip: `/forum/settings`.
### 用户&互动 `/users` (config kept)
auth, oauth, features, signin, credits, verify **settings**, level, badge, notifications, sms, wechat, wechat-template.
**Removed from SPA (ops):** messages, invite-codes, ban, report queues.
---
## Canonical domain keys
Internal keys remain: `global`, `page_display`, `post_list`, `permissions`, `users`, `payment`, `shop`, `forum`, `extensions`, `tools`.
Route paths may stay friendly (`/page-display/...`); ops native pages use `admin.php?page=aksrt_*` slugs above.
---
## Rollout phases
| Phase | Deliverable |
|-------|-------------|
| 0 | This map + gap matrix |
| 1 | CPT/tax native menus |
| 2 | `aksrt_pay` PHP list pages |
| 3 | `users.php` governance submenus |
| 4 | Strip SPA ops routes/components |
| 5+ | Runtime behavior parity backlog |
See also: [zibll-gap-matrix.md](./zibll-gap-matrix.md).
+105
View File
@@ -0,0 +1,105 @@
# zibll ↔ AKSRT gap matrix (admin ops entry)
Three-way mapping: **zibll current → AKSRT before migration → AKSRT target**.
Focus: admin **entry & page shape**. Runtime field parity is Phase 5+.
---
## Shop
| zibll | AKSRT before | AKSRT target | Data / service |
|-------|--------------|--------------|----------------|
| CPT `shop_product` pos 35, `dashicons-store`, super-admin `show_ui` | `aksrt_product` `show_ui=true`, **`show_in_menu=false`** | Native menu pos 35, store icon; gate on `shop_s` | CPT |
| Tax `shop_cat` | `aksrt_product_cat` show_ui false | show_ui + admin column under product | taxonomy |
| Tax `shop_tag` | `aksrt_product_tag` show_ui false | show_ui under product | taxonomy |
| Tax `shop_discount` | `shop_discount` show_ui false | show_ui under product | `AKSRT_Shop_Term_Meta` |
| Product list columns | Trait exists, wired in `functions.php` | Keep/enhance on native list | admin columns trait |
| Product edit meta | SPA `ShopProducts` + REST | Native meta box (Phase 1b) | product ops / post meta |
| Orders | SPA `ShopOrders` | `admin.php?page=aksrt_orders` | `AKSRT_Order` |
| Shipping | SPA `ShopShipping` | `aksrt_shipping` | `AKSRT_Shipping` |
| After-sale | SPA `ShopAfterSale` | `aksrt_after_sale` | `AKSRT_After_Sale` |
| Coupons | SPA `ShopCoupons` / zibpay coupon page | `aksrt_coupons` | `AKSRT_Coupon` |
| Shop CSF config | SPA shop schema | **Keep SPA schema** | `AKSRT_Settings::get_shop_settings()` |
---
## Forum / community
| zibll | AKSRT before | AKSRT target | Data / service |
|-------|--------------|--------------|----------------|
| CPT `plate` pos 40, forums icon | `aksrt_forum_plate` **show_in_menu false** | show_in_menu true, pos 40, `dashicons-buddicons-forums` | CPT |
| Tax `plate_cat` | `aksrt_plate_cat` | show_ui under plate | taxonomy |
| CPT `forum_post` pos 40, topics icon | `aksrt_forum_topic` default menu, comments icon | pos 40, `dashicons-buddicons-topics`, explicit menu | CPT |
| Tax `forum_topic` / `forum_tag` | `aksrt_forum_topic_cat` / `aksrt_forum_tag` | show_ui under topic | taxonomy |
| Legacy board tax | — | `aksrt_forum_board` keep rewrite bridge, **hide admin UI** (plate is canonical) | taxonomy |
| Boards/topics SPA | `ForumBoards` / `ForumTopics` | Native CPT lists | `AKSRT_Forum` |
| Moderators / applications | SPA | Plate meta box + optional subpage | moderation service |
| BBS CSF config | SPA forum schema | **Keep SPA schema** | `get_forum_settings()` |
---
## Payment / zibpay ops
| zibll page | Purpose | AKSRT before | Target slug | Service |
|------------|---------|--------------|-------------|---------|
| `zibpay_page` | Dashboard | SPA dashboards | `aksrt_pay` | aggregates |
| `zibpay_page#/order` | Orders (new) | SPA ShopOrders | `aksrt_orders` | `AKSRT_Order` |
| `zibpay_order_page` | Orders (legacy) | SPA | same native list | |
| `zibpay_page#/shipping` | Shipping | SPA | `aksrt_shipping` | `AKSRT_Shipping` |
| `zibpay_page#/after-sale` | After-sale | SPA | `aksrt_after_sale` | `AKSRT_After_Sale` |
| `zibpay_product_page` | Paid-post sales report | partial | optional later `aksrt_pay_products` | content pay |
| `zibpay_income_page` | Creator income | `PaymentRevenue` | `aksrt_income` | `AKSRT_Revenue` |
| `zibpay_rebate_page` | Rebate | `PaymentRebate` | `aksrt_rebate` | `AKSRT_Rebate` |
| `zibpay_withdraw` | Withdraw | `ShopWithdrawals` | `aksrt_withdraw` | `AKSRT_Withdrawal` |
| `zibpay_charge_card_page` | Charge cards | `PaymentChargeCard` | `aksrt_charge_cards` | `AKSRT_Charge_Card` |
| `zibpay_coupon_page` | Coupons | `ShopCoupons` | `aksrt_coupons` | `AKSRT_Coupon` |
| CSF pay sections | Gateways/VIP/… | SPA payment schema | **Keep SPA** | settings |
Note: zibll「商品管理」`zibpay_product_page` is **paid article sales**, not the physical `shop_product` CPT list.
---
## User governance
| zibll | slug | AKSRT before | Target |
|-------|------|--------------|--------|
| 消息管理 | `user_messags` under users.php | SPA `UsersMessages` | `users.php?page=aksrt_messages` |
| 邀请码管理 | `invit_code` | SPA `UsersInviteCodes` | `aksrt_invite_codes` |
| 身份认证 | `user_auth` | SPA `UsersVerify` queue | `aksrt_user_auth` |
| 举报&禁封申诉 | `user_ban` | SPA Ban + Report | single `aksrt_user_ban` with tabs |
| Credits column | users list | `AKSRT_User_Credits_Admin` | keep |
| CSF user config | — | SPA users schema | keep |
---
## SPA ops routes to delete (Phase 4)
### shop.js
`shop-products`, `shop-orders`, `shop-after-sale`, `shop-shipping`, `shop-coupons`, `shop-withdrawals`, `shop-dashboard`
### forum.js
`forum-boards`, `forum-topics`, `forum-moderators`, `forum-moderator-applications`, `forum-dashboard`
### payment.js
`payment-charge-card`, `payment-revenue`, `payment-rebate` (ops tables)
### users.js
`users-messages`, `users-invite-codes`, `users-ban`, `users-report` (queues)
---
## Phase status
| Phase | Status |
|-------|--------|
| 0 Docs + matrix | in progress |
| 1 Native CPT/tax menus | in progress |
| 2 Pay list tables | pending |
| 3 users.php submenus | pending |
| 4 SPA strip | pending (after 1–3) |
| 5+ behavior parity | backlog |
## Dual-UI rule
Native write path must work **before** removing the matching SPA ops route. No data migration: same tables/meta; UI only.
+26 -12
View File
@@ -121,10 +121,20 @@ class AKSRT_Setup {
$product_slug = sanitize_key((string) ($shop_rewrite['product_slug'] ?? 'product'));
$suffix_html = !empty($shop_rewrite['suffix_html']);
// 商品 CPT
// Shop admin visibility: align with zibll native sidebar when shop is enabled.
$shop_enabled = true;
if (class_exists('AKSRT_Settings')) {
$shop_settings = AKSRT_Settings::get_shop_settings();
$shop_enabled = !empty($shop_settings['enabled']);
}
// Always register UI in admin so settings/tools remain reachable; hide menu when disabled.
$shop_show_ui = true;
$shop_show_menu = is_admin() ? $shop_enabled : false;
// 商品 CPT — native WP sidebar (zibll: shop_product @ pos 35)
register_post_type('aksrt_product', [
'labels' => [
'name' => __('商品', 'aksrt'),
'name' => __('商城', 'aksrt'),
'singular_name' => __('商品', 'aksrt'),
'add_new' => __('新增商品', 'aksrt'),
'add_new_item' => __('新增商品', 'aksrt'),
@@ -134,15 +144,18 @@ class AKSRT_Setup {
'search_items' => __('搜索商品', 'aksrt'),
'not_found' => __('未找到商品', 'aksrt'),
'not_found_in_trash' => __('回收站中无商品', 'aksrt'),
'menu_name' => __('商品', 'aksrt'),
'all_items' => __('所有商品', 'aksrt'),
'menu_name' => __('商城', 'aksrt'),
],
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => false,
'show_ui' => $shop_show_ui,
'show_in_menu' => $shop_show_menu,
'show_in_rest' => true,
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 35,
'menu_icon' => 'dashicons-store',
'supports' => ['title', 'editor', 'excerpt', 'thumbnail', 'author', 'revisions'],
'rewrite' => ['slug' => $product_slug, 'with_front' => false],
'capability_type' => 'post',
@@ -163,9 +176,10 @@ class AKSRT_Setup {
],
'public' => true,
'hierarchical' => true,
'show_ui' => false,
'show_ui' => $shop_show_ui,
'show_in_menu' => $shop_show_menu,
'show_in_rest' => true,
'show_admin_column' => false,
'show_admin_column' => true,
'rewrite' => ['slug' => 'product-cat', 'with_front' => false],
]);
@@ -178,15 +192,15 @@ class AKSRT_Setup {
'all_items' => __('所有商品标签', 'aksrt'),
'edit_item' => __('编辑标签', 'aksrt'),
'add_new_item' => __('新增标签', 'aksrt'),
'menu_name' => __('商品标签', 'aksrt'),
'menu_name' => __('特色标签', 'aksrt'),
],
'public' => true,
'hierarchical' => false,
'show_ui' => false,
'show_ui' => $shop_show_ui,
'show_in_menu' => $shop_show_menu,
'show_in_rest' => true,
'show_admin_column' => false,
'rewrite' => ['slug' => 'product-tag', 'with_front' => false,
],
'show_admin_column' => true,
'rewrite' => ['slug' => 'product-tag', 'with_front' => false],
]);
// 项目展示
+11 -2
View File
@@ -45,6 +45,14 @@ class AKSRT_Shop_Term_Meta {
return;
}
$shop_enabled = true;
if (class_exists('AKSRT_Settings')) {
$shop_settings = AKSRT_Settings::get_shop_settings();
$shop_enabled = !empty($shop_settings['enabled']);
}
$shop_show_ui = true;
$shop_show_menu = is_admin() ? $shop_enabled : false;
register_taxonomy('shop_discount', 'aksrt_product', [
'labels' => [
'name' => __('优惠活动', 'aksrt'),
@@ -57,9 +65,10 @@ class AKSRT_Shop_Term_Meta {
],
'public' => true,
'hierarchical' => false,
'show_ui' => false,
'show_ui' => $shop_show_ui,
'show_in_menu' => $shop_show_menu,
'show_in_rest' => true,
'show_admin_column' => false,
'show_admin_column' => true,
'rewrite' => ['slug' => 'shop-discount', 'with_front' => false],
]);
}
@@ -5,7 +5,7 @@ trait AKSRT_Setup_Part_2 {
/**
* 隐藏默认WordPress菜单项目
* 隐藏默认WordPress菜单项目 + zibll 风格运营菜单分隔线
*/
public function hide_default_menus(): void {
// 移除评论默认菜单(已移除该操作以恢复 Comments 菜单)
@@ -13,10 +13,22 @@ trait AKSRT_Setup_Part_2 {
// 移除链接管理(已废弃但仍可能存在)
//remove_menu_page('link-manager.php');
// 移除仪表盘中的不必要组件
remove_meta_box('dashboard_primary', 'dashboard', 'normal');
remove_meta_box('dashboard_quick_press', 'dashboard', 'side');
// Separators around shop (35) and forum (40) — match zibll admin_menu_separator.
global $menu;
if (!is_array($menu)) {
return;
}
if (!isset($menu[34])) {
$menu[34] = ['', 'read', 'separator-aksrt-shop', '', 'wp-menu-separator'];
}
if (!isset($menu[39])) {
$menu[39] = ['', 'read', 'separator-aksrt-forum', '', 'wp-menu-separator'];
}
}
/**
+82 -44
View File
@@ -92,16 +92,25 @@ function aksrt_register_forum_cpt() {
}
}
// Read custom slugs from settings when available
$plate_slug = 'board';
$topic_slug = 'topic';
// Read custom slugs / names from settings when available
$plate_slug = 'board';
$topic_slug = 'topic';
$forum_enabled = true;
$forum_settings = [];
if (class_exists('AKSRT_Settings')) {
$forum = AKSRT_Settings::get_forum_settings();
$plate_slug = !empty($forum['other']['plate_slug']) ? $forum['other']['plate_slug'] : 'board';
$topic_slug = !empty($forum['other']['posts_slug']) ? $forum['other']['posts_slug'] : 'topic';
$forum_settings = AKSRT_Settings::get_forum_settings();
$plate_slug = !empty($forum_settings['other']['plate_slug']) ? $forum_settings['other']['plate_slug'] : 'board';
$topic_slug = !empty($forum_settings['other']['posts_slug']) ? $forum_settings['other']['posts_slug'] : 'topic';
$forum_enabled = !empty($forum_settings['enabled']);
}
// Forum Board taxonomy
// Admin always registers types; menu follows bbs_s (zibll: show when forum on).
$forum_show_menu = is_admin() ? $forum_enabled : false;
$names = !empty($forum_settings['names']) ? $forum_settings['names'] : [];
$forum_label = sanitize_text_field((string) ($names['forum'] ?? __('论坛', 'aksrt')));
$posts_label = sanitize_text_field((string) ($names['posts'] ?? __('帖子', 'aksrt')));
$topic_label = sanitize_text_field((string) ($names['topic'] ?? __('话题', 'aksrt')));
$tag_label = sanitize_text_field((string) ($names['tag'] ?? __('标签', 'aksrt')));
// Legacy board taxonomy: keep rewrite/bridge, hide from admin (plate CPT is canonical).
register_taxonomy('aksrt_forum_board', 'aksrt_forum_topic', [
'labels' => [
'name' => __('论坛版块', 'aksrt'),
@@ -113,58 +122,72 @@ function aksrt_register_forum_cpt() {
],
'hierarchical' => true,
'public' => true,
'show_ui' => false,
'show_in_menu' => false,
'show_in_rest' => true,
'show_admin_column' => true,
'show_admin_column' => false,
'rewrite' => ['slug' => $plate_slug],
]);
// Forum Tag taxonomy
register_taxonomy('aksrt_forum_tag', 'aksrt_forum_topic', [
'labels' => [
'name' => __('论坛标签', 'aksrt'),
'singular_name' => __('标签', 'aksrt'),
'search_items' => __('搜索标签', 'aksrt'),
'all_items' => __('所有标签', 'aksrt'),
'edit_item' => __('编辑标签', 'aksrt'),
'add_new_item' => __('添加标签', 'aksrt'),
'name' => sprintf(/* translators: %s: forum name */ __('%s标签', 'aksrt'), $forum_label),
'singular_name' => $tag_label,
'search_items' => sprintf(/* translators: %s: tag name */ __('搜索%s', 'aksrt'), $tag_label),
'all_items' => sprintf(/* translators: %s: tag name */ __('所有%s', 'aksrt'), $tag_label),
'edit_item' => sprintf(/* translators: %s: tag name */ __('编辑%s', 'aksrt'), $tag_label),
'add_new_item' => sprintf(/* translators: %s: tag name */ __('添加%s', 'aksrt'), $tag_label),
'menu_name' => $tag_label,
],
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => $forum_show_menu,
'show_in_rest' => true,
'show_admin_column' => false,
'show_admin_column' => true,
'rewrite' => ['slug' => 'forum-tag'],
]);
// Forum Topic taxonomy (话题,单选,区别于标签)
register_taxonomy('aksrt_forum_topic_cat', 'aksrt_forum_topic', [
'labels' => [
'name' => __('论坛话题', 'aksrt'),
'singular_name' => __('话题', 'aksrt'),
'search_items' => __('搜索话题', 'aksrt'),
'all_items' => __('所有话题', 'aksrt'),
'edit_item' => __('编辑话题', 'aksrt'),
'add_new_item' => __('添加话题', 'aksrt'),
'name' => sprintf(/* translators: %s: forum name */ __('%s话题', 'aksrt'), $forum_label),
'singular_name' => $topic_label,
'search_items' => sprintf(/* translators: %s: topic name */ __('搜索%s', 'aksrt'), $topic_label),
'all_items' => sprintf(/* translators: %s: topic name */ __('所有%s', 'aksrt'), $topic_label),
'edit_item' => sprintf(/* translators: %s: topic name */ __('编辑%s', 'aksrt'), $topic_label),
'add_new_item' => sprintf(/* translators: %s: topic name */ __('添加%s', 'aksrt'), $topic_label),
'menu_name' => $topic_label,
],
'hierarchical' => false,
'public' => true,
'show_ui' => true,
'show_in_menu' => $forum_show_menu,
'show_in_rest' => true,
'show_admin_column' => true,
'rewrite' => ['slug' => 'forum-topic'],
]);
// Forum Topic CPT
// Forum Topic CPT — native sidebar (zibll: forum_post @ pos 40)
register_post_type('aksrt_forum_topic', [
'labels' => [
'name' => __('论坛主题', 'aksrt'),
'singular_name' => __('主题', 'aksrt'),
'add_new_item' => __('发布新主题', 'aksrt'),
'edit_item' => __('编辑主题', 'aksrt'),
'view_item' => __('查看主题', 'aksrt'),
'name' => $forum_label . $posts_label,
'singular_name' => $posts_label,
'add_new' => sprintf(/* translators: %s: posts name */ __('添加%s', 'aksrt'), $posts_label),
'add_new_item' => sprintf(/* translators: %s: posts name */ __('发布新%s', 'aksrt'), $posts_label),
'edit_item' => sprintf(/* translators: %s: posts name */ __('编辑%s', 'aksrt'), $posts_label),
'view_item' => sprintf(/* translators: %s: posts name */ __('查看%s', 'aksrt'), $posts_label),
'all_items' => sprintf(/* translators: %s: posts name */ __('所有%s', 'aksrt'), $posts_label),
'menu_name' => $forum_label . $posts_label,
],
'public' => true,
'show_ui' => true,
'show_in_menu' => $forum_show_menu,
'show_in_rest' => true,
'has_archive' => true,
'menu_icon' => 'dashicons-comments',
'menu_position' => 40,
'menu_icon' => 'dashicons-buddicons-topics',
'supports' => ['title', 'editor', 'author', 'comments', 'thumbnail', 'excerpt'],
'capability_type' => 'post',
'rewrite' => ['slug' => $topic_slug],
@@ -186,50 +209,65 @@ function aksrt_register_forum_plate_cpt() {
}
}
$plate_slug = 'board';
$plate_slug = 'board';
$forum_enabled = true;
$forum = [];
if (class_exists('AKSRT_Settings')) {
$forum = AKSRT_Settings::get_forum_settings();
$plate_slug = !empty($forum['other']['plate_slug']) ? $forum['other']['plate_slug'] : 'board';
$forum = AKSRT_Settings::get_forum_settings();
$plate_slug = !empty($forum['other']['plate_slug']) ? $forum['other']['plate_slug'] : 'board';
$forum_enabled = !empty($forum['enabled']);
}
$forum_show_menu = is_admin() ? $forum_enabled : false;
$names = !empty($forum['names']) ? $forum['names'] : [];
$forum_label = sanitize_text_field((string) ($names['forum'] ?? __('论坛', 'aksrt')));
$plate_label = sanitize_text_field((string) ($names['plate'] ?? __('版块', 'aksrt')));
// Plate category taxonomy (分区)
register_taxonomy('aksrt_plate_cat', 'aksrt_forum_plate', [
'labels' => [
'name' => __('板块分区', 'aksrt'),
'name' => sprintf(/* translators: %s: plate name */ __('%s分区', 'aksrt'), $plate_label),
'singular_name' => __('分区', 'aksrt'),
'search_items' => __('搜索分区', 'aksrt'),
'all_items' => __('所有分区', 'aksrt'),
'edit_item' => __('编辑分区', 'aksrt'),
'add_new_item' => __('添加分区', 'aksrt'),
'menu_name' => __('分区', 'aksrt'),
],
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_in_menu' => $forum_show_menu,
'show_in_rest' => true,
'show_admin_column' => true,
'rewrite' => ['slug' => 'plate-cat'],
]);
// Plate CPT (板块)
// Plate CPT (板块) — native sidebar (zibll: plate @ pos 40)
register_post_type('aksrt_forum_plate', [
'labels' => [
'name' => __('论坛版块', 'aksrt'),
'singular_name' => __('版块', 'aksrt'),
'add_new_item' => __('创建版块', 'aksrt'),
'edit_item' => __('编辑版块', 'aksrt'),
'view_item' => __('查看版块', 'aksrt'),
'search_items' => __('搜索版块', 'aksrt'),
'not_found' => __('未找到版块', 'aksrt'),
'not_found_in_trash' => __('回收站中未找到版块', 'aksrt'),
'name' => $forum_label . $plate_label,
'singular_name' => $plate_label,
'add_new' => sprintf(/* translators: %s: plate name */ __('添加%s', 'aksrt'), $plate_label),
'add_new_item' => sprintf(/* translators: %s: plate name */ __('创建%s', 'aksrt'), $plate_label),
'edit_item' => sprintf(/* translators: %s: plate name */ __('编辑%s', 'aksrt'), $plate_label),
'view_item' => sprintf(/* translators: %s: plate name */ __('查看%s', 'aksrt'), $plate_label),
'search_items' => sprintf(/* translators: %s: plate name */ __('搜索%s', 'aksrt'), $plate_label),
'not_found' => sprintf(/* translators: %s: plate name */ __('未找到%s', 'aksrt'), $plate_label),
'not_found_in_trash' => sprintf(/* translators: %s: plate name */ __('回收站中未找到%s', 'aksrt'), $plate_label),
'all_items' => sprintf(/* translators: %s: plate name */ __('所有%s', 'aksrt'), $plate_label),
'menu_name' => $forum_label . $plate_label,
],
'public' => true,
'hierarchical' => true,
'show_ui' => true,
'show_in_menu' => $forum_show_menu,
'show_in_rest' => true,
'has_archive' => false,
'menu_icon' => 'dashicons-grid-view',
'menu_position' => 40,
'menu_icon' => 'dashicons-buddicons-forums',
'supports' => ['title', 'editor', 'author', 'excerpt', 'thumbnail', 'page-attributes'],
'capability_type' => 'post',
'rewrite' => ['slug' => $plate_slug, 'with_front' => false],
'show_in_menu' => false,
]);
// Keep aksrt_forum_topic assignable to plates via taxonomy bridge