Files
2026-06-16 14:17:05 +08:00

156 lines
7.3 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AGV 拍摄系统</title>
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<div id="app">
<!-- 顶部导航 -->
<header class="topbar">
<div class="logo">🤖 AGV 拍摄系统</div>
<nav class="nav">
<a href="/" class="nav-link active">🏠 首页</a>
<a href="/setting" class="nav-link">⚙️ 设置</a>
<a href="/running" class="nav-link">▶️ 运行</a>
</nav>
<div class="status-bar" style="display:flex;align-items:center;gap:12px">
<label class="env-toggle" title="切换测试/正式环境">
<span class="env-label" :class="testMode ? 'test' : 'prod'">{% raw %}{{ testMode ? '🧪 测试' : '🏭 正式' }}{% endraw %}</span>
<div class="toggle-switch" @click="toggleEnvMode" :class="{active: testMode}">
<div class="toggle-knob"></div>
</div>
</label>
<span class="status-item" :class="statusClass">
{% raw %}{{ statusText }}{% endraw %}
</span>
</div>
</header>
<!-- 主内容 -->
<main class="container">
<!-- 系统状态卡片 -->
<section class="card">
<h2>📡 系统连接状态</h2>
<div class="grid-3">
<div class="status-card" :class="agvConnected ? 'ok' : 'error'"
@click="connectDevice('agv')" style="cursor:pointer">
<div class="status-icon">
<span v-if="reconnectingDevice==='agv'"></span>
<span v-else>{% raw %}{{ agvConnected ? '✅' : '❌' }}{% endraw %}</span>
</div>
<div class="status-label">AGV</div>
<div class="status-value">
<span v-if="reconnectingDevice==='agv'">重连中...</span>
<span v-else>{% raw %}{{ agvConnected ? '已连接' : '未连接' }}{% endraw %}(点击重连)</span>
</div>
</div>
<div class="status-card" :class="armConnected ? 'ok' : 'error'"
@click="connectDevice('arm')" style="cursor:pointer">
<div class="status-icon">
<span v-if="reconnectingDevice==='arm'"></span>
<span v-else>{% raw %}{{ armConnected ? '✅' : '❌' }}{% endraw %}</span>
</div>
<div class="status-label">机械臂</div>
<div class="status-value">
<span v-if="reconnectingDevice==='arm'">重连中...</span>
<span v-else>{% raw %}{{ armConnected ? '已连接' : '未连接' }}{% endraw %}(点击重连)</span>
</div>
</div>
<div class="status-card" :class="cameraOpened ? 'ok' : 'error'"
@click="connectDevice('camera')" style="cursor:pointer">
<div class="status-icon">
<span v-if="reconnectingDevice==='camera'"></span>
<span v-else>{% raw %}{{ cameraOpened ? '✅' : '❌' }}{% endraw %}</span>
</div>
<div class="status-label">AGV摄像头</div>
<div class="status-value">
<span v-if="reconnectingDevice==='camera'">重连中...</span>
<span v-else>{% raw %}{{ cameraOpened ? '已打开' : '未打开' }}{% endraw %}(点击重连)</span>
</div>
</div>
<div class="status-card" :class="armCameraOpened ? 'ok' : 'error'"
@click="connectDevice('arm_camera')" style="cursor:pointer">
<div class="status-icon">
<span v-if="reconnectingDevice==='arm_camera'"></span>
<span v-else>{% raw %}{{ armCameraOpened ? '✅' : '❌' }}{% endraw %}</span>
</div>
<div class="status-label">机械臂摄像头</div>
<div class="status-value">
<span v-if="reconnectingDevice==='arm_camera'">重连中...</span>
<span v-else>{% raw %}{{ armCameraOpened ? '已打开' : '未打开' }}{% endraw %}(点击重连)</span>
</div>
</div>
</div>
<div class="btn-row">
<button class="btn btn-primary" @click="connectAll" :disabled="connecting">
{% raw %}{{ connecting ? '连接中...' : '🔗 连接全部设备' }}{% endraw %}
</button>
<button class="btn btn-secondary" @click="disconnectAll" :disabled="!agvConnected && !armConnected && !cameraOpened">
断开连接
</button>
</div>
</section>
<!-- 双摄像头预览 -->
<section class="card">
<h2>📷 摄像头预览</h2>
<div class="camera-row">
<div class="camera-box">
<div class="camera-label">AGV 摄像头 <button class="btn btn-small" @click="refreshAgvCamera()">刷新</button></div>
<img v-if="cameraOpened && hasAgvCamera && !agvCameraError" :src="agvCameraSrc" class="camera-img" @error="agvCameraError=true">
<div v-if="cameraOpened && agvCameraError && hasAgvCamera" class="camera-placeholder">AGV 摄像头异常</div>
<div v-if="cameraOpened && !hasAgvCamera" class="camera-placeholder">AGV 无可用彩色摄像头</div>
<div v-else-if="!cameraOpened" class="camera-placeholder">未打开(先点击连接设备)</div>
</div>
<div class="camera-box">
<div class="camera-label">机械臂摄像头 <button class="btn btn-small" @click="armCameraSrc='/api/camera/arm_preview?t='+Date.now(); armCameraError=false">刷新</button></div>
<img v-if="armCameraOpened && !armCameraError" :src="armCameraSrc" class="camera-img" @error="armCameraError=true">
<div v-if="armCameraOpened && armCameraError" class="camera-placeholder">机械臂摄像头异常</div>
<div v-else-if="!armCameraOpened" class="camera-placeholder">未连接</div>
</div>
</div>
</section>
<!-- 地图信息 -->
<section class="card">
<h2>🗺️ 地图信息</h2>
<div v-if="mapLoaded">
<p>地图目录: <code>{% raw %}{{ mapConfig.map_dir }}{% endraw %}</code></p>
<p>地图文件: <code>{% raw %}{{ mapConfig.map_file }}{% endraw %}</code></p>
</div>
<div v-else>
<p class="hint">尚未加载地图,请前往 <a href="/setting">设置页面</a> 配置地图</p>
</div>
</section>
<!-- 点位概览 -->
<section class="card">
<h2>📍 点位概览</h2>
<p>已配置 <strong>{% raw %}{{ pointsCount }}{% endraw %}</strong> 个拍摄点位</p>
<div class="btn-row">
<a href="/setting" class="btn btn-primary">前往设置点位 →</a>
</div>
</section>
<!-- 快捷入口 -->
<section class="card">
<h2>🚀 快捷入口</h2>
<div class="btn-row">
<a href="/setting" class="btn btn-large btn-primary">进入设置模式 ⚙️</a>
<a href="/running" class="btn btn-large btn-success" :class="{disabled: !allReady}" @click.prevent="checkReady">
开始运行 ▶️
</a>
</div>
<p v-if="!allReady" class="hint">请先连接所有设备并加载地图</p>
</section>
</main>
</div>
<script src="/static/js/vue3.global.prod.js"></script>
<script src="/static/js/app.js"></script>
</body>
</html>