Commit d76da1203619251f8778789f2891ec432ed90b54

Authored by 王鑫
1 parent 4bfd97b7

fix():修改历史记录位置,增加12宫格,修改历史记录搜索问题

web_src/config/index.js
... ... @@ -11,14 +11,14 @@ module.exports = {
11 11 assetsPublicPath: "/",
12 12 proxyTable: {
13 13 "/debug": {
14   - target: "http://118.113.164.50:18989",
  14 + target: "http://127.0.0.1:28080",
15 15 changeOrigin: true,
16 16 pathRewrite: {
17 17 "^/debug": "/",
18 18 },
19 19 },
20 20 "/static/snap": {
21   - target: "http://118.113.164.50:18989",
  21 + target: "http://127.0.0.1:28080",
22 22 changeOrigin: true,
23 23 // pathRewrite: {
24 24 // '^/static/snap': '/static/snap'
... ...
web_src/package.json
... ... @@ -17,6 +17,7 @@
17 17 "axios": "^0.24.0",
18 18 "core-js": "^2.6.5",
19 19 "echarts": "^4.9.0",
  20 + "el-tree-transfer": "^2.4.7",
20 21 "element-ui": "^2.15.6",
21 22 "fingerprintjs2": "^2.1.2",
22 23 "flv.js": "^1.6.2",
... ...
web_src/src/components/DeviceList1078.vue
1 1 <template>
2 2 <div id="devicePosition" style="width:100vw; height: 91vh">
3   -
4 3 <el-container v-loading="loading" style="height: 91vh;" element-loading-text="拼命加载中">
5 4 <el-aside width="300px" style="background-color: #ffffff">
6 5 <div class="device-tree-main-box">
7 6 <div id="DeviceTree" style="width: 100%;height: 100%; background-color: #FFFFFF; overflow: auto">
8 7 <el-container>
9 8 <el-header>设备列表</el-header>
10   - <el-main style="background-color: #ffffff;">
11   - <tree :nodes="nodes" @onClick="onClick" @onCheck="onCheck" @onExpand="onExpand" @onRightClick="treeRightMenuFun" @onCreated="handleCreated" :props="defaultProps"/>
12   - </el-main>
13   - </el-container>
14   - </div>
  9 + <el-main style="background-color: #ffffff;">
  10 + <tree :nodes="nodes" @onClick="onClick" @onCheck="onCheck" @onExpand="onExpand"
  11 + @onRightClick="treeRightMenuFun" @onCreated="handleCreated" :props="defaultProps"/>
  12 + </el-main>
  13 + </el-container>
  14 + </div>
15 15 </div>
16 16 </el-aside>
17 17 <el-container>
18   -
19   - <el-header height="5vh" style="text-align: left;font-size: 17px;line-height:5vh;width:90%">
20   - 分屏:
21   - <i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spiltClickFun(1)"/>
22   - <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spiltClickFun(4)"/>
23   - <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spiltClickFun(9)"/>
24   -
25   - <button style="margin-left: 15px;" @click="openViewDIalog()">历史数据</button>
26   - <button style="margin-left: 15px;" @click="OneClickPlayback()">一键播放车辆视频</button>
27   - <button style="margin-left: 15px;" @click="closeSelectItem()">关闭选中画面流</button>
28   - <button style="margin-left: 15px;" @click="closeSelectCarItem()">一键关闭选中车辆流</button>
29   - </el-header>
30   -
31   -
  18 + <el-header height="5vh" style="text-align: left;font-size: 17px;line-height:5vh;width:90%">
  19 +
  20 + <i class="el-icon-s-platform btn" :class="{active:spilt==1}" @click="spiltClickFun(1)"/>
  21 + <i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spiltClickFun(4)"/>
  22 + <i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spiltClickFun(9)"/>
  23 + <i class="el-icon-full-screen btn" :class="{active:spilt==12}" @click="spiltClickFun(12)"/>
  24 +
  25 + <el-button size="mini" style="margin-left: 15px;" @click="oneClickPlayback()">一键播放车辆视频</el-button>
  26 + <el-button size="mini" style="margin-left: 15px;" @click="closeSelectItem()">关闭选中画面流</el-button>
  27 + <el-button size="mini" style="margin-left: 15px;" @click="closeSelectCarItem()">一键关闭选中车辆流</el-button>
  28 + <el-button size="mini" style="margin-left: 15px;" @click="inspectionsDialog">视屏巡查</el-button>
  29 + </el-header>
  30 +
32 31 <el-main style="padding: 0;">
33   - <div style="width: 99%;height: 85vh;display: flex;flex-wrap: wrap;background-color: #000;">
  32 + <div class="scroll-container" style="width: 100%;height: 85vh;display: flex;flex-wrap: wrap;background-color: #000;">
34 33 <div v-for="i in spilt" :key="i" class="play-box"
35 34 :style="liveStyle" :class="{redborder:playerIdx == (i-1)}"
36 35 @click="playerIdx = (i-1)">
37 36 <div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{ i }}</div>
38 37 <player ref="player" v-else :videoUrl="videoUrl[i-1]" fluent autoplay @screenshot="shot"
39   - @destroy="destroy"/>
  38 + @destroy="destroy" style="width: 100%;"/>
40 39 </div>
41 40 </div>
42 41 </el-main>
... ... @@ -45,100 +44,100 @@
45 44  
46 45 <div id="carRMenu" class="rMenu">
47 46 <ul>
48   - <li id="m_add" @click="OneClickPlayback();">一键播放视频</li>
  47 + <li id="m_add" @click="oneClickPlayback();">一键播放视频</li>
49 48 <li id="m_del" @click="closeSelectCarItem();">一键关闭选中车辆流</li>
50 49 </ul>
51 50 </div>
52 51  
53 52 <div id="channelCarRMenu" class="rMenu">
54 53 <ul>
55   - <li id="m_add" @click="OneClickPlayback();">一键播放视频</li>
  54 + <li id="m_add" @click="oneClickPlayback();">一键播放视频</li>
56 55 <li id="m_del" @click="closeSelectCarItem();">一键关闭选中车辆流</li>
57   - <li id="m_del" @click="openViewDIalog();">历史数据</li>
58 56 </ul>
59 57 </div>
60 58  
61   -
62   -
63   - <el-dialog title="历史视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog"
64   - v-if="showVideoDialog" width="800px" :close-delay="5000" :fullscreen="true" :show-close="false">
65   - <el-container v-loading="loading" style="height: 88vh;" element-loading-text="拼命加载中">
66   -
67   - <div style="width:100%;display: flex;flex-direction: column;justify-content: space-between;">
68   - <div style="width: 90%;text-align:left;margin-bottom:5px;margin-left: 25px;">
69   - <el-date-picker size="smaill" v-model="startTime" type="datetime" style="width:220px" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期时间" />
70   - <el-date-picker size="smaill" v-model="endTime" type="datetime" style="width:220px" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期时间" />
71   -
72   - <button @click="searchHitoryList()">搜索</button>
73   - <button @click="downloadFunction()">下载播放视频</button>
74   - <button @click="close()">关闭窗口</button>
75   - </div>
76   -
77   - <div style="width: 100%;display:flex;flex-direction:row; justify-content:space-between;">
78   - <div style="width:20%" v-html="historyPlayListHtml" @click="playHistoryItem">
79   -
80   - </div>
81   - <div style="width: 78%;">
82   - <div style="width: 95%;height: 80vh;display: flex;flex-wrap: wrap;background-color: #000;">
83   - <div v-if="!videoUrl[0]" style="color: #ffffff;font-size: 30px;font-weight: bold;"></div>
84   - <player ref="player" v-else :videoUrl="videoUrl[0]" fluent autoplay @screenshot="shot"
85   - @destroy="destroy"/>
86   - </div>
87   - </div>
88   - </div>
89   - </div>
90   - </el-container>
91   - </el-dialog>
92   -
  59 + <el-dialog title="视屏巡查设置" width="600" append-to-body
  60 + :close-on-click-modal="false"
  61 + :visible.sync="showVideoDialog" >
  62 + <tree-transfer
  63 + style="text-align: left; display: inline-block"
  64 + :to_data="targetValue"
  65 + :filter="true"
  66 + :title="['源列表', '巡查列表']"
  67 + @change="handleChange"
  68 + :from_data="sourceValue">
  69 + </tree-transfer>
  70 + <div slot="footer" class="dialog-footer">
  71 + <el-button type="primary" @click="submitForm">确 定</el-button>
  72 + <el-button @click="cancel">取 消</el-button>
  73 + </div>
  74 + </el-dialog>
93 75 </div>
94 76 </template>
95   -
96 77 <script>
97 78 import tree from "vue-giant-tree";
98 79 import uiHeader from "../layout/UiHeader.vue";
99   -import player from './common/jessibuca.vue'
  80 +import player from './common/jessibuca.vue';
100 81 import DeviceTree from './common/DeviceTree.vue'
101   -import { isEmpty } from "ol/extent";
102   -
103   -
  82 +import treeTransfer from "el-tree-transfer";
104 83 export default {
105 84 name: "live",
106 85 components: {
107   - uiHeader, player, DeviceTree,tree
  86 + uiHeader, player, DeviceTree, tree, treeTransfer
108 87 },
109 88 data() {
110 89 return {
  90 + //穿梭框数据-----------↓
  91 + //源列表数据
  92 + sourceValue: [],
  93 + //目标列表数据
  94 + targetValue: [],
  95 + //prop参数
  96 + treeProps:{
  97 + children: 'children',
  98 + label: 'label',
  99 + name: 'name'
  100 + },
  101 + //巡查按钮
  102 + patrolValue: false,
  103 + //巡查数据定时器
  104 + carInfoTimeout: '',
  105 + //巡查定时器
  106 + timer : '',
  107 + //上线车辆
  108 + onlineCar: new Map(),
  109 + //车载key集合
  110 + onlineCarKeys: [],
111 111 videoUrl: [''],
112 112 videoUrlHistory: "",
113 113 spilt: 1,//分屏
114 114 playerIdx: 0,//激活播放器
115   -
116 115 updateLooper: 0, //数据刷新轮训标志
117 116 count: 15,
118   - historyLoadingFlag:true,
  117 + historyLoadingFlag: true,
119 118 total: 0,
120   - startTime:'',
121   - endTime:'',
  119 + startTime: '',
  120 + endTime: '',
122 121 //channel
123 122 loading: false,
124 123 device: null,
125   - nodes:[],
126   - carPlayTimer:null,
127   - carTreeNode:null,
128   - ztreeObj:null,
129   - ztreeNode:null,
130   - fullscreenLoading:true,
131   - fullscreenLoadingStyle:'',
132   - showVideoDialog:false,
133   - historyPlayListHtml:'',
134   - hisotoryPlayFlag:false,
135   - downloadURL:null,
136   - rightMenuId:null,
137   - port:-1,
138   - httpPort:-1,
139   - stream:"",
140   - sim:"",
141   - channel:"",
  124 + nodes: [],
  125 + carPlayTimer: null,
  126 + carTreeNode: null,
  127 + ztreeObj: null,
  128 + ztreeNode: null,
  129 + fullscreenLoading: true,
  130 + fullscreenLoadingStyle: '',
  131 + showVideoDialog: false,
  132 + historyPlayListHtml: '',
  133 + hisotoryPlayFlag: false,
  134 + downloadURL: null,
  135 + rightMenuId: null,
  136 + port: -1,
  137 + httpPort: -1,
  138 + stream: "",
  139 + sim: "",
  140 + channel: "",
142 141 setting: {
143 142 callback: {
144 143 beforeExpand: this.beforeExpand
... ... @@ -157,23 +156,26 @@ export default {
157 156 isLeaf: 'spread',
158 157 nameIsHTML: true,
159 158 view: {
160   - nameIsHTML: true
161   - }
162   - }
  159 + nameIsHTML: true
  160 + }
  161 + },
163 162 };
164 163 },
165   -
166 164 mounted() {
167 165 let that = this;
168   - that.initTreeData();
  166 + that.initTreeData();
169 167 },
170 168 created() {
171   - this.checkPlayByParam()
  169 + this.checkPlayByParam();
  170 + },
  171 + beforeDestroy() {
  172 + if (!this.isEmpty(this.timer)) {
  173 + clearInterval(this.timer);
  174 + }
172 175 },
173   -
174 176 computed: {
175 177 liveStyle() {
176   - let style = {width: '100%', height: '100%'}
  178 + let style = {width: '99%', height: '99%'}
177 179 switch (this.spilt) {
178 180 case 4:
179 181 style = {width: '49%', height: '49%'}
... ... @@ -181,6 +183,9 @@ export default {
181 183 case 9:
182 184 style = {width: '32%', height: '32%'}
183 185 break
  186 + case 12:
  187 + style = {width: '24.5%', height: '32%'}
  188 + break
184 189 }
185 190 this.$nextTick(() => {
186 191 for (let i = 0; i < this.spilt; i++) {
... ... @@ -206,24 +211,99 @@ export default {
206 211 that.$refs['player' + i].resize()
207 212 }
208 213 })
209   -
210 214 }
211 215 window.localStorage.setItem('split', newValue)
212 216 },
213 217 '$route.fullPath': 'checkPlayByParam'
214 218 },
215 219 destroyed() {
216   - this.sendIORequestStop(this.sim,this.channel);
  220 + this.sendIORequestStop(this.sim, this.channel);
217 221 clearTimeout(this.updateLooper);
218   - if(!this.isEmpty(this.carPlayTimer)){
219   - console.log("bbbbbbbbbbbbbbb");
220   -
  222 + if (!this.isEmpty(this.carPlayTimer)) {
221 223 clearTimeout(this.carPlayTimer);
222 224 }
223 225 },
224 226 methods: {
  227 + handleChange(value, direction, movedKeys) {
  228 + console.log(value, direction, movedKeys);
  229 + },
  230 + //查询车辆信息
  231 + getCarInfo(){
  232 + this.$axios({
  233 + method: 'get',
  234 + url: `/api/jt1078/query/car/tree/100`,
  235 + }).then((res) => {
  236 + if (res && res.data && res.data.data) {
  237 + if (res.data.data.code == 1) {
  238 + l
  239 +
  240 +
  241 +
  242 + this.carInfoTimeout = setTimeout(function () {
  243 + this.getCarInfo()
  244 + }, 15000);
  245 + } else if (res.data.data.message) {
  246 + this.$message.error(res.data.data.message);
  247 + }
  248 + } else {
  249 + this.$message.error("请求错误,请刷新再试");
  250 + }
  251 + })
  252 + },
  253 + inspectionsDialog(){
  254 + if (this.nodes.length < 1) {
  255 +
  256 + }
  257 + this.showVideoDialog = true
  258 + },
  259 +
  260 + //视频巡查按钮改变事件
  261 + videoPatrolChange(newValue) {
  262 + if (newValue) {
  263 + this.videoPatrolStart();
  264 + }else {
  265 + if (!this.isEmpty(this.timer)) {
  266 + //关闭巡查定时器
  267 + clearInterval(this.timer);
  268 + }
  269 + }
  270 + },
  271 + //开启巡查定时器
  272 + videoPatrolStart(itemData){
  273 + let onlineCarKeys = this.onlineCarKeys;
  274 + if (!onlineCarKeys || onlineCarKeys.length === 0 ) {
  275 + this.$message.error("没有在线设备")
  276 + return
  277 + }
  278 + let count = this.onlineCarKeys.length - 1;
  279 + setInterval(() => {
  280 + if (itemData){
  281 + this.sendDevicePush(itemData);
  282 + itemData = null
  283 + }else {
  284 + if (count == -1){
  285 + count = this.onlineCarKeys.length - 1
  286 + }
  287 + let onlineCarKey = onlineCarKeys[count];
  288 + let split = onlineCarKey.split("-");
  289 + let onlineCar = this.onlineCar.get(split[0])
  290 + let sim = onlineCar.sim
  291 + let data = {
  292 + channelId: split[1],
  293 + deviceId: sim,
  294 + sim: sim
  295 + }
  296 + this.sendDevicePush(data);
  297 + count --;
  298 + }
  299 + },30000)
  300 + },
  301 +
  302 +
  303 +
  304 +
  305 +
225 306 destroy(idx) {
226   - console.log(idx);
227 307 this.clear(idx.substring(idx.length - 1))
228 308 },
229 309 treeChannelClick(device, data, isCatalog) {
... ... @@ -232,19 +312,22 @@ export default {
232 312 this.$message.error('设备离线!不允许点播');
233 313 this.closeLoading();
234 314 return false;
235   - }else {
236   - let pageObj = this;
237   -
238   - pageObj.sendDevicePush(data);
239   -
  315 + } else {
  316 + this.isSendDevicePush(data,this.patrolValue);
240 317 }
241 318 }
242 319 },
243 320 contextMenuEvent: function (device, event, data, isCatalog) {
244   -
  321 + },
  322 + isSendDevicePush(itemData, patrolValue) {
  323 + if (patrolValue){
  324 + this.videoPatrolStart(itemData);
  325 + }else {
  326 + this.sendDevicePush(itemData);
  327 + }
245 328 },
246 329 //通知设备上传媒体流
247   - sendDevicePush: function (itemData,fun) {
  330 + sendDevicePush: function (itemData, fun) {
248 331 // if (itemData.status === 0) {
249 332 // this.$message.error('设备离线!');
250 333 // return
... ... @@ -253,35 +336,26 @@ export default {
253 336 let deviceId = itemData.deviceId;
254 337 // this.isLoging = true;
255 338 let channelId = itemData.channelId;
256   -
257   - if(this.isEmpty(deviceId)){
  339 + if (this.isEmpty(deviceId)) {
258 340 this.$message.error("没有获取到sim卡,请检查设备是否接入");
259 341 this.closeLoading();
260   - if(fun){
261   - fun();
262   - }
  342 + if (fun) {fun();}
263 343 return;
264 344 }
265   -
266   -
267 345 console.log("通知设备推流1:" + deviceId + " : " + channelId);
268 346 let idxTmp = this.playerIdx
269 347 let that = this;
270   -
271 348 this.$axios({
272 349 method: 'get',
273 350 url: '/api/jt1078/query/send/request/io/' + deviceId + '/' + channelId
274 351 }).then(function (res) {
275   -
276   - if (res.data.code === 0 && res.data.data && (res.data.data.code ==="1" || res.data.data.code==1) ) {
  352 + if (res.data.code === 0 && res.data.data && (res.data.data.code === "1" || res.data.data.code == 1)) {
277 353 let videoUrl;
278   - that.port=res.data.data.port;
  354 + that.port = res.data.data.port;
279 355 that.httpPort = res.data.data.httpPort;
280 356 that.stream = res.data.data.stream;
281   -
282 357 console.log(res.data.data.data);
283   -
284   - if(!that.isEmpty(res.data.data.data)){
  358 + if (!that.isEmpty(res.data.data.data)) {
285 359 that.downloadURL = res.data.data.data.flv;
286 360 if (location.protocol === "https:") {
287 361 videoUrl = res.data.data.data.wss_flv;
... ... @@ -289,44 +363,29 @@ export default {
289 363 videoUrl = res.data.data.data.ws_flv;
290 364 }
291 365 console.log(videoUrl);
292   -
293   -
294 366 itemData.playUrl = videoUrl;
295 367 that.setPlayUrl(videoUrl, idxTmp);
296 368 }
297   -
298   - }else {
299   - if(!that.isEmpty(res.data.data) && !that.isEmpty( res.data.data.msg)){
  369 + } else {
  370 + if (!that.isEmpty(res.data.data) && !that.isEmpty(res.data.data.msg)) {
300 371 that.$message.error(res.data.data.msg);
301   - }else{
302   -
  372 + } else {
303 373 that.$message.error(res.data.msg);
304 374 }
305   -
306   - }
307   -
308   - if(fun){
309   -
310   - fun();
311 375 }
  376 + if (fun) {fun();}
312 377 }).catch(function (e) {
313   - if(fun){
314   - fun();
315   - }
  378 + if (fun) {fun();}
316 379 }).finally(() => {
317 380 this.closeLoading();
318 381 });
319   -
320   -
321 382 },
322 383 setPlayUrl(url, idx) {
323   -
324 384 this.$set(this.videoUrl, idx, url)
325 385 let _this = this
326 386 setTimeout(() => {
327 387 window.localStorage.setItem('videoUrl', JSON.stringify(_this.videoUrl))
328 388 }, 100)
329   -
330 389 },
331 390 checkPlayByParam() {
332 391 let {deviceId, channelId} = this.$route.query
... ... @@ -371,362 +430,290 @@ export default {
371 430 console.log(data);
372 431 window.localStorage.setItem('playData', JSON.stringify(data))
373 432 },
374   - initTreeData(){
  433 + initTreeData() {
375 434 this.showLoading();
376 435 this.$axios({
377   - method: 'get',
378   - url:`/api/jt1078/query/company/tree`,
  436 + method: 'get',
  437 + url: `/api/jt1078/query/company/tree`,
379 438 }).then((res) => {
380   - if(res && res.data && res.data.data){
381   - if(res.data.data.code == 1){
  439 + if (res && res.data && res.data.data) {
  440 + if (res.data.data.code == 1) {
382 441 let data = res.data.data.result;
383   - this.initDate(this.nodes,data);
384   - }else if(res.data.data.message){
  442 + this.initDate(this.nodes, data);
  443 + } else if (res.data.data.message) {
385 444 this.$message.error(res.data.data.message);
386 445 }
387   - }else{
  446 + } else {
388 447 this.$message.error("请求错误,请刷新再试");
389 448 }
390   -
391 449 this.closeLoading();
392   -
393   -
394 450 });
395   - },
396   -
397   - initDate(nodes,datas){
398   - if(nodes && datas){
399   - let len = datas.length;
400   - for (let i = 0; i < len; i++) {
401   - if(null == datas[i].id || undefined == datas[i].id || "" == datas[i].id){
402   - continue;
403   - }
404   -
405   - let node = this.combationNodeValue(datas[i].name,datas[i].id,datas[i].type,true,datas[i].sim,datas[i].abnormalStatus)
406   -
407   - nodes.push(node);
408   - if(datas[i].children){
409   - node.children = [];
410   - this.initDate(node.children,datas[i].children);
411   - }
412   - }
413   - }
414   - },
415   - combationNodeValue(name,id,type,isParent,sim,abnormalStatus){
416   - if(this.isEmpty(sim)){
417   - sim = "";
418   - }
419   -
420   - if(abnormalStatus >= 10 && abnormalStatus < 20){
421   - name = "<view style='color:red'>" + name + "</view>";
422   - }else if(abnormalStatus >= 20 && abnormalStatus < 30){
423   - name = "<view style='color:#ccc'>" + name + "</view>";
424   - }
425   -
426   - return {
427   - name: name,
428   - id: id,
429   - abnormalStatus:abnormalStatus,
430   - sim:sim,
431   - type: type,
432   - isParent: isParent,
433   -
434   - }
435   - },
436   - onClick(evt, treeId, treeNode) {
437   - this.combationChildNode(treeNode);
438   - },
439   - onCheck(evt, treeId, treeNode) {
440   -
441   - },
442   - beforeExpand(treeId, treeNode) {
443   -
444   - return true;
445   - },
446   - onExpand(evt, treeId, treeNode) {
447   - this.combationChildNode(treeNode);
448   - },
449   - handleCreated(ztreeObj) {
450   - this.ztreeObj = ztreeObj;
451   - this.ztreeObj.setting.view.nameIsHTML=true;
452   -
453   - },
454   -
455   - combationChildNode(treeNo){
456   - this.ztreeNode = treeNo;
457   - if(treeNo.seachChild && (treeNo.seachChild == 'true')){
458   - return;
459   - }
460   -
461   - this.showLoading();
462   -
463   - if(treeNo.type == 401 || treeNo.type == '401'){
464   - let device = new Object();
465   - if(this.isEmpty(treeNo.online)){
466   - treeNo.online = 1;
467   - }
468   - device.online = treeNo.online;
469   -
470   - if(this.spilt == 1){
471   - this.videoUrl=[]
472   - }
473   -
474   - this.closeLoading();
475   -
476   - let pageObj = this;
477   -
478   - if(!this.isEmpty(this.sim) && !this.channel && this.sim != treeNo.sim && this.channel != treeNo.id){
479   - let data = new Object();
480   - data.channelId =treeNo.id;
481   - data.sim = treeNo.sim;
482   - data.deviceId = treeNo.sim;
483   - this.sim = treeNo.sim;
484   - this.channel = treeNo.id;
485   - console.log("stop");
486   -
487   - this.sendIORequestStop(data.sim,data.channelId,function(){
488   -
489   - let flag = pageObj.treeChannelClick(device,data,false);
490   - if(false == flag){
491   - treeNo.online = 0;
492   - }
493   - });
494   - }else{
495   - let data = new Object();
496   - data.channelId =treeNo.id;
497   - data.sim = treeNo.sim;
498   - data.deviceId = treeNo.sim;
499   - this.sim = treeNo.sim;
500   - this.channel = treeNo.id;
501   -
502   - let flag = pageObj.treeChannelClick(device,data,false);
503   - if(false == flag){
504   - treeNo.online = 0;
505   - }
506   - }
507   - }else if(treeNo.type ==301 || treeNo.type=='301'){
508   - this.addChannel(treeNo);
509   - this.carTreeNode = treeNo;
510   - this.channel = null;
511   - }else if(treeNo.type==2|| treeNo.type=='2') {
512   - this.requestChildNode(treeNo);
513   - this.sim = null;
514   - this.channel = null;
515   - this.carTreeNode = null;
516   - }else{
517   - this.carTreeNode = null;
518   - this.sim = null;
519   - this.channel = null;
520   - this.closeLoading();
  451 + },
  452 + initDate(nodes, datas) {
  453 + if (nodes && datas) {
  454 + let len = datas.length;
  455 + for (let i = 0; i < len; i++) {
  456 + if (null == datas[i].id || undefined == datas[i].id || "" == datas[i].id) {
  457 + continue;
521 458 }
522   -
523   - },
524   - addChannel(treeNo){
525   -
526   -
527   - let labels=['ADAS','DSM','路况','司机','整车前','中门','倒车','前门客流','后面客流'];
528   - let children=[];
529   - let len = labels.length;
530   - let i = 0;
531   -
532   - let pageObj = this;
533   - for(;i<len;i++){
534   - console.log(treeNo.abnormalStatus+"==========================>"+i);
535   -
536   - let node = this.combationNodeValue(labels[i],i+1,401,false,treeNo.sim,treeNo.abnormalStatus);
537   - node.sim = treeNo.sim;
538   - node.zbh = treeNo.name;
539   - node.id=i+1;
540   - children.push(node);
  459 + let node = this.combationNodeValue(datas[i].name, datas[i].id, datas[i].type, true, datas[i].sim, datas[i].abnormalStatus)
  460 + nodes.push(node);
  461 + if (datas[i].children) {
  462 + node.children = [];
  463 + this.initDate(node.children, datas[i].children);
541 464 }
542   - this.ztreeObj.addNodes(treeNo,0,children,true);
543   - treeNo.seachChild='true';
  465 + }
  466 + }
  467 + },
  468 + combationNodeValue(name, id, type, isParent, sim, abnormalStatus) {
  469 + if (this.isEmpty(sim)) {
  470 + sim = "";
  471 + }
  472 + if (abnormalStatus >= 10 && abnormalStatus < 20) {
  473 + name = "<view style='color:red'>" + name + "</view>";
  474 + } else if (abnormalStatus >= 20 && abnormalStatus < 30) {
  475 + name = "<view style='color:#ccc'>" + name + "</view>";
  476 + }
  477 + return {
  478 + name: name,
  479 + id: id,
  480 + abnormalStatus: abnormalStatus,
  481 + sim: sim,
  482 + type: type,
  483 + isParent: isParent,
  484 + }
  485 + },
  486 + onClick(evt, treeId, treeNode) {
  487 + this.combationChildNode(treeNode);
  488 + },
  489 + onCheck(evt, treeId, treeNode) {
544 490  
545   - pageObj.sim = treeNo.sim;
  491 + },
  492 + beforeExpand(treeId, treeNode) {
546 493  
547   - this.closeLoading();
548   -
549   - },
550   - requestChildNode(treeNo){
551   -
552   - if(treeNo.spread==='false' || !treeNo.spread){
553   - let id = treeNo.id;
554   - let that = this;
555   - this.$axios({
556   - method: 'get',
557   - url:`/api/jt1078/query/car/tree/`+id,
558   - }).then((res) => {
559   -
560   - if(res && res.data && res.data.data){
561   - if(res.data.data.code == 1){
562   - let children =[];
563   - this.initDate(children,res.data.data.result);
564   -
565   - this.ztreeObj.addNodes(treeNo,-1,children,true);
566   - treeNo.seachChild='true';
567   -
568   - this.carPlayTimer = setTimeout(function(){
569   - that.requestChildNode1();
570   - },15000);
571   -
572   - }else if(res.data.data.message){
573   - this.$message.error(res.data.data.message);
574   - }
575   - }else{
576   - this.$message.error("请求错误,请刷新再试");
577   - }
  494 + return true;
  495 + },
  496 + onExpand(evt, treeId, treeNode) {
  497 + this.combationChildNode(treeNode);
  498 + },
  499 + handleCreated(ztreeObj) {
  500 + this.ztreeObj = ztreeObj;
  501 + this.ztreeObj.setting.view.nameIsHTML = true;
578 502  
579   - this.closeLoading();
580   - })
  503 + },
  504 + combationChildNode(treeNo) {
  505 + this.ztreeNode = treeNo;
  506 + if (treeNo.seachChild && (treeNo.seachChild == 'true')) {
  507 + return;
  508 + }
  509 + this.showLoading();
  510 + if (treeNo.type == 401 || treeNo.type == '401') {
  511 + let device = new Object();
  512 + if (this.isEmpty(treeNo.online)) {
  513 + treeNo.online = 1;
581 514 }
582   - },
583   - requestChildNode1(treeNo){
584   - let that = this;
585   - this.$axios({
586   - method: 'get',
587   - url:`/api/jt1078/query/car/tree/`+100,
588   - }).then((res) => {
589   -
590   - if(res && res.data && res.data.data){
591   - if(res.data.data.code == 1){
592   - this.refreshRequestRefresh(res.data.data.result);
593   -
594   - }else if(res.data.data.message){
595   - this.$message.error(res.data.data.message);
596   - }
597   - }else{
598   - this.$message.error("请求错误,请刷新再试");
  515 + device.online = treeNo.online;
  516 + if (this.spilt == 1) {
  517 + this.videoUrl = []
  518 + }
  519 + this.closeLoading();
  520 + let pageObj = this;
  521 + if (!this.isEmpty(this.sim) && !this.channel && this.sim != treeNo.sim && this.channel != treeNo.id) {
  522 + let data = new Object();
  523 + data.channelId = treeNo.id;
  524 + data.sim = treeNo.sim;
  525 + data.deviceId = treeNo.sim;
  526 + this.sim = treeNo.sim;
  527 + this.channel = treeNo.id;
  528 + console.log("stop");
  529 + this.sendIORequestStop(data.sim, data.channelId, function () {
  530 + let flag = pageObj.treeChannelClick(device, data, false);
  531 + if (false == flag) {
  532 + treeNo.online = 0;
599 533 }
600   - })
  534 + });
  535 + } else {
  536 + let data = new Object();
  537 + data.channelId = treeNo.id;
  538 + data.sim = treeNo.sim;
  539 + data.deviceId = treeNo.sim;
  540 + this.sim = treeNo.sim;
  541 + this.channel = treeNo.id;
  542 +
  543 + let flag = pageObj.treeChannelClick(device, data, false);
  544 + if (false == flag) {
  545 + treeNo.online = 0;
  546 + }
  547 + }
  548 + } else if (treeNo.type == 301 || treeNo.type == '301') {
  549 + this.addChannel(treeNo);
  550 + this.carTreeNode = treeNo;
  551 + this.channel = null;
  552 + } else if (treeNo.type == 2 || treeNo.type == '2') {
  553 + this.requestChildNode(treeNo);
  554 + this.sim = null;
  555 + this.channel = null;
  556 + this.carTreeNode = null;
  557 + } else {
  558 + this.carTreeNode = null;
  559 + this.sim = null;
  560 + this.channel = null;
  561 + this.closeLoading();
  562 + }
601 563 },
602   -
603   - refreshRequestRefresh(nodes){
604   - if(nodes){
605   - let length = nodes.length;
606   - for(let i=0;i<length;i++){
607   - let findNode = this.ztreeObj.getNodeByParam("id",nodes[i].id+"",null);
608   - if(findNode){
609   - findNode.name = nodes[i].name;
610   - if(findNode.type==301 || findNode.type=='301'){
611   - findNode.name = nodes[i].name;
612   - }else{
613   - findNode.name = nodes[i].name;
614   - }
615   - this.ztreeObj.updateNode(findNode);
616   -
617   - if(nodes[i].children){
618   - this.refreshRequestRefresh(nodes[i].children);
619   - }
  564 + addChannel(treeNo) {
  565 + let labels = ['ADAS', 'DSM', '路况', '司机', '整车前', '中门', '倒车', '前门客流', '后面客流'];
  566 + let children = [];
  567 + let len = labels.length;
  568 + let i = 0;
  569 + let pageObj = this;
  570 + for (; i < len; i++) {
  571 + console.log(treeNo.abnormalStatus + "==========================>" + i);
  572 + let node = this.combationNodeValue(labels[i], i + 1, 401, false, treeNo.sim, treeNo.abnormalStatus);
  573 + node.sim = treeNo.sim;
  574 + node.zbh = treeNo.name;
  575 + node.id = i + 1;
  576 + children.push(node);
  577 + }
  578 + this.ztreeObj.addNodes(treeNo, 0, children, true);
  579 + treeNo.seachChild = 'true';
  580 + pageObj.sim = treeNo.sim;
  581 + this.closeLoading();
  582 + },
  583 + requestChildNode(treeNo) {
  584 + if (treeNo.spread === 'false' || !treeNo.spread) {
  585 + let id = treeNo.id;
  586 + this.$axios({
  587 + method: 'get',
  588 + url: `/api/jt1078/query/car/tree/` + id,
  589 + }).then((res) => {
  590 + if (res && res.data && res.data.data) {
  591 + if (res.data.data.code == 1) {
  592 + let children = [];
  593 + this.initDate(children, res.data.data.result);
  594 + this.ztreeObj.addNodes(treeNo, -1, children, true);
  595 + treeNo.seachChild = 'true';
  596 + this.carPlayTimer = setTimeout(function () {
  597 + this.requestChildNode1();
  598 + }, 15000);
  599 + } else if (res.data.data.message) {
  600 + this.$message.error(res.data.data.message);
620 601 }
621   -
622   -
  602 + } else {
  603 + this.$message.error("请求错误,请刷新再试");
623 604 }
624   - }
  605 + this.closeLoading();
  606 + })
  607 + }
625 608 },
626   - showLoading(){
627   -
628   -
629   - this.loading = true;
630   - this.fullscreenLoading = true;
631   - // this.fullscreenLoadingStyle ='display:block';
632   - },
633   - closeLoading(){
634   - this.loading = false;
635   - //this.fullscreenLoadingStyle ='display:none';
636   - this.fullscreenLoading = false;
637   - console.log("已经关闭");
638   -
639   -
640   - },
641   - sendIORequestStop(sim,channel,fun){
642   - if(this.isEmpty(sim) || this.isEmpty(channel)){
643   - console.log("sim:"+sim+";channel:"+channel);
644   - if(fun){
645   - fun();
  609 + requestChildNode1() {
  610 + this.$axios({
  611 + method: 'get',
  612 + url: `/api/jt1078/query/car/tree/` + 100,
  613 + }).then((res) => {
  614 + if (res && res.data && res.data.data) {
  615 + if (res.data.data.code == 1) {
  616 + this.refreshRequestRefresh(res.data.data.result);
  617 + } else if (res.data.data.message) {
  618 + this.$message.error(res.data.data.message);
646 619 }
647   - return;
  620 + } else {
  621 + this.$message.error("请求错误,请刷新再试");
648 622 }
649   -
650   - this.videoUrl=[''];
651   - this.$axios({
652   - method: 'get',
653   - url:`/api/jt1078/query/send/stop/io/`+sim+"/"+channel+"/"+this.stream+"/"+this.port+"/"+this.httpPort,
654   - }).then((res) => {
655   - console.log(res);
656   - if(fun){
657   - fun();
658   - }
659   - });
660   - },
  623 + })
  624 + },
  625 + refreshRequestRefresh(nodes) {
  626 + if (nodes) {
  627 + let length = nodes.length;
  628 + for (let i = 0; i < length; i++) {
  629 + let findNode = this.ztreeObj.getNodeByParam("id", nodes[i].id + "", null);
  630 + if (findNode) {
  631 + findNode.name = nodes[i].name;
  632 + if (findNode.type == 301 || findNode.type == '301') {
  633 + findNode.name = nodes[i].name;
  634 + } else {
  635 + findNode.name = nodes[i].name;
  636 + }
  637 + this.ztreeObj.updateNode(findNode);
661 638  
662   - sendIORequestStop1(sim,channel,fun){
663   - if(this.isEmpty(sim) || this.isEmpty(channel)){
664   - console.log("sim:"+sim+";channel:"+channel);
665   - if(fun){
666   - fun();
  639 + if (nodes[i].children) {
  640 + this.refreshRequestRefresh(nodes[i].children);
  641 + }
667 642 }
668   - return;
669 643 }
670   -
671   - this.videoUrl=[''];
672   - this.$axios({
673   - method: 'get',
674   - url:`/api/jt1078/query/send/stop/io/`+sim+"/"+channel,
675   - }).then((res) => {
676   - console.log(res);
677   - if(fun){
678   - fun();
679   - }
680   - });
681   - },
682   -
683   - isEmpty(val){
684   - return null == val || undefined == val || "" == val;
685   - },
686   - openViewDIalog(){
687   - if(this.isEmpty(this.carTreeNode)){
688   - this.$message.error('请选择车辆');
689   - return;
  644 + }
  645 + },
  646 + showLoading() {
  647 + this.loading = true;
  648 + this.fullscreenLoading = true;
  649 + // this.fullscreenLoadingStyle ='display:block';
  650 + },
  651 + closeLoading() {
  652 + this.loading = false;
  653 + //this.fullscreenLoadingStyle ='display:none';
  654 + this.fullscreenLoading = false;
  655 + console.log("已经关闭");
  656 + },
  657 + sendIORequestStop(sim, channel, fun) {
  658 + if (this.isEmpty(sim) || this.isEmpty(channel)) {
  659 + console.log("sim:" + sim + ";channel:" + channel);
  660 + if (fun) {
  661 + fun();
690 662 }
691   - if(this.isEmpty(this.sim)){
692   - this.$message.error('无法获取SIM卡信息,请检查设备');
693   - return;
  663 + return;
  664 + }
  665 + this.videoUrl = [''];
  666 + this.$axios({
  667 + method: 'get',
  668 + url: `/api/jt1078/query/send/stop/io/` + sim + "/" + channel + "/" + this.stream + "/" + this.port + "/" + this.httpPort,
  669 + }).then((res) => {
  670 + console.log(res);
  671 + if (fun) {
  672 + fun();
694 673 }
695   -
696   - if(this.isEmpty(this.channel)){
697   -
698   - this.$message.error('请选择通道');
699   - return;
  674 + });
  675 + },
  676 + sendIORequestStop1(sim, channel, fun) {
  677 + if (this.isEmpty(sim) || this.isEmpty(channel)) {
  678 + console.log("sim:" + sim + ";channel:" + channel);
  679 + if (fun) {
  680 + fun();
700 681 }
701   - this.showLoading();
702   - let pageObj =this;
703   - this.videoUrl=[''];
704   -
705   -
706   - pageObj.showVideoDialog = true;
707   - pageObj.closeLoading();
708   -
709   -
710   - },
711   - close() {
712   - let pageObj = this;
713   - this.showLoading();
714   - this.historyPlayListHtml =null;
715   - this.startTime = null;
716   - this.endTime = null;
717   - if(this.hisotoryPlayFlag){
718   - this.sendIORequestStop(this.sim,this.channel,function(){
719   - pageObj.showVideoDialog = false;
720   - pageObj.videoUrl=[''];
721   - pageObj.closeLoading();
722   - console.log("关闭弹窗");
723   - });
724   - }else{
  682 + return;
  683 + }
  684 + this.videoUrl = [''];
  685 + this.$axios({
  686 + method: 'get',
  687 + url: `/api/jt1078/query/send/stop/io/` + sim + "/" + channel,
  688 + }).then((res) => {
  689 + console.log(res);
  690 + if (fun) {
  691 + fun();
  692 + }
  693 + });
  694 + },
  695 + isEmpty(val) {
  696 + return null == val || undefined == val || "" == val;
  697 + },
  698 + close() {
  699 + let pageObj = this;
  700 + this.showLoading();
  701 + this.historyPlayListHtml = null;
  702 + this.startTime = null;
  703 + this.endTime = null;
  704 + if (this.hisotoryPlayFlag) {
  705 + this.sendIORequestStop(this.sim, this.channel, function () {
725 706 pageObj.showVideoDialog = false;
  707 + pageObj.videoUrl = [''];
726 708 pageObj.closeLoading();
727   - }
728   - },
729   - searchHitoryList(){
  709 + console.log("关闭弹窗");
  710 + });
  711 + } else {
  712 + pageObj.showVideoDialog = false;
  713 + pageObj.closeLoading();
  714 + }
  715 + },
  716 + searchHitoryList(){
730 717 if(this.isEmpty(this.carTreeNode)){
731 718 this.$message.error('请选择车辆');
732 719 return;
... ... @@ -751,7 +738,7 @@ export default {
751 738 this.$message.error('请选择结束时间');
752 739 return;
753 740 }
754   -
  741 +
755 742 this.showLoading();
756 743  
757 744 let pageObj = this;
... ... @@ -759,8 +746,8 @@ export default {
759 746 method: 'get',
760 747 url: '/api/jt1078/query/history/list/' + this.sim + '/' + this.channel+"/"+this.startTime+"/"+this.endTime
761 748 }).then(function (res) {
762   -
763   -
  749 +
  750 +
764 751 if(res &&res.data && res.data.data && res.data.data.obj && res.data.data.code==1 && res.data.data.obj.data && res.data.data.obj.data.items){
765 752 let length = res.data.data.obj.data.items.length;
766 753 let html = "<div class='historyListDiv'><ul>";
... ... @@ -781,225 +768,190 @@ export default {
781 768 }
782 769 });
783 770 },
784   - playHistoryItem(e){
785   - if(this.isEmpty(this.carTreeNode)){
786   - this.$message.error('请选择车辆');
787   - return;
788   - }
789   - if(this.isEmpty(this.sim)){
790   - this.$message.error('无法获取SIM卡信息,请检查设备');
791   - return;
792   - }
793   -
  771 + playHistoryItem(e){
  772 + if(this.isEmpty(this.carTreeNode)){
  773 + this.$message.error('请选择车辆');
  774 + return;
  775 + }
  776 + if(this.isEmpty(this.sim)){
  777 + this.$message.error('无法获取SIM卡信息,请检查设备');
  778 + return;
  779 + }
794 780  
795   - if(this.isEmpty(this.channel)){
796   - this.$message.error('请选择通道');
797   - return;
798   - }
799 781  
800   - if(this.isEmpty(this.startTime)){
801   - this.$message.error('请选择开始时间');
802   - return;
803   - }
  782 + if(this.isEmpty(this.channel)){
  783 + this.$message.error('请选择通道');
  784 + return;
  785 + }
804 786  
805   - if(this.isEmpty(this.endTime)){
806   - this.$message.error('请选择结束时间');
807   - return;
808   - }
  787 + if(this.isEmpty(this.startTime)){
  788 + this.$message.error('请选择开始时间');
  789 + return;
  790 + }
809 791  
810   - let pageObj = this;
811   -
812   -
813   - this.videoUrl =[];
814   -
815   -
816   - pageObj.$axios({
817   - method: 'get',
818   - url: '/api/jt1078/query/send/request/io/history/' + pageObj.sim + '/' + pageObj.channel+"/"+e.target.getAttribute('startTime')+"/"+e.target.getAttribute('endTime')+"/"+e.target.getAttribute('channelMapping')
819   - }).then(function (res) {
820   -
821   -
822   - if (res.data && res.data.data && res.data.data.data) {
823   - let videoUrl1;
824   - if (location.protocol === "https:") {
825   - videoUrl1 = res.data.data.data.wss_flv;
826   - } else {
827   - videoUrl1 = res.data.data.data.ws_flv;
828   - }
829   - pageObj.downloadURL = res.data.data.data.flv;
830   - pageObj.port=res.data.data.port;
831   - pageObj.httpPort = res.data.data.httpPort;
832   - pageObj.stream = res.data.data.stream;
833   - pageObj.videoUrlHistory = videoUrl1;
834   -
835   - let itemData = new Object();
836   - itemData.deviceId = pageObj.sim;
837   - // this.isLoging = true;
838   - itemData.channelId= pageObj.channel;
839   - itemData.playUrl = videoUrl1;
840   - console.log(pageObj.playerIdx);
841   -
842   - pageObj.setPlayUrl(videoUrl1, 0);
843   - pageObj.hisotoryPlayFlag = true;
844   - // pageObj.$nextTick(() => {
845   - // pageObj.createdPlay();
846   - // pageObj.closeLoading();
847   - // })
848   - } else if(res.data.data && res.data.data.msg){
849   - pageObj.$message.error(res.data.data.msg);
850   - } else if(res.data.msg){
851   - pageObj.$message.error(res.data.msg);
852   - }else if(res.msg){
853   - pageObj.$message.error(res.msg);
854   - }
855   - pageObj.closeLoading();
856   - });
857   -
858   - },
859   - createdPlay() {
860   - if (flvjs.isSupported()) {
861   - // var videoDom = document.getElementById('myVideo')
862   - console.log(this.videoUrlHistory);
863   - let videoDom = this.$refs.myVideo
864   - // 创建一个播放器实例
865   - var player = flvjs.createPlayer({
866   - type: 'flv', // 媒体类型,默认是 flv,
867   - isLive: false, // 是否是直播流
868   - url: this.videoUrlHistory // 流地址
869   - }, {
870   - // 其他的配置项可以根据项目实际情况参考 api 去配置
871   - autoCleanupMinBackwardDuration: true, // 清除缓存 对 SourceBuffer 进行自动清理
872   - })
873   - player.attachMediaElement(videoDom)
874   - player.load()
875   - player.play()
876   - this.player = player
  792 + if(this.isEmpty(this.endTime)){
  793 + this.$message.error('请选择结束时间');
  794 + return;
877 795 }
878   - },
879   - OneClickPlayback(){
880   - console.log(this.carTreeNode);
881   -
882   - if(this.isEmpty(this.carTreeNode)){
883   - this.$message.error('请选择车辆');
884   - return;
885   - }
886 796  
887   - if(this.isEmpty(this.carTreeNode.abnormalStatus)){
888   - this.$message.error('请检查车辆状态');
889   - return;
890   - }
  797 + let pageObj = this;
891 798  
892   -
893   - if(this.carTreeNode.abnormalStatus!=1){
894   - this.$message.error('车辆设备离线,请检查设备');
895   - return;
896   - }
897   - if(this.isEmpty(this.sim)){
898   - this.$message.error('无法获取SIM卡信息,请检查设备');
899   - return;
900   - }
901 799  
902   - this.spilt = 9;
  800 + this.videoUrl =[];
  801 +
903 802  
904   - this.playOneAllChannel(0);
  803 + pageObj.$axios({
  804 + method: 'get',
  805 + url: '/api/jt1078/query/send/request/io/history/' + pageObj.sim + '/' + pageObj.channel+"/"+e.target.getAttribute('startTime')+"/"+e.target.getAttribute('endTime')+"/"+e.target.getAttribute('channelMapping')
  806 + }).then(function (res) {
  807 +
  808 +
  809 + if (res.data && res.data.data && res.data.data.data) {
  810 + let videoUrl1;
  811 + if (location.protocol === "https:") {
  812 + videoUrl1 = res.data.data.data.wss_flv;
  813 + } else {
  814 + videoUrl1 = res.data.data.data.ws_flv;
  815 + }
  816 + pageObj.downloadURL = res.data.data.data.flv;
  817 + pageObj.port=res.data.data.port;
  818 + pageObj.httpPort = res.data.data.httpPort;
  819 + pageObj.stream = res.data.data.stream;
  820 + pageObj.videoUrlHistory = videoUrl1;
  821 +
  822 + let itemData = new Object();
  823 + itemData.deviceId = pageObj.sim;
  824 + // this.isLoging = true;
  825 + itemData.channelId= pageObj.channel;
  826 + itemData.playUrl = videoUrl1;
  827 + console.log(pageObj.playerIdx);
  828 +
  829 + pageObj.setPlayUrl(videoUrl1, 0);
  830 + pageObj.hisotoryPlayFlag = true;
  831 + // pageObj.$nextTick(() => {
  832 + // pageObj.createdPlay();
  833 + // pageObj.closeLoading();
  834 + // })
  835 + } else if(res.data.data && res.data.data.msg){
  836 + pageObj.$message.error(res.data.data.msg);
  837 + } else if(res.data.msg){
  838 + pageObj.$message.error(res.data.msg);
  839 + }else if(res.msg){
  840 + pageObj.$message.error(res.msg);
  841 + }
  842 + pageObj.closeLoading();
  843 + });
  844 +
  845 + },
  846 + oneClickPlayback() {
  847 + if (this.isEmpty(this.carTreeNode)) {
  848 + this.$message.error('请选择车辆');
  849 + return;
  850 + }
  851 + if (this.isEmpty(this.carTreeNode.abnormalStatus)) {
  852 + this.$message.error('请检查车辆状态');
  853 + return;
  854 + }
  855 + if (this.carTreeNode.abnormalStatus != 1) {
  856 + this.$message.error('车辆设备离线,请检查设备');
  857 + return;
  858 + }
  859 + if (this.isEmpty(this.sim)) {
  860 + this.$message.error('无法获取SIM卡信息,请检查设备');
  861 + return;
  862 + }
  863 + this.spilt = 12;
  864 + this.playOneAllChannel(0);
905 865 },
906   - playOneAllChannel(channel){
907   - if(channel ==9){
  866 + playOneAllChannel(channel) {
  867 + if (channel == 9) {
908 868 return;
909 869 }
910 870 let item = new Object();
911 871 item.deviceId = this.sim;
912   - item.channelId = 1+channel;
913   - this.playerIdx=channel;
  872 + item.channelId = 1 + channel;
  873 + this.playerIdx = channel;
914 874 let that = this;
915   - this.sendDevicePush(item,function(){
916   - that.playOneAllChannel(1+channel);
  875 + this.sendDevicePush(item, function () {
  876 + that.playOneAllChannel(1 + channel);
917 877 });
918 878 },
919   - spiltClickFun(val){
920   - this.spilt = val;
921   - if(val-1 < this.playerIdx){
922   - this.playerIdx = val-1;
923   - }
  879 + spiltClickFun(val) {
  880 + this.spilt = val;
  881 + if (val - 1 < this.playerIdx) {
  882 + this.playerIdx = val - 1;
  883 + }
924 884 },
925 885 downloadFunction(){
926 886 console.log(this.downloadURL);
927   -
  887 +
928 888 if(this.isEmpty(this.downloadURL)){
929   - return;
  889 + return;
930 890 }
931   -
  891 +
932 892 window.open(this.downloadURL,"_download");
933 893 },
934   - closeSelectItem(){
935   - console.log("============================>"+this.playerIdx);
936   - this.setPlayUrl(null,this.playerIdx)
  894 +
  895 + closeSelectItem() {
  896 + console.log("============================>" + this.playerIdx);
  897 + this.setPlayUrl(null, this.playerIdx)
937 898 // this.videoUrl[this.playerIdx]=null;
938   - // this.sendIORequestStop1(this.sim,this.playerIdx+1);
939   -
  899 + // this.sendIORequestStop1(this.sim,this.playerIdx+1);
940 900 },
941   - closeSelectCarItem(){
  901 + closeSelectCarItem() {
942 902 for (let index = 0; index < 9; index++) {
943   - this.setPlayUrl(null,index)
944   - // this.videoUrl[this.playerIdx]=null;
945   - this.sendIORequestStop1(this.sim,index+1);
946   -
  903 + this.setPlayUrl(null, index)
  904 + // this.videoUrl[this.playerIdx]=null;
  905 + this.sendIORequestStop1(this.sim, index + 1);
947 906 }
948   -
949   -
950 907 },
951   - treeRightMenuFun(event,treeId,treeNode){
952   - if(treeNode.type == '301' || treeNode.type==301){
953   - this.rightMenuId = "carRMenu";
954   - this.showRMenu(event);
955   - this.carTreeNode = treeNode;
956   - this.sim = treeNode.sim;
957   - this.channel = null;
958   - }else if(treeNode.type == '401' || treeNode.type==401){
959   - this.rightMenuId ="channelCarRMenu";
960   - this.showRMenu(event);
961   - this.channel = treeNode.id;
962   - }else{
  908 + treeRightMenuFun(event, treeId, treeNode) {
  909 + if (treeNode.type == '301' || treeNode.type == 301) {
  910 + this.rightMenuId = "carRMenu";
  911 + this.showRMenu(event);
  912 + this.carTreeNode = treeNode;
  913 + this.sim = treeNode.sim;
  914 + this.channel = null;
  915 + } else if (treeNode.type == '401' || treeNode.type == 401) {
  916 + this.rightMenuId = "channelCarRMenu";
  917 + this.showRMenu(event);
  918 + this.channel = treeNode.id;
  919 + } else {
963 920 this.carTreeNode = null;
964   - this.sim = null;
  921 + this.sim = null;
965 922 this.channel = null;
966 923 hidden();
967 924 }
968 925 },
969   - showRMenu(event) {
970   - if(this.isEmpty(this.rightMenuId)){
971   - return ;
972   - }
973   - let carMenu = document.getElementById(this.rightMenuId);
974   - carMenu.setAttribute("style","display:block");
975   -
976   - let x = event.clientX;
977   - let y = event.clientY;
978   - carMenu.setAttribute("style","display:block;top:"+y+"px;left:"+x+"px");
979   - document.addEventListener("click", this.hideMenu);
980   -
981   - console.log(this.rightMenuId);
982   -
  926 + showRMenu(event) {
  927 + if (this.isEmpty(this.rightMenuId)) {
  928 + return;
  929 + }
  930 + let carMenu = document.getElementById(this.rightMenuId);
  931 + carMenu.setAttribute("style", "display:block");
  932 +
  933 + let x = event.clientX;
  934 + let y = event.clientY;
  935 + carMenu.setAttribute("style", "display:block;top:" + y + "px;left:" + x + "px");
  936 + document.addEventListener("click", this.hideMenu);
  937 + console.log(this.rightMenuId);
983 938 },
984   - hideMenu() {
985   - if(this.isEmpty(this.rightMenuId)){
986   - return ;
987   - }
  939 + hideMenu() {
  940 + if (this.isEmpty(this.rightMenuId)) {
  941 + return;
  942 + }
988 943 let carMenu = document.getElementById(this.rightMenuId);
989   - carMenu.setAttribute("style","display:none");
  944 + carMenu.setAttribute("style", "display:none");
990 945 this.rightMenuId = null;
991 946 }
992   -
993 947 }
994 948 };
995   -
996   -
997 949 </script>
998   -
999 950 <style>
1000   -.device-tree-main-box{
  951 +.device-tree-main-box {
1001 952 text-align: left;
1002 953 }
  954 +
1003 955 .btn {
1004 956 margin: 0 10px;
1005 957  
... ... @@ -1025,51 +977,54 @@ export default {
1025 977 align-items: center;
1026 978 justify-content: center;
1027 979 }
1028   -.historyListLi{
1029   - width: 97%;
1030   - white-space: nowrap;
  980 +
  981 +.historyListLi {
  982 + width: 97%;
  983 + white-space: nowrap;
1031 984 text-overflow: ellipsis;
1032 985 cursor: pointer;
1033 986 padding: 3px;
1034 987 margin-bottom: 6px;
1035 988 border: 1px solid #000000;
1036 989 }
1037   -.historyListDiv{
1038   - height:80vh;
1039   - width:100%;
1040   - overflow-y:auto;
1041   - overflow-x:hidden;
  990 +
  991 +.historyListDiv {
  992 + height: 80vh;
  993 + width: 100%;
  994 + overflow-y: auto;
  995 + overflow-x: hidden;
1042 996 }
1043 997  
1044 998  
1045   - /* 菜单的样式 */
  999 +/* 菜单的样式 */
1046 1000 .rMenu {
1047   - position:absolute;
1048   - top:0;
1049   - display: none;
1050   - margin: 0;
1051   - padding: 0;
1052   - text-align: left;
1053   - border: 1px solid #BFBFBF;
1054   - border-radius: 3px;
1055   - background-color: #EEE;
1056   - box-shadow: 0 0 10px #AAA;
  1001 + position: absolute;
  1002 + top: 0;
  1003 + display: none;
  1004 + margin: 0;
  1005 + padding: 0;
  1006 + text-align: left;
  1007 + border: 1px solid #BFBFBF;
  1008 + border-radius: 3px;
  1009 + background-color: #EEE;
  1010 + box-shadow: 0 0 10px #AAA;
1057 1011 }
1058 1012  
1059 1013 .rMenu li {
1060   - width: 170px;
1061   - list-style: none outside none;
1062   - cursor: default;
1063   - color: #666;
1064   - margin-left: -20px;
  1014 + width: 170px;
  1015 + list-style: none outside none;
  1016 + cursor: default;
  1017 + color: #666;
  1018 + margin-left: -20px;
1065 1019 }
  1020 +
1066 1021 .rMenu li:hover {
1067   - color: #EEE;
1068   - background-color: #666;
  1022 + color: #EEE;
  1023 + background-color: #666;
1069 1024 }
1070 1025  
1071 1026 li#menu-item-delete, li#menu-item-rename {
1072   - margin-top: 1px;
  1027 + margin-top: 1px;
1073 1028 }
1074 1029 </style>
1075 1030 <style>
... ... @@ -1145,4 +1100,14 @@ li#menu-item-delete, li#menu-item-rename {
1145 1100 .baidumap > .anchorBL {
1146 1101 display: none !important;
1147 1102 }
1148   -</style>
1149 1103 \ No newline at end of file
  1104 +
  1105 +.scroll-container {
  1106 + max-height: 85vh; /* 设置最大高度为85%的视口高度 */
  1107 + overflow-y: auto; /* 内容超出时显示垂直滚动条 */
  1108 + overflow-x: hidden; /* 隐藏水平滚动条 */
  1109 +}
  1110 +.transfer-footer {
  1111 + margin-left: 20px;
  1112 + padding: 6px 5px;
  1113 +}
  1114 +</style>
... ...
web_src/src/components/HistoricalRecord.vue 0 → 100644
  1 +<template>
  2 + <div style="width: 2000px">
  3 + <el-container v-loading="loading" style="height: 100%;width: 100%" element-loading-text="拼命加载中">
  4 + <div style="width:100%;display: flex;flex-direction: column;justify-content: space-between;">
  5 + <div class="block" style="width: 99%;text-align:left;margin-bottom:15px;">
  6 + <el-card class="box-card" style="width: 100%">
  7 + <car-tree v-model="sim_channel"/>
  8 + <el-date-picker
  9 + v-model="date"
  10 + align="right"
  11 + type="date"
  12 + placeholder="选择日期"
  13 + :picker-options="pickerOptions">
  14 + </el-date-picker>
  15 + <el-time-picker
  16 + is-range
  17 + v-model="timeList"
  18 + range-separator="至"
  19 + start-placeholder="开始时间"
  20 + end-placeholder="结束时间"
  21 + placeholder="选择时间范围">
  22 + </el-time-picker>
  23 + <el-button @click="searchHitoryList()">搜索</el-button>
  24 + <el-button @click="downloadFunction()">下载播放视频</el-button>
  25 + </el-card>
  26 + </div>
  27 +
  28 + <div style="width: 100%;display:flex;flex-direction:row; justify-content:space-between;">
  29 + <div style="width:20%;height: 80vh" >
  30 + <historical-data :history-data="historyData" @click="clickHistoricalPlay" />
  31 + </div>
  32 + <div style="width: 78%;">
  33 + <div style="width: 99%;height: 80vh;display: flex;flex-wrap: wrap;background-color: #000;">
  34 + <div v-if="!videoUrl[0]" style="color: #ffffff;font-size: 30px;font-weight: bold;"></div>
  35 + <player ref="player" v-else :videoUrl="videoUrl[0]" fluent autoplay @screenshot="shot"
  36 + @destroy="destroy" style="width: 100%;height: 100%;"/>
  37 + </div>
  38 + </div>
  39 + </div>
  40 + </div>
  41 + </el-container>
  42 + </div>
  43 +</template>
  44 +
  45 +<script>
  46 +//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等),
  47 +//例如:import 《组件名称》 from '《组件路径》,
  48 +import player from "./common/jessibuca.vue";
  49 +import CarTree from "./JT1078Components/cascader/CarTree.vue";
  50 +import {parseTime} from "../../utils/ruoyi";
  51 +import HistoricalData from "./JT1078Components/historical/HistoricalDataTree.vue";
  52 +
  53 +export default {
  54 + //import引入的组件需要注入到对象中才能使用"
  55 + components: {HistoricalData, CarTree, player},
  56 + props: {},
  57 + data() {
  58 + //这里存放数据"
  59 + return {
  60 + historyData: [],
  61 + //遮罩层
  62 + loading: false,
  63 + //sim号和通道号,格式为:sim-channel
  64 + sim_channel: null,
  65 + //日期快捷选择
  66 + pickerOptions: {
  67 + disabledDate(time) {
  68 + return time.getTime() > Date.now();
  69 + },
  70 + shortcuts: [{
  71 + text: '今天',
  72 + onClick(picker) {
  73 + picker.$emit('pick', new Date());
  74 + }
  75 + }, {
  76 + text: '昨天',
  77 + onClick(picker) {
  78 + const date = new Date();
  79 + date.setTime(date.getTime() - 3600 * 1000 * 24);
  80 + picker.$emit('pick', date);
  81 + }
  82 + }, {
  83 + text: '一周前',
  84 + onClick(picker) {
  85 + const date = new Date();
  86 + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
  87 + picker.$emit('pick', date);
  88 + }
  89 + }]
  90 + },
  91 + //选中的时间
  92 + timeList: [new Date(2016, 9, 10, 0, 1),
  93 + new Date(2016, 9, 10, 0, 1)],
  94 + //选中的日期
  95 + date: null,
  96 + historyPlayListHtml: '',
  97 + videoUrl: []
  98 + };
  99 + },
  100 + //计算属性 类似于data概念",
  101 + computed: {},
  102 + //监控data中的数据变化",
  103 + watch: {},
  104 + //方法集合",
  105 + methods: {
  106 + /**
  107 + * 点击播放视频
  108 + */
  109 + clickHistoricalPlay(data) {
  110 + this.playHistoryItem(data)
  111 + },
  112 + simChannelChange(val) {
  113 + console.log(val);
  114 + console.log(this.sim_channel)
  115 + },
  116 + /**
  117 + * 下载历史视频
  118 + */
  119 + downloadFunction() {
  120 + this.getDateTime();
  121 + console.log(this.downloadURL);
  122 + if (this.isEmpty(this.downloadURL)) {
  123 + return;
  124 + }
  125 + window.open(this.downloadURL, "_download");
  126 + },
  127 + /**
  128 + * 搜索历史视频
  129 + */
  130 + searchHitoryList() {
  131 + this.getDateTime();
  132 + let simChannel = this.sim_channel;
  133 + if (this.isEmpty(simChannel)) {
  134 + this.$message.error('请选择车辆');
  135 + return;
  136 + }
  137 + let split = simChannel[simChannel.length - 1].split('-');
  138 + let sim = split[0];
  139 + if (this.isEmpty(sim)) {
  140 + this.$message.error('无法获取SIM卡信息,请检查设备');
  141 + return;
  142 + }
  143 + let channel = split[1];
  144 + if (this.isEmpty(channel)) {
  145 + this.$message.error('请选择通道');
  146 + return;
  147 + }
  148 + if (this.isEmpty(this.startTime) || this.isEmpty(this.endTime)) {
  149 + this.$message.error('请选择开始和结束时间');
  150 + return;
  151 + }
  152 + this.loading = true
  153 + this.$axios({
  154 + method: 'get',
  155 + url: '/api/jt1078/query/history/list/' + sim + '/' + channel + "/" + this.startTime + "/" + this.endTime
  156 + }).then(
  157 + res=>{
  158 + let items = res.data.data.obj.data.items;
  159 + if (res && res.data && res.data.data && res.data.data.obj && res.data.data.code == 1 && res.data.data.obj.data && items) {
  160 + for (let i in items) {
  161 + items[i].sim = res.data.data.obj.data.clientId;
  162 + items[i].name = items[i].startTime + '-' + items[i].endTime;
  163 + }
  164 + this.historyData = items
  165 + this.loading = false
  166 + } else if (res && res.data && res.data.data && res.data.data.msg) {
  167 + this.$message.error(res.data.data.msg);
  168 + this.loading = false
  169 + } else {
  170 + this.loading = false
  171 + }
  172 + });
  173 + },
  174 + /**
  175 + * 时间转换
  176 + */
  177 + getDateTime() {
  178 + let date = this.date;
  179 + let timeList = this.timeList;
  180 + console.log(date)
  181 + console.log(timeList)
  182 + if (this.isEmpty(date)) {
  183 + this.$message.error("请选择日期")
  184 + return false;
  185 + }
  186 + if (this.isEmpty(timeList)) {
  187 + this.$message.error("请选择起始时间")
  188 + return false;
  189 + }
  190 + let year = date.getFullYear();
  191 + let month = date.getMonth();
  192 + let day = date.getDate()
  193 + let startTime = timeList[0];
  194 + startTime.setFullYear(year);
  195 + startTime.setMonth(month);
  196 + startTime.setDate(day);
  197 + let endTime = timeList[1];
  198 + endTime.setFullYear(year);
  199 + endTime.setMonth(month);
  200 + endTime.setDate(day);
  201 + startTime = parseTime(startTime, '{y}-{m}-{d} {h}:{i}:{s}');
  202 + endTime = parseTime(endTime, '{y}-{m}-{d} {h}:{i}:{s}');
  203 + console.log("startTime:" + startTime)
  204 + console.log("endTime:" + endTime)
  205 + this.startTime = startTime;
  206 + this.endTime = endTime;
  207 + return true
  208 + },
  209 + /**
  210 + * 播放历史数据
  211 + */
  212 + playHistoryItem(e) {
  213 + this.videoUrl = [];
  214 + this.$axios({
  215 + method: 'get',
  216 + url: '/api/jt1078/query/send/request/io/history/' + e.sim + '/' + e.channelNo + "/" + e.startTime + "/" + e.endTime + "/" + e.channelMapping
  217 + }).then(res=> {
  218 + if (res.data && res.data.data && res.data.data.data) {
  219 + let videoUrl1;
  220 + if (location.protocol === "https:") {
  221 + videoUrl1 = res.data.data.data.wss_flv;
  222 + } else {
  223 + videoUrl1 = res.data.data.data.ws_flv;
  224 + }
  225 + this.downloadURL = res.data.data.data.flv;
  226 + this.port = res.data.data.port;
  227 + this.httpPort = res.data.data.httpPort;
  228 + this.stream = res.data.data.stream;
  229 + this.videoUrlHistory = videoUrl1;
  230 +
  231 + let itemData = new Object();
  232 + itemData.deviceId = this.sim;
  233 + itemData.channelId = this.channel;
  234 + itemData.playUrl = videoUrl1;
  235 + console.log(this.playerIdx);
  236 + this.setPlayUrl(videoUrl1, 0);
  237 + this.hisotoryPlayFlag = true;
  238 +
  239 + } else if (res.data.data && res.data.data.msg) {
  240 + this.$message.error(res.data.data.msg);
  241 + } else if (res.data.msg) {
  242 + this.$message.error(res.data.msg);
  243 + } else if (res.msg) {
  244 + this.$message.error(res.msg);
  245 + }
  246 + this.closeLoading();
  247 + })
  248 + },
  249 +
  250 + /**
  251 + * 实时访问播放地址
  252 + * @param url
  253 + * @param idx
  254 + */
  255 + setPlayUrl(url, idx) {
  256 + this.$set(this.videoUrl, idx, url)
  257 + let _this = this
  258 + setTimeout(() => {
  259 + window.localStorage.setItem('videoUrl', JSON.stringify(_this.videoUrl))
  260 + }, 100)
  261 + },
  262 +
  263 + shot(e) {
  264 + // console.log(e)
  265 + // send({code:'image',data:e})
  266 + var base64ToBlob = function (code) {
  267 + let parts = code.split(';base64,');
  268 + let contentType = parts[0].split(':')[1];
  269 + let raw = window.atob(parts[1]);
  270 + let rawLength = raw.length;
  271 + let uInt8Array = new Uint8Array(rawLength);
  272 + for (let i = 0; i < rawLength; ++i) {
  273 + uInt8Array[i] = raw.charCodeAt(i);
  274 + }
  275 + return new Blob([uInt8Array], {
  276 + type: contentType
  277 + });
  278 + };
  279 + let aLink = document.createElement('a');
  280 + let blob = base64ToBlob(e); //new Blob([content]);
  281 + let evt = document.createEvent("HTMLEvents");
  282 + evt.initEvent("click", true, true); //initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为
  283 + aLink.download = '截图';
  284 + aLink.href = URL.createObjectURL(blob);
  285 + aLink.click();
  286 + },
  287 + destroy(idx) {
  288 + console.log(idx);
  289 + this.clear(idx.substring(idx.length - 1))
  290 + },
  291 +
  292 + createdPlay() {
  293 + if (flvjs.isSupported()) {
  294 + // var videoDom = document.getElementById('myVideo')
  295 + console.log(this.videoUrlHistory);
  296 + let videoDom = this.$refs.myVideo
  297 + // 创建一个播放器实例
  298 + var player = flvjs.createPlayer({
  299 + type: 'flv', // 媒体类型,默认是 flv,
  300 + isLive: false, // 是否是直播流
  301 + url: this.videoUrlHistory // 流地址
  302 + }, {
  303 + // 其他的配置项可以根据项目实际情况参考 api 去配置
  304 + autoCleanupMinBackwardDuration: true, // 清除缓存 对 SourceBuffer 进行自动清理
  305 + })
  306 + player.attachMediaElement(videoDom)
  307 + player.load()
  308 + player.play()
  309 + this.player = player
  310 + }
  311 + },
  312 + isEmpty(val) {
  313 + return null == val || undefined == val || "" == val;
  314 + }
  315 +
  316 +
  317 + },
  318 + //生命周期 - 创建完成(可以访问当前this实例)",
  319 + created() {
  320 + },
  321 + //生命周期 - 挂载完成(可以访问DOM元素)",
  322 + mounted() {
  323 + },
  324 + beforeCreate() {
  325 + }, //生命周期 - 创建之前",
  326 + beforeMount() {
  327 + }, //生命周期 - 挂载之前",
  328 + beforeUpdate() {
  329 + }, //生命周期 - 更新之前",
  330 + updated() {
  331 + }, //生命周期 - 更新之后",
  332 + beforeDestroy() {
  333 + }, //生命周期 - 销毁之前",
  334 + destroyed() {
  335 + }, //生命周期 - 销毁完成",
  336 + activated() {
  337 + } //如果页面有keep-alive缓存功能,这个函数会触发",
  338 +};
  339 +</script>
  340 +<style scoped>
  341 +.device-tree-main-box {
  342 + text-align: left;
  343 +}
  344 +
  345 +.btn {
  346 + margin: 0 10px;
  347 +
  348 +}
  349 +
  350 +.btn:hover {
  351 + color: #409EFF;
  352 +}
  353 +
  354 +.btn.active {
  355 + color: #409EFF;
  356 +
  357 +}
  358 +
  359 +.redborder {
  360 + border: 2px solid red !important;
  361 +}
  362 +
  363 +.play-box {
  364 + background-color: #000000;
  365 + border: 2px solid #505050;
  366 + display: flex;
  367 + align-items: center;
  368 + justify-content: center;
  369 +}
  370 +
  371 +.historyListLi {
  372 + width: 97%;
  373 + white-space: nowrap;
  374 + text-overflow: ellipsis;
  375 + cursor: pointer;
  376 + padding: 3px;
  377 + margin-bottom: 6px;
  378 + border: 1px solid #000000;
  379 +}
  380 +
  381 +.historyListDiv {
  382 + height: 80vh;
  383 + width: 100%;
  384 + overflow-y: auto;
  385 + overflow-x: hidden;
  386 +}
  387 +
  388 +
  389 +/* 菜单的样式 */
  390 +.rMenu {
  391 + position: absolute;
  392 + top: 0;
  393 + display: none;
  394 + margin: 0;
  395 + padding: 0;
  396 + text-align: left;
  397 + border: 1px solid #BFBFBF;
  398 + border-radius: 3px;
  399 + background-color: #EEE;
  400 + box-shadow: 0 0 10px #AAA;
  401 +}
  402 +
  403 +.rMenu li {
  404 + width: 170px;
  405 + list-style: none outside none;
  406 + cursor: default;
  407 + color: #666;
  408 + margin-left: -20px;
  409 +}
  410 +
  411 +.rMenu li:hover {
  412 + color: #EEE;
  413 + background-color: #666;
  414 +}
  415 +
  416 +li#menu-item-delete, li#menu-item-rename {
  417 + margin-top: 1px;
  418 +}
  419 +</style>
  420 +<style>
  421 +.videoList {
  422 + display: flex;
  423 + flex-wrap: wrap;
  424 + align-content: flex-start;
  425 +}
  426 +
  427 +.video-item {
  428 + position: relative;
  429 + width: 15rem;
  430 + height: 10rem;
  431 + margin-right: 1rem;
  432 + background-color: #000000;
  433 +}
  434 +
  435 +.video-item-img {
  436 + position: absolute;
  437 + top: 0;
  438 + bottom: 0;
  439 + left: 0;
  440 + right: 0;
  441 + margin: auto;
  442 + width: 100%;
  443 + height: 100%;
  444 +}
  445 +
  446 +.video-item-img:after {
  447 + content: "";
  448 + display: inline-block;
  449 + position: absolute;
  450 + z-index: 2;
  451 + top: 0;
  452 + bottom: 0;
  453 + left: 0;
  454 + right: 0;
  455 + margin: auto;
  456 + width: 3rem;
  457 + height: 3rem;
  458 + background-image: url("../assets/loading.png");
  459 + background-size: cover;
  460 + background-color: #000000;
  461 +}
  462 +
  463 +.video-item-title {
  464 + position: absolute;
  465 + bottom: 0;
  466 + color: #000000;
  467 + background-color: #ffffff;
  468 + line-height: 1.5rem;
  469 + padding: 0.3rem;
  470 + width: 14.4rem;
  471 +}
  472 +
  473 +.baidumap {
  474 + width: 100%;
  475 + height: 100%;
  476 + border: none;
  477 + position: absolute;
  478 + left: 0;
  479 + top: 0;
  480 + right: 0;
  481 + bottom: 0;
  482 + margin: auto;
  483 +}
  484 +
  485 +/* 去除百度地图版权那行字 和 百度logo */
  486 +.baidumap > .BMap_cpyCtrl {
  487 + display: none !important;
  488 +}
  489 +
  490 +.baidumap > .anchorBL {
  491 + display: none !important;
  492 +}
  493 +</style>
... ...
web_src/src/components/JT1078Components/cascader/CarTree.vue 0 → 100644
  1 +<template>
  2 + <el-cascader
  3 + placeholder="请选择/搜索车辆"
  4 + :options="options"
  5 + filterable
  6 + clearable
  7 + :props="prop"
  8 + v-model="valueList"
  9 + @change="getValue">
  10 + </el-cascader>
  11 +</template>
  12 +
  13 +<script>
  14 +//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等),
  15 +//例如:import 《组件名称》 from '《组件路径》,
  16 + export default {
  17 + //import引入的组件需要注入到对象中才能使用"
  18 + components: {},
  19 + props: {
  20 + value: {
  21 + type: Array,
  22 + default: []
  23 + }
  24 + },
  25 + data() {
  26 + //这里存放数据"
  27 + return {
  28 + options: [],
  29 + prop: {
  30 + value: 'sim',
  31 + label: `name`,
  32 + children: 'children',
  33 + },
  34 +
  35 + };
  36 + },
  37 + //计算属性 类似于data概念",
  38 + computed: {
  39 + valueList: {
  40 + get(){
  41 + let value = this.value;
  42 + if (value || value === null || value.length === 0) {
  43 + return value
  44 + }
  45 + return value[ value.length - 1 ];
  46 + },
  47 + set(val){
  48 + if (val || val === null || val.length === 0) {
  49 + this.$emit("input",val)
  50 + }
  51 + return val[ val.length - 1 ]
  52 +
  53 + console.log(val)
  54 + }
  55 + }
  56 + },
  57 + //监控data中的数据变化",
  58 + watch: {},
  59 + //方法集合",
  60 + methods: {
  61 + getValue(val){
  62 + console.log(val)
  63 + },
  64 + /**
  65 + * 查询级联数据列表
  66 + */
  67 + initTreeData() {
  68 + this.$axios({
  69 + method: 'get',
  70 + url: `/api/jt1078/query/car/tree/` + 100,
  71 + }).then((res) => {
  72 + if (res && res.data && res.data.data) {
  73 + if (res.data.data.code == 1) {
  74 + let data1 = res.data.data.result;
  75 + this.addChannel(data1);
  76 + } else if (res.data.data.message) {
  77 + this.$message.error(res.data.data.message);
  78 + }
  79 + } else {
  80 + this.$message.error("请求错误,请刷新再试");
  81 + }
  82 +
  83 + });
  84 + },
  85 + /**
  86 + * 整理数据结构
  87 + * @param treeNo
  88 + */
  89 + addChannel(data) {
  90 + for (let i in data) {
  91 + if (data[i] && data[i].sim){
  92 + data[i].name = data[i].code;
  93 + data[i].children = this.transformItems(data[i].sim)
  94 + }else if (data[i].children && data[i].children.length > 0){
  95 + this.addChannel(data[i].children);
  96 + }
  97 + }
  98 + this.options = data
  99 + },
  100 + /**
  101 + * 添加通道
  102 + */
  103 + transformItems(sim) {
  104 + let originalArray = ['ADAS', 'DSM', '路况', '司机', '整车前', '中门', '倒车', '前门客流', '后面客流'];
  105 + return originalArray.map((name, index) => ({
  106 + sim: `${sim}-${index + 1}`, // 创建唯一值,使用SIM号和索引
  107 + name: name
  108 + }));
  109 + }
  110 + },
  111 + //生命周期 - 创建完成(可以访问当前this实例)",
  112 + created() {
  113 + this.initTreeData();
  114 + },
  115 + //生命周期 - 挂载完成(可以访问DOM元素)",
  116 + mounted() {
  117 + },
  118 + beforeCreate() {
  119 + }, //生命周期 - 创建之前",
  120 + beforeMount() {
  121 + }, //生命周期 - 挂载之前",
  122 + beforeUpdate() {
  123 + }, //生命周期 - 更新之前",
  124 + updated() {
  125 + }, //生命周期 - 更新之后",
  126 + beforeDestroy() {
  127 + }, //生命周期 - 销毁之前",
  128 + destroyed() {
  129 + }, //生命周期 - 销毁完成",
  130 + activated() {
  131 + } //如果页面有keep-alive缓存功能,这个函数会触发",
  132 + };
  133 +</script>
  134 +<style scoped>
  135 +
  136 +</style>
... ...
web_src/src/components/JT1078Components/historical/HistoricalDataTree.vue 0 → 100644
  1 +<template>
  2 + <el-card class="box-card" style="width: 100%;height: 100%">
  3 + <el-tree v-if="historyData.length > 0" :data="historyData">
  4 + <span class="custom-tree-node" slot-scope="{ node , data }">
  5 + <span>
  6 + <el-button @click="clickButton(data)" style="margin-top: 30px;margin-left: -12px">{{ data.name }}</el-button>
  7 + </span>
  8 + </span>
  9 + </el-tree>
  10 + <el-empty v-else></el-empty>
  11 + </el-card>
  12 +</template>
  13 +<script>
  14 +export default {
  15 + name: 'historical-data',
  16 + props: {
  17 + historyData: {}
  18 + },
  19 + //计算属性 类似于data概念",
  20 + computed: {},
  21 + //监控data中的数据变化",
  22 + watch: {},
  23 + //方法集合",
  24 + methods: {
  25 + //点击事件
  26 + clickButton(data){
  27 + this.$emit('click', data);
  28 + }
  29 + },
  30 + //生命周期 - 创建完成(可以访问当前this实例)",
  31 + created() {
  32 + },
  33 + //生命周期 - 挂载完成(可以访问DOM元素)",
  34 + mounted() {
  35 + },
  36 + beforeCreate() {
  37 + }, //生命周期 - 创建之前",
  38 + beforeMount() {
  39 + }, //生命周期 - 挂载之前",
  40 + beforeUpdate() {
  41 + }, //生命周期 - 更新之前",
  42 + updated() {
  43 + }, //生命周期 - 更新之后",
  44 + beforeDestroy() {
  45 + }, //生命周期 - 销毁之前",
  46 + destroyed() {
  47 + }, //生命周期 - 销毁完成",
  48 + activated() {
  49 + } //如果页面有keep-alive缓存功能,这个函数会触发",
  50 +};
  51 +</script>
  52 +<style>
  53 +
  54 +
  55 +/* 菜单的样式 */
  56 +
  57 +.rMenu li {
  58 + width: 170px;
  59 + list-style: none outside none;
  60 + cursor: default;
  61 + color: #666;
  62 + margin-left: -20px;
  63 +}
  64 +
  65 +.rMenu li:hover {
  66 + color: #EEE;
  67 + background-color: #666;
  68 +}
  69 +.el-tree-node__content {
  70 + padding-bottom: 30px;
  71 + height: 20px;
  72 +}
  73 +
  74 +</style>
... ...
web_src/src/components/common/ h265web.vue deleted 100755 → 0
1   -<template>
2   - <div ref="container" @dblclick="fullscreenSwich" style="width:100%;height:100%;background-color: #000000;margin:0 auto;">
3   - <div class="buttons-box" id="buttonsBox">
4   - <div class="buttons-box-left">
5   - <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
6   - <i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause"></i>
7   - <i class="iconfont icon-stop jessibuca-btn" @click="destroy"></i>
8   - <i v-if="isNotMute" class="iconfont icon-audio-high jessibuca-btn" @click="mute()"></i>
9   - <i v-if="!isNotMute" class="iconfont icon-audio-mute jessibuca-btn" @click="cancelMute()"></i>
10   - </div>
11   - <div class="buttons-box-right">
12   - <span class="jessibuca-btn">{{ kBps }} kb/s</span>
13   - <!-- <i class="iconfont icon-file-record1 jessibuca-btn"></i>-->
14   - <!-- <i class="iconfont icon-xiangqing2 jessibuca-btn" ></i>-->
15   - <i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="jessibuca.screenshot('截图','png',0.5)"
16   - style="font-size: 1rem !important"></i>
17   - <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i>
18   - <i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich"></i>
19   - <i v-if="fullscreen" class="iconfont icon-weibiaoti11 jessibuca-btn" @click="fullscreenSwich"></i>
20   - </div>
21   - </div>
22   - </div>
23   -</template>
24   -
25   -<script>
26   -let jessibucaPlayer = {};
27   -export default {
28   - name: 'jessibuca',
29   - data() {
30   - return {
31   - playing: false,
32   - isNotMute: false,
33   - quieting: false,
34   - fullscreen: false,
35   - loaded: false, // mute
36   - speed: 0,
37   - performance: "", // 工作情况
38   - kBps: 0,
39   - btnDom: null,
40   - videoInfo: null,
41   - volume: 1,
42   - rotate: 0,
43   - vod: true, // 点播
44   - forceNoOffscreen: false,
45   - };
46   - },
47   - props: ['videoUrl', 'error', 'hasAudio', 'height'],
48   - mounted() {
49   - window.onerror = (msg) => {
50   - // console.error(msg)
51   - };
52   - console.log(this._uid)
53   - let paramUrl = decodeURIComponent(this.$route.params.url)
54   - this.$nextTick(() => {
55   - this.updatePlayerDomSize()
56   - window.onresize = () => {
57   - this.updatePlayerDomSize()
58   - }
59   - if (typeof (this.videoUrl) == "undefined") {
60   - this.videoUrl = paramUrl;
61   - }
62   - this.btnDom = document.getElementById("buttonsBox");
63   - console.log("初始化时的地址为: " + this.videoUrl)
64   - this.play(this.videoUrl)
65   - })
66   - },
67   - watch: {
68   - videoUrl(newData, oldData) {
69   - this.play(newData)
70   - },
71   - immediate: true
72   - },
73   - methods: {
74   - updatePlayerDomSize() {
75   - let dom = this.$refs.container;
76   - let width = dom.parentNode.clientWidth
77   - let height = (9 / 16) * width
78   -
79   - const clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight)
80   - if (height > clientHeight) {
81   - height = clientHeight
82   - width = (16 / 9) * height
83   - }
84   -
85   - dom.style.width = width + 'px';
86   - dom.style.height = height + "px";
87   - },
88   - create() {
89   - let options = {};
90   - console.log("hasAudio " + this.hasAudio)
91   -
92   - jessibucaPlayer[this._uid] = new window.Jessibuca(Object.assign(
93   - {
94   - container: this.$refs.container,
95   - videoBuffer: 0.2, // 最大缓冲时长,单位秒
96   - isResize: true,
97   - decoder: "static/js/jessibuca/decoder.js",
98   - useMSE: false,
99   - showBandwidth: false,
100   - isFlv: true,
101   - // text: "WVP-PRO",
102   - // background: "static/images/zlm-logo.png",
103   - loadingText: "加载中",
104   - hasAudio: typeof (this.hasAudio) == "undefined" ? true : this.hasAudio,
105   - debug: false,
106   - supportDblclickFullscreen: false, // 是否支持屏幕的双击事件,触发全屏,取消全屏事件。
107   - operateBtns: {
108   - fullscreen: false,
109   - screenshot: false,
110   - play: false,
111   - audio: false,
112   - recorder: false,
113   - },
114   - record: "record",
115   - vod: this.vod,
116   - forceNoOffscreen: this.forceNoOffscreen,
117   - isNotMute: this.isNotMute,
118   - },
119   - options
120   - ));
121   - let jessibuca = jessibucaPlayer[this._uid];
122   - let _this = this;
123   - jessibuca.on("load", function () {
124   - console.log("on load init");
125   - });
126   -
127   - jessibuca.on("log", function (msg) {
128   - console.log("on log", msg);
129   - });
130   - jessibuca.on("record", function (msg) {
131   - console.log("on record:", msg);
132   - });
133   - jessibuca.on("pause", function () {
134   - _this.playing = false;
135   - });
136   - jessibuca.on("play", function () {
137   - _this.playing = true;
138   - });
139   - jessibuca.on("fullscreen", function (msg) {
140   - console.log("on fullscreen", msg);
141   - _this.fullscreen = msg
142   - });
143   -
144   - jessibuca.on("mute", function (msg) {
145   - console.log("on mute", msg);
146   - _this.isNotMute = !msg;
147   - });
148   - jessibuca.on("audioInfo", function (msg) {
149   - // console.log("audioInfo", msg);
150   - });
151   -
152   - jessibuca.on("videoInfo", function (msg) {
153   - // this.videoInfo = msg;
154   - console.log("videoInfo", msg);
155   -
156   - });
157   -
158   - jessibuca.on("bps", function (bps) {
159   - // console.log('bps', bps);
160   -
161   - });
162   - let _ts = 0;
163   - jessibuca.on("timeUpdate", function (ts) {
164   - // console.log('timeUpdate,old,new,timestamp', _ts, ts, ts - _ts);
165   - _ts = ts;
166   - });
167   -
168   - jessibuca.on("videoInfo", function (info) {
169   - console.log("videoInfo", info);
170   - });
171   -
172   - jessibuca.on("error", function (error) {
173   - console.log("error", error);
174   - });
175   -
176   - jessibuca.on("timeout", function () {
177   - console.log("timeout");
178   - });
179   -
180   - jessibuca.on('start', function () {
181   - console.log('start');
182   - })
183   -
184   - jessibuca.on("performance", function (performance) {
185   - let show = "卡顿";
186   - if (performance === 2) {
187   - show = "非常流畅";
188   - } else if (performance === 1) {
189   - show = "流畅";
190   - }
191   - _this.performance = show;
192   - });
193   - jessibuca.on('buffer', function (buffer) {
194   - // console.log('buffer', buffer);
195   - })
196   -
197   - jessibuca.on('stats', function (stats) {
198   - // console.log('stats', stats);
199   - })
200   -
201   - jessibuca.on('kBps', function (kBps) {
202   - _this.kBps = Math.round(kBps);
203   - });
204   -
205   - // 显示时间戳 PTS
206   - jessibuca.on('videoFrame', function () {
207   -
208   - })
209   -
210   - //
211   - jessibuca.on('metadata', function () {
212   -
213   - });
214   - },
215   - playBtnClick: function (event) {
216   - this.play(this.videoUrl)
217   - },
218   - play: function (url) {
219   - console.log(url)
220   - if (jessibucaPlayer[this._uid]) {
221   - this.destroy();
222   - }
223   - this.create();
224   - jessibucaPlayer[this._uid].on("play", () => {
225   - this.playing = true;
226   - this.loaded = true;
227   - this.quieting = jessibuca.quieting;
228   - });
229   - if (jessibucaPlayer[this._uid].hasLoaded()) {
230   - jessibucaPlayer[this._uid].play(url);
231   - } else {
232   - jessibucaPlayer[this._uid].on("load", () => {
233   - console.log("load 播放")
234   - jessibucaPlayer[this._uid].play(url);
235   - });
236   - }
237   - },
238   - pause: function () {
239   - if (jessibucaPlayer[this._uid]) {
240   - jessibucaPlayer[this._uid].pause();
241   - }
242   - this.playing = false;
243   - this.err = "";
244   - this.performance = "";
245   - },
246   - mute: function () {
247   - if (jessibucaPlayer[this._uid]) {
248   - jessibucaPlayer[this._uid].mute();
249   - }
250   - },
251   - cancelMute: function () {
252   - if (jessibucaPlayer[this._uid]) {
253   - jessibucaPlayer[this._uid].cancelMute();
254   - }
255   - },
256   - destroy: function () {
257   - if (jessibucaPlayer[this._uid]) {
258   - jessibucaPlayer[this._uid].destroy();
259   - }
260   - if (document.getElementById("buttonsBox") == null) {
261   - this.$refs.container.appendChild(this.btnDom)
262   - }
263   - jessibucaPlayer[this._uid] = null;
264   - this.playing = false;
265   - this.err = "";
266   - this.performance = "";
267   -
268   - },
269   - eventcallbacK: function (type, message) {
270   - // console.log("player 事件回调")
271   - // console.log(type)
272   - // console.log(message)
273   - },
274   - fullscreenSwich: function () {
275   - let isFull = this.isFullscreen()
276   - jessibucaPlayer[this._uid].setFullscreen(!isFull)
277   - this.fullscreen = !isFull;
278   - },
279   - isFullscreen: function () {
280   - return document.fullscreenElement ||
281   - document.msFullscreenElement ||
282   - document.mozFullScreenElement ||
283   - document.webkitFullscreenElement || false;
284   - }
285   - },
286   - destroyed() {
287   - if (jessibucaPlayer[this._uid]) {
288   - jessibucaPlayer[this._uid].destroy();
289   - }
290   - this.playing = false;
291   - this.loaded = false;
292   - this.performance = "";
293   - },
294   -}
295   -</script>
296   -
297   -<style>
298   -.buttons-box {
299   - width: 100%;
300   - height: 28px;
301   - background-color: rgba(43, 51, 63, 0.7);
302   - position: absolute;
303   - display: -webkit-box;
304   - display: -ms-flexbox;
305   - display: flex;
306   - left: 0;
307   - bottom: 0;
308   - user-select: none;
309   - z-index: 10;
310   -}
311   -
312   -.jessibuca-btn {
313   - width: 20px;
314   - color: rgb(255, 255, 255);
315   - line-height: 27px;
316   - margin: 0px 10px;
317   - padding: 0px 2px;
318   - cursor: pointer;
319   - text-align: center;
320   - font-size: 0.8rem !important;
321   -}
322   -
323   -.buttons-box-right {
324   - position: absolute;
325   - right: 0;
326   -}
327   -</style>
web_src/src/layout/UiHeader.vue
... ... @@ -5,9 +5,11 @@
5 5 active-text-color="#1890ff" mode="horizontal">
6 6  
7 7 <el-menu-item index="/console">控制台</el-menu-item>
8   -
  8 +
9 9 <el-menu-item index="/deviceList1078">设备列表</el-menu-item>
10   -
  10 +
  11 + <el-menu-item index="/historicalRecord">历史记录</el-menu-item>
  12 +
11 13 <el-menu-item v-if="editUser" index="/userManager">用户管理</el-menu-item>
12 14  
13 15 <!-- <el-submenu index="/setting">-->
... ...
web_src/src/router/index.js
... ... @@ -26,6 +26,7 @@ import web from &#39;../components/setting/Web.vue&#39;
26 26  
27 27 import wasmPlayer from '../components/common/jessibuca.vue'
28 28 import rtcPlayer from '../components/dialog/rtcPlayer.vue'
  29 +import historicalRecord from "../components/HistoricalRecord.vue";
29 30  
30 31 const originalPush = VueRouter.prototype.push
31 32 VueRouter.prototype.push = function push(location) {
... ... @@ -61,6 +62,10 @@ export default new VueRouter({
61 62 component: deviceList1078,
62 63 },
63 64 {
  65 + path: '/historicalRecord',
  66 + component: historicalRecord,
  67 + },
  68 + {
64 69 path: '/minhang/deviceList',
65 70 name: 'minhang',
66 71 component: minhang,
... ...
web_src/utils/cache.js 0 → 100644
  1 +const sessionCache = {
  2 + set (key, value) {
  3 + if (!sessionStorage) {
  4 + return
  5 + }
  6 + if (key != null && value != null) {
  7 + sessionStorage.setItem(key, value)
  8 + }
  9 + },
  10 + get (key) {
  11 + if (!sessionStorage) {
  12 + return null
  13 + }
  14 + if (key == null) {
  15 + return null
  16 + }
  17 + return sessionStorage.getItem(key)
  18 + },
  19 + setJSON (key, jsonValue) {
  20 + if (jsonValue != null) {
  21 + this.set(key, JSON.stringify(jsonValue))
  22 + }
  23 + },
  24 + getJSON (key) {
  25 + const value = this.get(key)
  26 + if (value != null) {
  27 + return JSON.parse(value)
  28 + }
  29 + },
  30 + remove (key) {
  31 + sessionStorage.removeItem(key);
  32 + }
  33 +}
  34 +const localCache = {
  35 + set (key, value) {
  36 + if (!localStorage) {
  37 + return
  38 + }
  39 + if (key != null && value != null) {
  40 + localStorage.setItem(key, value)
  41 + }
  42 + },
  43 + get (key) {
  44 + if (!localStorage) {
  45 + return null
  46 + }
  47 + if (key == null) {
  48 + return null
  49 + }
  50 + return localStorage.getItem(key)
  51 + },
  52 + setJSON (key, jsonValue) {
  53 + if (jsonValue != null) {
  54 + this.set(key, JSON.stringify(jsonValue))
  55 + }
  56 + },
  57 + getJSON (key) {
  58 + const value = this.get(key)
  59 + if (value != null) {
  60 + return JSON.parse(value)
  61 + }
  62 + },
  63 + remove (key) {
  64 + localStorage.removeItem(key);
  65 + }
  66 +}
  67 +
  68 +export default {
  69 + /**
  70 + * 会话级缓存
  71 + */
  72 + session: sessionCache,
  73 + /**
  74 + * 本地缓存
  75 + */
  76 + local: localCache
  77 +}
... ...
web_src/utils/request.js 0 → 100644
  1 +import axios from 'axios'
  2 +import { Notification, MessageBox, Message, Loading } from 'element-ui'
  3 +import store from '@/store'
  4 +import { getToken } from '@/utils/auth'
  5 +import errorCode from '@/utils/errorCode'
  6 +import { tansParams, blobValidate } from "@/utils/bashap";
  7 +import cache from '@/utils/cache'
  8 +import { saveAs } from 'file-saver'
  9 +
  10 +let downloadLoadingInstance;
  11 +// 是否显示重新登录
  12 +export let isRelogin = { show: false };
  13 +
  14 +axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
  15 +// 创建axios实例
  16 +const service = axios.create({
  17 + // axios中请求配置有baseURL选项,表示请求URL公共部分
  18 + baseURL: process.env.VUE_APP_BASE_API,
  19 + // 超时
  20 + timeout: 10000
  21 +})
  22 +
  23 +// request拦截器
  24 +service.interceptors.request.use(config => {
  25 + // 是否需要设置 token
  26 + const isToken = (config.headers || {}).isToken === false
  27 + // 是否需要防止数据重复提交
  28 + const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
  29 + if (getToken() && !isToken) {
  30 + config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
  31 + }
  32 + // get请求映射params参数
  33 + if (config.method === 'get' && config.params) {
  34 + let url = config.url + '?' + tansParams(config.params);
  35 + url = url.slice(0, -1);
  36 + config.params = {};
  37 + config.url = url;
  38 + }
  39 + if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
  40 + const requestObj = {
  41 + url: config.url,
  42 + data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
  43 + time: new Date().getTime()
  44 + }
  45 + const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
  46 + const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
  47 + if (requestSize >= limitSize) {
  48 + console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制,无法进行防重复提交验证。')
  49 + return config;
  50 + }
  51 + const sessionObj = cache.session.getJSON('sessionObj')
  52 + if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
  53 + cache.session.setJSON('sessionObj', requestObj)
  54 + } else {
  55 + const s_url = sessionObj.url; // 请求地址
  56 + const s_data = sessionObj.data; // 请求数据
  57 + const s_time = sessionObj.time; // 请求时间
  58 + const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
  59 + if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
  60 + const message = '数据正在处理,请勿重复提交';
  61 + console.warn(`[${s_url}]: ` + message)
  62 + return Promise.reject(new Error(message))
  63 + } else {
  64 + cache.session.setJSON('sessionObj', requestObj)
  65 + }
  66 + }
  67 + }
  68 + return config
  69 +}, error => {
  70 + console.log(error)
  71 + Promise.reject(error)
  72 +})
  73 +
  74 +// 响应拦截器
  75 +service.interceptors.response.use(res => {
  76 + // 未设置状态码则默认成功状态
  77 + const code = res.data.code || 200;
  78 + // 获取错误信息
  79 + const msg = errorCode[code] || res.data.msg || errorCode['default']
  80 + // 二进制数据则直接返回
  81 + if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
  82 + return res.data
  83 + }
  84 + if (code === 401) {
  85 + if (!isRelogin.show) {
  86 + isRelogin.show = true;
  87 + MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
  88 + store.dispatch('LogOut').then(() => {
  89 + // location.href = '/index';
  90 + //单点开始
  91 + location.href = '/getInfo';
  92 + //单点结束
  93 + })
  94 + }).catch(() => {
  95 + isRelogin.show = false;
  96 + });
  97 + }
  98 + return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
  99 + } else if (code === 500) {
  100 + Message({ message: msg, type: 'error' })
  101 + return Promise.reject(new Error(msg))
  102 + } else if (code === 601) {
  103 + Message({ message: msg, type: 'warning' })
  104 + return Promise.reject('error')
  105 + } else if (code !== 200) {
  106 + Notification.error({ title: msg })
  107 + return Promise.reject('error')
  108 + } else {
  109 + return res.data
  110 + }
  111 + },
  112 + error => {
  113 + console.log('err' + error)
  114 + let { message } = error;
  115 + if (message == "Network Error") {
  116 + message = "后端接口连接异常";
  117 + } else if (message.includes("timeout")) {
  118 + message = "系统接口请求超时";
  119 + } else if (message.includes("Request failed with status code")) {
  120 + message = "系统接口" + message.substr(message.length - 3) + "异常";
  121 + }
  122 + Message({ message: message, type: 'error', duration: 5 * 1000 })
  123 + return Promise.reject(error)
  124 + }
  125 +)
  126 +
  127 +// 通用下载方法
  128 +export function download(url, params, filename, config) {
  129 + downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
  130 + return service.post(url, params, {
  131 + transformRequest: [(params) => { return tansParams(params) }],
  132 + headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  133 + responseType: 'blob',
  134 + ...config
  135 + }).then(async (data) => {
  136 + const isBlob = blobValidate(data);
  137 + if (isBlob) {
  138 + const blob = new Blob([data])
  139 + saveAs(blob, filename)
  140 + } else {
  141 + const resText = await data.text();
  142 + const rspObj = JSON.parse(resText);
  143 + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
  144 + Message.error(errMsg);
  145 + }
  146 + downloadLoadingInstance.close();
  147 + }).catch((r) => {
  148 + console.error(r)
  149 + Message.error('下载文件出现错误,请联系管理员!')
  150 + downloadLoadingInstance.close();
  151 + })
  152 +}
  153 +
  154 +export default service
... ...
web_src/utils/ruoyi.js 0 → 100644
  1 +
  2 +
  3 +/**
  4 + * 通用js方法封装处理
  5 + * Copyright (c) 2019 ruoyi
  6 + */
  7 +
  8 +// 日期格式化
  9 +export function parseTime(time, pattern) {
  10 + if (arguments.length === 0 || !time) {
  11 + return null
  12 + }
  13 + const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
  14 + let date
  15 + if (typeof time === 'object') {
  16 + date = time
  17 + } else {
  18 + if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
  19 + time = parseInt(time)
  20 + } else if (typeof time === 'string') {
  21 + time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
  22 + }
  23 + if ((typeof time === 'number') && (time.toString().length === 10)) {
  24 + time = time * 1000
  25 + }
  26 + date = new Date(time)
  27 + }
  28 + const formatObj = {
  29 + y: date.getFullYear(),
  30 + m: date.getMonth() + 1,
  31 + d: date.getDate(),
  32 + h: date.getHours(),
  33 + i: date.getMinutes(),
  34 + s: date.getSeconds(),
  35 + a: date.getDay()
  36 + }
  37 + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
  38 + let value = formatObj[key]
  39 + // Note: getDay() returns 0 on Sunday
  40 + if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
  41 + if (result.length > 0 && value < 10) {
  42 + value = '0' + value
  43 + }
  44 + return value || 0
  45 + })
  46 + return time_str
  47 +}
  48 +
  49 +// 表单重置
  50 +export function resetForm(refName) {
  51 + if (this.$refs[refName]) {
  52 + this.$refs[refName].resetFields();
  53 + }
  54 +}
  55 +
  56 +// 添加日期范围
  57 +export function addDateRange(params, dateRange, propName) {
  58 + let search = params;
  59 + search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
  60 + dateRange = Array.isArray(dateRange) ? dateRange : [];
  61 + if (typeof (propName) === 'undefined') {
  62 + search.params['beginTime'] = dateRange[0];
  63 + search.params['endTime'] = dateRange[1];
  64 + } else {
  65 + search.params['begin' + propName] = dateRange[0];
  66 + search.params['end' + propName] = dateRange[1];
  67 + }
  68 + return search;
  69 +}
  70 +
  71 +// 回显数据字典
  72 +export function selectDictLabel(datas, value) {
  73 + if (value === undefined) {
  74 + return "";
  75 + }
  76 + var actions = [];
  77 + Object.keys(datas).some((key) => {
  78 + if (datas[key].value == ('' + value)) {
  79 + actions.push(datas[key].label);
  80 + return true;
  81 + }
  82 + })
  83 + if (actions.length === 0) {
  84 + actions.push(value);
  85 + }
  86 + return actions.join('');
  87 +}
  88 +
  89 +// 回显数据字典(字符串、数组)
  90 +export function selectDictLabels(datas, value, separator) {
  91 + if (value === undefined || value.length ===0) {
  92 + return "";
  93 + }
  94 + if (Array.isArray(value)) {
  95 + value = value.join(",");
  96 + }
  97 + var actions = [];
  98 + var currentSeparator = undefined === separator ? "," : separator;
  99 + var temp = value.split(currentSeparator);
  100 + Object.keys(value.split(currentSeparator)).some((val) => {
  101 + var match = false;
  102 + Object.keys(datas).some((key) => {
  103 + if (datas[key].value == ('' + temp[val])) {
  104 + actions.push(datas[key].label + currentSeparator);
  105 + match = true;
  106 + }
  107 + })
  108 + if (!match) {
  109 + actions.push(temp[val] + currentSeparator);
  110 + }
  111 + })
  112 + return actions.join('').substring(0, actions.join('').length - 1);
  113 +}
  114 +
  115 +// 字符串格式化(%s )
  116 +export function sprintf(str) {
  117 + var args = arguments, flag = true, i = 1;
  118 + str = str.replace(/%s/g, function () {
  119 + var arg = args[i++];
  120 + if (typeof arg === 'undefined') {
  121 + flag = false;
  122 + return '';
  123 + }
  124 + return arg;
  125 + });
  126 + return flag ? str : '';
  127 +}
  128 +
  129 +// 转换字符串,undefined,null等转化为""
  130 +export function parseStrEmpty(str) {
  131 + if (!str || str == "undefined" || str == "null") {
  132 + return "";
  133 + }
  134 + return str;
  135 +}
  136 +
  137 +// 数据合并
  138 +export function mergeRecursive(source, target) {
  139 + for (var p in target) {
  140 + try {
  141 + if (target[p].constructor == Object) {
  142 + source[p] = mergeRecursive(source[p], target[p]);
  143 + } else {
  144 + source[p] = target[p];
  145 + }
  146 + } catch (e) {
  147 + source[p] = target[p];
  148 + }
  149 + }
  150 + return source;
  151 +};
  152 +
  153 +/**
  154 + * 构造树型结构数据
  155 + * @param {*} data 数据源
  156 + * @param {*} id id字段 默认 'id'
  157 + * @param {*} parentId 父节点字段 默认 'parentId'
  158 + * @param {*} children 孩子节点字段 默认 'children'
  159 + */
  160 +export function handleTree(data, id, parentId, children) {
  161 + let config = {
  162 + id: id || 'id',
  163 + parentId: parentId || 'parentId',
  164 + childrenList: children || 'children'
  165 + };
  166 +
  167 + var childrenListMap = {};
  168 + var nodeIds = {};
  169 + var tree = [];
  170 +
  171 + for (let d of data) {
  172 + let parentId = d[config.parentId];
  173 + if (childrenListMap[parentId] == null) {
  174 + childrenListMap[parentId] = [];
  175 + }
  176 + nodeIds[d[config.id]] = d;
  177 + childrenListMap[parentId].push(d);
  178 + }
  179 +
  180 + for (let d of data) {
  181 + let parentId = d[config.parentId];
  182 + if (nodeIds[parentId] == null) {
  183 + tree.push(d);
  184 + }
  185 + }
  186 +
  187 + for (let t of tree) {
  188 + adaptToChildrenList(t);
  189 + }
  190 +
  191 + function adaptToChildrenList(o) {
  192 + if (childrenListMap[o[config.id]] !== null) {
  193 + o[config.childrenList] = childrenListMap[o[config.id]];
  194 + }
  195 + if (o[config.childrenList]) {
  196 + for (let c of o[config.childrenList]) {
  197 + adaptToChildrenList(c);
  198 + }
  199 + }
  200 + }
  201 + return tree;
  202 +}
  203 +
  204 +/**
  205 +* 参数处理
  206 +* @param {*} params 参数
  207 +*/
  208 +export function tansParams(params) {
  209 + let result = ''
  210 + for (const propName of Object.keys(params)) {
  211 + const value = params[propName];
  212 + var part = encodeURIComponent(propName) + "=";
  213 + if (value !== null && value !== "" && typeof (value) !== "undefined") {
  214 + if (typeof value === 'object') {
  215 + for (const key of Object.keys(value)) {
  216 + if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
  217 + let params = propName + '[' + key + ']';
  218 + var subPart = encodeURIComponent(params) + "=";
  219 + result += subPart + encodeURIComponent(value[key]) + "&";
  220 + }
  221 + }
  222 + } else {
  223 + result += part + encodeURIComponent(value) + "&";
  224 + }
  225 + }
  226 + }
  227 + return result
  228 +}
  229 +
  230 +// 验证是否为blob格式
  231 +export function blobValidate(data) {
  232 + return data.type !== 'application/json'
  233 +}
... ...