feat(admin): redesign order list and detail workspace

Replace the type/method tab rows with status views backed by one GROUP BY
count, move filters into a single toolbar card, show gateway names, keep
list context across detail and actions, and split the detail page into a
summary/timeline column and an actions/buyer/note sidebar. Confirmations
move to admin-orders.js; PayOrders splits into flat List/Detail traits.

Remove dead code: unused Order AJAX endpoints and init(), get_orders_count(),
shipping flash codes, and the legacy raw-note fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Fable 5 committed 2026-10-31 14:03:57 +08:00
1 parent 8c553c7221
commit b32b56f8bc
11 files changed
+962 -537

No files matched your search

@@ -53,7 +53,7 @@ test('commission ledger and withdrawals retain their flow while order flows are
test('orders have no independent flow page or visible flow number', () => {
const menu = read('src/Admin/Native/PayMenus.php')
const payOrders = read('src/Admin/Native/PayOrders.php')
const payOrders = ['PayOrders', 'PayOrdersList', 'PayOrdersDetail'].map((f) => read(`src/Admin/Native/${f}.php`)).join('\n')
assert.doesNotMatch(menu, /PayFlows|流水明细/)
assert.equal(fs.existsSync(path.join(root, 'src/Admin/Native/PayFlows.php')), false)
assert.equal(fs.existsSync(path.join(root, 'src/Finance/FinancialFlowQuery.php')), false)
@@ -125,7 +125,7 @@ test('flow retention and archive were deliberately removed', () => {
assert.equal(fs.existsSync(path.join(root, 'src/Finance/FinancialFlowRetention.php')), false)
})
test('order detail page drops tabs; ticket center replaces the after-sale submenu', () => {
const page = read('src/Admin/Native/PayOrders.php')
const page = ['PayOrders', 'PayOrdersList', 'PayOrdersDetail'].map((f) => read(`src/Admin/Native/${f}.php`)).join('\n')
const menus = read('src/Admin/Native/PayMenus.php')
const repository = read('src/Payment/OrderRepositoryCore.php')
// 订单明细页不再有 Tab 分页:统计 Tab 与页面整体删除
@@ -152,10 +152,10 @@ test('order detail page drops tabs; ticket center replaces the after-sale submen
})
test('paid orders expose a refund button next to the detail link', () => {
const page = read('src/Admin/Native/PayOrders.php')
// 「退款」紧跟在「详情」右侧,仅已支付订单可见——已退款是已支付的唯一后继状态
assert.match(page, /详情', 'aksrt'\) \. '<\/a>';\s*\n\s*\/\/ 已支付是已退款的唯一前置状态[\s\S]*?aksrt_pay_refund_order/)
assert.ok(page.includes("if ($status_key === \\AKSRT\\Core\\DomainModel::ORDER_STATUS_PAID) {"),
const page = ['PayOrders', 'PayOrdersList', 'PayOrdersDetail'].map((f) => read(`src/Admin/Native/${f}.php`)).join('\n')
// 「标记退款」紧跟在「详情」右侧(行操作区由 order_actions_html 输出),仅已支付订单可见——已退款是已支付的唯一后继状态
assert.match(page, /详情', 'aksrt'\) \. '<\/a>'\s*\n\s*\. \$this->order_actions_html\(\$order_number, \$status\)/)
assert.match(page, /\/\/ 已支付是已退款的唯一前置状态。\s*\n\s*if \(\$status === DomainModel::ORDER_STATUS_PAID\) \{[\s\S]*?'aksrt_pay_refund_order'/,
'refund button only renders for paid orders')
assert.ok(page.includes('aksrt_pay_refund_order_'), 'per-order nonce covers the refund')
assert.ok(page.includes("add_action('admin_post_aksrt_pay_refund_order', [$this, 'handle_refund_order'])"),
@@ -202,7 +202,7 @@ test('caller-supplied order numbers are constrained to allocator shapes', () =>
test('order cleanup no longer guards on financial records', () => {
const repository = read('src/Payment/OrderRepositoryCore.php')
const payOrders = read('src/Admin/Native/PayOrders.php')
const payOrders = ['PayOrders', 'PayOrdersList', 'PayOrdersDetail'].map((f) => read(`src/Admin/Native/${f}.php`)).join('\n')
assert.match(repository, /public function clear_closed_orders\(int \$days = 14\): int/)
assert.match(repository, /public function delete_order\(string \$order_number\): bool/)
for (const source of [repository, payOrders]) {
@@ -7,7 +7,7 @@ const root = path.resolve(__dirname, '..', '..')
const read = (relativePath) => fs.readFileSync(path.join(root, relativePath), 'utf8')
test('admin order filters expose only the current order and payment categories', () => {
const page = read('src/Admin/Native/PayOrders.php')
const page = ['PayOrders', 'PayOrdersList', 'PayOrdersDetail'].map((f) => read(`src/Admin/Native/${f}.php`)).join('\n')
for (const [type, label] of [
['READING', '付费阅读'], ['DOWNLOAD', '付费下载'], ['IMAGE', '付费图片'], ['VIDEO', '付费视频'],
@@ -24,7 +24,7 @@ test('admin order filters expose only the current order and payment categories',
})
test('third-party payment filter resolves registered external gateways as one query', () => {
const page = read('src/Admin/Native/PayOrders.php')
const page = ['PayOrders', 'PayOrdersList', 'PayOrdersDetail'].map((f) => read(`src/Admin/Native/${f}.php`)).join('\n')
const repository = read('src/Payment/OrderRepositoryAdmin.php')
assert.match(page, /\$args\['payment_methods'\]\s*=\s*\$this->third_party_gateway_ids\(\)/)