+
+
+
+
+
+
+ diff --git a/docs/admin-ia-map.md b/docs/admin-ia-map.md index 7b074bbe..9ca7ea06 100644 --- a/docs/admin-ia-map.md +++ b/docs/admin-ia-map.md @@ -28,6 +28,7 @@ Do **not** reintroduce operational workbenches into the SPA once native pages sh ├─ 概览 aksrt_pay ├─ 订单 aksrt_orders ├─ 付费文章 aksrt_pay_products +├─ 下载记录 aksrt_download_logs ├─ 发货及物流 aksrt_shipping ├─ 售后管理 aksrt_after_sale ├─ 优惠码 aksrt_coupons diff --git a/docs/zibll-gap-matrix.md b/docs/zibll-gap-matrix.md index 4a8822e6..f52696c0 100644 --- a/docs/zibll-gap-matrix.md +++ b/docs/zibll-gap-matrix.md @@ -99,8 +99,8 @@ Note: zibll「商品管理」`zibpay_product_page` is **paid article sales**, no | 2b Shipping/after-sale/coupons/income/rebate | done | | 3 users.php submenus | done | | 4 SPA strip | done (ops routes redirect to native) | -| 5+ behavior parity | done — native ops shell modularized (orders/shipping/after-sale/coupons/charge-cards/income/rebate/withdraw) + plate moderator roles/advanced limits/icon/sort + coupon product_scope create/edit/batch + paid-post sales report (`aksrt_pay_products`) + topic pay/points visibility admin/runtime alignment + plate follow-pay MVP + post list sales column + order type tabs + topic plate re-check | -| 5 remaining | download-log admin page; topic VIP1/2 full matrix; hidecontent shortcode partial-hide; users commerce columns | +| 5+ behavior parity | done — native ops shell modularized + plate follow-pay MVP + topic pay/points + sales report + post sales column + order type tabs + download logs page + hidecontent alias + topic VIP1/2 matrix + users commerce column + topic partial hide | +| 5 remaining | optional: multi-gateway for forum/topics; full zibll download modal UX; topic virtual_sales/coupon fields | ## Dual-UI rule diff --git a/functions.php b/functions.php index 4c793d43..c0d7c035 100644 --- a/functions.php +++ b/functions.php @@ -374,6 +374,9 @@ if (is_admin() && class_exists('AKSRT_Admin_Pay_Orders')) { if (is_admin() && class_exists('AKSRT_Admin_Pay_Products')) { AKSRT_Admin_Pay_Products::get_instance()->init(); } +if (is_admin() && class_exists('AKSRT_Admin_Pay_Download_Logs')) { + AKSRT_Admin_Pay_Download_Logs::get_instance()->init(); +} if (is_admin() && class_exists('AKSRT_Admin_Pay_Withdrawals')) { AKSRT_Admin_Pay_Withdrawals::get_instance()->init(); } diff --git a/inc/bootstrap.php b/inc/bootstrap.php index db167446..3dddba83 100644 --- a/inc/bootstrap.php +++ b/inc/bootstrap.php @@ -179,6 +179,7 @@ require_once AKSRT_DIR . '/inc/classes/admin/native/class-aksrt-admin-pay-shippi require_once AKSRT_DIR . '/inc/classes/admin/native/class-aksrt-admin-pay-after-sale.php'; require_once AKSRT_DIR . '/inc/classes/admin/native/class-aksrt-admin-pay-orders.php'; require_once AKSRT_DIR . '/inc/classes/admin/native/class-aksrt-admin-pay-products.php'; +require_once AKSRT_DIR . '/inc/classes/admin/native/class-aksrt-admin-pay-download-logs.php'; require_once AKSRT_DIR . '/inc/classes/admin/native/class-aksrt-admin-pay-withdrawals.php'; require_once AKSRT_DIR . '/inc/classes/admin/native/class-aksrt-admin-pay-income.php'; require_once AKSRT_DIR . '/inc/classes/admin/native/class-aksrt-admin-pay-rebate.php'; diff --git a/inc/classes/admin/native/class-aksrt-admin-pay-download-logs.php b/inc/classes/admin/native/class-aksrt-admin-pay-download-logs.php new file mode 100644 index 00000000..038243dc --- /dev/null +++ b/inc/classes/admin/native/class-aksrt-admin-pay-download-logs.php @@ -0,0 +1,202 @@ +ensure_cap(); + echo '
' . esc_html__('数据库服务不可用。', 'aksrt') . '
' . esc_html__('下载令牌表未初始化。', 'aksrt') . '
' . esc_html__('基于下载令牌表(aksrt_dl_token)。已使用记录会保留一段时间后清理;未使用且过期的令牌会被定期删除。', 'aksrt') . '
'; + + echo ''; + + // Fix: unchecked checkbox means used filter off — re-read without default if form submitted with no used. + // Already handled via isset($_GET['used']). + + echo '| ' . esc_html__('时间', 'aksrt') . ' | '; + echo '' . esc_html__('用户', 'aksrt') . ' | '; + echo '' . esc_html__('文章', 'aksrt') . ' | '; + echo '' . esc_html__('源序号', 'aksrt') . ' | '; + echo '' . esc_html__('积分消耗', 'aksrt') . ' | '; + echo '' . esc_html__('使用', 'aksrt') . ' | '; + echo '' . esc_html__('过期', 'aksrt') . ' | '; + echo '' . esc_html__('IP', 'aksrt') . ' | '; + echo '
|---|---|---|---|---|---|---|---|
| ' . esc_html__('暂无下载记录。', 'aksrt') . ' | |||||||
| ' . esc_html((string) ($row['created_at'] ?? '')) . ' | '; + echo '';
+ if ($user) {
+ echo esc_html($user->display_name . ' (#' . $uid . ')');
+ echo ' ' . esc_html__('仅此用户', 'aksrt') . ''; + } else { + echo esc_html((string) $uid); + } + echo ' | ';
+ echo '';
+ if ($edit) {
+ echo '' . esc_html($title) . '';
+ } else {
+ echo esc_html($title);
+ }
+ if ($pid > 0) {
+ echo ' ' . esc_html__('仅此文章', 'aksrt') . ''; + } + echo ' | ';
+ echo '' . esc_html((string) (int) ($row['source_index'] ?? 0)) . ' | '; + echo '' . esc_html((string) (int) ($row['cost'] ?? 0)) . ' | '; + echo '' . esc_html($used . ' / ' . $max) . ($used > 0 ? ' ' : '') . ' | '; + echo '' . esc_html((string) ($row['expires_at'] ?? '')) . ' | '; + echo '' . esc_html((string) ($row['ip_bind'] ?? '')) . ' | ';
+ echo '