|
@@ -1,176 +1,278 @@
|
|
|
|
|
+<!-- eslint-disable prettier/prettier -->
|
|
|
<template>
|
|
<template>
|
|
|
- <div class="p-2">
|
|
|
|
|
- <div style="display: flex;flex-direction: row;">
|
|
|
|
|
- <div style="width:20%">
|
|
|
|
|
|
|
+ <div class="p-2" style="padding: 10px">
|
|
|
|
|
+ <div style="display: flex; flex-direction: row">
|
|
|
|
|
+ <div style="width: 20%">
|
|
|
<div class="card-header">
|
|
<div class="card-header">
|
|
|
- <div style="display: flex;flex-direction: row;">
|
|
|
|
|
- <div style="width: 8px;height: 19px;opacity: 1;background: #409EFF"></div>
|
|
|
|
|
|
|
+ <div style="display: flex; flex-direction: row">
|
|
|
|
|
+ <div style="width: 4px; height: 19px; opacity: 1; background: #409eff"></div>
|
|
|
<span
|
|
<span
|
|
|
- style="font-family: PingFang SC;font-size: 14px;font-weight: normal;line-height: 19px;height: 19px;margin-left: 2px;">车辆信息</span>
|
|
|
|
|
|
|
+ style="
|
|
|
|
|
+ font-family: PingFang SC;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: normal;
|
|
|
|
|
+ line-height: 19px;
|
|
|
|
|
+ height: 19px;
|
|
|
|
|
+ margin-left: 5px;
|
|
|
|
|
+ "
|
|
|
|
|
+ >站点列表</span
|
|
|
|
|
+ >
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div style="margin-top: 1vh;">
|
|
|
|
|
- <el-input v-model="filterText" placeholder="输入车牌号" />
|
|
|
|
|
- <el-tree show-checkbox ref="treeRef" class="filter-tree" :data="data" :props="defaultProps" default-expand-all
|
|
|
|
|
- :filter-node-method="filterNode" />
|
|
|
|
|
|
|
+ <div style="margin-top: 20px; padding-left: 10px">
|
|
|
|
|
+ <el-input v-model="filterText" placeholder="输入关键字" />
|
|
|
|
|
+ <el-tree-v2
|
|
|
|
|
+ style="margin-top: 10px"
|
|
|
|
|
+ ref="treeRef"
|
|
|
|
|
+ class="filter-tree"
|
|
|
|
|
+ :height="gettreeheight()"
|
|
|
|
|
+ :data="data"
|
|
|
|
|
+ :indent="treeIndent"
|
|
|
|
|
+ :props="defaultProps"
|
|
|
|
|
+ :filter-method="filterNode"
|
|
|
|
|
+ @node-click="treeclick"
|
|
|
|
|
+
|
|
|
|
|
+ >
|
|
|
|
|
+ <template v-slot:default="{ node }">
|
|
|
|
|
+ <element-tree-line
|
|
|
|
|
+ :node="node"
|
|
|
|
|
+ :treeData="data"
|
|
|
|
|
+ :showLabelLine="false"
|
|
|
|
|
+ :indent="treeIndent"
|
|
|
|
|
+
|
|
|
|
|
+ >
|
|
|
|
|
+ </element-tree-line>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-tree-v2>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div style="width: 77%;margin-left: 2%;">
|
|
|
|
|
|
|
+ <div style="width: 77%; margin-left: 2%">
|
|
|
<div class="card-header">
|
|
<div class="card-header">
|
|
|
- <div style="display: flex;flex-direction: row;">
|
|
|
|
|
- <div style="width: 8px;height: 19px;opacity: 1;background: #409EFF"></div>
|
|
|
|
|
|
|
+ <div style="display: flex; flex-direction: row">
|
|
|
|
|
+ <div style="width: 4px; height: 19px; opacity: 1; background: #409eff"></div>
|
|
|
<span
|
|
<span
|
|
|
- style="font-family: PingFang SC;font-size: 14px;font-weight: normal;line-height: 19px;height: 19px;margin-left: 2px;">视频</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div>
|
|
|
|
|
- <img style="width: 14.5px;height:14.5px;" @click="videoType = 1" src="@/assets/images/icon/容器.png" />
|
|
|
|
|
- <img style="width: 14.5px;height:14.5px;margin-left: 5px" @click="videoType = 4" src="@/assets/images/icon/四宫格.png" />
|
|
|
|
|
- <img style="width: 14.5px;height:14.5px;margin-left: 5px;" @click="videoType = 9" src="@/assets/images/icon/九宫格.png" />
|
|
|
|
|
|
|
+ style="
|
|
|
|
|
+ font-family: PingFang SC;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ font-weight: normal;
|
|
|
|
|
+ line-height: 19px;
|
|
|
|
|
+ height: 19px;
|
|
|
|
|
+ margin-left: 5px;
|
|
|
|
|
+ "
|
|
|
|
|
+ >站点设备</span
|
|
|
|
|
+ >
|
|
|
|
|
+ <span style="margin-left: 30px; font-size: 14px">{{currentdata?.label}}</span>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div style="margin-top: 5vh;">
|
|
|
|
|
- <div style="width: 100%;" v-if="videoType == 1">
|
|
|
|
|
- <!-- <div v-for="item in 9"> -->
|
|
|
|
|
- <video v-for="item in 1" style="width: 99%;margin-left:0.5%" controls="controls" :autoplay="false"
|
|
|
|
|
- muted="muted" :ref="`videoref${item}`"></video>
|
|
|
|
|
- <!-- </div> -->
|
|
|
|
|
- </div>
|
|
|
|
|
- <div style="width: 100%;" v-if="videoType == 4">
|
|
|
|
|
- <!-- <div v-for="item in 9"> -->
|
|
|
|
|
- <video v-for="item in 4" style="width: 49%;margin-left:0.5%" controls="controls" :autoplay="false"
|
|
|
|
|
- muted="muted" :ref="`videoref${item}`"></video>
|
|
|
|
|
- <!-- </div> -->
|
|
|
|
|
- </div>
|
|
|
|
|
- <div style="width: 100%;" v-if="videoType == 9">
|
|
|
|
|
- <!-- <div v-for="item in 9"> -->
|
|
|
|
|
- <video v-for="item in 9" style="width: 32%;margin-left:0.5%" controls="controls" :autoplay="false"
|
|
|
|
|
- muted="muted" :ref="`videoref${item}`"></video>
|
|
|
|
|
- <!-- </div> -->
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div style="margin-top: 20px">
|
|
|
|
|
+ <el-table :data="tableData" border style="width: 100%">
|
|
|
|
|
+ <el-table-column prop="name" label="设备名称" width="160" >
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <span>{{ scope.row.name }}</span> <el-tag style="margin-left: 40px;" type="success" v-if="scope.row.type=='cabinet'" >{{ '在线' }}</el-tag>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="type" label="类型" >
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <el-tag type="success" effect="dark">{{ scope.row.type }}</el-tag> <span style="margin-left: 20px;" v-if="scope.row.type=='cabinet'">{{ `共 ${currentCabinet.total} 格` }}<span style="margin-left: 5px;color:green" >{{ `可用 ${currentCabinet.total-currentCabinet.unused} 格` }}</span></span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="code" label="设备序列号" >
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div style="display: flex;flex-wrap: nowrap;align-items: center;justify-content: space-between;">
|
|
|
|
|
+ <el-input v-model="scope.row.code" style="width: 240px" placeholder="请输入" />
|
|
|
|
|
+ <el-button type="primary" size="small" @click="savedata">保存</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ <el-table-column prop="code" label="操作" >
|
|
|
|
|
+ <template #default="scope">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <el-button v-if="scope.row.type=='cabinet'" type="primary" link size="small">立即同步</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
|
|
+ </el-table>
|
|
|
|
|
+
|
|
|
|
|
+ <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleTabClick">
|
|
|
|
|
+ <el-tab-pane v-if="tableData.filter(i=>i.type=='camera').length>0" label="摄像头" name="camera">
|
|
|
|
|
+ <div id="video-container" style="border-radius: 10px;"></div>
|
|
|
|
|
+ </el-tab-pane>
|
|
|
|
|
+ <el-tab-pane v-if="tableData.filter(i=>i.type=='cabinet').length>0" label="快递柜" name="cabinet">
|
|
|
|
|
+ <div style="display: flex;align-items: center;flex-wrap: wrap;gap: 10px;place-content: center;width: 80vw;justify-content: flex-start;flex-direction: row;align-content: center;">
|
|
|
|
|
+ <div :class="item.box_status==1?'boxunused':''" v-for="(item,index) in currentCabinet.boxlist" style="width: 60px;height:60px;border: 1px solid #33333317;border-radius: 6px;margin-right:20px;margin-bottom: 10px;position: relative;">
|
|
|
|
|
+ <div style="font-size: 10px;padding:8px">{{ item.box_name }}</div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-button size="small" v-if="item.box_status!=1" text style="position: absolute;right: 0;bottom: 0;" @click="openbox">
|
|
|
|
|
+ <img style="width:10px" src="@/assets/images/unlock@2x.png">
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-tab-pane>
|
|
|
|
|
+ </el-tabs>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
<script setup name="CarInfo" lang="ts">
|
|
<script setup name="CarInfo" lang="ts">
|
|
|
-import { listCarInfo, getCarInfo, delCarInfo, addCarInfo, updateCarInfo } from '@/api/carInfo';
|
|
|
|
|
-import { CarInfoVO, CarInfoQuery, CarInfoForm } from '@/api/carInfo/types';
|
|
|
|
|
-import tableElm from "@/components/Public/table.vue";
|
|
|
|
|
|
|
+import { TreeNode } from "element-plus";
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
|
|
+import EZUIKit from 'ezuikit-js';
|
|
|
|
|
+import { getCameraPlayerConfig } from '@/api/gpsData';
|
|
|
|
|
+import { updateData } from "@/api/system/dict/data";
|
|
|
|
|
+import imgulock from "@/assets/images/unlock@2x.png";
|
|
|
|
|
+
|
|
|
|
|
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
|
|
+const { tbl_sites } = toRefs<any>(proxy?.useDict('tbl_sites'));
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
|
|
|
-import videojs from "video.js"
|
|
|
|
|
-import "video.js/dist/video-js.css"
|
|
|
|
|
|
|
|
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
|
|
|
|
|
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
|
|
|
|
+const tableData = ref([]);
|
|
|
|
|
|
|
|
-const carInfoList = ref<CarInfoVO[]>([]);
|
|
|
|
|
-const buttonLoading = ref(false);
|
|
|
|
|
-const loading = ref(true);
|
|
|
|
|
-const showSearch = ref(true);
|
|
|
|
|
-const ids = ref<Array<string | number>>([]);
|
|
|
|
|
-const single = ref(true);
|
|
|
|
|
-const multiple = ref(true);
|
|
|
|
|
-const total = ref(0);
|
|
|
|
|
|
|
+const activeName=ref("camera")
|
|
|
|
|
|
|
|
-const queryFormRef = ref<ElFormInstance>();
|
|
|
|
|
-const carInfoFormRef = ref<ElFormInstance>();
|
|
|
|
|
|
|
+const filterText = ref("");
|
|
|
|
|
+const treeRef = ref(null);
|
|
|
|
|
|
|
|
-const videoPlayer = ref(null)
|
|
|
|
|
|
|
+const gettreeheight = () => {
|
|
|
|
|
+ return document.body.clientHeight - 100;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-const myPlayer = ref(null)
|
|
|
|
|
|
|
+const defaultProps = {
|
|
|
|
|
+ children: "children",
|
|
|
|
|
+ label: "label",
|
|
|
|
|
+ value: 'id',
|
|
|
|
|
+};
|
|
|
|
|
+const treeIndent = ref(40);
|
|
|
|
|
|
|
|
-const dialog = reactive<DialogOption>({
|
|
|
|
|
- visible: false,
|
|
|
|
|
- title: ''
|
|
|
|
|
|
|
+watch(filterText, (val) => {
|
|
|
|
|
+ if (treeRef.value) {
|
|
|
|
|
+ treeRef.value.filter(val);
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-const table = ref(tableElm)
|
|
|
|
|
-
|
|
|
|
|
-const videoType = ref(4)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-const initFormData: CarInfoForm = {
|
|
|
|
|
- id: undefined,
|
|
|
|
|
- carNum: undefined,
|
|
|
|
|
- carType: undefined,
|
|
|
|
|
- deviceInfos: undefined,
|
|
|
|
|
- repairInfo: undefined,
|
|
|
|
|
- maintenanceInfo: undefined,
|
|
|
|
|
- insuranceInfo: undefined,
|
|
|
|
|
- inspectionInfo: undefined,
|
|
|
|
|
- trafficAccidentInfo: undefined,
|
|
|
|
|
- violationInfo: undefined,
|
|
|
|
|
- changeInfo: undefined,
|
|
|
|
|
- ext1: undefined,
|
|
|
|
|
- ext2: undefined
|
|
|
|
|
|
|
+const savedata = () => {
|
|
|
|
|
+ //保存数据
|
|
|
|
|
+ var data = {
|
|
|
|
|
+ dictCode: currentdata.value.dictCode,
|
|
|
|
|
+ dictValue: currentdata.value.value,
|
|
|
|
|
+ dictLabel: currentdata.value.label,
|
|
|
|
|
+ dictType: "tbl_sites",
|
|
|
|
|
+ remark: JSON.stringify(tableData.value)
|
|
|
|
|
+ }
|
|
|
|
|
+ updateData(data).then(res => {
|
|
|
|
|
+ ElMessage.success("成功!");
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-interface Tree {
|
|
|
|
|
- [key: string]: any
|
|
|
|
|
|
|
+const handleTabClick = () => {
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const filterText = ref('')
|
|
|
|
|
-const treeRef = ref<InstanceType<typeof ElTree>>()
|
|
|
|
|
|
|
+const filterNode = (value: string, node: TreeNode) => {
|
|
|
|
|
+ if (node.id == 1) return true;
|
|
|
|
|
+ console.log(node.label.indexOf(value)!=-1)
|
|
|
|
|
+ return node.label.indexOf(value)!=-1;
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
-const defaultProps = {
|
|
|
|
|
- children: 'children',
|
|
|
|
|
- label: 'carNum',
|
|
|
|
|
-}
|
|
|
|
|
|
|
+const currentdata = ref(null)
|
|
|
|
|
|
|
|
-watch(filterText, (val) => {
|
|
|
|
|
- treeRef.value!.filter(val)
|
|
|
|
|
-})
|
|
|
|
|
|
|
+const treeclick = (data: TreeNodeData, node: TreeNode) => {
|
|
|
|
|
+
|
|
|
|
|
+ currentdata.value = tbl_sites.value.filter(i => {
|
|
|
|
|
+ return i.label == data.label
|
|
|
|
|
+ })[0];
|
|
|
|
|
+ tableData.value = [];
|
|
|
|
|
+ if (currentdata.value) {
|
|
|
|
|
+ tableData.value = JSON.parse(currentdata.value.remark);
|
|
|
|
|
+ var cameras = tableData.value.filter(i => i.type == 'camera');
|
|
|
|
|
+ if (cameras.length > 0) {
|
|
|
|
|
+ var cameracode = cameras[0].code;
|
|
|
|
|
+ //存在视频播放视频
|
|
|
|
|
+ getCameraPlayerConfig(cameracode).then(res => {
|
|
|
|
|
+ var player = new EZUIKit.EZUIKitPlayer({
|
|
|
|
|
+ template: "pcLive",
|
|
|
|
|
+ id: 'video-container', // 视频容器ID
|
|
|
|
|
+ ...res.data
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var cabinets = tableData.value.filter(i => i.type == 'cabinet');
|
|
|
|
|
+ if (cabinets.length > 0) {
|
|
|
|
|
+ var cabinetcode = cameras[0].code;
|
|
|
|
|
+ SycCabinet(cabinetcode);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-const filterNode = (value: string, data: Tree) => {
|
|
|
|
|
- if (!value) return true
|
|
|
|
|
- return data.label.includes(value)
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const data: Tree[] = [
|
|
|
|
|
- {
|
|
|
|
|
- id: 1,
|
|
|
|
|
- carNum: '在线车辆',
|
|
|
|
|
- children: [
|
|
|
|
|
- {carNum:'苏A8762'},
|
|
|
|
|
- {carNum:'苏A8762'},
|
|
|
|
|
- ],
|
|
|
|
|
- },
|
|
|
|
|
-]
|
|
|
|
|
-
|
|
|
|
|
-const { queryParams, form, rules } = toRefs(data);
|
|
|
|
|
-
|
|
|
|
|
-/** 查询车辆信息列表 */
|
|
|
|
|
-const getList = async () => {
|
|
|
|
|
- const res = await listCarInfo({ pageSize:1000 });
|
|
|
|
|
- for(var index in res.rows){
|
|
|
|
|
- data[0].children.push(res.rows[index]);
|
|
|
|
|
|
|
+const currentCabinet = ref({
|
|
|
|
|
+ total: 40,
|
|
|
|
|
+ unused: 10,
|
|
|
|
|
+ boxlist:[]
|
|
|
|
|
+})
|
|
|
|
|
+const SycCabinet = (code) => {
|
|
|
|
|
+ //TODO 获取格数
|
|
|
|
|
+ // var toalnum
|
|
|
|
|
+ currentCabinet.value.boxlist = [];
|
|
|
|
|
+ for (var i = 0; i < currentCabinet.value.total; i++) {
|
|
|
|
|
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
|
+ //@ts-ignore
|
|
|
|
|
+ currentCabinet.value.boxlist.push( {
|
|
|
|
|
+ box_id: 1,
|
|
|
|
|
+ box_name: (i+1)+"",
|
|
|
|
|
+ box_status:i%2
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
- console.log(data);
|
|
|
|
|
|
|
+}
|
|
|
|
|
+const openbox = (code) => {
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ ElMessage.success("指令已发送!");
|
|
|
|
|
+ }, 1000);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+const data = computed(() => {
|
|
|
|
|
+
|
|
|
|
|
+ var index = 1;
|
|
|
|
|
+
|
|
|
|
|
+ return [{
|
|
|
|
|
+ id: 1,
|
|
|
|
|
+ label: "站点",
|
|
|
|
|
+ children: tbl_sites.value.map(i => { return {id:++index,label:i.label} }),
|
|
|
|
|
+ },]
|
|
|
|
|
+});
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
- getList();
|
|
|
|
|
|
|
+ if (treeRef.value) {
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ treeRef.value.expandNode(treeRef.value.getNode(1))
|
|
|
|
|
+ }, 100);
|
|
|
|
|
+ // treeRef.value.expandNode(treeRef.value.getNode(1))
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-onUnmounted(() => {
|
|
|
|
|
- if (myPlayer.value) {
|
|
|
|
|
- myPlayer.value.dispose()
|
|
|
|
|
- }
|
|
|
|
|
-})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
-
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
.card-header {
|
|
.card-header {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: row;
|
|
flex-direction: row;
|
|
|
justify-content: space-between;
|
|
justify-content: space-between;
|
|
|
}
|
|
}
|
|
|
|
|
+.boxunused{
|
|
|
|
|
+ background: #3333332d;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|
|
|
-
|
|
|