modify
This commit is contained in:
268
002/all.html
268
002/all.html
@@ -59,8 +59,8 @@
|
||||
.brand { font-size: 18px; font-weight: 700; display: flex; align-items: center; gap: 10px; }
|
||||
.brand span { padding: 4px 8px; background: var(--primary); border-radius: 4px; font-size: 14px; }
|
||||
|
||||
.nav-top a { padding: 8px 12px; color: #94a3b8; font-size: 13px; border-radius: 4px; }
|
||||
.nav-top a:hover, .nav-top a.active { color: white; background: rgba(255,255,255,0.1); }
|
||||
.nav-top button { padding: 8px 12px; color: #94a3b8; font-size: 13px; border-radius: 4px; background: transparent; border: none; cursor: pointer; }
|
||||
.nav-top button:hover, .nav-top button.active { color: white; background: rgba(255,255,255,0.1); }
|
||||
|
||||
.user-area { display: flex; align-items: center; gap: 15px; }
|
||||
.avatar { width: 32px; height: 32px; background: var(--primary); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; border: 2px solid rgba(255,255,255,0.2); }
|
||||
@@ -70,7 +70,7 @@
|
||||
.sidebar { width: var(--sidebar-w); background: var(--bg-sidebar); border-right: 1px solid var(--border); display: flex; flex-direction: column; padding-top: 10px; transition: background 0.3s; }
|
||||
.menu-group { margin-bottom: 20px; }
|
||||
.menu-header { font-size: 11px; text-transform: uppercase; color: var(--text-muted); padding: 0 20px; margin-bottom: 8px; font-weight: 700; }
|
||||
.menu-item { padding: 10px 20px; display: flex; align-items: center; color: var(--text-muted); font-weight: 500; border-left: 3px solid transparent; }
|
||||
.menu-item { padding: 10px 20px; display: flex; align-items: center; color: var(--text-muted); font-weight: 500; border-left: 3px solid transparent; background: transparent; border: none; width: 100%; cursor: pointer; text-align: left; }
|
||||
.menu-item:hover { background: var(--bg-body); color: var(--text-main); }
|
||||
.menu-item.active { background: var(--primary-light); color: var(--primary); border-left-color: var(--primary); }
|
||||
.badge { margin-left: auto; background: var(--danger); color: white; font-size: 10px; padding: 2px 6px; border-radius: 10px; }
|
||||
@@ -177,46 +177,46 @@
|
||||
</svg>
|
||||
|
||||
<div class="app-container">
|
||||
<header class="header">
|
||||
<header class="header" role="banner">
|
||||
<div class="brand">
|
||||
<svg class="icon" style="width:24px; height:24px;"><use xlink:href="#i-check"></use></svg>
|
||||
<svg class="icon" style="width:24px; height:24px;" aria-hidden="true"><use xlink:href="#i-check"></use></svg>
|
||||
GlobalGuard <span>Audit V9.4</span>
|
||||
</div>
|
||||
<div class="nav-top">
|
||||
<a onclick="app.nav('dashboard')" class="active">Workspace</a>
|
||||
<a onclick="app.nav('orders')">Order Queue (200+)</a>
|
||||
<a onclick="app.nav('settings')">Settings</a>
|
||||
</div>
|
||||
<nav class="nav-top" aria-label="Main navigation">
|
||||
<button onclick="app.nav('dashboard')" class="active" aria-current="page">Workspace</button>
|
||||
<button onclick="app.nav('orders')">Order Queue (200+)</button>
|
||||
<button onclick="app.nav('settings')">Settings</button>
|
||||
</nav>
|
||||
<div class="user-area">
|
||||
<div style="text-align: right; font-size:12px;">
|
||||
<div>Auditor_4421</div>
|
||||
<div style="color:rgba(255,255,255,0.6)">East China Audit Group</div>
|
||||
</div>
|
||||
<div class="avatar">A</div>
|
||||
<div class="avatar" aria-label="User avatar">A</div>
|
||||
<button class="btn" style="background:rgba(255,255,255,0.1); padding:5px 10px;" onclick="app.showLogout()">Logout</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="main-body">
|
||||
<aside class="sidebar">
|
||||
<div class="menu-group">
|
||||
<div class="menu-header">Core Operations</div>
|
||||
<div class="menu-item active" onclick="app.nav('dashboard')" id="menu-dashboard">
|
||||
<svg class="icon"><use xlink:href="#i-home"></use></svg> Dashboard Overview
|
||||
</div>
|
||||
<div class="menu-item" onclick="app.nav('orders')" id="menu-orders">
|
||||
<svg class="icon"><use xlink:href="#i-list"></use></svg> Audit Queue
|
||||
<span class="badge" id="sidebar-count">--</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-group">
|
||||
<div class="menu-header">Tools</div>
|
||||
<div class="menu-item" onclick="app.nav('settings')" id="menu-settings">
|
||||
<svg class="icon"><use xlink:href="#i-settings"></use></svg> System Settings
|
||||
</div>
|
||||
</div>
|
||||
<aside class="sidebar" role="navigation" aria-label="Sidebar navigation">
|
||||
<nav class="menu-group">
|
||||
<h2 class="menu-header">Core Operations</h2>
|
||||
<button class="menu-item active" onclick="app.nav('dashboard')" id="menu-dashboard" role="menuitem" aria-current="page">
|
||||
<svg class="icon" aria-hidden="true"><use xlink:href="#i-home"></use></svg> Dashboard Overview
|
||||
</button>
|
||||
<button class="menu-item" onclick="app.nav('orders')" id="menu-orders" role="menuitem">
|
||||
<svg class="icon" aria-hidden="true"><use xlink:href="#i-list"></use></svg> Audit Queue
|
||||
<span class="badge" id="sidebar-count" aria-label="Pending orders count">--</span>
|
||||
</button>
|
||||
</nav>
|
||||
<nav class="menu-group">
|
||||
<h2 class="menu-header">Tools</h2>
|
||||
<button class="menu-item" onclick="app.nav('settings')" id="menu-settings" role="menuitem">
|
||||
<svg class="icon" aria-hidden="true"><use xlink:href="#i-settings"></use></svg> System Settings
|
||||
</button>
|
||||
</nav>
|
||||
<div style="margin-top:auto; padding:20px;">
|
||||
<div style="background:var(--bg-body); padding:10px; border-radius:4px; font-size:11px; color:var(--text-muted);">
|
||||
<div style="background:var(--bg-body); padding:10px; border-radius:4px; font-size:11px; color:var(--text-muted);" role="status" aria-live="polite">
|
||||
<strong>Server Status:</strong><br>
|
||||
<span style="color:var(--success)">●</span> Live Data Stream<br>
|
||||
<span style="color:var(--success)">●</span> Database (OK)
|
||||
@@ -229,33 +229,33 @@
|
||||
<div id="view-dashboard" class="view-panel active">
|
||||
<h2 style="margin-bottom:20px;">Today's Data Overview (Live)</h2>
|
||||
|
||||
<div class="stat-grid">
|
||||
<div class="stat-box">
|
||||
<div class="stat-grid" role="region" aria-label="Today's statistics">
|
||||
<article class="stat-box">
|
||||
<span class="stat-label">Pending Orders</span>
|
||||
<span class="stat-num" id="dash-pending">--</span>
|
||||
<span class="stat-num" id="dash-pending" role="status" aria-live="polite">--</span>
|
||||
<span class="stat-trend trend-down">Action Required</span>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
</article>
|
||||
<article class="stat-box">
|
||||
<span class="stat-label">High Risk Intercepts</span>
|
||||
<span class="stat-num" style="color:var(--danger)" id="dash-risk">--</span>
|
||||
<span class="stat-trend">Ratio <span id="dash-risk-rate">--%</span></span>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<span class="stat-num" style="color:var(--danger)" id="dash-risk" role="status" aria-live="polite">--</span>
|
||||
<span class="stat-trend">Ratio <span id="dash-risk-rate" aria-label="Risk ratio percentage">--%</span></span>
|
||||
</article>
|
||||
<article class="stat-box">
|
||||
<span class="stat-label">Total Amount (CNY)</span>
|
||||
<span class="stat-num" id="dash-amount">--</span>
|
||||
<span class="stat-num" id="dash-amount" role="status" aria-live="polite">--</span>
|
||||
<span class="stat-trend trend-up">vs Yesterday ↑ 23%</span>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
</article>
|
||||
<article class="stat-box">
|
||||
<span class="stat-label">My Performance (Today)</span>
|
||||
<span class="stat-num" style="color:var(--success)">42</span>
|
||||
<span class="stat-trend">KPI Achievement 80%</span>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<section class="card" role="region" aria-labelledby="announcements-title">
|
||||
<div class="card-header">
|
||||
<span class="card-title">System Announcements</span>
|
||||
<span class="tag tag-urgent">New</span>
|
||||
<h3 id="announcements-title" class="card-title" style="margin:0;">System Announcements</h3>
|
||||
<span class="tag tag-urgent" aria-label="New announcements">New</span>
|
||||
</div>
|
||||
<div style="font-size:13px; color:var(--text-muted); line-height:1.6;">
|
||||
<p><strong>[Security Alert] Notification on Risk Upgrade for Graphics Card Proxy Buying</strong></p>
|
||||
@@ -264,20 +264,22 @@
|
||||
<p><strong>[System Update] V9.4 Patch Notes</strong></p>
|
||||
<p>Integrated mock data generation engine, demo environment now supports 200+ concurrent order displays.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="view-orders" class="view-panel">
|
||||
<h2 style="margin-bottom:20px;">Manual Audit Queue</h2>
|
||||
|
||||
<div class="filter-panel">
|
||||
<fieldset class="filter-panel" aria-label="Order filters">
|
||||
<legend style="display:none;">Filter orders</legend>
|
||||
<div class="form-group">
|
||||
<label>Keywords (Order/User/Product)</label>
|
||||
<input type="text" class="input-control" id="search-keyword" placeholder="Enter keywords...">
|
||||
<label for="search-keyword">Keywords (Order/User/Product)</label>
|
||||
<input type="text" class="input-control" id="search-keyword" placeholder="Enter keywords..." aria-describedby="keyword-help">
|
||||
<span id="keyword-help" style="display:none;">Search by order ID, user name, or product name</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Risk Level</label>
|
||||
<select class="input-control" id="search-risk">
|
||||
<label for="search-risk">Risk Level</label>
|
||||
<select class="input-control" id="search-risk" aria-label="Filter by risk level">
|
||||
<option value="all">All Levels</option>
|
||||
<option value="high">High (High Risk)</option>
|
||||
<option value="medium">Medium (Medium Risk)</option>
|
||||
@@ -285,46 +287,46 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Order Status</label>
|
||||
<select class="input-control" id="search-status">
|
||||
<label for="search-status">Order Status</label>
|
||||
<select class="input-control" id="search-status" aria-label="Filter by order status">
|
||||
<option value="pending">Pending Audit</option>
|
||||
<option value="all_history">All History</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="margin-left:auto; display:flex; gap:10px;">
|
||||
<button class="btn btn-secondary" onclick="app.resetFilter()">Reset</button>
|
||||
<button class="btn btn-primary" onclick="app.applyFilter()">
|
||||
<svg class="icon"><use xlink:href="#i-list"></use></svg> Search
|
||||
<button class="btn btn-secondary" onclick="app.resetFilter()" aria-label="Reset all filters">Reset</button>
|
||||
<button class="btn btn-primary" onclick="app.applyFilter()" aria-label="Apply filters and search">
|
||||
<svg class="icon" aria-hidden="true"><use xlink:href="#i-list"></use></svg> Search
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="order-table-wrapper">
|
||||
<table class="order-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px;"><input type="checkbox" id="check-all" onclick="app.toggleSelectAll()"></th>
|
||||
<th>Order Info</th>
|
||||
<th>User Profile</th>
|
||||
<th>Product Overview</th>
|
||||
<th>Amount</th>
|
||||
<th>Risk Score</th>
|
||||
<th>Status</th>
|
||||
<th style="text-align:right;">Actions</th>
|
||||
<div class="order-table-wrapper" role="region" aria-label="Orders table">
|
||||
<table class="order-table" role="table" aria-label="Audit queue orders">
|
||||
<thead role="rowgroup">
|
||||
<tr role="row">
|
||||
<th role="columnheader" style="width:40px;"><input type="checkbox" id="check-all" onclick="app.toggleSelectAll()" aria-label="Select all orders"></th>
|
||||
<th role="columnheader">Order Info</th>
|
||||
<th role="columnheader">User Profile</th>
|
||||
<th role="columnheader">Product Overview</th>
|
||||
<th role="columnheader">Amount</th>
|
||||
<th role="columnheader">Risk Score</th>
|
||||
<th role="columnheader">Status</th>
|
||||
<th role="columnheader" style="text-align:right;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="table-body">
|
||||
<tbody id="table-body" role="rowgroup">
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="empty-state" style="padding:40px; text-align:center; color:var(--text-muted); display:none;">
|
||||
<div id="empty-state" style="padding:40px; text-align:center; color:var(--text-muted); display:none;" role="status" aria-live="polite">
|
||||
No orders found matching your criteria
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top:15px; display:flex; gap:10px; align-items:center;">
|
||||
<button class="btn btn-primary" onclick="app.batchAction('approve')">Batch Approve</button>
|
||||
<button class="btn btn-danger" onclick="app.batchAction('reject')">Batch Reject</button>
|
||||
<span style="margin-left:auto; font-size:12px; color:var(--text-muted);">
|
||||
<button class="btn btn-primary" onclick="app.batchAction('approve')" aria-label="Batch approve selected orders">Batch Approve</button>
|
||||
<button class="btn btn-danger" onclick="app.batchAction('reject')" aria-label="Batch reject selected orders">Batch Reject</button>
|
||||
<span style="margin-left:auto; font-size:12px; color:var(--text-muted);" role="status" aria-live="polite">
|
||||
Showing <strong id="current-count">0</strong> results / Total <span id="total-db-count">0</span>
|
||||
</span>
|
||||
</div>
|
||||
@@ -332,15 +334,16 @@
|
||||
|
||||
<div id="view-settings" class="view-panel">
|
||||
<h2>System Preferences</h2>
|
||||
<div class="card" style="margin-top:20px; max-width:600px;">
|
||||
<section class="card" style="margin-top:20px; max-width:600px;" role="region" aria-labelledby="settings-title">
|
||||
<h3 id="settings-title" style="display:none;">Settings</h3>
|
||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">
|
||||
<div>
|
||||
<h4 style="margin:0 0 5px 0;">Dark Mode</h4>
|
||||
<div style="font-size:12px; color:var(--text-muted);">Switch interface to dark theme, suitable for night work.</div>
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="theme-toggle" onchange="app.toggleTheme()">
|
||||
<span class="slider"></span>
|
||||
<label class="switch" for="theme-toggle">
|
||||
<input type="checkbox" id="theme-toggle" onchange="app.toggleTheme()" aria-label="Toggle dark mode">
|
||||
<span class="slider" aria-hidden="true"></span>
|
||||
</label>
|
||||
</div>
|
||||
<hr style="border:0; border-top:1px solid var(--border); margin:15px 0;">
|
||||
@@ -349,65 +352,67 @@
|
||||
<h4 style="margin:0 0 5px 0;">Auto-Refresh List</h4>
|
||||
<div style="font-size:12px; color:var(--text-muted);">Automatically fetch new orders every 60 seconds.</div>
|
||||
</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" checked>
|
||||
<span class="slider"></span>
|
||||
<label class="switch" for="auto-refresh-toggle">
|
||||
<input type="checkbox" id="auto-refresh-toggle" checked aria-label="Toggle auto-refresh">
|
||||
<span class="slider" aria-hidden="true"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<div class="drawer-backdrop" id="drawer-backdrop" onclick="app.closeDrawer()"></div>
|
||||
<div class="drawer" id="drawer-panel">
|
||||
<div class="drawer-backdrop" id="drawer-backdrop" onclick="app.closeDrawer()" role="presentation" aria-hidden="true"></div>
|
||||
<aside class="drawer" id="drawer-panel" role="complementary" aria-label="Order details panel" aria-modal="true">
|
||||
<div class="drawer-header">
|
||||
<h3 style="margin:0;">Order Details <span id="d-id" style="font-weight:400; color:var(--text-muted);"></span></h3>
|
||||
<button class="btn btn-secondary" style="padding:4px 8px;" onclick="app.closeDrawer()">×</button>
|
||||
<button class="btn btn-secondary" style="padding:4px 8px;" onclick="app.closeDrawer()" aria-label="Close order details panel">×</button>
|
||||
</div>
|
||||
<div class="drawer-body" id="d-content">
|
||||
<div class="drawer-body" id="d-content" role="region" aria-label="Order information">
|
||||
</div>
|
||||
<div class="drawer-footer" id="d-footer">
|
||||
<button class="btn btn-danger" onclick="app.rejectCurrent()">Reject Order</button>
|
||||
<button class="btn btn-primary" onclick="app.approveCurrent()">Approve Order</button>
|
||||
<button class="btn btn-danger" onclick="app.rejectCurrent()" aria-label="Reject this order">Reject Order</button>
|
||||
<button class="btn btn-primary" onclick="app.approveCurrent()" aria-label="Approve this order">Approve Order</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<div class="modal-overlay" id="modal-reject">
|
||||
<div class="modal">
|
||||
<div class="modal-overlay" id="modal-reject" role="presentation" aria-hidden="true">
|
||||
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="reject-title">
|
||||
<div class="modal-body">
|
||||
<h3 style="margin-top:0;">Confirm Reject?</h3>
|
||||
<h3 id="reject-title" style="margin-top:0;">Confirm Reject?</h3>
|
||||
<p style="color:var(--text-muted); font-size:13px; margin-bottom:15px;">Please select a reason for rejection. The system will notify the user.</p>
|
||||
<select class="input-control" id="reject-reason" style="width:100%; margin-bottom:10px;">
|
||||
<label for="reject-reason" style="display:block; margin-bottom:8px; font-weight:600; font-size:13px;">Rejection Reason</label>
|
||||
<select class="input-control" id="reject-reason" style="width:100%; margin-bottom:10px;" aria-label="Select rejection reason">
|
||||
<option value="风险拦截-疑似盗刷">Risk Intercept - Suspected Fraud</option>
|
||||
<option value="信息不全-地址模糊">Incomplete Info - Vague Address</option>
|
||||
<option value="限购限制-超出数量">Purchase Limit - Exceeded Quantity</option>
|
||||
<option value="其他原因">Other Reason</option>
|
||||
</select>
|
||||
<textarea class="input-control" id="reject-note" style="width:100%; height:80px;" placeholder="Notes (Optional)..."></textarea>
|
||||
<label for="reject-note" style="display:block; margin-bottom:8px; font-weight:600; font-size:13px;">Additional Notes</label>
|
||||
<textarea class="input-control" id="reject-note" style="width:100%; height:80px;" placeholder="Notes (Optional)..." aria-label="Additional rejection notes"></textarea>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button onclick="app.closeModal('modal-reject')">Cancel</button>
|
||||
<button class="confirm" onclick="app.confirmReject()">Confirm Reject</button>
|
||||
<button onclick="app.closeModal('modal-reject')" aria-label="Cancel rejection">Cancel</button>
|
||||
<button class="confirm" onclick="app.confirmReject()" aria-label="Confirm order rejection">Confirm Reject</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-overlay" id="modal-logout">
|
||||
<div class="modal">
|
||||
<div class="modal-overlay" id="modal-logout" role="presentation" aria-hidden="true">
|
||||
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="logout-title">
|
||||
<div class="modal-body">
|
||||
<h3>System Logout</h3>
|
||||
<h3 id="logout-title">System Logout</h3>
|
||||
<p style="color:var(--text-muted);">Are you sure you want to log out? Unsaved changes will be lost.</p>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button onclick="app.closeModal('modal-logout')">Cancel</button>
|
||||
<button class="confirm" onclick="location.reload()">Confirm Logout</button>
|
||||
<button onclick="app.closeModal('modal-logout')" aria-label="Cancel logout">Cancel</button>
|
||||
<button class="confirm" onclick="location.reload()" aria-label="Confirm logout">Confirm Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast-container" id="toast-root"></div>
|
||||
<div class="toast-container" id="toast-root" role="region" aria-live="polite" aria-atomic="true" aria-label="Notifications"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -506,10 +511,10 @@ const app = {
|
||||
const menuEl = document.getElementById(menuId);
|
||||
if(menuEl) menuEl.classList.add('active');
|
||||
|
||||
document.querySelectorAll('.nav-top a').forEach(el => el.classList.remove('active'));
|
||||
if(viewId === 'orders') document.querySelector('.nav-top a:nth-child(2)').classList.add('active');
|
||||
if(viewId === 'dashboard') document.querySelector('.nav-top a:nth-child(1)').classList.add('active');
|
||||
if(viewId === 'settings') document.querySelector('.nav-top a:nth-child(3)').classList.add('active');
|
||||
document.querySelectorAll('.nav-top button').forEach(el => el.classList.remove('active'));
|
||||
if(viewId === 'orders') document.querySelector('.nav-top button:nth-child(2)').classList.add('active');
|
||||
if(viewId === 'dashboard') document.querySelector('.nav-top button:nth-child(1)').classList.add('active');
|
||||
if(viewId === 'settings') document.querySelector('.nav-top button:nth-child(3)').classList.add('active');
|
||||
},
|
||||
|
||||
toggleTheme() {
|
||||
@@ -596,29 +601,29 @@ const app = {
|
||||
}).join('');
|
||||
|
||||
htmlBuffer += `
|
||||
<tr>
|
||||
<td><input type="checkbox" class="row-check" value="${order.id}" onchange="app.toggleSelect('${order.id}')" ${this.data.selectedIds.has(order.id) ? 'checked' : ''} ${order.status !== 'pending' ? 'disabled' : ''}></td>
|
||||
<td>
|
||||
<tr role="row">
|
||||
<td role="cell"><input type="checkbox" class="row-check" value="${order.id}" onchange="app.toggleSelect('${order.id}')" aria-label="Select order ${order.id}" ${this.data.selectedIds.has(order.id) ? 'checked' : ''} ${order.status !== 'pending' ? 'disabled' : ''}></td>
|
||||
<td role="cell">
|
||||
<div style="font-weight:600; font-family:'Consolas', monospace;">${order.id}</div>
|
||||
<div style="font-size:12px; color:var(--text-muted);">${order.date}</div>
|
||||
<div style="margin-top:4px;">${tagsHtml}</div>
|
||||
</td>
|
||||
<td>
|
||||
<td role="cell">
|
||||
<div>${order.user}</div>
|
||||
<div style="font-size:11px; color:var(--text-muted);">Credit Score: ${order.userScore || 'N/A'}</div>
|
||||
</td>
|
||||
<td><div title="${itemSummary}">${itemSummary}</div></td>
|
||||
<td style="font-weight:600; color:var(--text-main);">¥ ${order.total.toLocaleString()}</td>
|
||||
<td>
|
||||
<td role="cell"><div title="${itemSummary}">${itemSummary}</div></td>
|
||||
<td role="cell" style="font-weight:600; color:var(--text-main);">¥ ${order.total.toLocaleString()}</td>
|
||||
<td role="cell">
|
||||
<div style="font-weight:bold; color:${riskColor};">${order.score} / 100</div>
|
||||
<div class="risk-bar-container">
|
||||
<div class="risk-bar-container" role="progressbar" aria-valuenow="${order.score}" aria-valuemin="0" aria-valuemax="100" aria-label="Risk score progress">
|
||||
<div class="risk-bar-fill" style="width: ${order.score}%; background: ${riskColor};"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td>${statusBadge}</td>
|
||||
<td style="text-align:right;">
|
||||
<button class="btn btn-secondary" style="padding:4px 8px;" onclick="app.openDrawer('${order.id}')">
|
||||
<svg class="icon" style="margin:0;"><use xlink:href="#i-eye"></use></svg>
|
||||
<td role="cell">${statusBadge}</td>
|
||||
<td role="cell" style="text-align:right;">
|
||||
<button class="btn btn-secondary" style="padding:4px 8px;" onclick="app.openDrawer('${order.id}')" aria-label="View details for order ${order.id}">
|
||||
<svg class="icon" aria-hidden="true" style="margin:0;"><use xlink:href="#i-eye"></use></svg>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -650,36 +655,38 @@ const app = {
|
||||
const content = document.getElementById('d-content');
|
||||
|
||||
let itemsHtml = order.items.map(item => `
|
||||
<div style="display:flex; justify-content:space-between; border-bottom:1px dashed #eee; padding:8px 0;">
|
||||
<span>${item.name} x ${item.qty}</span>
|
||||
<span style="font-weight:600;">¥ ${(item.price * item.qty).toLocaleString()}</span>
|
||||
<div style="display:flex; justify-content:space-between; border-bottom:1px dashed #eee; padding:8px 0;" role="row">
|
||||
<span role="cell">${item.name} x ${item.qty}</span>
|
||||
<span role="cell" style="font-weight:600;">¥ ${(item.price * item.qty).toLocaleString()}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
content.innerHTML = `
|
||||
<div class="detail-section">
|
||||
<section class="detail-section">
|
||||
<h4>Risk Control Decision Engine</h4>
|
||||
<div style="background:${order.risk === 'high' ? '#fff5f5' : '#f0fdf4'}; padding:10px; border-radius:4px; border:1px solid ${order.risk === 'high' ? '#feb2b2' : '#bbf7d0'};">
|
||||
<div style="background:${order.risk === 'high' ? '#fff5f5' : '#f0fdf4'}; padding:10px; border-radius:4px; border:1px solid ${order.risk === 'high' ? '#feb2b2' : '#bbf7d0'};" role="status" aria-live="polite">
|
||||
<div style="font-weight:bold; color:${order.risk === 'high' ? '#c53030' : '#22543d'};">
|
||||
Composite Risk Score: ${order.score} (${order.risk.toUpperCase()})
|
||||
</div>
|
||||
<p style="margin:5px 0 0 0; font-size:12px; color:var(--text-muted);">${order.logs}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section">
|
||||
</section>
|
||||
<section class="detail-section">
|
||||
<h4>Shipping Info</h4>
|
||||
<div class="info-grid">
|
||||
<span class="info-label">Consignee:</span> <span class="info-val">${order.user}</span>
|
||||
<span class="info-label">Address:</span> <span class="info-val" style="grid-column:span 2">${order.address}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section">
|
||||
</section>
|
||||
<section class="detail-section">
|
||||
<h4>Item List</h4>
|
||||
${itemsHtml}
|
||||
<div role="table" aria-label="Order items">
|
||||
${itemsHtml}
|
||||
</div>
|
||||
<div style="text-align:right; margin-top:10px; font-size:16px; font-weight:700;">
|
||||
Total: ¥ ${order.total.toLocaleString()}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
`;
|
||||
|
||||
const footer = document.getElementById('d-footer');
|
||||
@@ -795,6 +802,9 @@ const app = {
|
||||
const container = document.getElementById('toast-root');
|
||||
const el = document.createElement('div');
|
||||
el.className = `toast ${type}`;
|
||||
el.setAttribute('role', 'status');
|
||||
el.setAttribute('aria-live', 'polite');
|
||||
el.setAttribute('aria-atomic', 'true');
|
||||
el.innerHTML = `<span>${msg}</span>`;
|
||||
container.appendChild(el);
|
||||
setTimeout(() => el.classList.add('show'), 10);
|
||||
|
||||
Reference in New Issue
Block a user