Refactor LED control UI to Vue3
This commit is contained in:
@@ -7,25 +7,95 @@
|
||||
<link rel="stylesheet" href="/static/admin/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<main id="adminApp" class="shell" v-cloak>
|
||||
<header class="topbar">
|
||||
<div>
|
||||
<h1>LED 大屏投放控制台</h1>
|
||||
<p id="stateText">正在连接控制服务...</p>
|
||||
<p>{{ statusText }}</p>
|
||||
</div>
|
||||
<div class="connection">
|
||||
<span id="wsDot" class="dot"></span>
|
||||
<span id="wsText">WebSocket</span>
|
||||
<span class="dot" :class="{ ok: wsConnected }"></span>
|
||||
<span>{{ wsText }}</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="grid">
|
||||
<section class="consoleLayout">
|
||||
<section class="panel previewPanel">
|
||||
<div class="panelHead">
|
||||
<div>
|
||||
<h2>画面回显</h2>
|
||||
<p class="panelHint">14880 x 3510 拼接预览,只读不 ACK</p>
|
||||
</div>
|
||||
<div class="previewLinks">
|
||||
<a href="/output/left" target="_blank">左输出</a>
|
||||
<a href="/output/right" target="_blank">右输出</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="previewGrid">
|
||||
<article class="previewTile">
|
||||
<header>
|
||||
<strong>left</strong>
|
||||
<span>{{ previewLabels.left }}</span>
|
||||
</header>
|
||||
<iframe title="left 输出预览" src="/output/left?preview=1"></iframe>
|
||||
</article>
|
||||
<article class="previewTile">
|
||||
<header>
|
||||
<strong>right</strong>
|
||||
<span>{{ previewLabels.right }}</span>
|
||||
</header>
|
||||
<iframe title="right 输出预览" src="/output/right?preview=1"></iframe>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel scenes">
|
||||
<div class="panelHead">
|
||||
<h2>场景切换</h2>
|
||||
<button id="refreshBtn">刷新</button>
|
||||
<button type="button" @click="loadScenes">刷新</button>
|
||||
</div>
|
||||
<div id="sceneList" class="sceneList"></div>
|
||||
<div class="sceneList">
|
||||
<article
|
||||
v-for="scene in scenes"
|
||||
:key="scene.id"
|
||||
class="scene"
|
||||
:class="{ active: scene.id === state?.active_scene_id }"
|
||||
>
|
||||
<div>
|
||||
<h3>{{ scene.name }}</h3>
|
||||
<p>{{ scene.view }} | {{ scene.url }}</p>
|
||||
<p>{{ scene.description }}</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
:disabled="busySceneId === scene.id"
|
||||
@click="switchScene(scene.id)"
|
||||
>
|
||||
{{ busySceneId === scene.id ? "计划中" : "切换" }}
|
||||
</button>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panelHead">
|
||||
<h2>局部动作</h2>
|
||||
</div>
|
||||
<div class="actionGrid">
|
||||
<button
|
||||
v-for="action in quickActions"
|
||||
:key="action.action + JSON.stringify(action.args || {})"
|
||||
type="button"
|
||||
@click="postAction(action.action, action.args || {})"
|
||||
>
|
||||
{{ action.label }}
|
||||
</button>
|
||||
</div>
|
||||
<label class="customAction">
|
||||
<span>自定义结构化动作</span>
|
||||
<textarea v-model="actionInput" rows="3"></textarea>
|
||||
</label>
|
||||
<button type="button" class="primary" @click="runCustomAction">同步执行</button>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
@@ -38,30 +108,54 @@
|
||||
<a href="/api/sync/status" target="_blank">同步状态</a>
|
||||
<a href="/docs" target="_blank">API 文档</a>
|
||||
</div>
|
||||
<div id="syncStatus" class="syncStatus"></div>
|
||||
<div class="syncStatus">
|
||||
<div class="syncRow">
|
||||
<span>输出节点</span>
|
||||
<strong>{{ nodes.length }}/{{ targetTiles.length }}</strong>
|
||||
</div>
|
||||
<div v-for="node in nodes" :key="node.node_id" class="syncRow">
|
||||
<span>{{ node.tile_id }} {{ node.node_id.slice(0, 16) }}</span>
|
||||
<span>{{ nodeMetric(node) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<div class="panelHead">
|
||||
<h2>局部动作</h2>
|
||||
<div class="panelHead compact">
|
||||
<div>
|
||||
<h2>生产命令回显</h2>
|
||||
<p class="panelHint">真实输出端 ACK,不代表上方预览</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actionGrid">
|
||||
<button data-action="page.prev">上一页</button>
|
||||
<button data-action="page.next">下一页</button>
|
||||
<button data-action="energy.mode" data-args='{"mode":"削峰"}'>削峰模式</button>
|
||||
<button data-action="energy.mode" data-args='{"mode":"保供"}'>保供模式</button>
|
||||
<button data-action="security.alert" data-args='{"text":"门禁异常联动"}'>新增告警</button>
|
||||
<button data-action="timeline.pause">暂停时间轴</button>
|
||||
<button data-action="timeline.resume">恢复时间轴</button>
|
||||
<div class="commandEcho">
|
||||
<div v-if="recentCommands.length === 0" class="emptyEcho">暂无命令回显</div>
|
||||
<article v-for="command in recentCommands" :key="command.command_id" class="echoCard">
|
||||
<div class="echoHead">
|
||||
<div>
|
||||
<h4>{{ commandTitle(command) }}</h4>
|
||||
<p>{{ command.command_id.slice(0, 12) }} | 计划 {{ formatClock(command.apply_at_ms) }} | {{ releaseText(command) }}</p>
|
||||
<p>{{ commandNote(command) }}</p>
|
||||
</div>
|
||||
<span class="echoState" :class="commandStateClass(command)">{{ commandStateText(command) }}</span>
|
||||
</div>
|
||||
<div class="tileEchoGrid">
|
||||
<div
|
||||
v-for="tileId in targetTiles"
|
||||
:key="command.command_id + tileId"
|
||||
class="tileEcho"
|
||||
:class="tileEchoClass(command, tileId)"
|
||||
>
|
||||
<span>{{ tileId }}</span>
|
||||
<strong>{{ tileEchoLabel(command, tileId) }}</strong>
|
||||
<small>{{ tileEchoDetail(command, tileId) }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<label class="customAction">
|
||||
<span>自定义结构化动作</span>
|
||||
<textarea id="actionInput" rows="5" placeholder='{"action":"security.alert","args":{"text":"消防通道占用"}}'></textarea>
|
||||
</label>
|
||||
<button id="runActionBtn" class="primary">同步执行</button>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
<script src="/static/vendor/vue.global.prod.js"></script>
|
||||
<script src="/static/admin/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user