|
@@ -30,7 +30,7 @@
|
|
<!--Waves end-->
|
|
<!--Waves end-->
|
|
</template>
|
|
</template>
|
|
<div class="card_control">
|
|
<div class="card_control">
|
|
- <div class="map_card">
|
|
|
|
|
|
+ <div class="map_card" v-loading="mapLoading">
|
|
<div id="container"></div>
|
|
<div id="container"></div>
|
|
</div>
|
|
</div>
|
|
<div class="card_bottom_control" :class="logisticsFlag ? 'height_300' : 'height_30'">
|
|
<div class="card_bottom_control" :class="logisticsFlag ? 'height_300' : 'height_30'">
|
|
@@ -42,39 +42,72 @@
|
|
<div class="card_unpack_control">
|
|
<div class="card_unpack_control">
|
|
<div style="display: flex;align-items: center;">
|
|
<div style="display: flex;align-items: center;">
|
|
<div style="width: 260px;margin-right: 10px;">
|
|
<div style="width: 260px;margin-right: 10px;">
|
|
- <el-input v-model="input" placeholder="请输入内容"></el-input>
|
|
|
|
|
|
+ <el-input size="small" v-model="input" placeholder="请输入内容"></el-input>
|
|
</div>
|
|
</div>
|
|
- <el-date-picker v-model="value1" type="datetimerange" range-separator="至" start-placeholder="开始日期"
|
|
|
|
- end-placeholder="结束日期">
|
|
|
|
- </el-date-picker>
|
|
|
|
|
|
+ <!-- <el-date-picker size="small" v-model="value1" type="datetimerange" range-separator="至"
|
|
|
|
+ start-placeholder="开始日期" end-placeholder="结束日期">
|
|
|
|
+ </el-date-picker> -->
|
|
</div>
|
|
</div>
|
|
- </div>
|
|
|
|
- <div class="card_table_grid">
|
|
|
|
- <div class="item_index1 center_in">序号</div>
|
|
|
|
- <div class="item_grid center_in" v-for="(item,index) in headerList" :key="index">
|
|
|
|
- {{item.title}}
|
|
|
|
|
|
+ <div>
|
|
|
|
+ <el-button type="primary" size="small" @click="examine">查看实时数据</el-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
- <vue-seamless-scroll ref="vueSeamlessScroll" :data="tableData" :class-option="classOption" class="warp"
|
|
|
|
- @mousewheel.native="handleScroll">
|
|
|
|
- <div class="card_table_grid" v-for="(item, index) in tableData" :key="index">
|
|
|
|
- <div class="item_index center_in">{{index + 1}}</div>
|
|
|
|
- <div class="item_each center_in">{{item.name}}</div>
|
|
|
|
- <div class="item_each center_in">{{item.sn}}</div>
|
|
|
|
- <div class="item_each center_in">{{item.status}}</div>
|
|
|
|
- <div class="item_each center_in">{{item.deviceData.T_t}}</div>
|
|
|
|
- <div class="item_each center_in">{{item.deviceData.T_time}}</div>
|
|
|
|
|
|
+ <div class="history_warp">
|
|
|
|
+ <el-table ref="multipleTable" :data="tableData" height="calc(100% - 51px)" border style="width: 100%"
|
|
|
|
+ @selection-change="handleSelectionChange" @cell-click="selectIncubator" :key="currentId">
|
|
|
|
+ <el-table-column type="selection" width="55" v-if="currentId == 1"></el-table-column>
|
|
|
|
+ <el-table-column type="index" width="50" v-else></el-table-column>
|
|
|
|
+ <el-table-column prop="name" label="名称"></el-table-column>
|
|
|
|
+ <el-table-column prop="sn" label="SN"></el-table-column>
|
|
|
|
+ <el-table-column prop="status" label="状态"></el-table-column>
|
|
|
|
+ <el-table-column prop="T_t" label="当前地址"></el-table-column>
|
|
|
|
+ <el-table-column prop="T_t" label="最新温度"></el-table-column>
|
|
|
|
+ <el-table-column prop="T_time" label="最新记录时间"></el-table-column>
|
|
|
|
+ </el-table>
|
|
|
|
+ <div v-if="Total">
|
|
|
|
+ <pagination :total="Total" :currentPage="Pagination.PageIndex" @changeSize="changeSize"
|
|
|
|
+ @changeCurrent="changeCurrent">
|
|
|
|
+ </pagination>
|
|
</div>
|
|
</div>
|
|
- </vue-seamless-scroll>
|
|
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="track_visit scale-up-tr" v-if="currentId == 2 && playbackControl">
|
|
|
|
+ <div class="playback">轨迹回放控制</div>
|
|
|
|
+ <div class="card_cartoon">
|
|
|
|
+ <div class="cartoo_title center_in margin_10" @click="startAnimation()">开始动画</div>
|
|
|
|
+ <div class="cartoo_title center_in" @click="pauseAnimation()">暂停动画</div>
|
|
|
|
+ <div class="cartoo_title center_in margin_10" @click="resumeAnimation()">继续动画</div>
|
|
|
|
+ <div class="cartoo_title center_in" @click="stopAnimation()">停止动画</div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="card_right_information" v-if="currentId == 2">
|
|
|
|
+ <div class="hide_information center_in" v-if="!optionFlag && trackCircle" @click="reelect">
|
|
|
|
+ <span class="iconfont icon-guiji"></span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="information_card scale-up-tr" v-if="optionFlag && timeData.length > 0">
|
|
|
|
+ <div class="card_time_box" v-for="(item,index) in timeData" :key="index" @click="getTrack(item)">
|
|
|
|
+ <div class="sn_card_box">{{item.sn}}</div>
|
|
|
|
+ <div class="box_time">{{item.start_time}}</div>
|
|
|
|
+ <div class="box_time">{{item.end_time}}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
+ <div class="information_card" v-else-if="optionFlag && timeData.length == 0">
|
|
|
|
+ <el-empty description="暂无数据"></el-empty>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
</el-dialog>
|
|
</el-dialog>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script>
|
|
<script>
|
|
- import vueSeamlessScroll from "vue-seamless-scroll";
|
|
|
|
|
|
+ import {
|
|
|
|
+ getCoolerBoxLocus,
|
|
|
|
+ getHistoryLocus,
|
|
|
|
+ getNewlocus
|
|
|
|
+ } from '@/api/incubator'
|
|
|
|
+ import pagination from '@/components/pagination'
|
|
export default {
|
|
export default {
|
|
name: 'centerControl',
|
|
name: 'centerControl',
|
|
props: {
|
|
props: {
|
|
@@ -85,7 +118,7 @@
|
|
},
|
|
},
|
|
},
|
|
},
|
|
components: {
|
|
components: {
|
|
- vueSeamlessScroll,
|
|
|
|
|
|
+ pagination,
|
|
},
|
|
},
|
|
data() {
|
|
data() {
|
|
return {
|
|
return {
|
|
@@ -105,68 +138,81 @@
|
|
}],
|
|
}],
|
|
controlVisible: false,
|
|
controlVisible: false,
|
|
map: null,
|
|
map: null,
|
|
- headerList: [{
|
|
|
|
- title: '名称'
|
|
|
|
- }, {
|
|
|
|
- title: 'SN'
|
|
|
|
- }, {
|
|
|
|
- title: '状态'
|
|
|
|
- }, {
|
|
|
|
- title: '最新温度'
|
|
|
|
- }, {
|
|
|
|
- title: '最新记录时间'
|
|
|
|
- }]
|
|
|
|
|
|
+ currentId: 1,
|
|
|
|
+ incubatorData: [],
|
|
|
|
+ incubatorID: null,
|
|
|
|
+ optionFlag: false,
|
|
|
|
+ timeData: [],
|
|
|
|
+ polyline: null,
|
|
|
|
+ passedPolyline: null,
|
|
|
|
+ marker: null,
|
|
|
|
+ endMarker: null,
|
|
|
|
+ trackList: [],
|
|
|
|
+ trackPlayback: null,
|
|
|
|
+ playbackControl: false,
|
|
|
|
+ trackCircle: false,
|
|
|
|
+ Total: 100,
|
|
|
|
+ Pagination: {
|
|
|
|
+ PageIndex: 1,
|
|
|
|
+ PageSize: 10,
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ eventSource: [],
|
|
|
|
+ incubatorSn: [],
|
|
|
|
+ jointSn: [],
|
|
|
|
+ realTimeTrajectory: [],
|
|
|
|
+ carMarker: [],
|
|
|
|
+ mapLoading: false,
|
|
}
|
|
}
|
|
},
|
|
},
|
|
computed: {
|
|
computed: {
|
|
classOption() {
|
|
classOption() {
|
|
return {
|
|
return {
|
|
limitMoveNum: 10,
|
|
limitMoveNum: 10,
|
|
- singleHeight: 30,
|
|
|
|
|
|
+ singleHeight: 42,
|
|
|
|
+ waitTime: 2000,
|
|
};
|
|
};
|
|
},
|
|
},
|
|
},
|
|
},
|
|
watch: {
|
|
watch: {
|
|
tableData: {
|
|
tableData: {
|
|
- handler() {
|
|
|
|
- // 数据更改时也要加
|
|
|
|
- // this.$nextTick(() => {
|
|
|
|
- // this.$refs.vueSeamlessScroll.reset()
|
|
|
|
- // })
|
|
|
|
|
|
+ handler(newVal) {
|
|
|
|
+ let arr = newVal
|
|
|
|
+ arr.forEach((item) => {
|
|
|
|
+ if (item.id == this.incubatorID) {
|
|
|
|
+ item.flag = true
|
|
|
|
+ } else {
|
|
|
|
+ item.flag = false
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ this.incubatorData = arr
|
|
},
|
|
},
|
|
immediate: true,
|
|
immediate: true,
|
|
|
|
+ deep: true // 开启深度监听
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mounted() {
|
|
mounted() {
|
|
// this.keyUpSearch()
|
|
// this.keyUpSearch()
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
- // 滚动代码
|
|
|
|
- handleScroll(e) {
|
|
|
|
- if (this.tableData.length > 10) {
|
|
|
|
- // 改变组件内部 yPos 的值,这样html的translate(0, yPos)就会随之改变
|
|
|
|
- // e.deltaY是滚动的距离
|
|
|
|
- this.$refs.vueSeamlessScroll.yPos = this.$refs.vueSeamlessScroll.yPos - e.deltaY
|
|
|
|
- // 如果是正数 说明是往上滚
|
|
|
|
- if (this.$refs.vueSeamlessScroll.yPos > 0) {
|
|
|
|
- this.$refs.vueSeamlessScroll.yPos = 0
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- // 如果yPos超过内部实际高度的一半则重新到顶部滚动
|
|
|
|
- // 一半的原因是因为组件实际上创建了两个dom,以达到无缝衔接的效果
|
|
|
|
- if (Math.abs(this.$refs.vueSeamlessScroll.yPos) > this.$refs.vueSeamlessScroll.realBoxHeight / 2) {
|
|
|
|
- this.$refs.vueSeamlessScroll.yPos = 0
|
|
|
|
|
|
+ selectRol(event) {
|
|
|
|
+ if (this.currentId != event.id) {
|
|
|
|
+ if (event.id == 1) {
|
|
|
|
+ this.playbackControl = false
|
|
|
|
+ this.keyUpSearch()
|
|
|
|
+ } else {
|
|
|
|
+ this.historicalRoute()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- },
|
|
|
|
- selectRol(event) {
|
|
|
|
this.list.forEach(item => {
|
|
this.list.forEach(item => {
|
|
if (item.id == event.id) {
|
|
if (item.id == event.id) {
|
|
|
|
+ this.currentId = event.id
|
|
item.flag = true
|
|
item.flag = true
|
|
} else {
|
|
} else {
|
|
item.flag = false
|
|
item.flag = false
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
+ this.$forceUpdate
|
|
},
|
|
},
|
|
// 展开收起
|
|
// 展开收起
|
|
getUnpack() {
|
|
getUnpack() {
|
|
@@ -175,22 +221,334 @@
|
|
close() {
|
|
close() {
|
|
this.controlVisible = false
|
|
this.controlVisible = false
|
|
},
|
|
},
|
|
|
|
+ // 选择
|
|
|
|
+ handleSelectionChange(event) {
|
|
|
|
+ let arr = []
|
|
|
|
+ event.forEach(item => {
|
|
|
|
+ arr.push(item.sn)
|
|
|
|
+ })
|
|
|
|
+ this.incubatorSn = arr
|
|
|
|
+ // console.log(arr, 35)
|
|
|
|
+ },
|
|
|
|
+ // 查看实时数据
|
|
|
|
+ async examine() {
|
|
|
|
+ const that = this
|
|
|
|
+
|
|
|
|
+ function difference(arr1, arr2) {
|
|
|
|
+ return arr1.filter(item => !arr2.includes(item));
|
|
|
|
+ }
|
|
|
|
+ const uniqueToFirstArray = difference(that.incubatorSn, that.jointSn);
|
|
|
|
+ const uniqueToFirstArray1 = difference(that.jointSn, that.incubatorSn);
|
|
|
|
+ // console.log(uniqueToFirstArray, uniqueToFirstArray1, 999)
|
|
|
|
+ uniqueToFirstArray1.forEach(ique => {
|
|
|
|
+ that.jointSn = deleteElementById(that.jointSn, ique)
|
|
|
|
+
|
|
|
|
+ function deleteElementById(arr, id) {
|
|
|
|
+ return arr.filter((item) => item !== id);
|
|
|
|
+ }
|
|
|
|
+ that.eventSource[ique].close()
|
|
|
|
+ if (that.carMarker[ique].marker) {
|
|
|
|
+ that.carMarker[ique].marker.setMap(null)
|
|
|
|
+ }
|
|
|
|
+ if (that.carMarker[ique].polyline) {
|
|
|
|
+ that.carMarker[ique].polyline.setMap(null)
|
|
|
|
+ }
|
|
|
|
+ that.carMarker[ique] = null
|
|
|
|
+ })
|
|
|
|
+ that.jointSn = that.incubatorSn
|
|
|
|
+ const userData = localStorage.getItem('userList')
|
|
|
|
+ const deptId = JSON.parse(userData)
|
|
|
|
+ if (that.incubatorSn.length > 0) {
|
|
|
|
+ for (let i = 0; i < uniqueToFirstArray.length; i++) {
|
|
|
|
+ const T_sn = uniqueToFirstArray[i]
|
|
|
|
+ // 处理 SSE 流
|
|
|
|
+ that.mapLoading = true
|
|
|
|
+ that.eventSource[T_sn] = await new EventSource(
|
|
|
|
+ `http://182.43.247.65:6280/api/waybill/newlocus?T_sn=${T_sn}&id=${deptId.dept.id}`);
|
|
|
|
+ that.eventSource[T_sn].onopen = function(e) {
|
|
|
|
+ // console.log('Connection to SSE opened.', e);
|
|
|
|
+ };
|
|
|
|
+ that.eventSource[T_sn].onmessage = function(e) {
|
|
|
|
+ // console.log('Message from SSE stream:', e.data);
|
|
|
|
+ const arr = JSON.parse(e.data)
|
|
|
|
+ if (arr.code == 200) {
|
|
|
|
+ // 判断数组对象中是否存在该对象
|
|
|
|
+ let index = that.realTimeTrajectory.findIndex((item) => item.sn === arr.sn);
|
|
|
|
+ // 如果有就替换,没有就添加
|
|
|
|
+ if (index !== -1) {
|
|
|
|
+ that.realTimeTrajectory.splice(index, 1, arr);
|
|
|
|
+ } else {
|
|
|
|
+ that.realTimeTrajectory.push(arr);
|
|
|
|
+ }
|
|
|
|
+ that.realTimeTrajectory.forEach(event => {
|
|
|
|
+ that.initMarker(event.data[0], event)
|
|
|
|
+ })
|
|
|
|
+ } else {
|
|
|
|
+ console.log(T_sn, that.jointSn, 23)
|
|
|
|
+ that.jointSn = deleteElementById(that.jointSn, T_sn)
|
|
|
|
+
|
|
|
|
+ function deleteElementById(arr, id) {
|
|
|
|
+ return arr.filter((item) => item !== id);
|
|
|
|
+ }
|
|
|
|
+ that.$message.error(arr.msg);
|
|
|
|
+ that.eventSource[T_sn].close()
|
|
|
|
+ }
|
|
|
|
+ that.mapLoading = false
|
|
|
|
+ };
|
|
|
|
+ that.eventSource[T_sn].onerror = function(e) {
|
|
|
|
+ that.mapLoading = false
|
|
|
|
+ console.error('Error from SSE stream:', uniqueToFirstArray[i], e);
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ that.$message({
|
|
|
|
+ message: '请选择保温箱',
|
|
|
|
+ type: 'warning'
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ // 初始化坐标点的icon
|
|
|
|
+ initMarker(location, item) {
|
|
|
|
+ let latitude = location.T_site.split(',')
|
|
|
|
+ let dataList = item.data
|
|
|
|
+ var trackList = []
|
|
|
|
+ var positions = item.data
|
|
|
|
+ if (positions.length > 0) {
|
|
|
|
+ positions.forEach(item => {
|
|
|
|
+ if (item.T_site != '0,0' && item.T_site) {
|
|
|
|
+ const data = item.T_site.split(',')
|
|
|
|
+ let arrTrack = [Number(data[0]), Number(data[1])]
|
|
|
|
+ trackList.push(arrTrack)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ // 生成坐标点icon
|
|
|
|
+ if (this.carMarker[item.sn]) {
|
|
|
|
+ if (this.carMarker[item.sn].marker) {
|
|
|
|
+ this.carMarker[item.sn].marker.setPosition([Number(latitude[0]), Number(latitude[1])])
|
|
|
|
+ }
|
|
|
|
+ if (this.carMarker[item.sn].polyline) {
|
|
|
|
+ this.carMarker[item.sn].polyline.setPath(trackList)
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ let icon = new AMap.Icon({
|
|
|
|
+ size: new AMap.Size(40, 45),
|
|
|
|
+ image: require(`@/assets/images/truck.png`),
|
|
|
|
+ imageSize: new AMap.Size(40, 45),
|
|
|
|
+ });
|
|
|
|
+ this.carMarker[item.sn] = {
|
|
|
|
+ marker: null,
|
|
|
|
+ polyline: null,
|
|
|
|
+ }
|
|
|
|
+ // 坐标点 生成方法
|
|
|
|
+ this.carMarker[item.sn].marker = new AMap.Marker({
|
|
|
|
+ icon: icon, // 坐标点图标
|
|
|
|
+ position: [Number(latitude[0]), Number(latitude[1])], // 左边点的经纬度
|
|
|
|
+ offset: new AMap.Pixel(0, -30) // 坐标点偏移量
|
|
|
|
+ });
|
|
|
|
+ // 点标记显示内容,HTML要素字符串
|
|
|
|
+ var markerContent = '' +
|
|
|
|
+ '<div class="incubator_card_map">' +
|
|
|
|
+ ' <div class="map_title_incu">保温箱1</div>' +
|
|
|
|
+ ' <div class="map_title_incu1">' + item.sn + '</div>' +
|
|
|
|
+ ' <div class="map_title_incu1">最新温度: <span>' + location.T_t + '</span></div>' +
|
|
|
|
+ ' <div class="map_title_incu2">记录时间: ' + location.T_time + '</div>' +
|
|
|
|
+ ' <div class="map_title_incu2">当前地址: ' + location.T_time + '</div>' +
|
|
|
|
+ ' <div class="map_arrows"></div>' +
|
|
|
|
+ '</div>';
|
|
|
|
+ this.carMarker[item.sn].marker.setLabel({
|
|
|
|
+ offset: new AMap.Pixel(-7, -68),
|
|
|
|
+ content: markerContent,
|
|
|
|
+ direction: 'center',
|
|
|
|
+ })
|
|
|
|
+ this.carMarker[item.sn].polyline = new AMap.Polyline({
|
|
|
|
+ map: this.map,
|
|
|
|
+ path: trackList,
|
|
|
|
+ showDir: true,
|
|
|
|
+ strokeColor: "#28F", //线颜色
|
|
|
|
+ strokeWeight: 10, //线宽
|
|
|
|
+ strokeStyle: "solid",
|
|
|
|
+ lineJoin: 'round',
|
|
|
|
+ lineCap: 'round',
|
|
|
|
+ });
|
|
|
|
+ this.carMarker[item.sn].marker.setMap(this.map)
|
|
|
|
+ }
|
|
|
|
+ this.map.setFitView(null, false, [150, 60, 100, 60])
|
|
|
|
+ },
|
|
keyUpSearch() {
|
|
keyUpSearch() {
|
|
var that = this
|
|
var that = this
|
|
// var positions = this.trackList;
|
|
// var positions = this.trackList;
|
|
that.map = new AMap.Map("container", {
|
|
that.map = new AMap.Map("container", {
|
|
resizeEnable: true,
|
|
resizeEnable: true,
|
|
- zoom: 14,
|
|
|
|
- center: [106.638415, 26.652217],
|
|
|
|
|
|
+ zoom: 2,
|
|
|
|
+ });
|
|
|
|
+ that.map.setFitView()
|
|
|
|
+ },
|
|
|
|
+ // 历史轨迹
|
|
|
|
+ historicalRoute() {
|
|
|
|
+ var that = this
|
|
|
|
+ that.map = new AMap.Map("container", {
|
|
|
|
+ resizeEnable: true,
|
|
|
|
+ zoom: 2,
|
|
});
|
|
});
|
|
- AMap.service(["AMap.PlaceSearch"], function() {
|
|
|
|
- var placeSearch = new AMap.PlaceSearch({ //构造地点查询类
|
|
|
|
|
|
+ that.map.setFitView()
|
|
|
|
+ },
|
|
|
|
+ // 选择保温箱
|
|
|
|
+ selectIncubator(event) {
|
|
|
|
+ this.$refs.multipleTable.toggleRowSelection(event);
|
|
|
|
+ this.incubatorID = event.id
|
|
|
|
+ if (this.currentId == 2) {
|
|
|
|
+ event.flag = true
|
|
|
|
+ this.optionFlag = true
|
|
|
|
+ this.getBoxLocus(event.id)
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ // 重选时间段轨迹
|
|
|
|
+ reelect() {
|
|
|
|
+ this.optionFlag = true
|
|
|
|
+ },
|
|
|
|
+ // 获取保温箱历史时间段
|
|
|
|
+ getBoxLocus(boxID) {
|
|
|
|
+ getCoolerBoxLocus({
|
|
|
|
+ id: boxID,
|
|
|
|
+ }).then(res => {
|
|
|
|
+ if (res.code == 200 && res.data != null) {
|
|
|
|
+ this.timeData = res.data
|
|
|
|
+ } else {
|
|
|
|
+ this.timeData = []
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ // 获取保温箱历史轨迹
|
|
|
|
+ getTrack(event) {
|
|
|
|
+ if (this.marker) {
|
|
|
|
+ this.marker.stopMove();
|
|
|
|
+ }
|
|
|
|
+ getHistoryLocus({
|
|
|
|
+ sn: event.sn,
|
|
|
|
+ start_time: event.start_time,
|
|
|
|
+ end_time: event.end_time,
|
|
|
|
+ t_id: event.t_id,
|
|
|
|
+ page: 1,
|
|
|
|
+ page_z: 999,
|
|
|
|
+ }).then(res => {
|
|
|
|
+ if (res.code == 200) {
|
|
|
|
+ var trackList = []
|
|
|
|
+ var positions = res.data
|
|
|
|
+ if (positions.length > 0) {
|
|
|
|
+ positions.forEach(item => {
|
|
|
|
+ if (item.T_site != '0,0' && item.T_site) {
|
|
|
|
+ const data = item.T_site.split(',')
|
|
|
|
+ trackList.push(data)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ if (this.polyline) {
|
|
|
|
+ this.polyline.setMap(null); // 移除轨迹
|
|
|
|
+ }
|
|
|
|
+ this.polyline = null
|
|
|
|
+ if (this.passedPolyline) {
|
|
|
|
+ this.passedPolyline.setMap(null)
|
|
|
|
+ }
|
|
|
|
+ this.passedPolyline = null
|
|
|
|
+ if (this.marker) {
|
|
|
|
+ this.marker.setMap(null)
|
|
|
|
+ }
|
|
|
|
+ this.marker = null
|
|
|
|
+ if (this.endMarker) {
|
|
|
|
+ this.endMarker.setMap(null)
|
|
|
|
+ }
|
|
|
|
+ this.endMarker = null
|
|
|
|
+ this.trackList = trackList
|
|
|
|
+ this.optionFlag = false
|
|
|
|
+ this.trackCircle = true
|
|
|
|
+ this.initMap(trackList)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ // 历史轨迹
|
|
|
|
+ initMap(arr) {
|
|
|
|
+ // 聚焦到标记点位置的方法
|
|
|
|
+ // this.map.setZoomAndCenter(10, arr[0].split(','))
|
|
|
|
+ var marker, positions = arr
|
|
|
|
+ const that = this
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ // 地图渲染完成后修改zoom
|
|
|
|
+ that.map.setZoom(14);
|
|
|
|
+ const num = positions.length
|
|
|
|
+ // 创建一个 终点icon
|
|
|
|
+ var endIcon = new AMap.Icon({
|
|
|
|
+ size: new AMap.Size(25, 34),
|
|
|
|
+ image: '//a.amap.com/jsapi_demos/static/demo-center/icons/dir-marker.png',
|
|
|
|
+ imageSize: new AMap.Size(135, 40),
|
|
|
|
+ imageOffset: new AMap.Pixel(-95, -3)
|
|
|
|
+ });
|
|
|
|
+ if (positions.length > 0) {
|
|
|
|
+ // 终点
|
|
|
|
+ that.endMarker = new AMap.Marker({
|
|
|
|
+ position: positions[num - 1],
|
|
|
|
+ icon: endIcon,
|
|
|
|
+ offset: new AMap.Pixel(-13, -30),
|
|
|
|
+ });
|
|
|
|
+ that.map.add(that.endMarker);
|
|
|
|
+ }
|
|
|
|
+ var truckIcon = new AMap.Icon({
|
|
|
|
+ size: new AMap.Size(40, 45),
|
|
|
|
+ image: require(`@/assets/images/truck.png`),
|
|
|
|
+ imageSize: new AMap.Size(40, 45),
|
|
|
|
+ });
|
|
|
|
+ that.marker = new AMap.Marker({
|
|
map: that.map,
|
|
map: that.map,
|
|
- panel: "result",
|
|
|
|
- autoFitView: true
|
|
|
|
|
|
+ position: positions[0],
|
|
|
|
+ icon: truckIcon,
|
|
|
|
+ offset: new AMap.Pixel(-13, -23),
|
|
|
|
+ autoRotation: true,
|
|
});
|
|
});
|
|
- })
|
|
|
|
- that.map.setFitView()
|
|
|
|
|
|
+ // 绘制轨迹
|
|
|
|
+ that.polyline = new AMap.Polyline({
|
|
|
|
+ map: that.map,
|
|
|
|
+ path: positions,
|
|
|
|
+ showDir: true,
|
|
|
|
+ strokeColor: "#28F", //线颜色
|
|
|
|
+ strokeWeight: 10, //线宽
|
|
|
|
+ strokeStyle: "solid",
|
|
|
|
+ lineJoin: 'round',
|
|
|
|
+ lineCap: 'round',
|
|
|
|
+ });
|
|
|
|
+ that.passedPolyline = new AMap.Polyline({
|
|
|
|
+ map: that.map,
|
|
|
|
+ strokeColor: "#AF5", //线颜色
|
|
|
|
+ strokeWeight: 10, //线宽
|
|
|
|
+ strokeOpacity: .7,
|
|
|
|
+ strokeStyle: "solid",
|
|
|
|
+ lineJoin: 'round',
|
|
|
|
+ lineCap: 'round',
|
|
|
|
+ });
|
|
|
|
+ that.map.add(that.polyline);
|
|
|
|
+ that.map.setFitView(null, false, [150, 60, 100, 60]);
|
|
|
|
+ that.marker.on("moving", function(e) {
|
|
|
|
+ that.passedPolyline.setPath(e.passedPath);
|
|
|
|
+ });
|
|
|
|
+ that.playbackControl = true
|
|
|
|
+ }, 500)
|
|
|
|
+ },
|
|
|
|
+ // 开始动画
|
|
|
|
+ startAnimation() {
|
|
|
|
+ var num = this.trackList.length * 3
|
|
|
|
+ this.optionFlag = false
|
|
|
|
+ this.marker.moveAlong(this.trackList, num);
|
|
|
|
+ },
|
|
|
|
+ // 暂停动画
|
|
|
|
+ pauseAnimation() {
|
|
|
|
+ this.marker.pauseMove();
|
|
|
|
+ },
|
|
|
|
+ // 继续动画
|
|
|
|
+ resumeAnimation() {
|
|
|
|
+ this.marker.resumeMove();
|
|
|
|
+ },
|
|
|
|
+ // 停止动画
|
|
|
|
+ stopAnimation() {
|
|
|
|
+ this.marker.stopMove();
|
|
},
|
|
},
|
|
destroyMap() {
|
|
destroyMap() {
|
|
this.map && this.map.destroy();
|
|
this.map && this.map.destroy();
|
|
@@ -242,13 +600,39 @@
|
|
},
|
|
},
|
|
// 弹窗关闭
|
|
// 弹窗关闭
|
|
dialogClose() {
|
|
dialogClose() {
|
|
|
|
+ if (this.incubatorSn.length > 0) {
|
|
|
|
+ this.incubatorSn.forEach(item => {
|
|
|
|
+ this.eventSource[item].close()
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ this.map = null
|
|
|
|
+ this.currentId = 1
|
|
|
|
+ this.list.forEach((item) => {
|
|
|
|
+ if (item.id == 1) {
|
|
|
|
+ item.flag = true
|
|
|
|
+ } else {
|
|
|
|
+ item.flag = false
|
|
|
|
+ }
|
|
|
|
+ })
|
|
this.logisticsFlag = true
|
|
this.logisticsFlag = true
|
|
- }
|
|
|
|
|
|
+ },
|
|
|
|
+ changeSize(val) {
|
|
|
|
+ this.Pagination.PageSize = val
|
|
|
|
+ },
|
|
|
|
+ changeCurrent(val) {
|
|
|
|
+ this.Pagination.PageIndex = val
|
|
|
|
+ },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
<style lang="scss" scoped>
|
|
|
|
+ ::v-deep .amap-marker-label {
|
|
|
|
+ border: unset !important;
|
|
|
|
+ padding: 0px !important;
|
|
|
|
+ background-color: unset !important;
|
|
|
|
+ }
|
|
|
|
+
|
|
.center_control ::v-deep .el-dialog__header {
|
|
.center_control ::v-deep .el-dialog__header {
|
|
padding: 0px !important;
|
|
padding: 0px !important;
|
|
}
|
|
}
|
|
@@ -330,6 +714,8 @@
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
.map_card {
|
|
.map_card {
|
|
width: 100%;
|
|
width: 100%;
|
|
// height: 100%;
|
|
// height: 100%;
|
|
@@ -351,16 +737,14 @@
|
|
}
|
|
}
|
|
|
|
|
|
.card_unpack_control {
|
|
.card_unpack_control {
|
|
- padding: 0px 10px;
|
|
|
|
- height: 50px;
|
|
|
|
|
|
+ padding: 0px 10px 5px 10px;
|
|
display: flex;
|
|
display: flex;
|
|
align-items: center;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
justify-content: space-between;
|
|
- border-bottom: 1px solid #DCDFE6;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- .warp {
|
|
|
|
- height: calc(100% - 81px);
|
|
|
|
|
|
+ .history_warp {
|
|
|
|
+ height: calc(100% - 35px);
|
|
width: 100%;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
}
|
|
}
|
|
@@ -369,41 +753,10 @@
|
|
transform: rotate(180deg);
|
|
transform: rotate(180deg);
|
|
}
|
|
}
|
|
|
|
|
|
- .card_table_grid {
|
|
|
|
- display: flex;
|
|
|
|
- align-items: center;
|
|
|
|
- justify-content: space-around;
|
|
|
|
- border-bottom: 1px solid #DCDFE6;
|
|
|
|
- padding: 0px 10px;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- .item_index1 {
|
|
|
|
- width: 40px;
|
|
|
|
- height: 30px;
|
|
|
|
- font-size: 15px;
|
|
|
|
- font-weight: bold;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- .item_index {
|
|
|
|
- width: 40px;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- .item_grid {
|
|
|
|
- flex: 1;
|
|
|
|
- height: 30px;
|
|
|
|
- font-size: 15px;
|
|
|
|
- font-weight: bold;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- .item_each {
|
|
|
|
- flex: 1;
|
|
|
|
- height: 40px;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
.header {
|
|
.header {
|
|
position: relative;
|
|
position: relative;
|
|
text-align: center;
|
|
text-align: center;
|
|
- background: linear-gradient(60deg, rgba(84, 58, 183, 1) 0%, rgba(0, 172, 193, 1) 100%);
|
|
|
|
|
|
+ background: linear-gradient(60deg, rgba(0, 172, 193, 1) 0%, rgba(84, 58, 183, 1) 100%);
|
|
color: white;
|
|
color: white;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -463,4 +816,175 @@
|
|
font-size: 24px;
|
|
font-size: 24px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ ::v-deep .incubator_card_map {
|
|
|
|
+ position: relative;
|
|
|
|
+ width: 180px;
|
|
|
|
+ background-color: #fff;
|
|
|
|
+ border: 1px solid #DCDFE6;
|
|
|
|
+ padding: 5px;
|
|
|
|
+ border-radius: 8px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ::v-deep .map_title_incu {
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ font-weight: 600;
|
|
|
|
+ margin-bottom: 4px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ::v-deep .map_title_incu1 {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+
|
|
|
|
+ span {
|
|
|
|
+ font-weight: bold;
|
|
|
|
+ color: #67C23A;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ::v-deep .map_title_incu2 {
|
|
|
|
+ font-size: 12px;
|
|
|
|
+ margin: 2px 0px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ::v-deep .map_arrows {
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 0px;
|
|
|
|
+ left: 90px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ::v-deep .map_arrows::before {
|
|
|
|
+ position: absolute;
|
|
|
|
+ content: '';
|
|
|
|
+ border-top: 11px #DCDFE6 solid;
|
|
|
|
+ border-left: 10px transparent solid;
|
|
|
|
+ border-right: 10px transparent solid;
|
|
|
|
+ border-bottom: 10px transparent solid;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ::v-deep .map_arrows::after {
|
|
|
|
+ position: absolute;
|
|
|
|
+ content: '';
|
|
|
|
+ border-top: 10px #fff solid;
|
|
|
|
+ border-left: 10px transparent solid;
|
|
|
|
+ border-right: 10px transparent solid;
|
|
|
|
+ border-bottom: 10px transparent solid;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .card_right_information {
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 60px;
|
|
|
|
+ right: 10px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .information_card {
|
|
|
|
+ width: 260px;
|
|
|
|
+ max-height: 400px;
|
|
|
|
+ overflow: hidden auto;
|
|
|
|
+ border-radius: 5px;
|
|
|
|
+ background-color: #ffffff;
|
|
|
|
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .hide_information {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ width: 50px;
|
|
|
|
+ height: 50px;
|
|
|
|
+ background-color: #ffffff;
|
|
|
|
+ border-radius: 50%;
|
|
|
|
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
|
+
|
|
|
|
+ span {
|
|
|
|
+ color: #009efd;
|
|
|
|
+ font-size: 30px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .track_visit {
|
|
|
|
+ position: absolute;
|
|
|
|
+ right: 10px;
|
|
|
|
+ top: -130px;
|
|
|
|
+ width: 240px;
|
|
|
|
+ height: auto;
|
|
|
|
+ background-color: #ffffff;
|
|
|
|
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
|
+ padding: 10px;
|
|
|
|
+ border-radius: 5px;
|
|
|
|
+
|
|
|
|
+ .playback {
|
|
|
|
+ font-size: 15px;
|
|
|
|
+ padding-bottom: 10px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .card_cartoon {
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: row;
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .cartoo_title {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ margin-bottom: 8px;
|
|
|
|
+ width: 7rem;
|
|
|
|
+ color: #25A5F7;
|
|
|
|
+ border: 1px solid #25A5F7;
|
|
|
|
+ border-radius: 30px;
|
|
|
|
+ padding: 2px 0px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .margin_10 {
|
|
|
|
+ margin-right: 10px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .card_time_box {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ padding: 6px 10px;
|
|
|
|
+ border-bottom: 1px solid #E4E7ED;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .sn_card_box {
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ font-weight: bold;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .box_time {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .scale-up-tr {
|
|
|
|
+ -webkit-animation: scale-up-tr 0.4s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
|
|
|
|
+ animation: scale-up-tr 0.4s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @-webkit-keyframes scale-up-tr {
|
|
|
|
+ 0% {
|
|
|
|
+ -webkit-transform: scale(0.5);
|
|
|
|
+ transform: scale(0.5);
|
|
|
|
+ -webkit-transform-origin: 100% 0%;
|
|
|
|
+ transform-origin: 100% 0%;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 100% {
|
|
|
|
+ -webkit-transform: scale(1);
|
|
|
|
+ transform: scale(1);
|
|
|
|
+ -webkit-transform-origin: 100% 0%;
|
|
|
|
+ transform-origin: 100% 0%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @keyframes scale-up-tr {
|
|
|
|
+ 0% {
|
|
|
|
+ -webkit-transform: scale(0.5);
|
|
|
|
+ transform: scale(0.5);
|
|
|
|
+ -webkit-transform-origin: 100% 0%;
|
|
|
|
+ transform-origin: 100% 0%;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 100% {
|
|
|
|
+ -webkit-transform: scale(1);
|
|
|
|
+ transform: scale(1);
|
|
|
|
+ -webkit-transform-origin: 100% 0%;
|
|
|
|
+ transform-origin: 100% 0%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
</style>
|
|
</style>
|