99 lines
4.3 KiB
HTML
99 lines
4.3 KiB
HTML
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="zh-CN">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<link href="https://cdn.staticfile.org/twitter-bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
|
||
|
|
<style>
|
||
|
|
[v-cloak] { display: none; }
|
||
|
|
body { background: #f4f6f9; padding: 20px; font-size: 0.85rem; }
|
||
|
|
.card { border: none; border-radius: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.08); background: #fff; }
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div id="app" v-cloak>
|
||
|
|
<div v-if="!deviceId" class="text-center mt-5 text-muted">
|
||
|
|
<i class="bi bi-cpu display-1 opacity-25"></i>
|
||
|
|
<p class="mt-3">请选择设备以载入配置</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div v-else class="card p-4">
|
||
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||
|
|
<h5 class="m-0 fw-bold">AI 配置 (ID: {{ deviceId }})</h5>
|
||
|
|
<button class="btn btn-primary btn-sm" @click="save">下发配置</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="row">
|
||
|
|
<div class="col-md-6 border-end">
|
||
|
|
<label class="fw-bold mb-2">缩放控制</label>
|
||
|
|
<div class="form-check form-switch mb-2">
|
||
|
|
<input class="form-check-input" type="checkbox" v-model="proc.enableShrink">
|
||
|
|
<label>启用缩小</label>
|
||
|
|
</div>
|
||
|
|
<div class="input-group input-group-sm mb-3">
|
||
|
|
<input type="number" class="form-control" v-model.number="proc.targetWidth">
|
||
|
|
<span class="input-group-text">x</span>
|
||
|
|
<input type="number" class="form-control" v-model.number="proc.targetHeight">
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="col-md-6 ps-4">
|
||
|
|
<label class="fw-bold mb-2">图像增强</label>
|
||
|
|
<div class="form-check form-switch mb-2">
|
||
|
|
<input class="form-check-input" type="checkbox" v-model="proc.enableEnhance">
|
||
|
|
<label>开启亮度补偿</label>
|
||
|
|
</div>
|
||
|
|
<input type="range" class="form-range" v-model.number="proc.brightnessLevel" :disabled="!proc.enableEnhance">
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script src="https://cdn.staticfile.org/vue/3.3.4/vue.global.prod.min.js"></script>
|
||
|
|
<script src="https://cdn.staticfile.org/axios/1.5.0/axios.min.js"></script>
|
||
|
|
<script>
|
||
|
|
const { createApp, ref, reactive, onMounted } = Vue;
|
||
|
|
const API_BASE = "http://localhost:5000";
|
||
|
|
|
||
|
|
createApp({
|
||
|
|
setup() {
|
||
|
|
const deviceId = ref(null);
|
||
|
|
const proc = reactive({ enableShrink: true, targetWidth: 640, targetHeight: 360, enableEnhance: false, brightnessLevel: 30 });
|
||
|
|
|
||
|
|
// 【修复点】路径对齐到 GET /api/Monitor/{id}
|
||
|
|
const loadDetail = async (id) => {
|
||
|
|
const fullUrl = `${API_BASE}/api/Monitor/${id}`;
|
||
|
|
try {
|
||
|
|
const res = await axios.get(fullUrl);
|
||
|
|
// 假设返回的 JSON 包含 processingOptions 字段
|
||
|
|
if (res.data && res.data.processingOptions) {
|
||
|
|
Object.assign(proc, res.data.processingOptions);
|
||
|
|
}
|
||
|
|
window.parent.postMessage({ type: 'API_LOG', log: { method: 'GET', url: fullUrl, status: 200, msg: '配置载入成功' }}, '*');
|
||
|
|
} catch (e) {
|
||
|
|
window.parent.postMessage({ type: 'API_LOG', log: { method: 'GET', url: fullUrl, status: 'FAIL', msg: e.message }}, '*');
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const save = async () => {
|
||
|
|
// 对齐到 POST /api/Monitor/update-processing
|
||
|
|
const fullUrl = `${API_BASE}/api/Monitor/update-processing`;
|
||
|
|
try {
|
||
|
|
await axios.post(fullUrl, { deviceId: deviceId.value, ...proc });
|
||
|
|
alert("配置已更新");
|
||
|
|
} catch (e) { alert("更新失败"); }
|
||
|
|
};
|
||
|
|
|
||
|
|
onMounted(() => {
|
||
|
|
window.addEventListener('message', (event) => {
|
||
|
|
if (event.data.type === 'LOAD_DEVICE') {
|
||
|
|
deviceId.value = event.data.deviceId;
|
||
|
|
loadDetail(event.data.deviceId);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
return { deviceId, proc, save };
|
||
|
|
}
|
||
|
|
}).mount('#app');
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|