feat: RTSP頁 串接 get device api
This commit is contained in:
parent
2bf5f9042a
commit
ba7fda3d07
@ -1,5 +1,4 @@
|
|||||||
// 開關 RTSP(啟用/停用)
|
// 開關 RTSP(啟用/停用)
|
||||||
export const POST_SET_RTSP_ENABLE = `/api/rtsp/set-rtsp-enable`;
|
export const POST_SET_RTSP_ENABLE = `/api/rtsp/set-rtsp-enable`;
|
||||||
|
|
||||||
// 設定 SAMBA 儲存目錄
|
export const POST_GET_RTSP_DEVICE = `/api/rtsp/get-rtsp-device`;
|
||||||
export const POST_SET_SAMBA_DIRECTORY = `/api/rtsp/set-samba-directory`;
|
|
@ -1,6 +1,8 @@
|
|||||||
|
// src/apis/rtsp/index.js
|
||||||
import {
|
import {
|
||||||
POST_SET_RTSP_ENABLE,
|
POST_SET_RTSP_ENABLE,
|
||||||
POST_SET_SAMBA_DIRECTORY,
|
POST_SET_SAMBA_DIRECTORY,
|
||||||
|
POST_GET_RTSP_DEVICE,
|
||||||
} from "./api";
|
} from "./api";
|
||||||
import instance from "@/util/request";
|
import instance from "@/util/request";
|
||||||
import apihandler from "@/util/apihandler";
|
import apihandler from "@/util/apihandler";
|
||||||
@ -16,14 +18,16 @@ export const setRtspEnable = async ({ main_id, enable }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 設定 SAMBA 儲存目錄
|
* 取得 RTSP 裝置清單
|
||||||
* Swagger: POST /api/rtsp/set-samba-directory
|
* Swagger: POST /api/rtsp/get-rtsp-device
|
||||||
* body: { main_id: number, directory: string }
|
* body: 可為空物件 {} 或依後端需求帶 building_guid 等參數
|
||||||
|
* response.data: [
|
||||||
|
* { main_id, device_number, full_name, device_ip, device_port, rtsp_url,
|
||||||
|
* enable_traffic, start_btn_enable, stop_btn_enable, alarm_message }
|
||||||
|
* ]
|
||||||
*/
|
*/
|
||||||
export const setSambaDirectory = async ({ main_id, directory }) => {
|
export const getRtspDevices = async (payload = {}) => {
|
||||||
const res = await instance.post(POST_SET_SAMBA_DIRECTORY, {
|
const res = await instance.post(POST_GET_RTSP_DEVICE, payload);
|
||||||
main_id,
|
// 後端回傳格式如題:{ code, msg, data: [...] }
|
||||||
directory,
|
|
||||||
});
|
|
||||||
return apihandler(res.code, res.data, { msg: res.msg, code: res.code });
|
return apihandler(res.code, res.data, { msg: res.msg, code: res.code });
|
||||||
};
|
};
|
||||||
|
@ -432,7 +432,7 @@
|
|||||||
"selectPathFirst": "請先選擇儲存資料夾",
|
"selectPathFirst": "請先選擇儲存資料夾",
|
||||||
"startSuccess": "已開始偵測…",
|
"startSuccess": "已開始偵測…",
|
||||||
"startFail": "開始偵測失敗,請稍後再試",
|
"startFail": "開始偵測失敗,請稍後再試",
|
||||||
"stopSuccess": "已請求結束偵測…",
|
"stopSuccess": "結束偵測",
|
||||||
"stopFail": "結束偵測失敗,請稍後再試",
|
"stopFail": "結束偵測失敗,請稍後再試",
|
||||||
"noPermission": "沒有取得寫入權限,請重新選擇資料夾並允許",
|
"noPermission": "沒有取得寫入權限,請重新選擇資料夾並允許",
|
||||||
"selectFolderSuccess": "已選擇資料夾:{name}",
|
"selectFolderSuccess": "已選擇資料夾:{name}",
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, defineProps, watch, inject, nextTick } from "vue";
|
import {
|
||||||
|
ref,
|
||||||
|
defineProps,
|
||||||
|
watch,
|
||||||
|
inject,
|
||||||
|
nextTick,
|
||||||
|
onMounted,
|
||||||
|
toRaw,
|
||||||
|
} from "vue";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { postOperationRecord } from "@/apis/alert";
|
import { postOperationRecord } from "@/apis/alert";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
@ -13,6 +21,27 @@ const props = defineProps({
|
|||||||
editRecord: Object,
|
editRecord: Object,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** ================= Debug Helpers ================= */
|
||||||
|
const debugLog = (label, payload) => {
|
||||||
|
try {
|
||||||
|
console.log(
|
||||||
|
`[AlertActionItem] ${label}:`,
|
||||||
|
JSON.parse(JSON.stringify(payload))
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`[AlertActionItem] ${label}:`, payload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始就印出整個 props 與 editRecord 內容
|
||||||
|
debugLog("props", props);
|
||||||
|
debugLog("initial props.editRecord", props?.editRecord);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
debugLog("onMounted props", props);
|
||||||
|
debugLog("onMounted props.editRecord", props?.editRecord);
|
||||||
|
});
|
||||||
|
|
||||||
const form = ref(null);
|
const form = ref(null);
|
||||||
|
|
||||||
const dateItem = ref([
|
const dateItem = ref([
|
||||||
@ -64,18 +93,43 @@ const updateFileList = (files) => {
|
|||||||
formState.value.lorf = files;
|
formState.value.lorf = files;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ---------------------- 告警影片儲存位置:顯示 API 的 video_url ----------------------
|
||||||
|
// 重要:你的 <Input name="videoLocation" :value="..."> 會從 value[name] 取值
|
||||||
|
// 所以我們把 videoLocation 寫成 { videoLocation: string } 的物件
|
||||||
|
const videoLocation = ref({ videoLocation: "" });
|
||||||
|
const showTooltip = ref(false);
|
||||||
|
|
||||||
|
async function copyToClipboard() {
|
||||||
|
const text = videoLocation.value.videoLocation || "";
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
// 觸發 tooltip 動畫
|
||||||
|
showTooltip.value = false;
|
||||||
|
await nextTick();
|
||||||
|
showTooltip.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
showTooltip.value = false;
|
||||||
|
}, 1500);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("複製失敗:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const onOk = async () => {
|
const onOk = async () => {
|
||||||
const formData = new FormData(form.value);
|
const formData = new FormData(form.value);
|
||||||
formData.delete("oriFile");
|
formData.delete("oriFile");
|
||||||
|
|
||||||
formState.value?.lorf.forEach((file, index) => {
|
(formState.value?.lorf ?? []).forEach((file, index) => {
|
||||||
formData.append(`lorf[${index}].id`, file.id ? file.id : "");
|
formData.append(`lorf[${index}].id`, file?.id ? file.id : "");
|
||||||
formData.append(`lorf[${index}].file`, file.id ? null : file);
|
// 只有新檔案才上傳檔案本體
|
||||||
|
if (!file?.id && file) {
|
||||||
|
formData.append(`lorf[${index}].file`, file);
|
||||||
|
}
|
||||||
formData.append(
|
formData.append(
|
||||||
`lorf[${index}].save_file_name`,
|
`lorf[${index}].save_file_name`,
|
||||||
file.id ? file.save_file_name : ""
|
file?.id ? file.save_file_name : ""
|
||||||
);
|
);
|
||||||
formData.append(`lorf[${index}].ori_file_name`, file.name);
|
formData.append(`lorf[${index}].ori_file_name`, file?.name ?? "");
|
||||||
});
|
});
|
||||||
|
|
||||||
formData.append(
|
formData.append(
|
||||||
@ -83,9 +137,9 @@ const onOk = async () => {
|
|||||||
dayjs(dateItem.value[0].value).format("YYYY-MM-DD")
|
dayjs(dateItem.value[0].value).format("YYYY-MM-DD")
|
||||||
);
|
);
|
||||||
|
|
||||||
props.editRecord.id && formData.append("id", props.editRecord.id);
|
if (props.editRecord.id) formData.append("id", props.editRecord.id);
|
||||||
|
if (props.editRecord.uuid)
|
||||||
props.editRecord.uuid && formData.append("error_code", props.editRecord.uuid);
|
formData.append("error_code", props.editRecord.uuid);
|
||||||
|
|
||||||
formData.append("work_type", 2);
|
formData.append("work_type", 2);
|
||||||
formData.append(
|
formData.append(
|
||||||
@ -96,7 +150,7 @@ const onOk = async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const value = await handleSubmit(alertSchema, formState.value);
|
await handleSubmit(alertSchema, formState.value);
|
||||||
const res = await postOperationRecord(formData);
|
const res = await postOperationRecord(formData);
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
search?.();
|
search?.();
|
||||||
@ -123,58 +177,40 @@ const onCancel = () => {
|
|||||||
description: "",
|
description: "",
|
||||||
lorf: [],
|
lorf: [],
|
||||||
};
|
};
|
||||||
|
// 重置顯示用的影片路徑
|
||||||
|
videoLocation.value.videoLocation = "";
|
||||||
handleErrorReset();
|
handleErrorReset();
|
||||||
updateEditRecord?.(null);
|
updateEditRecord?.(null);
|
||||||
alert_action_item.close();
|
alert_action_item.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 同步 props.editRecord -> formState / 日期 / 維修項目 / 影片網址
|
||||||
watch(
|
watch(
|
||||||
() => props.editRecord,
|
() => props.editRecord,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
|
debugLog("watch props.editRecord changed", newVal);
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
for (let [key, value] of Object.entries(newVal)) {
|
for (let [key, value] of Object.entries(newVal)) {
|
||||||
// 僅更新 formState 中已有的屬性
|
|
||||||
if (key in formState.value) {
|
if (key in formState.value) {
|
||||||
formState.value[key] = value;
|
formState.value[key] = value;
|
||||||
}
|
}
|
||||||
// 處理 start_time
|
|
||||||
if (key === "start_time") {
|
if (key === "start_time") {
|
||||||
formState.value.start_time = value
|
const d = value ? dayjs(value) : dayjs();
|
||||||
? dayjs(value).format("YYYY-MM-DD")
|
formState.value.start_time = d.format("YYYY-MM-DD");
|
||||||
: dayjs().format("YYYY-MM-DD");
|
dateItem.value[0].value = d; // 一律用 dayjs 物件
|
||||||
dateItem.value[0].value = value;
|
|
||||||
}
|
}
|
||||||
// 維修項目
|
|
||||||
if (key === "full_name") {
|
if (key === "full_name") {
|
||||||
formState.value.fix_do = value;
|
formState.value.fix_do = value ?? "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 取 API 回傳的影片位址(與 device_number 同來源物件)
|
||||||
|
videoLocation.value.videoLocation =
|
||||||
|
newVal?.video_url ?? newVal?.videoUrl ?? newVal?.video_path ?? "";
|
||||||
|
debugLog("derived videoLocation", videoLocation.value.videoLocation);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
const videoLocation = ref("https://your-video-storage-path.com/alert-video");
|
|
||||||
const showTooltip = ref(false);
|
|
||||||
const hasCopiedOnce = ref(false);
|
|
||||||
|
|
||||||
async function copyToClipboard() {
|
|
||||||
const text = videoLocation.value;
|
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(text);
|
|
||||||
|
|
||||||
// 確保 tooltip 每次都重新觸發
|
|
||||||
showTooltip.value = false;
|
|
||||||
await nextTick();
|
|
||||||
showTooltip.value = true;
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
showTooltip.value = false;
|
|
||||||
}, 1500);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("複製失敗:", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<section class="min-h-[600px] h-screen">
|
<section class="min-h-[600px] h-screen">
|
||||||
<h1 class="text-2xl font-extrabold mb-2">{{ $t("rtsp.title") }}</h1>
|
<h1 class="text-2xl font-extrabold mb-2">{{ $t("rtsp.title") }}</h1>
|
||||||
|
|
||||||
<!-- Tabs:選擇要顯示的攝影機 -->
|
<!-- Tabs:選擇攝影機 -->
|
||||||
<div class="flex items-center gap-4 mb-6">
|
<div class="flex items-center gap-4 mb-6">
|
||||||
<h2 class="text-lg font-bold whitespace-nowrap">
|
<h2 class="text-lg font-bold whitespace-nowrap">
|
||||||
{{ $t("rtsp.selectDevice") }} :
|
{{ $t("rtsp.selectDevice") }} :
|
||||||
@ -38,41 +38,49 @@
|
|||||||
></iframe>
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 右側:開始/結束偵測(已移除選擇資料夾相關 UI) -->
|
<!-- 右側:開始/結束偵測 -->
|
||||||
<aside class="w-1/2 flex flex-col gap-6 p-4">
|
<aside class="w-1/2 flex flex-col gap-6 p-4">
|
||||||
<div class="flex gap-3">
|
<div class="flex gap-3">
|
||||||
<button
|
<button
|
||||||
class="btn btn-add w-40"
|
class="btn btn-add w-40"
|
||||||
@click="startDetection"
|
@click="startDetection"
|
||||||
:disabled="isStarting || !selectedMainId"
|
:disabled="
|
||||||
|
isStarting || !selectedMainId || !currentDevice?.start_btn_enable
|
||||||
|
"
|
||||||
:title="!selectedMainId ? $t('rtsp.pleaseSelectDevice') : ''"
|
:title="!selectedMainId ? $t('rtsp.pleaseSelectDevice') : ''"
|
||||||
>
|
>
|
||||||
{{ $t("rtsp.start") }}
|
{{ $t("rtsp.start") }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="btn btn-error text-white w-40"
|
class="btn btn-error text-white w-40"
|
||||||
@click="stopDetection"
|
@click="stopDetection"
|
||||||
:disabled="isStopping || !selectedMainId"
|
:disabled="
|
||||||
|
isStopping || !selectedMainId || !currentDevice?.stop_btn_enable
|
||||||
|
"
|
||||||
:title="!selectedMainId ? $t('rtsp.pleaseSelectDevice') : ''"
|
:title="!selectedMainId ? $t('rtsp.pleaseSelectDevice') : ''"
|
||||||
>
|
>
|
||||||
{{ $t("rtsp.stop") }}
|
{{ $t("rtsp.stop") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p v-if="message" class="text-sm text-info">{{ message }}</p>
|
<!-- 顯示後端傳來的提示文字 -->
|
||||||
|
<p v-if="currentDevice?.alarm_message" class="text-sm text-info">
|
||||||
|
{{ currentDevice.alarm_message }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p v-if="message" class="text-sm">{{ message }}</p>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getSystemDevices } from "@/apis/system";
|
import { getRtspDevices, setRtspEnable } from "@/apis/rtsp";
|
||||||
import { setRtspEnable } from "@/apis/rtsp"; // 已移除 setSambaDirectory
|
|
||||||
import useActiveBtn from "@/hooks/useActiveBtn";
|
import useActiveBtn from "@/hooks/useActiveBtn";
|
||||||
|
|
||||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
|
||||||
const DEFAULT_MONITOR_URL =
|
const DEFAULT_MONITOR_URL =
|
||||||
"http://192.168.0.219:8026/?url=rtsp://admin02:mjmAdmin_99@192.168.0.200:554/stream1?tcp";
|
"http://192.168.0.219:8026/?url=rtsp://admin02:mjmAdmin_99@192.168.0.200:554/stream1";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Rtsp",
|
name: "Rtsp",
|
||||||
@ -83,22 +91,23 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
monitorUrl: DEFAULT_MONITOR_URL,
|
monitorUrl: DEFAULT_MONITOR_URL,
|
||||||
|
|
||||||
// 偵測控制
|
|
||||||
isStarting: false,
|
isStarting: false,
|
||||||
isStopping: false,
|
isStopping: false,
|
||||||
|
|
||||||
// UI 狀態
|
|
||||||
message: "",
|
message: "",
|
||||||
|
rtspDevices: [],
|
||||||
// 資料整理
|
|
||||||
deviceData: {},
|
|
||||||
rtspDevices: [], // { main_id, full_name, rtsp_url, ... }
|
|
||||||
selectedMainId: null, // 目前選中的設備 main_id
|
selectedMainId: null, // 目前選中的設備 main_id
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
currentDevice() {
|
||||||
|
if (!this.selectedMainId) return null;
|
||||||
|
return (
|
||||||
|
this.rtspDevices.find((d) => d.main_id === this.selectedMainId) || null
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
await this.getData();
|
await this.loadRtspDevices();
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
selectedBtn: {
|
selectedBtn: {
|
||||||
@ -111,114 +120,38 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getData() {
|
async loadRtspDevices() {
|
||||||
try {
|
try {
|
||||||
const useBuildingStore = (await import("@/stores/useBuildingStore"))
|
const res = await getRtspDevices({});
|
||||||
.default;
|
const list = Array.isArray(res) ? res : res?.data || [];
|
||||||
const buildingStore = useBuildingStore();
|
|
||||||
const building_guid =
|
|
||||||
buildingStore?.selectedBuilding?.building_guid || "";
|
|
||||||
|
|
||||||
const res = await getSystemDevices({ building_guid });
|
this.rtspDevices = list;
|
||||||
const transformedData = {};
|
|
||||||
|
|
||||||
(res?.data || []).forEach((floor) => {
|
|
||||||
if (floor?.device_list?.length > 0) {
|
|
||||||
const fullUrl = floor.floor_map_name;
|
|
||||||
const uuid = fullUrl ? fullUrl.replace(/\.svg$/, "") : "";
|
|
||||||
transformedData[uuid] = floor.device_list.map((device) => {
|
|
||||||
let x = 0,
|
|
||||||
y = 0;
|
|
||||||
try {
|
|
||||||
const coordinates = JSON.parse(
|
|
||||||
device?.device_coordinate || "[0,0]"
|
|
||||||
);
|
|
||||||
x = Number(coordinates?.[0] ?? 0);
|
|
||||||
y = Number(coordinates?.[1] ?? 0);
|
|
||||||
} catch (_) {}
|
|
||||||
|
|
||||||
let state = "Online";
|
|
||||||
let bgColor = device?.device_normal_color;
|
|
||||||
if (
|
|
||||||
device?.device_status === "Offline" ||
|
|
||||||
device?.device_status == null
|
|
||||||
) {
|
|
||||||
state = "Offline";
|
|
||||||
bgColor = device?.device_close_color;
|
|
||||||
}
|
|
||||||
if (device?.device_status === "Error") {
|
|
||||||
state = "Error";
|
|
||||||
bgColor = device?.device_error_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
{
|
|
||||||
device_number: device?.device_number || "",
|
|
||||||
device_coordinate: device?.device_coordinate || "",
|
|
||||||
device_image_url: device?.device_image_url,
|
|
||||||
full_name: device?.full_name,
|
|
||||||
main_id: device?.main_id,
|
|
||||||
points: device?.points || [],
|
|
||||||
floor: floor?.full_name,
|
|
||||||
state,
|
|
||||||
icon: device?.device_image
|
|
||||||
? `${FILE_BASEURL}/upload/device_icon/${device.device_image}`
|
|
||||||
: "",
|
|
||||||
bgColor,
|
|
||||||
Online_color: device?.device_normal_color,
|
|
||||||
Offline_color: device?.device_close_color,
|
|
||||||
Error_color: device?.device_error_color,
|
|
||||||
brand: device?.brand || "",
|
|
||||||
device_model: device?.device_model,
|
|
||||||
operation_name: device?.operation_name,
|
|
||||||
operation_contact_person: device?.operation_contact_person,
|
|
||||||
buying_date: device?.buying_date,
|
|
||||||
created_at: device?.created_at,
|
|
||||||
bgSize: 50,
|
|
||||||
is_rtsp: device?.is_rtsp === true,
|
|
||||||
rtsp_url: device?.rtsp_url || "",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.deviceData = transformedData;
|
|
||||||
|
|
||||||
const allRows = Object.values(transformedData).flat();
|
|
||||||
this.rtspDevices = allRows
|
|
||||||
.map((row) => row?.[2])
|
|
||||||
.filter((p) => p && p.is_rtsp && p.rtsp_url)
|
|
||||||
.reduce((acc, cur) => {
|
|
||||||
if (!acc.find((x) => x.main_id === cur.main_id)) acc.push(cur);
|
|
||||||
return acc;
|
|
||||||
}, [])
|
|
||||||
.sort((a, b) => (a.full_name || "").localeCompare(b.full_name || ""));
|
|
||||||
|
|
||||||
|
// 建立 Tabs
|
||||||
const cate = this.rtspDevices.map((d, index) => ({
|
const cate = this.rtspDevices.map((d, index) => ({
|
||||||
title: d.full_name || d.main_id,
|
title: d.full_name || d.main_id,
|
||||||
key: d.main_id,
|
key: d.main_id,
|
||||||
active: this.selectedMainId
|
active: this.selectedMainId
|
||||||
? this.selectedMainId === d.main_id
|
? this.selectedMainId === d.main_id
|
||||||
: index === 0,
|
: index === 0,
|
||||||
...d,
|
|
||||||
}));
|
}));
|
||||||
this.setItems(cate);
|
this.setItems(cate);
|
||||||
|
|
||||||
|
// 預設選第一台
|
||||||
if (this.rtspDevices.length > 0) {
|
if (this.rtspDevices.length > 0) {
|
||||||
const first = this.rtspDevices[0];
|
const chosenId = this.selectedMainId ?? this.rtspDevices[0].main_id;
|
||||||
this.selectedMainId = first.main_id;
|
const chosen =
|
||||||
this.monitorUrl = first.rtsp_url;
|
this.rtspDevices.find((d) => d.main_id === chosenId) ||
|
||||||
|
this.rtspDevices[0];
|
||||||
|
this.selectDevice(chosen);
|
||||||
} else {
|
} else {
|
||||||
this.selectedMainId = null;
|
this.selectedMainId = null;
|
||||||
this.monitorUrl = DEFAULT_MONITOR_URL;
|
this.monitorUrl = DEFAULT_MONITOR_URL;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("getData() 失敗", err);
|
console.error("loadRtspDevices() 失敗", err);
|
||||||
this.setItems([]);
|
|
||||||
this.rtspDevices = [];
|
this.rtspDevices = [];
|
||||||
|
this.setItems([]);
|
||||||
this.selectedMainId = null;
|
this.selectedMainId = null;
|
||||||
this.monitorUrl = DEFAULT_MONITOR_URL;
|
this.monitorUrl = DEFAULT_MONITOR_URL;
|
||||||
}
|
}
|
||||||
@ -230,18 +163,19 @@ export default {
|
|||||||
this.monitorUrl = d.rtsp_url || DEFAULT_MONITOR_URL;
|
this.monitorUrl = d.rtsp_url || DEFAULT_MONITOR_URL;
|
||||||
},
|
},
|
||||||
|
|
||||||
// 開始偵測:setRtspEnable(true)
|
// 開始偵測
|
||||||
async startDetection() {
|
async startDetection() {
|
||||||
if (!this.selectedMainId) {
|
if (!this.selectedMainId) {
|
||||||
this.message = this.$t("rtsp.pleaseSelectDevice");
|
this.message = this.$t("rtsp.pleaseSelectDevice");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isStarting = true;
|
this.isStarting = true;
|
||||||
|
const keepId = this.selectedMainId;
|
||||||
try {
|
try {
|
||||||
await setRtspEnable({
|
await setRtspEnable({ main_id: keepId, enable: true });
|
||||||
main_id: this.selectedMainId,
|
await this.loadRtspDevices();
|
||||||
enable: true,
|
const found = this.rtspDevices.find((d) => d.main_id === keepId);
|
||||||
});
|
if (found) this.selectDevice(found);
|
||||||
this.message = this.$t("rtsp.startSuccess");
|
this.message = this.$t("rtsp.startSuccess");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@ -251,18 +185,19 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 結束偵測:setRtspEnable(false)
|
// 結束偵測
|
||||||
async stopDetection() {
|
async stopDetection() {
|
||||||
if (!this.selectedMainId) {
|
if (!this.selectedMainId) {
|
||||||
this.message = this.$t("rtsp.pleaseSelectDevice");
|
this.message = this.$t("rtsp.pleaseSelectDevice");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isStopping = true;
|
this.isStopping = true;
|
||||||
|
const keepId = this.selectedMainId;
|
||||||
try {
|
try {
|
||||||
await setRtspEnable({
|
await setRtspEnable({ main_id: keepId, enable: false });
|
||||||
main_id: this.selectedMainId,
|
await this.loadRtspDevices();
|
||||||
enable: false,
|
const found = this.rtspDevices.find((d) => d.main_id === keepId);
|
||||||
});
|
if (found) this.selectDevice(found);
|
||||||
this.message = this.$t("rtsp.stopSuccess");
|
this.message = this.$t("rtsp.stopSuccess");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
Loading…
Reference in New Issue
Block a user