diff --git a/functions.php b/functions.php
index e5e06080..56694bc9 100644
--- a/functions.php
+++ b/functions.php
@@ -315,6 +315,11 @@ if (is_admin() && class_exists('AKSRT_Topic_Admin_List')) {
if (is_admin() && class_exists('AKSRT_Topic_Meta_Box')) {
AKSRT_Topic_Meta_Box::get_instance()->init();
}
+// 论坛版块列表列
+if (is_admin() && class_exists('AKSRT_Plate_Admin_List')) {
+ AKSRT_Plate_Admin_List::get_instance()->init();
+}
+
diff --git a/inc/bootstrap.php b/inc/bootstrap.php
index 21fcc75a..accb5d0f 100644
--- a/inc/bootstrap.php
+++ b/inc/bootstrap.php
@@ -325,6 +325,7 @@ require_once AKSRT_DIR . '/inc/classes/shop/class-aksrt-product-variants-meta-bo
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-plate-meta-box.php';
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-topic-admin-list.php';
require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-topic-meta-box.php';
+require_once AKSRT_DIR . '/inc/classes/forum/class-aksrt-plate-admin-list.php';
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-1.php';
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-2.php';
require_once AKSRT_DIR . '/inc/classes/shop/shop-traits/trait-aksrt-shop-part-3.php';
diff --git a/inc/classes/admin/native/class-aksrt-admin-pay-menus.php b/inc/classes/admin/native/class-aksrt-admin-pay-menus.php
index a49e4336..34f523b9 100644
--- a/inc/classes/admin/native/class-aksrt-admin-pay-menus.php
+++ b/inc/classes/admin/native/class-aksrt-admin-pay-menus.php
@@ -35,7 +35,9 @@ class AKSRT_Admin_Pay_Menus {
add_action('admin_post_aksrt_pay_disable_charge_card', [$this, 'handle_disable_charge_card']);
add_action('admin_post_aksrt_pay_batch_charge_cards', [$this, 'handle_batch_charge_cards']);
add_action('admin_post_aksrt_pay_update_shipping', [$this, 'handle_update_shipping']);
+ add_action('admin_post_aksrt_pay_create_shipping', [$this, 'handle_create_shipping']);
add_action('admin_post_aksrt_pay_update_after_sale', [$this, 'handle_update_after_sale']);
+ add_action('admin_post_aksrt_pay_create_after_sale', [$this, 'handle_create_after_sale']);
add_action('admin_post_aksrt_pay_create_coupon', [$this, 'handle_create_coupon']);
add_action('admin_post_aksrt_pay_disable_coupon', [$this, 'handle_disable_coupon']);
add_action('admin_post_aksrt_pay_settle_income', [$this, 'handle_settle_income']);
@@ -202,8 +204,12 @@ class AKSRT_Admin_Pay_Menus {
'card_batch_failed' => __('卡密批量生成失败。', 'aksrt'),
'shipping_updated' => __('物流状态已更新。', 'aksrt'),
'shipping_failed' => __('物流状态更新失败。', 'aksrt'),
+ 'shipping_created' => __('发货记录已创建。', 'aksrt'),
+ 'shipping_create_failed' => __('发货记录创建失败。', 'aksrt'),
'after_sale_updated' => __('售后状态已更新。', 'aksrt'),
'after_sale_failed' => __('售后状态更新失败。', 'aksrt'),
+ 'after_sale_created' => __('售后工单已创建。', 'aksrt'),
+ 'after_sale_create_failed' => __('售后工单创建失败。', 'aksrt'),
'coupon_created' => __('优惠码已创建。', 'aksrt'),
'coupon_create_failed'=> __('优惠码创建失败(可能重复)。', 'aksrt'),
'coupon_disabled' => __('优惠码已禁用。', 'aksrt'),
@@ -463,8 +469,18 @@ class AKSRT_Admin_Pay_Menus {
echo '';
echo '
' . esc_html__('物流记录', 'aksrt') . '
';
+ echo '';
if (!$shipping_items) {
- echo '' . esc_html__('暂无物流记录。', 'aksrt') . ' ' . esc_html__('去物流管理', 'aksrt') . '
';
+ echo '' . esc_html__('暂无物流记录。', 'aksrt') . '
';
} else {
echo '| ID | ' . esc_html__('承运商', 'aksrt') . ' | ' . esc_html__('运单号', 'aksrt') . ' | ' . esc_html__('状态', 'aksrt') . ' | ' . esc_html__('时间', 'aksrt') . ' |
';
foreach ($shipping_items as $item) {
@@ -480,8 +496,29 @@ class AKSRT_Admin_Pay_Menus {
}
echo '' . esc_html__('售后工单', 'aksrt') . '
';
+ echo '';
if (!$after_sale) {
- echo '' . esc_html__('暂无售后工单。', 'aksrt') . ' ' . esc_html__('去售后管理', 'aksrt') . '
';
+ echo '' . esc_html__('暂无售后工单。', 'aksrt') . '
';
} else {
echo '| ID | ' . esc_html__('类型', 'aksrt') . ' | ' . esc_html__('状态', 'aksrt') . ' | ' . esc_html__('时间', 'aksrt') . ' |
';
foreach ($after_sale as $item) {
@@ -1019,6 +1056,64 @@ class AKSRT_Admin_Pay_Menus {
exit;
}
+ public function handle_create_shipping(): void {
+ if (!current_user_can(self::CAPABILITY)) {
+ wp_die(esc_html__('权限不足', 'aksrt'));
+ }
+ $order_number = isset($_POST['order_number']) ? sanitize_text_field((string) wp_unslash($_POST['order_number'])) : '';
+ check_admin_referer('aksrt_pay_create_shipping_' . $order_number);
+
+ $ok = false;
+ if ($order_number !== '' && class_exists('AKSRT_Shipping')) {
+ $id = AKSRT_Shipping::get_instance()->create([
+ 'order_number' => $order_number,
+ 'carrier' => sanitize_text_field((string) wp_unslash($_POST['carrier'] ?? '')),
+ 'tracking_no' => sanitize_text_field((string) wp_unslash($_POST['tracking_no'] ?? '')),
+ 'note' => sanitize_textarea_field((string) wp_unslash($_POST['note'] ?? '')),
+ 'operator_id' => get_current_user_id(),
+ ]);
+ $ok = $id > 0;
+ }
+
+ wp_safe_redirect($this->page_url('aksrt_orders', [
+ 'order' => $order_number,
+ 'aksrt_pay_msg' => $ok ? 'shipping_created' : 'shipping_create_failed',
+ ]));
+ exit;
+ }
+
+ public function handle_create_after_sale(): void {
+ if (!current_user_can(self::CAPABILITY)) {
+ wp_die(esc_html__('权限不足', 'aksrt'));
+ }
+ $order_number = isset($_POST['order_number']) ? sanitize_text_field((string) wp_unslash($_POST['order_number'])) : '';
+ check_admin_referer('aksrt_pay_create_after_sale_' . $order_number);
+
+ $ok = false;
+ if ($order_number !== '' && class_exists('AKSRT_After_Sale')) {
+ $user_id = isset($_POST['user_id']) ? (int) $_POST['user_id'] : 0;
+ if ($user_id <= 0 && class_exists('AKSRT_Order_Repository')) {
+ $order = AKSRT_Order_Repository::get_instance()->get($order_number);
+ $user_id = (int) ($order['user_id'] ?? 0);
+ }
+ $id = AKSRT_After_Sale::get_instance()->create([
+ 'order_number' => $order_number,
+ 'user_id' => $user_id,
+ 'type' => sanitize_key((string) wp_unslash($_POST['type'] ?? 'refund')),
+ 'reason' => sanitize_textarea_field((string) wp_unslash($_POST['reason'] ?? '')),
+ 'amount' => (float) ($_POST['amount'] ?? 0),
+ 'note' => sanitize_textarea_field((string) wp_unslash($_POST['note'] ?? '')),
+ ]);
+ $ok = $id > 0;
+ }
+
+ wp_safe_redirect($this->page_url('aksrt_orders', [
+ 'order' => $order_number,
+ 'aksrt_pay_msg' => $ok ? 'after_sale_created' : 'after_sale_create_failed',
+ ]));
+ exit;
+ }
+
/* ------------------------------------------------------------------
* After-sale
* ----------------------------------------------------------------*/
diff --git a/inc/classes/forum/class-aksrt-plate-admin-list.php b/inc/classes/forum/class-aksrt-plate-admin-list.php
new file mode 100644
index 00000000..5ef7cb95
--- /dev/null
+++ b/inc/classes/forum/class-aksrt-plate-admin-list.php
@@ -0,0 +1,107 @@
+ $label) {
+ $new[$key] = $label;
+ if ($key === 'title') {
+ $new['aksrt_plate_mods'] = __('版主数', 'aksrt');
+ $new['aksrt_plate_posts'] = __('帖子数', 'aksrt');
+ $new['aksrt_plate_reply'] = __('回复数', 'aksrt');
+ $new['aksrt_plate_views'] = __('浏览', 'aksrt');
+ $new['aksrt_plate_follow'] = __('关注', 'aksrt');
+ $new['aksrt_plate_pending_apps'] = __('待审申请', 'aksrt');
+ }
+ }
+ return $new;
+ }
+
+ public function sortable_columns(array $columns): array {
+ $columns['aksrt_plate_posts'] = 'aksrt_posts_count';
+ $columns['aksrt_plate_views'] = 'aksrt_plate_views';
+ return $columns;
+ }
+
+ public function render_column(string $column, int $post_id): void {
+ switch ($column) {
+ case 'aksrt_plate_mods':
+ $mods = get_post_meta($post_id, '_aksrt_moderators', true);
+ $count = is_array($mods) ? count(array_filter(array_map('intval', $mods))) : 0;
+ echo esc_html((string) $count);
+ break;
+ case 'aksrt_plate_posts':
+ echo esc_html((string) (int) get_post_meta($post_id, '_aksrt_posts_count', true));
+ break;
+ case 'aksrt_plate_reply':
+ echo esc_html((string) (int) get_post_meta($post_id, '_aksrt_reply_count', true));
+ break;
+ case 'aksrt_plate_views':
+ echo esc_html((string) (int) get_post_meta($post_id, '_aksrt_plate_views', true));
+ break;
+ case 'aksrt_plate_follow':
+ echo esc_html((string) (int) get_post_meta($post_id, '_aksrt_follow_count', true));
+ break;
+ case 'aksrt_plate_pending_apps':
+ $apps = get_post_meta($post_id, '_aksrt_moderator_applications', true);
+ $pending = 0;
+ if (is_array($apps)) {
+ foreach ($apps as $app) {
+ if (is_array($app) && (($app['status'] ?? '') === 'pending')) {
+ $pending++;
+ }
+ }
+ }
+ if ($pending > 0) {
+ echo '' . esc_html((string) $pending) . '';
+ } else {
+ echo '0';
+ }
+ break;
+ }
+ }
+
+ public function apply_orderby(WP_Query $query): void {
+ if (!is_admin() || !$query->is_main_query()) {
+ return;
+ }
+ if ($query->get('post_type') !== 'aksrt_forum_plate') {
+ return;
+ }
+ $orderby = $query->get('orderby');
+ if ($orderby === 'aksrt_posts_count') {
+ $query->set('meta_key', '_aksrt_posts_count');
+ $query->set('orderby', 'meta_value_num');
+ } elseif ($orderby === 'aksrt_plate_views') {
+ $query->set('meta_key', '_aksrt_plate_views');
+ $query->set('orderby', 'meta_value_num');
+ }
+ }
+}