加入二维码设置
This commit is contained in:
+119
-13
@@ -4,7 +4,7 @@
|
||||
<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?v=20260519a">
|
||||
<link rel="stylesheet" href="/static/css/style.css?v=20260520g">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
@@ -21,6 +21,7 @@
|
||||
<div class="tabs">
|
||||
<button class="tab" :class="{active: tab === 'map'}" @click="tab = 'map'">🗺️ 地图</button>
|
||||
<button class="tab" :class="{active: tab === 'mission'}" @click="tab = 'mission'">🎯 任务配置</button>
|
||||
<button class="tab" :class="{active: tab === 'qr'}" @click="tab = 'qr'">📷 二维码配置</button>
|
||||
<button class="tab" :class="{active: tab === 'model'}" @click="tab = 'model'">📦 机型配置</button>
|
||||
<button class="tab" :class="{active: tab === 'arm'}" @click="tab = 'arm'">🤖 机械臂</button>
|
||||
<button class="tab" :class="{active: tab === 'agv'}" @click="tab = 'agv'">🚗 AGV控制</button>
|
||||
@@ -75,6 +76,13 @@
|
||||
:style="{ left: getMapX(p.coords) + '%', top: getMapY(p.coords) + '%' }"
|
||||
:title="p.coords ? p.coords.map(c => c.toFixed(2)).join(', ') : ''">
|
||||
</div>
|
||||
<!-- 二维码位置点 -->
|
||||
<div v-for="(m, mi) in missionConfig.machines" :key="'qrdot-'+mapVersion+'-'+mi"
|
||||
v-if="machineHasQr(m)"
|
||||
class="map-dot qr-dot"
|
||||
:style="qrMarkerStyle(m)"
|
||||
:title="qrMarkerTitle(m)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -289,12 +297,16 @@
|
||||
<div class="grid-cell grid-header">机器行 {% raw %}{{ ri }}{% endraw %}</div>
|
||||
<div v-for="(ci) in missionConfig.cols" :key="'m'+ri+'_'+ci"
|
||||
class="grid-cell"
|
||||
:class="{ active: getMachineAt(ri-1, ci-1) }"
|
||||
:class="{ active: selectedMachine && selectedMachine.row === ri-1 && selectedMachine.col === ci-1 }"
|
||||
@click="onCellClick(ri-1, ci-1)">
|
||||
<template v-if="getMachineAt(ri-1, ci-1)">
|
||||
<div class="cell-machine">✅</div>
|
||||
</template>
|
||||
<span v-else class="empty-cell">⬜</span>
|
||||
<label class="machine-toggle" @click.stop>
|
||||
<input type="checkbox"
|
||||
:checked="getMachineAt(ri-1, ci-1) !== null"
|
||||
@change="toggleMachine(ri-1, ci-1, $event)">
|
||||
<span class="machine-status" :class="getMachineAt(ri-1, ci-1) ? 'on' : 'off'">
|
||||
{% raw %}{{ getMachineAt(ri-1, ci-1) ? '有机器' : '无机器' }}{% endraw %}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- 点位行 ri+1 (pointRow=ri): 上面机器的背面 / 下面机器的正面 -->
|
||||
@@ -311,12 +323,16 @@
|
||||
<div class="grid-cell grid-header">机器行 {% raw %}{{ missionConfig.rows }}{% endraw %}</div>
|
||||
<div v-for="(ci) in missionConfig.cols" :key="'m'+missionConfig.rows+'_'+ci"
|
||||
class="grid-cell"
|
||||
:class="{ active: getMachineAt(missionConfig.rows-1, ci-1) }"
|
||||
:class="{ active: selectedMachine && selectedMachine.row === missionConfig.rows-1 && selectedMachine.col === ci-1 }"
|
||||
@click="onCellClick(missionConfig.rows-1, ci-1)">
|
||||
<template v-if="getMachineAt(missionConfig.rows-1, ci-1)">
|
||||
<div class="cell-machine">✅</div>
|
||||
</template>
|
||||
<span v-else class="empty-cell">⬜</span>
|
||||
<label class="machine-toggle" @click.stop>
|
||||
<input type="checkbox"
|
||||
:checked="getMachineAt(missionConfig.rows-1, ci-1) !== null"
|
||||
@change="toggleMachine(missionConfig.rows-1, ci-1, $event)">
|
||||
<span class="machine-status" :class="getMachineAt(missionConfig.rows-1, ci-1) ? 'on' : 'off'">
|
||||
{% raw %}{{ getMachineAt(missionConfig.rows-1, ci-1) ? '有机器' : '无机器' }}{% endraw %}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- 最后一个点位行 (pointRow=rows): 所有机器的背面拍摄点 -->
|
||||
@@ -406,6 +422,39 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 二维码位置 -->
|
||||
<div class="machine-form" style="margin-top:16px" v-if="hasQr">
|
||||
<h3>🔍 二维码位置</h3>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>X 坐标</label>
|
||||
<input type="number" step="0.01" :value="safeQrCoord(0)" @input="setQrCoord(0, Number($event.target.value))" placeholder="0.00">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Y 坐标</label>
|
||||
<input type="number" step="0.01" :value="safeQrCoord(1)" @input="setQrCoord(1, Number($event.target.value))" placeholder="0.00">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Yaw (弧度)</label>
|
||||
<input type="number" step="0.01" :value="safeQrCoord(2)" @input="setQrCoord(2, Number($event.target.value))" placeholder="0.00">
|
||||
</div>
|
||||
<div class="form-group" style="align-self:end">
|
||||
<button class="btn btn-small btn-primary" @click="readQRPosition" :disabled="!agvConnected">📍 读取当前位置</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- QR 扫描结果 -->
|
||||
<div v-if="hasQrValue" style="margin-top:8px;padding:8px;background:#0f1923;border-radius:6px">
|
||||
<span style="font-size:13px">📱 二维码值: <strong>{% raw %}{{ safeQr('qr_value') }}{% endraw %}</strong></span>
|
||||
<span v-if="hasQrModelId" style="margin-left:12px;font-size:13px">🏷️ 匹配机型: <strong>{% raw %}{{ safeQrModelName() }}{% endraw %}</strong></span>
|
||||
<span v-else style="margin-left:12px;font-size:13px;color:#ff9800">⚠️ 未匹配到机型</span>
|
||||
</div>
|
||||
<div class="btn-row" style="margin-top:8px">
|
||||
<button class="btn btn-small btn-success" @click="scanQRCode(selectedMachine.id)" :disabled="!cameraOpened || qrScanning">
|
||||
{% raw %}{{ qrScanning ? '扫描中...' : '📷 扫描二维码' }}{% endraw %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-row" style="margin-top:16px">
|
||||
<button class="btn btn-danger" @click="deleteMachine(selectedMachine.id)">🗑️ 删除此机器</button>
|
||||
<button class="btn btn-secondary" @click="saveMachineCoords">💾 保存此机器配置</button>
|
||||
@@ -470,6 +519,63 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ========== 二维码配置 Tab ========== -->
|
||||
<div v-if="tab === 'qr'">
|
||||
<section class="card">
|
||||
<h2>📷 二维码配置</h2>
|
||||
<p style="color:#9aa0a6;font-size:13px;margin-bottom:16px">配置机械臂姿态(6个关节角度),通过机械臂摄像头识别二维码并匹配机型。</p>
|
||||
<!-- 机械臂摄像头画面 -->
|
||||
<div style="margin-bottom:16px">
|
||||
<div class="camera-preview" style="max-width:640px">
|
||||
<img :src="armCameraUrl" @error="onArmPreviewError" style="width:100%;border-radius:8px">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;justify-content:flex-end;margin-bottom:16px">
|
||||
<input type="text" v-model="newQrName" placeholder="输入名称..." style="background:#0f1923;border:1px solid #2a3441;color:#fff;padding:8px 12px;border-radius:6px;margin-right:8px;width:180px">
|
||||
<button class="btn btn-primary" @click="addQrConfig()">➕ 添加</button>
|
||||
</div>
|
||||
<div v-if="qrConfigs.length === 0" style="text-align:center;color:#9aa0a6;padding:40px">
|
||||
<p>暂无二维码配置,请点击上方按钮添加</p>
|
||||
</div>
|
||||
<table v-else style="width:100%;border-collapse:collapse;margin-bottom:16px">
|
||||
<thead>
|
||||
<tr style="background:#1a2332;text-align:left">
|
||||
<th style="padding:10px 8px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">名称</th>
|
||||
<th style="padding:10px 4px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">J1</th>
|
||||
<th style="padding:10px 4px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">J2</th>
|
||||
<th style="padding:10px 4px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">J3</th>
|
||||
<th style="padding:10px 4px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">J4</th>
|
||||
<th style="padding:10px 4px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">J5</th>
|
||||
<th style="padding:10px 4px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">J6</th>
|
||||
<th style="padding:10px 8px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">二维码值</th>
|
||||
<th style="padding:10px 8px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px">匹配机型</th>
|
||||
<th style="padding:10px 8px;border-bottom:1px solid #2a3441;color:#9aa0a6;font-size:12px;text-align:center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="q in qrConfigs" :key="q.id" style="border-bottom:1px solid #1a2332">
|
||||
<td style="padding:10px 8px">
|
||||
<input type="text" v-model="q.name" @change="saveQrConfig(q.id)"
|
||||
style="background:transparent;border:1px solid transparent;color:#fff;padding:4px 6px;width:100px;font-size:13px"
|
||||
@focus="$event.target.style.borderColor='#388e3c'" @blur="$event.target.style.borderColor='transparent'">
|
||||
</td>
|
||||
<td style="padding:10px 4px" v-for="ji in 6" :key="ji">
|
||||
<input type="number" step="0.1" :value="getQrAngle(q, ji - 1)" @input="updateQrAngle(q.id, ji - 1, $event.target.value)" style="width:62px;padding:3px 4px;border:1px solid #2a3441;border-radius:4px;background:#0f1923;color:#fff;font-size:12px;text-align:center">
|
||||
</td>
|
||||
<td style="padding:10px 8px;color:#4fc3f7;font-size:12px;max-width:120px;overflow:hidden;text-overflow:ellipsis">{% raw %}{{ q.qr_value || '—' }}{% endraw %}</td>
|
||||
<td style="padding:10px 8px;color:#9aa0a6;font-size:12px">{% raw %}{{ getQrModelName(q.model_id) }}{% endraw %}</td>
|
||||
<td style="padding:10px 8px;text-align:center;white-space:nowrap">
|
||||
<button class="btn btn-secondary btn-small" @click="readQrAngles(q.id)" :disabled="!armConnected" title="读取当前机械臂角度">📐</button>
|
||||
<button class="btn btn-success btn-small" @click="scanQrEntry(q.id)" :disabled="qrScanningId === q.id" style="margin-left:3px" title="扫描二维码">📷</button>
|
||||
<button class="btn btn-danger btn-small" @click="deleteQrConfig(q.id)" style="margin-left:3px" title="删除">🗑️</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- 机械臂控制 (保持不变) -->
|
||||
<div v-if="tab === 'arm'">
|
||||
<section class="card">
|
||||
@@ -569,7 +675,7 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="/static/js/vue3.global.prod.js?v=20260519a"></script>
|
||||
<script src="/static/js/setting.js?v=20260519a"></script>
|
||||
<script src="/static/js/vue3.global.prod.js?v=20260520g"></script>
|
||||
<script src="/static/js/setting.js?v=20260520g"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user