|
@@ -2,19 +2,28 @@
|
|
<div class="tab-content h-full">
|
|
<div class="tab-content h-full">
|
|
<div class="subtitle"><span></span> <el-button type="primary" size="small" @click="addDevice()">添加监控</el-button></div>
|
|
<div class="subtitle"><span></span> <el-button type="primary" size="small" @click="addDevice()">添加监控</el-button></div>
|
|
<el-table :data="tableData" style="width: 100%" v-loading="loading" max-height="calc(100vh - 280px)">
|
|
<el-table :data="tableData" style="width: 100%" v-loading="loading" max-height="calc(100vh - 280px)">
|
|
- <el-table-column label="操作" width="120" align="center">
|
|
|
|
|
|
+ <el-table-column prop="DeviceName" label="设备名称" min-width="130" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="DeviceID" label="设备ID" min-width="210" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="Name" label="通道名称" min-width="140" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="Model" label="型号" width="100" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="Manufacturer" label="厂商" width="100" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="LiveStatus" label="状态" width="100" align="center" :formatter="formatLiveStatus" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="NetAddr" label="网络地址" width="180" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="LastKeepaliveAt" label="最后心跳时间" :formatter="formatTime" width="170" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="RegisterTime" label="注册时间" :formatter="formatTime" width="170" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column prop="UpdateTime" label="更新时间" :formatter="formatTime" width="170" align="center" show-overflow-tooltip></el-table-column>
|
|
|
|
+ <el-table-column label="操作" width="120" align="center" fixed="right">
|
|
<template #default="scope">
|
|
<template #default="scope">
|
|
- <el-button size="small" text type="primary" v-auth="'xxx'" @click="$router.push('/iotmanager/scene/manage/' + scope.row.id)">监控详情</el-button>
|
|
|
|
|
|
+ <el-button size="small" text type="primary" v-auth="'xxx'" @click="view(scope.row)">查看监控</el-button>
|
|
<el-button size="small" text type="warning" v-auth="'xxx'" @click="onDel(scope.row)">解绑</el-button>
|
|
<el-button size="small" text type="warning" v-auth="'xxx'" @click="onDel(scope.row)">解绑</el-button>
|
|
</template>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-table>
|
|
- <pagination v-if="params.total" :total="params.total" v-model:page="params.pageNum" v-model:limit="params.pageSize" @pagination="getList()" />
|
|
|
|
<el-dialog title="添加监控" v-model="isShowDialog" width="400">
|
|
<el-dialog title="添加监控" v-model="isShowDialog" width="400">
|
|
<el-form v-if="isShowDialog">
|
|
<el-form v-if="isShowDialog">
|
|
- <el-form-item label="监控" style="margin-bottom: 0;">
|
|
|
|
|
|
+ <el-form-item label="监控" style="margin-bottom: 0">
|
|
<el-select v-model="form.resourcesKey" filterable placeholder="选择监控" :clearable="false" style="width: 100%">
|
|
<el-select v-model="form.resourcesKey" filterable placeholder="选择监控" :clearable="false" style="width: 100%">
|
|
- <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
|
|
|
+ <el-option v-for="item in options" :disabled="item.disabled" :key="item.value" :label="item.label" :value="item.value" />
|
|
</el-select>
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-form>
|
|
@@ -25,90 +34,148 @@
|
|
</span>
|
|
</span>
|
|
</template>
|
|
</template>
|
|
</el-dialog>
|
|
</el-dialog>
|
|
|
|
+ <el-dialog title="预览监控" v-model="isShowPreviewDialog" width="90vh">
|
|
|
|
+ <template #header>
|
|
|
|
+ <span class="dialog-footer">
|
|
|
|
+ <el-button type="primary" size="small" @click="openToNewWindow">新窗口预览</el-button>
|
|
|
|
+ </span>
|
|
|
|
+ </template>
|
|
|
|
+ <iframe v-if="isShowPreviewDialog" :src="previewUrl" style="width: 100%; height: 50vh"></iframe>
|
|
|
|
+ </el-dialog>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
-import { reactive, ref } from 'vue';
|
|
|
|
-import topoApi from '/@/api/configuration';
|
|
|
|
-import api from '/@/api/projects';
|
|
|
|
-import { useSearch } from '/@/hooks/useCommon';
|
|
|
|
-import { useRoute } from 'vue-router';
|
|
|
|
-import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
|
|
|
+import { reactive, ref } from "vue";
|
|
|
|
+import api from "/@/api/projects";
|
|
|
|
+import { useRoute } from "vue-router";
|
|
|
|
+import { dayjs, ElMessage, ElMessageBox } from "element-plus";
|
|
|
|
+import axios from "axios";
|
|
|
|
+import { getMediaOrigin } from "/@/utils/origin";
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
|
|
|
|
-const props = defineProps({ resourcesTypes: Number })
|
|
|
|
-const isShowDialog = ref(false)
|
|
|
|
-const options = ref<any[]>([])
|
|
|
|
-const resourcesTypes = props.resourcesTypes
|
|
|
|
-const projectsCode = route.params.id
|
|
|
|
|
|
+const props = defineProps({ resourcesTypes: Number });
|
|
|
|
+const isShowDialog = ref(false);
|
|
|
|
+const isShowPreviewDialog = ref(false);
|
|
|
|
+const loading = ref(false);
|
|
|
|
+const previewUrl = ref("");
|
|
|
|
+const options = ref<any[]>([]);
|
|
|
|
+const tableData = ref<any[]>([]);
|
|
|
|
+const channels = ref<any[]>([]);
|
|
|
|
+const resourcesTypes = props.resourcesTypes!;
|
|
|
|
+const projectsCode = route.params.id;
|
|
|
|
|
|
const baseForm = {
|
|
const baseForm = {
|
|
- resourcesKey: '',
|
|
|
|
|
|
+ resourcesKey: "",
|
|
projectsCode,
|
|
projectsCode,
|
|
- resourcesTypes
|
|
|
|
-}
|
|
|
|
|
|
+ resourcesTypes,
|
|
|
|
+};
|
|
|
|
|
|
const form = reactive({
|
|
const form = reactive({
|
|
- ...baseForm
|
|
|
|
-})
|
|
|
|
-
|
|
|
|
-const { params, tableData, getList, loading } = useSearch<any[]>(topoApi.getList, 'data', { ids: [], status: undefined });
|
|
|
|
|
|
+ ...baseForm,
|
|
|
|
+});
|
|
|
|
|
|
getOptions();
|
|
getOptions();
|
|
-getSourceList();
|
|
|
|
|
|
|
|
function getSourceList() {
|
|
function getSourceList() {
|
|
api.getProjectResourcesByCode({ projectsCode }).then((res: any) => {
|
|
api.getProjectResourcesByCode({ projectsCode }).then((res: any) => {
|
|
- params.ids = (res || []).filter((item: any) => item.resourcesTypes === resourcesTypes).map((item: any) => item.resourcesKey)
|
|
|
|
- if (!params.ids.length) {
|
|
|
|
- params.pageNum = 1
|
|
|
|
- tableData.value = []
|
|
|
|
- } else {
|
|
|
|
- getList();
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
|
|
+ const ids = (res || []).filter((item: any) => item.resourcesTypes === resourcesTypes).map((item: any) => item.resourcesKey);
|
|
|
|
+
|
|
|
|
+ const tableDataList: any[] = [];
|
|
|
|
+
|
|
|
|
+ ids.forEach((id: string) => {
|
|
|
|
+ const [deviceID, channelID] = id.split("-");
|
|
|
|
+ const channel = channels.value.find((channel: any) => channel.ID === deviceID && channel.DeviceID === channelID);
|
|
|
|
+ if (channel) {
|
|
|
|
+ options.value.find((item: any) => item.value === id).disabled = true;
|
|
|
|
+ tableDataList.push(channel);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ tableData.value = tableDataList;
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
function getOptions() {
|
|
function getOptions() {
|
|
- topoApi.getList({ status: -1, pageNum: 1, pageSize: 500 }).then((res: any) => {
|
|
|
|
- options.value = (res?.data || []).map((item: any) => ({ label: item.name, value: item.id }))
|
|
|
|
- })
|
|
|
|
|
|
+ // 获取流媒体设备列表,拼接成通道列表 设备ID-通道ID
|
|
|
|
+ axios.get(getMediaOrigin("/gb28181/api/list?format=json")).then((res: any) => {
|
|
|
|
+ // console.log(res.data.data);
|
|
|
|
+ const optionsList: any[] = [];
|
|
|
|
+ const channelsList: any[] = [];
|
|
|
|
+ res.data.data.forEach((item: any) => {
|
|
|
|
+ item.Channels.forEach((channel: any) => {
|
|
|
|
+ optionsList.push({ label: item.Name + " - " + channel.Name, value: item.ID + "-" + channel.DeviceID });
|
|
|
|
+ channelsList.push({
|
|
|
|
+ ...channel,
|
|
|
|
+ DeviceName: item.Name,
|
|
|
|
+ NetAddr: item.NetAddr,
|
|
|
|
+ RegisterTime: item.RegisterTime,
|
|
|
|
+ UpdateTime: item.UpdateTime,
|
|
|
|
+ LastKeepaliveAt: item.LastKeepaliveAt,
|
|
|
|
+ ID: item.ID,
|
|
|
|
+ DeviceID: channel.DeviceID,
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ options.value = optionsList;
|
|
|
|
+ channels.value = channelsList;
|
|
|
|
+ getSourceList();
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
function onCancel() {
|
|
function onCancel() {
|
|
- Object.assign(form, baseForm)
|
|
|
|
- isShowDialog.value = false
|
|
|
|
|
|
+ Object.assign(form, baseForm);
|
|
|
|
+ isShowDialog.value = false;
|
|
}
|
|
}
|
|
|
|
|
|
function onSubmit() {
|
|
function onSubmit() {
|
|
- if (!form.resourcesKey) return ElMessage('请先选择监控')
|
|
|
|
- api.bindResources(form).then((res: any) => {
|
|
|
|
- onCancel()
|
|
|
|
- getSourceList()
|
|
|
|
- ElMessage.success('添加成功')
|
|
|
|
- })
|
|
|
|
|
|
+ if (!form.resourcesKey) return ElMessage("请先选择监控");
|
|
|
|
+ api.bindResources(form).then(() => {
|
|
|
|
+ onCancel();
|
|
|
|
+ getSourceList();
|
|
|
|
+ ElMessage.success("添加成功");
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
function addDevice() {
|
|
function addDevice() {
|
|
- isShowDialog.value = true
|
|
|
|
|
|
+ isShowDialog.value = true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function view(row: any) {
|
|
|
|
+ previewUrl.value = import.meta.env.VITE_SERVER_ORIGIN + "/plugin/media/index.html?ID=" + row.ID + "&DeviceID=" + row.DeviceID + "#/screen-preview";
|
|
|
|
+ isShowPreviewDialog.value = true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function openToNewWindow() {
|
|
|
|
+ window.open(previewUrl.value);
|
|
|
|
+ isShowPreviewDialog.value = false;
|
|
}
|
|
}
|
|
|
|
|
|
function onDel(row: any) {
|
|
function onDel(row: any) {
|
|
- ElMessageBox.confirm(`确定要解绑该监控?`, '提示', {
|
|
|
|
- confirmButtonText: '确认',
|
|
|
|
- cancelButtonText: '取消',
|
|
|
|
- type: 'warning',
|
|
|
|
|
|
+ ElMessageBox.confirm(`确定要解绑该监控?`, "提示", {
|
|
|
|
+ confirmButtonText: "确认",
|
|
|
|
+ cancelButtonText: "取消",
|
|
|
|
+ type: "warning",
|
|
}).then(() => {
|
|
}).then(() => {
|
|
- api.unbindResources({
|
|
|
|
- projectsCode,
|
|
|
|
- resourcesTypes,
|
|
|
|
- resourcesKey: row.id
|
|
|
|
- }).then(() => {
|
|
|
|
- getSourceList()
|
|
|
|
- ElMessage.success('解绑成功')
|
|
|
|
- })
|
|
|
|
|
|
+ api
|
|
|
|
+ .unbindResources({
|
|
|
|
+ projectsCode,
|
|
|
|
+ resourcesTypes,
|
|
|
|
+ resourcesKey: row.ID + "-" + row.DeviceID,
|
|
|
|
+ })
|
|
|
|
+ .then(() => {
|
|
|
|
+ getSourceList();
|
|
|
|
+ ElMessage.success("解绑成功");
|
|
|
|
+ });
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+function formatTime(row: any, column: any) {
|
|
|
|
+ return dayjs(row[column.property]).format("YYYY-MM-DD HH:mm:ss");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function formatLiveStatus(row: any, column: any) {
|
|
|
|
+ // 0 代表空闲,1 代表正在调用 invite,2 代表正在拉流
|
|
|
|
+ return row[column.property] === 0 ? "空闲" : row[column.property] === 1 ? "调用中" : "拉流中";
|
|
|
|
+}
|
|
</script>
|
|
</script>
|