| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <!doctype html>
- <html lang="zh-CN">
- <head>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <title>Cockpit Work Order Seven States Demo</title>
- <style>
- body { margin:0; min-height:100vh; background:#08131f; color:#e8f1f8; font:15px/1.5 "Microsoft YaHei",sans-serif; }
- main { width:min(1280px,calc(100vw - 32px)); margin:28px auto; display:grid; gap:16px; }
- header, section { background:#0e1e2d; border:1px solid #21465f; padding:20px; }
- h1,h2,h3 { margin:0 0 10px; } h1 { font-size:22px; } h2 { font-size:17px; } h3 { font-size:15px; }
- .endpoint { color:#78a2b8; font-family:Consolas,monospace; margin:0; }
- .toolbar { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px; }
- button { border:1px solid #2f7098; background:#123247; color:#dff2ff; padding:8px 14px; cursor:pointer; }
- button.active { outline:2px solid #61c2ff; }
- .layout { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:start; }
- .orders { display:grid; gap:12px; }
- .order { border:1px solid #275b74; background:#0b1922; padding:12px; }
- .order.alarm { border-color:#ff7a7a; } .order.warning { border-color:#f2c94c; }
- .title { display:flex; justify-content:space-between; gap:8px; align-items:flex-start; }
- .code { color:#78a2b8; font-family:Consolas,monospace; font-size:12px; overflow-wrap:anywhere; }
- .badge { font-size:12px; padding:3px 8px; border:1px solid; white-space:nowrap; }
- .active { color:#68d095; border-color:#68d095; } .cancelled { color:#ff7a7a; border-color:#ff7a7a; } .finished { color:#a9b7c0; border-color:#a9b7c0; }
- .timeline { margin-top:10px; display:grid; gap:8px; }
- .entry { border-left:3px solid #61c2ff; background:#0e1e2d; padding:8px 10px; }
- .entry.cancelled { border-left-color:#ff7a7a; } .entry.finished { border-left-color:#a9b7c0; }
- .meta { color:#8fb3c7; font-size:13px; margin:6px 0 0; overflow-wrap:anywhere; }
- .dictionary { display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:8px; }
- .state { border:1px solid #275b74; background:#0b1922; padding:8px; } .state.cancelled { border-color:#ff7a7a; }
- .mono { font-family:Consolas,monospace; overflow-wrap:anywhere; } pre { max-height:340px; overflow:auto; background:#071019; border:1px solid #275b74; padding:12px; }
- .note { color:#8fb3c7; font-size:13px; }
- </style>
- </head>
- <body>
- <main>
- <header>
- <h1>驾驶舱事件关联工单七态演示</h1>
- <p class="endpoint">GET /api/cockpit/v1/equipments/{deviceCode}/work-orders</p>
- <p class="endpoint">GET /api/cockpit/v1/events/{eventSource}/{eventCode}/work-orders</p>
- <p class="endpoint">GET /api/cockpit/v1/work-orders/{workOrderCode}/timeline</p>
- </header>
- <section>
- <div class="toolbar">
- <button type="button" data-mode="all" class="active">七态总览</button>
- <button type="button" data-mode="multi">同设备多类型报警</button>
- </div>
- <div class="layout">
- <div>
- <h2>工单列表</h2>
- <div id="orders" class="orders"></div>
- </div>
- <div>
- <h2>状态字典</h2>
- <div id="dictionary" class="dictionary"></div>
- </div>
- </div>
- </section>
- <section>
- <h2>响应契约</h2>
- <p class="note">状态字典采用 ADR-0008 新七态:1 待派单、2 待接单、3 已接单、4 处理中、5 待验收、6 已结案、7 已取消;已废止状态不再输出。</p>
- <pre id="payload" class="mono"></pre>
- </section>
- </main>
- <script>
- const stateDictionary = [
- {code:1,name:'待派单'}, {code:2,name:'待接单'}, {code:3,name:'已接单'},
- {code:4,name:'处理中'}, {code:5,name:'待验收'}, {code:6,name:'已结案'}, {code:7,name:'已取消'}
- ];
- const summary = (code, state, source, eventCode, desc) => {
- const stateName = stateDictionary[state - 1].name;
- return {
- workOrderCode:code, deviceCode:'TC-PS-WS-202609020012', orderType:1, orderTypeName:'故障维修',
- orderLevel:2, orderDesc:desc,
- stateCode:state, stateName,
- createTime:'2026-09-02T09:00:00+08:00', updateTime:'2026-09-02T10:00:00+08:00',
- planFinishTime:'2026-09-03T09:00:00+08:00', realFinishTime:state === 6 ? '2026-09-02T10:00:00+08:00' : null,
- eventAssociation:{ eventSource:source, eventCode, associatedAt:'2026-09-02T10:00:00+08:00' }
- };
- };
- const allOrders = stateDictionary.map(state => summary(
- 'WO-202609020000' + state.code, state.code, 'ALARM', 'ALM-20260902-00' + state.code, '演示第 ' + state.code + ' 态'));
- const multiOrders = [
- summary('WO-2026090200101', 4, 'ALARM', 'ALM-WS_ENV_HIGH-001', '污水COD超标维修'),
- summary('WO-2026090200102', 5, 'ALARM', 'ALM-WS_ENV_PH-002', '污水pH越界维修')
- ];
- const timelines = {
- 'WO-2026090200101': ['创建:待派单','派单:待接单','开始处置:处理中'],
- 'WO-2026090200102': ['创建:待派单','派单:待接单','提交验收:待验收']
- };
- function badgeClass(order) {
- if (order.stateCode === 6) return 'finished';
- if (order.stateCode === 7) return 'cancelled';
- return 'active';
- }
- function renderOrder(order) {
- const timeline = timelines[order.workOrderCode] || ['创建:' + order.stateName];
- return `<article class="order ${order.eventAssociation.eventSource === 'ALARM' ? 'alarm' : 'warning'}">
- <div class="title">
- <div><h3>${order.orderDesc}</h3><div class="code">${order.workOrderCode}</div></div>
- <span class="badge ${badgeClass(order)}">${order.stateCode} ${order.stateName}</span>
- </div>
- <p class="meta">事件:${order.eventAssociation.eventSource} ${order.eventAssociation.eventCode}</p>
- <div class="timeline">${timeline.map(item => `<div class="entry ${badgeClass(order)}">${item}</div>`).join('')}</div>
- </article>`;
- }
- function render(mode) {
- document.querySelectorAll('button[data-mode]').forEach(button => button.classList.toggle('active', button.dataset.mode === mode));
- const orders = mode === 'all' ? allOrders : multiOrders;
- document.getElementById('orders').innerHTML = orders.map(renderOrder).join('');
- document.getElementById('dictionary').innerHTML = stateDictionary.map(state => `
- <div class="state ${state.code === 7 ? 'cancelled' : ''}"><strong>${state.code} ${state.name}</strong>
- <p class="meta">${state.code === 7 ? '终态' : '中间态'}</p>
- </div>`).join('');
- document.getElementById('payload').textContent = JSON.stringify({
- code:200, msg:'操作成功', data:{
- requestId:'work-order-demo', apiVersion:'v1', readOnly:true,
- deviceCode:'TC-PS-WS-202609020012', eventSource:mode === 'all' ? null : 'ALARM',
- eventCode:mode === 'all' ? null : 'WS_ENV_MULTI', state:'READY', stateReason:'READY',
- stateDictionary, workOrders:orders
- }
- }, null, 2);
- }
- document.querySelectorAll('button[data-mode]').forEach(button => button.addEventListener('click', () => render(button.dataset.mode)));
- render('all');
- </script>
- </body>
- </html>
|