You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1899 lines
54 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="tableContain">
<div class="headTitle">
<div class="xfMl">
<el-form :inline="true" :model="formIssue" class="demo-form-inline">
<el-form-item label="运维操作">
<el-select v-model="formIssue.operate" placeholder="请输入运维操作">
<el-option
v-for="item in operateOptions"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onIssue">下发命令</el-button>
</el-form-item>
</el-form>
</div>
<div class="zzMsg">
<p class="total">
<span
>已选中:<el-tag type="primary">{{
multipleSelection.length
}}</el-tag></span
>
<span
>运维:<el-tag type="primary">{{ ywNumber }}</el-tag></span
>
<span
>快心跳:<el-tag type="primary">{{ kxtNumber }}</el-tag></span
>
<span
>在线:<el-tag type="success">{{ onlineNum }}</el-tag></span
>
<span
>离线:<el-tag type="danger">{{ offlineNum }}</el-tag></span
>
<span
>未上传图片:<el-tag type="danger">{{ noPicNum }}</el-tag></span
>
<span
>磁盘异常数量:<el-tag type="danger">{{ freeNum }}</el-tag></span
>
<span
>装置总数:<el-tag type="info">{{ tableData.length }}</el-tag></span
>
</p>
<el-button type="primary" @click="handleExport">导出</el-button>
<el-tooltip class="item" effect="dark" content="扩展列" placement="top">
<el-button
class="drawBox"
size="small"
type="primary"
icon="el-icon-s-operation"
@click="drawer = true"
></el-button>
</el-tooltip>
</div>
</div>
<el-table
v-loading="tableLoaidng"
class="ywTableBox"
id="ywTable"
ref="ywMultipleTable"
:data="tableData"
border
stripe
:row-key="getRowKey"
style="width: 100%"
@selection-change="handleSelectionChange"
height="calc(100% - 40px)"
:default-sort="{ order: 'descending' }"
:row-class-name="tableRowSetting"
>
<el-table-column
type="selection"
:reserve-selection="true"
width="50"
fixed
>
</el-table-column>
<el-table-column type="index" width="50" label="序号" fixed>
</el-table-column>
<!-- <el-table-column prop="id" label="ID" width="60" sortable>
</el-table-column> -->
<el-table-column prop="oid" label="出厂ID" width="180" sortable fixed>
<template slot-scope="scope">
<span
class="redMlxf"
v-if="
scope.row.list &&
scope.row.list[0].estimatedPublishTime * 1000 - newupdatatime > 0
"
>
<b v-if="scope.row.list[0].cmdDesc == ''">{{
cmdCn[scope.row.list[0].cmdName]
}}</b
><b v-else>{{ scope.row.list[0].cmdDesc }}</b>
<b
v-if="
scope.row.list[0].estimatedPublishTime * 1000 - newupdatatime >
0
"
>
{{ remainingTime(scope.row.list[0]) }}
</b>
</span>
<span v-else>
{{
scope.row.raw_report.hasOwnProperty("oid")
? scope.row.raw_report.oid
: ""
}}
</span>
</template>
</el-table-column>
<el-table-column prop="cmdid" label="装置编号" width="150" sortable fixed>
</el-table-column>
<el-table-column label="状态" width="72" fixed>
<template slot-scope="scope">
<el-tag
type="success"
v-if="nowTime - scope.row.last_heartbeat_ts <= 720"
>在线</el-tag
>
<el-tag type="danger" v-else>离线</el-tag>
</template>
</el-table-column>
<el-table-column
label="运维"
prop="in_maintain"
width="100"
sortable
fixed
>
<template slot="header" slot-scope="scope">
<p :class="ywNumber != 0 ? 'redClass' : 'noClass'">
{{ ywNumber }}<span> / {{ tableData.length }}</span>
</p>
<span @click.stop>
<el-checkbox
v-model="checkAllYW"
@change="handlecheckAllYW"
:class="
(ywNumber == tableData.length && tableData.length != 0) ||
ywNumber == 0
? ''
: 'is-indeterminate'
"
></el-checkbox>
运维
</span>
</template>
<template slot-scope="scope">
<el-checkbox
v-model="scope.row.in_maintain"
:true-label="'1'"
:false-label="'0'"
@change="(val) => UpdateMaintainMode(val, scope.row)"
></el-checkbox>
</template>
</el-table-column>
<el-table-column
label="快心跳"
prop="quick_hb"
width="108"
sortable
fixed
>
<template slot="header" slot-scope="scope">
<p :class="kxtNumber != 0 ? 'redClass' : 'noClass'">
{{ kxtNumber }}<span> / {{ tableData.length }}</span>
</p>
<span @click.stop>
<el-checkbox
v-model="checkAllKXT"
@change="handlecheckAllKXT"
:class="
(kxtNumber == tableData.length && tableData.length != 0) ||
kxtNumber == 0
? ''
: 'is-indeterminate'
"
></el-checkbox>
快心跳
</span>
</template>
<template slot-scope="scope">
<el-checkbox
v-model="scope.row.quick_hb"
:true-label="'1'"
:false-label="'0'"
@change="(val) => UpdateQuickHbMode(val, scope.row)"
></el-checkbox>
</template>
</el-table-column>
<el-table-column
prop="last_heartbeat"
label="最后心跳"
width="142"
sortable
class-name="hbClass"
>
<template slot-scope="scope">
<span @click="handleMsgClick(scope.row)">{{
scope.row.last_heartbeat
}}</span>
</template>
</el-table-column>
<el-table-column
label="传图"
prop="raw_report.pic"
width="80"
class-name="picBg"
sortable
>
<template slot-scope="scope">
{{ scope.row.raw_report.pic }}
</template>
</el-table-column>
<el-table-column
prop="protocol"
label="规约"
width="80"
v-if="gycheck"
sortable
key="gy"
>
<template slot-scope="scope">
{{ protocolMap[scope.row.protocol] }}
</template>
</el-table-column>
<el-table-column label="电池状态" width="118" key="dc" v-if="dccheck">
<template slot-scope="scope">
{{
scope.row.raw_report.hasOwnProperty("msgs")
? scope.row.raw_report.msgs.battery
: ""
}}
</template>
</el-table-column>
<el-table-column label="心跳信息" v-if="xtcheck" key="xt">
<el-table-column
label="次数"
min-width="68"
sortable
:sort-method="sortnumberOfHb"
>
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("numberOfHb")
? Number(scope.row.raw_report.msgs.numberOfHb)
: ""
}}
</template>
</el-table-column>
<el-table-column label="周期" min-width="48">
<template slot-scope="scope">
{{
scope.row.raw_report.hasOwnProperty("msgs")
? scope.row.raw_report.msgs.heartbeatDuration
: ""
}}
</template>
</el-table-column>
<el-table-column label="CMA消息" min-width="60">
<template slot-scope="scope">
{{
scope.row.raw_report.hasOwnProperty("msgs")
? scope.row.raw_report.msgs.recv
: ""
}}
</template>
</el-table-column>
</el-table-column>
<el-table-column label="拍照" v-if="pzcheck" key="pz">
<el-table-column label="计划/实际" min-width="60">
<template slot-scope="scope">
{{
scope.row.raw_report.hasOwnProperty("msgs")
? scope.row.raw_report.msgs.photoTimes
: ""
}}
</template>
</el-table-column>
<el-table-column
label="成功"
min-width="70"
sortable
:sort-method="sortSuccess"
>
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("success")
? Number(scope.row.raw_report.msgs.success)
: ""
}}
</template>
</el-table-column>
<el-table-column
label="失败"
min-width="70"
sortable
:sort-method="sortFailure"
>
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("failure")
? Number(scope.row.raw_report.msgs.failure)
: ""
}}
</template>
</el-table-column>
</el-table-column>
<el-table-column label="网络信号" v-if="wlcheck" key="wl">
<el-table-column label="卡1" min-width="60" prop="signature1">
<template slot-scope="scope">
<el-tooltip
class="item"
effect="dark"
:content="scope.row.raw_report.msgs.signature1"
placement="top"
>
<span>{{
scope.row.raw_report.msgs.hasOwnProperty("signature1")
? scope.row.raw_report.msgs.signature1.split("/")[0]
: ""
}}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column label="卡2" min-width="60" prop="signature2">
<template slot-scope="scope">
<el-tooltip
class="item"
effect="dark"
:content="scope.row.raw_report.msgs.signature2"
placement="top"
>
<span>{{
scope.row.raw_report.msgs.hasOwnProperty("signature2")
? scope.row.raw_report.msgs.signature2.split("/")[0]
: ""
}}</span>
</el-tooltip>
<!-- {{
scope.row.raw_report.msgs.hasOwnProperty("signature2")
? scope.row.raw_report.msgs.signature2.split("/")[0]
: ""
}} -->
</template>
</el-table-column>
<el-table-column
label="错误"
min-width="48"
prop="networkError"
sortable
:sort-method="sortNumbersErr"
>
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("networkError")
? Number(scope.row.raw_report.msgs.networkError)
: ""
}}
</template>
</el-table-column>
</el-table-column>
<el-table-column label="重启次数" v-if="cqcheck" key="cq">
<el-table-column
label="系统"
min-width="48"
prop="rebootTimes"
sortable
:sort-method="sortNumbers"
>
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("rebootTimes")
? Number(scope.row.raw_report.msgs.rebootTimes)
: ""
}}
</template>
</el-table-column>
<el-table-column
label="I1"
min-width="48"
prop="i1RebootTimes"
sortable
:sort-method="sortNumbers2"
>
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("i1RebootTimes")
? Number(scope.row.raw_report.msgs.i1RebootTimes)
: ""
}}
</template>
</el-table-column>
</el-table-column>
<el-table-column label="SIM卡" v-if="simcheck" min-width="160" key="sim">
<el-table-column label="卡1" width="158" prop="simcard1">
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("simcard1")
? scope.row.raw_report.msgs.simcard1
: ""
}}
</template>
</el-table-column>
<el-table-column label="卡2" width="158" prop="simcard2">
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("simcard2")
? scope.row.raw_report.msgs.simcard2
: ""
}}
</template>
</el-table-column>
</el-table-column>
<el-table-column
label="磁盘剩余空间"
v-if="freecheck"
min-width="100"
key="free"
sortable
:sort-method="sortfreeNumbers"
>
<template slot-scope="scope">
<span>{{
scope.row.raw_report.msgs.hasOwnProperty("freeROM")
? scope.row.raw_report.msgs.freeROM
: ""
}}</span>
</template>
</el-table-column>
<el-table-column label="CMA服务器" v-if="cmacheck" width="160" key="cma">
<template slot-scope="scope">
{{
scope.row.raw_report.hasOwnProperty("msgs")
? scope.row.raw_report.msgs.cma
: ""
}}
</template>
</el-table-column>
<el-table-column label="I1版本" v-if="i1check" min-width="160" key="I1">
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.i1Version
}}</span>
<span v-else>{{
scope.row.raw_report.msgs.hasOwnProperty("i1Version")
? scope.row.raw_report.msgs.i1Version
: ""
}}</span>
</template>
</el-table-column>
<el-table-column
label="运维版本"
v-if="ywbbcheck"
min-width="160"
key="ywbb"
>
<template slot-scope="scope">
<span v-if="scope.row.raw_report.hasOwnProperty('XyDev')">{{
scope.row.raw_report.maintainVersion
}}</span>
<span v-else>
{{
scope.row.raw_report.msgs.hasOwnProperty("maintainVersion")
? scope.row.raw_report.msgs.maintainVersion
: ""
}}</span
>
</template>
</el-table-column>
<el-table-column
label="Camera版本"
v-if="Cameracheck"
width="100"
key="Camera"
>
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("cameraService")
? scope.row.raw_report.msgs.cameraService
: ""
}}
</template>
</el-table-column>
<el-table-column label="AI版本" v-if="AIcheck" width="80" key="AI">
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("aiVersion")
? scope.row.raw_report.msgs.aiVersion
: ""
}}
</template>
</el-table-column>
<el-table-column
label="MCU版本"
v-if="MCUcheck"
min-width="180"
key="MCU"
>
<template slot-scope="scope">
{{
scope.row.raw_report.msgs.hasOwnProperty("mcu")
? scope.row.raw_report.msgs.mcu
: ""
}}
</template>
</el-table-column>
</el-table>
<el-drawer
class="drawerBox"
:visible.sync="drawer"
direction="rtl"
:with-header="false"
>
<div class="drawerSelect">
<h3>表格列配置</h3>
<div class="selectBox">
<el-checkbox v-model="gycheck" @change="saveLocalStorage"
>规约</el-checkbox
>
<el-checkbox v-model="dccheck" @change="saveLocalStorage"
>电池状态</el-checkbox
>
<el-checkbox v-model="xtcheck" @change="saveLocalStorage"
>心跳信息</el-checkbox
>
<!-- <el-checkbox v-model="xtcs" @change="saveLocalStorage"
>心跳次数</el-checkbox
>
<el-checkbox v-model="xtzq" @change="saveLocalStorage"
>心跳周期</el-checkbox
> -->
<el-checkbox v-model="pzcheck" @change="saveLocalStorage"
>拍照</el-checkbox
>
<el-checkbox v-model="wlcheck" @change="saveLocalStorage"
>网络信号</el-checkbox
>
<el-checkbox v-model="cqcheck" @change="saveLocalStorage"
>重启次数</el-checkbox
>
<el-checkbox v-model="simcheck" @change="saveLocalStorage"
>SIM卡</el-checkbox
>
<el-checkbox v-model="freecheck" @change="saveLocalStorage"
>磁盘剩余空间</el-checkbox
>
<el-checkbox v-model="cmacheck" @change="saveLocalStorage"
>CMA服务器</el-checkbox
>
<el-checkbox v-model="i1check" @change="saveLocalStorage"
>I1版本</el-checkbox
>
<el-checkbox v-model="ywbbcheck" @change="saveLocalStorage"
>运维版本</el-checkbox
>
<el-checkbox v-model="Cameracheck" @change="saveLocalStorage"
>Camera版本</el-checkbox
>
<el-checkbox v-model="AIcheck" @change="saveLocalStorage"
>AI版本</el-checkbox
>
<el-checkbox v-model="MCUcheck" @change="saveLocalStorage"
>MCU版本</el-checkbox
>
</div>
</div>
</el-drawer>
<!-- 设置ie服务器 -->
<el-dialog
title="设置ie服务器"
:visible.sync="ieVisible"
width="30%"
:close-on-click-modal="false"
>
<el-form :model="ieform" ref="ieRuleForm" :rules="ieRules">
<el-form-item label="CMA IP" prop="ip">
<el-input v-model="ieform.ip" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="CMA Port" prop="port">
<el-input v-model.number="ieform.port" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="ieVisible = false">取 消</el-button>
<el-button type="primary" @click="handleIeServe">确 定</el-button>
</div>
</el-dialog>
<!-- 设置运维服务器 -->
<el-dialog
title="设置运维服务器"
:visible.sync="operationVisible"
:close-on-click-modal="false"
width="30%"
>
<el-form
:model="operationform"
ref="operationRuleForm"
:rules="operationRules"
>
<el-form-item label="运维服务器IP" prop="ip">
<el-input v-model="operationform.ip" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="运维服务器Port" prop="port">
<el-input
v-model.number="operationform.port"
autocomplete="off"
></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="ieVisible = false">取 消</el-button>
<el-button type="primary" @click="handleOperationServe"
>确 定</el-button
>
</div>
</el-dialog>
<!-- 设置心跳周期 -->
<el-dialog
title="设置运维服务器"
:visible.sync="heartBeatVisible"
:close-on-click-modal="false"
width="30%"
>
<el-form
:model="heartBeatform"
ref="heartBeatRuleForm"
:rules="heartBeatRules"
>
<el-form-item label="心跳周期:(分钟)" prop="heart">
<el-input
v-model.number="heartBeatform.heart"
autocomplete="off"
></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="heartBeatVisible = false">取 消</el-button>
<el-button type="primary" @click="handleheartBeat">确 定</el-button>
</div>
</el-dialog>
<!-- 升级 -->
<el-dialog
class="upDialogBox"
title="请选择升级文件"
:visible.sync="upgradationVisible"
:close-on-click-modal="false"
width="30%"
>
<el-form
:model="upgradationform"
:rules="upgradationRules"
ref="upgradationRuleForm"
>
<el-form-item label="文件名称" prop="upVal">
<el-select
v-model="upgradationform.upVal"
placeholder="请选择升级文件"
@change="selectChanged"
>
<el-option
v-for="item in upOptions"
:key="item.id"
:label="item.fileName"
:value="item.path"
:title="item.title"
>
{{ item.fileName }}
<i class="title">{{ item.title }}</i
><i class="time">{{ item.createTime }}</i>
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="upgradationVisible = false">取 消</el-button>
<el-button type="primary" @click="handleupgradation">确 定</el-button>
</div>
</el-dialog>
<!-- 开启frpc服务器 -->
<el-dialog
title="设置frpc"
:visible.sync="frpcVisible"
:close-on-click-modal="false"
width="40%"
class="frpcDialogBox"
>
<el-button type="primary" @click="handleModelForm">模板一</el-button>
<el-form
:model="frpcform"
ref="frpcRuleForm"
:rules="frpcRules"
label-width="132px"
>
<el-form-item label="服务器IP" prop="server_addr">
<el-input
v-model="frpcform.server_addr"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="服务器端口:" prop="server_port">
<el-input
v-model.number="frpcform.server_port"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="FRPC类型">
<el-select v-model="frpcform.frpc_type" placeholder="请选择">
<el-option
v-for="item in frpc_typeOption"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="网络类型:">
<el-select v-model="frpcform.type" placeholder="请选择">
<el-option
v-for="item in typeOption"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="本地IP" prop="local_ip">
<el-input v-model="frpcform.local_ip" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="本地端口:" prop="local_port">
<el-input
v-model.number="frpcform.local_port"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="远程端口:" prop="remote_port">
<el-input
v-model.number="frpcform.remote_port"
autocomplete="off"
></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="frpcVisible = false">取 消</el-button>
<el-button type="primary" @click="handleFrpc">确 定</el-button>
</div>
</el-dialog>
<!-- 装置详细信息 -->
<rowMsgDialog ref="rowMsgDialogref"></rowMsgDialog>
</div>
</template>
<script>
import { getdoActionApi, getqueryUpgradesApi } from "@/utils/api/index";
import rowMsgDialog from "./rowMsgDialog.vue";
import htmlToExcel from "@/utils/htmlToExcel";
import { saveAs } from "file-saver";
import XLSX from "xlsx";
export default {
props: ["tableData", "onlineNum", "offlineNum", "noPicNum", "tableLoaidng"],
components: {
rowMsgDialog,
},
data() {
//判断ip
let validateIPAddress = (rule, value, callback) => {
let regexp =
/^((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}$/;
let valdata = value.split(",");
let isCorrect = true;
if (valdata.length) {
for (let i = 0; i < valdata.length; i++) {
if (regexp.test(valdata[i]) == false) {
isCorrect = false;
}
}
}
if (value == "") {
return callback(new Error("请输入iP地址"));
} else if (!isCorrect) {
callback(new Error("请输入正确对ip地址"));
} else {
callback();
}
};
return {
newupdatatime: null,
cmdCn: {
yw_cmd_android_reboot: "重启设备",
yw_cmd_mcu_reboot: "MCU单片机重启",
i1_cmd_set_i1_server_ip_port: "设置I1服务器",
i1_cmd_set_xy_yw_ip_port: "设置运维服务器",
i1_cmd_set_i1_heart_beat_time: "设置心跳周期",
yw_cmd_upload_i1_zip_log: "上传日志",
upgrade: "升级",
yw_cmd_start_frpc: "开启frpc",
yw_cmd_stop_frpc: "停止frpc",
i1_cmd_stop_aging_test: "停止老化测试",
},
taskdrawer: false,
drawer: false,
protocolMap: {
65280: "国网I1",
65296: "陕西",
65281: "安徽",
65282: "江苏",
65283: "湖南",
65284: "浙江",
65285: "河南全景",
65286: "河南郑州",
65290: "河南统一视频v2020",
},
multipleSelection: [],
checkAllYW: false,
checkAllKXT: false,
ywNumber: 0,
kxtNumber: 0,
freeNum: 0,
nowTime: new Date().getTime() / 1000,
gycheck: true,
dccheck: false,
xtcheck: false,
// xtcs: false,
// xtzq: false,
pzcheck: false,
wlcheck: false,
cqcheck: false,
simcheck: false,
cmacheck: true,
// bbcheck: true,
i1check: true,
ywbbcheck: true,
Cameracheck: false,
AIcheck: false,
MCUcheck: false,
freecheck: false,
//运维操作列表
operateOptions: [
{ id: 1, name: "重启设备" },
{ id: 2, name: "MCU单片机重启" },
{ id: 3, name: "设置I1服务器" },
// { id: 4, name: "设置运维服务器" },
{ id: 5, name: "设置心跳周期" },
{ id: 6, name: "上传日志" },
{ id: 7, name: "升级" },
{ id: 8, name: "开启frpc" },
{ id: 9, name: "停止frpc" },
{ id: 10, name: "停止老化测试" },
],
formIssue: {
operate: "",
}, //运维操作
idArray: [], //选中的数组 id
//设置ie服务器
ieVisible: false,
ieform: {
ip: "",
port: "",
},
ieRules: {
ip: [{ required: true, validator: validateIPAddress, trigger: "blur" }],
port: [
{
required: true,
type: "number",
message: "请输入端口号(必须为数字)",
trigger: "blur",
},
],
},
//设置运维服务器
operationVisible: false,
operationform: {
ip: "",
port: "",
},
operationRules: {
ip: [{ required: true, validator: validateIPAddress, trigger: "blur" }],
port: [
{
required: true,
type: "number",
message: "请输入端口号(必须为数字)",
trigger: "blur",
},
],
},
//设置心跳周期
heartBeatVisible: false,
heartBeatform: {
heart: "",
},
heartBeatRules: {
heart: [
{
required: true,
type: "number",
message: "请输入心跳周期(必须为数字)",
trigger: "blur",
},
],
},
//升级
upgradationVisible: false,
upgradationform: {
upVal: "",
},
selectUpObj: {},
upgradationRules: {
upVal: [
{ required: true, message: "请选择升级文件", trigger: "change" },
],
},
upOptions: [],
//设置frpc服务器
frpcVisible: false,
frpcform: {
// ip: "",
// port: "",
server_addr: "",
server_port: "",
frpc_type: "adb",
type: "tcp",
local_ip: "",
local_port: "",
remote_port: "",
},
frpc_typeOption: [
{
value: "ssh",
label: "SSH",
},
{
value: "adb",
label: "ADB",
},
],
typeOption: [
{
value: "tcp",
label: "TCP",
},
{
value: "udp",
label: "UDP",
},
],
frpcRules: {
server_addr: [
{ required: true, validator: validateIPAddress, trigger: "blur" },
],
server_port: [
{
required: true,
type: "number",
message: "请输入端口号(必须为数字)",
trigger: "blur",
},
],
local_ip: [
{ required: true, validator: validateIPAddress, trigger: "blur" },
],
local_port: [
{
required: true,
type: "number",
message: "请输入端口号(必须为数字)",
trigger: "blur",
},
],
remote_port: [
{
required: true,
type: "number",
message: "请输入端口号(必须为数字)",
trigger: "blur",
},
],
},
newupdatatime: null,
};
},
mounted() {
this.loadLocalStorage();
},
watch: {
tableData: {
handler(newVal) {
// 数据发生变化时的处理逻辑
console.log("数据已更新:", newVal);
this.getNumber();
this.startCountdown();
},
deep: true,
},
},
created() {},
methods: {
tableRowSetting({ row }) {
if (row.raw_report.msgs.hasOwnProperty("freeROM")) {
// console.log(row.raw_report.msgs.freeROM);
// console.log(parseInt(row.raw_report.msgs.freeROM));
if (parseInt(row.raw_report.msgs.freeROM) < 40) {
return "has-color";
}
}
// 根据if条件定义到该行
// if (row.rank === 1) {
// return "has-color";
// }
// return "";
},
sortNumbers(a, b) {
return (
Number(a.raw_report.msgs.rebootTimes) -
Number(b.raw_report.msgs.rebootTimes)
);
},
sortNumbers2(a, b) {
return (
Number(a.raw_report.msgs.i1RebootTimes) -
Number(b.raw_report.msgs.i1RebootTimes)
);
},
sortNumbersErr(a, b) {
return (
Number(a.raw_report.msgs.networkError) -
Number(b.raw_report.msgs.networkError)
);
},
sortSuccess(a, b) {
return (
Number(a.raw_report.msgs.success) - Number(b.raw_report.msgs.success)
);
},
sortFailure(a, b) {
return (
Number(a.raw_report.msgs.failure) - Number(b.raw_report.msgs.failure)
);
},
sortnumberOfHb(a, b) {
return (
Number(a.raw_report.msgs.numberOfHb) -
Number(b.raw_report.msgs.numberOfHb)
);
},
sortfreeNumbers(a, b) {
return (
parseInt(a.raw_report.msgs.freeROM) -
parseInt(b.raw_report.msgs.freeROM)
);
},
// sortSignature1(a, b) {
// return (
// Number(a.raw_report.msgs.signature1.split("/")[0]) -
// Number(b.raw_report.msgs.signature1.split("/")[0])
// );
// },
// sortSignature2(a, b) {
// return (
// Number(a.raw_report.msgs.signature2.split("/")[0]) -
// Number(b.raw_report.msgs.signature2.split("/")[0])
// );
// },
//获取运维勾选和快心跳勾选个数
getNumber() {
console.log(this.tableData);
this.ywNumber = this.tableData.filter(
(item) => item.in_maintain == 1
).length;
this.kxtNumber = this.tableData.filter(
(item) => item.quick_hb == 1
).length;
console.log("我这里是运维和快心跳的数据");
console.log(this.ywNumber, this.kxtNumber);
if (
this.ywNumber == this.tableData.length &&
this.tableData.length !== 0
) {
this.checkAllYW = true;
} else {
this.checkAllYW = false;
}
if (
this.kxtNumber == this.tableData.length &&
this.tableData.length !== 0
) {
this.checkAllKXT = true;
} else {
this.checkAllKXT = false;
}
this.freeNum =
this.$refs.ywMultipleTable.$el.getElementsByClassName(
"has-color"
).length;
},
//导出表格
handleExport() {
htmlToExcel.getExcel("#ywTable", "设备运维信息");
},
// 保存选中的数据id,row-key就是要指定一个key标识这一行的数据
getRowKey(row) {
return row.id;
},
handleSelectionChange(val) {
this.multipleSelection = val;
console.log(this.multipleSelection);
this.idArray = [];
for (let i = 0; i < this.multipleSelection.length; i++) {
this.idArray.push(this.multipleSelection[i].id);
}
this.idArray = [...new Set(this.idArray)];
console.log(this.idArray);
},
// 点击装置名称
handleMsgClick(val) {
console.log(val);
this.$refs.rowMsgDialogref.display(val);
},
handlecheckAllYW(val) {
console.log(val);
if (val) {
console.log("我全选了了运维了");
console.log(this.tableData);
this.termidsArray = [];
for (let i = 0; i < this.tableData.length; i++) {
this.termidsArray.push(this.tableData[i].id);
}
this.termidsArray = [...new Set(this.termidsArray)];
console.log(this.termidsArray);
getdoActionApi({
act: "mntn",
termIds: this.termidsArray.join("-"),
mntn: 1,
})
.then((res) => {
console.log(res);
this.$parent.onSubmit();
})
.catch((err) => {});
} else {
console.log("我取消了运维全选了");
console.log(this.tableData);
this.termidsArray = [];
for (let i = 0; i < this.tableData.length; i++) {
this.termidsArray.push(this.tableData[i].id);
}
this.termidsArray = [...new Set(this.termidsArray)];
console.log(this.termidsArray);
getdoActionApi({
act: "mntn",
termIds: this.termidsArray.join("-"),
mntn: 0,
})
.then((res) => {
console.log(res);
this.$parent.onSubmit();
})
.catch((err) => {});
}
},
//运维
UpdateMaintainMode(val, row) {
console.log("运维");
console.log(val, row);
getdoActionApi({
act: "mntn",
termId: row.id,
mntn: val,
})
.then((res) => {
console.log(res);
})
.catch((err) => {});
},
//快心跳
handlecheckAllKXT(val) {
console.log(val);
if (val) {
console.log("我全选了快心跳了");
console.log(this.tableData);
this.termidsArray = [];
for (let i = 0; i < this.tableData.length; i++) {
this.termidsArray.push(this.tableData[i].id);
}
this.termidsArray = [...new Set(this.termidsArray)];
console.log(this.termidsArray);
getdoActionApi({
act: "quickhb",
termIds: this.termidsArray.join("-"),
quickhb: 1,
})
.then((res) => {
console.log(res);
this.$parent.onSubmit();
})
.catch((err) => {});
} else {
console.log("我取消了运维全选了");
console.log(this.tableData);
this.termidsArray = [];
for (let i = 0; i < this.tableData.length; i++) {
this.termidsArray.push(this.tableData[i].id);
}
this.termidsArray = [...new Set(this.termidsArray)];
console.log(this.termidsArray);
getdoActionApi({
act: "quickhb",
termIds: this.termidsArray.join("-"),
quickhb: 0,
})
.then((res) => {
console.log(res);
this.$parent.onSubmit();
})
.catch((err) => {});
}
},
//快心跳
UpdateQuickHbMode(val, row) {
console.log("快心跳");
getdoActionApi({
act: "quickhb",
termId: row.id,
quickhb: val,
})
.then((res) => {
console.log(res);
})
.catch((err) => {});
},
//下发命令
onIssue() {
console.log(this.formIssue.operate);
console.log(this.multipleSelection);
if (this.formIssue.operate == "") {
this.$message({
duration: 1500,
showClose: true,
message: "请选择运维操作",
type: "warning",
});
return;
}
if (this.multipleSelection.length == 0) {
this.$message({
duration: 1500,
showClose: true,
message: "至少选中一个设备",
type: "warning",
});
return;
}
this.$parent.fetchData();
switch (this.formIssue.operate) {
case 1:
console.log("重启");
var params = {
act: "reset",
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
return;
case 2:
console.log("重启MCU");
var params = {
act: "reset-mcu",
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
return;
case 3:
console.log("设置I1服务器");
this.ieVisible = true;
return;
case 4:
console.log("设置运维服务器");
this.operationVisible = true;
return;
case 5:
console.log("设置心跳周期");
this.heartBeatVisible = true;
return;
case 6:
console.log("上传日志");
var params = {
act: "upload-logs",
url: "http://180.166.218.222:40101/upload/",
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
return;
case 7:
console.log("升级");
this.upgradationVisible = true;
this.getUpgradeList();
return;
case 8:
console.log("开启frpc");
this.frpcVisible = true;
return;
case 9:
console.log("停止frpc");
var params = {
act: "stop-frpc",
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
return;
case 10:
console.log("停止老化测试");
var params = {
act: "stop-aging-test",
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
return;
}
},
//执行操作
changeIssue(params) {
getdoActionApi(params)
.then((res) => {
console.log(res);
this.$refs.ywMultipleTable.clearSelection();
this.idArray = [];
console.log(this.multipleSelection);
})
.catch((err) => {});
},
//点击ie服务器确定
handleIeServe() {
console.log(this.$refs.ieRuleForm);
this.$refs.ieRuleForm.validate((valid) => {
if (valid) {
var params = {
act: "set-cma",
ip: this.ieform.ip,
port: this.ieform.port,
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
this.ieVisible = false;
}
});
},
//点击运维服务器确定
handleOperationServe() {
console.log(this.$refs.operationRuleForm);
this.$refs.operationRuleForm.validate((valid) => {
if (valid) {
var params = {
act: "set-mntn",
ip: this.operationform.ip,
port: this.operationform.port,
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
this.operationVisible = false;
}
});
},
//点击运维服务器确定
handleheartBeat() {
console.log(this.$refs.heartBeatRuleForm);
this.$refs.heartBeatRuleForm.validate((valid) => {
if (valid) {
var params = {
act: "set-hb",
hb: this.heartBeatform.heart,
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
this.heartBeatVisible = false;
}
});
},
//获取升级apkList
getUpgradeList() {
getqueryUpgradesApi()
.then((res) => {
console.log(res);
this.upOptions = res.data;
})
.catch((err) => {});
},
selectChanged(val) {
console.log(val);
// 找到选中项的整个object对象
this.selectUpObj = this.upOptions.find((item) => {
return item["path"] === val;
});
console.log(this.selectUpObj);
},
//升级确定阿
handleupgradation() {
this.$refs.upgradationRuleForm.validate((valid) => {
if (valid) {
var params = {
act: "upgrade",
url: this.upgradationform.upVal,
md5: this.selectUpObj.md5,
fn: this.selectUpObj.fileName,
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
this.upgradationVisible = false;
}
});
},
//点击模板
handleModelForm() {
this.frpcform = {
// ip: "",
// port: "",
server_addr: "180.166.218.222",
server_port: 40204,
frpc_type: "adb",
type: "tcp",
local_ip: "127.0.0.1",
local_port: 5555,
remote_port: 40205,
};
},
//开启frpc
handleFrpc() {
console.log(this.$refs.frpcRuleForm);
this.$refs.frpcRuleForm.validate((valid) => {
if (valid) {
var params = {
act: "start-frpc",
server_addr: this.frpcform.server_addr,
server_port: this.frpcform.server_port,
local_ip: this.frpcform.local_ip,
local_port: this.frpcform.local_port,
remote_port: this.frpcform.remote_port,
frpc_type: this.frpcform.frpc_type,
type: this.frpcform.type,
termIds: this.idArray.join("-"),
};
this.changeIssue(params);
this.frpcVisible = false;
}
});
},
saveLocalStorage() {
localStorage.setItem("gycheck", this.gycheck);
localStorage.setItem("dccheck", this.dccheck);
localStorage.setItem("xtcheck", this.xtcheck);
// localStorage.setItem("xtcs", this.xtcs);
// localStorage.setItem("xtzq", this.xtzq);
localStorage.setItem("pzcheck", this.pzcheck);
localStorage.setItem("wlcheck", this.wlcheck);
localStorage.setItem("cqcheck", this.cqcheck);
localStorage.setItem("cmacheck", this.cmacheck);
localStorage.setItem("simcheck", this.simcheck);
localStorage.setItem("i1check", this.i1check);
localStorage.setItem("ywbbcheck", this.ywbbcheck);
localStorage.setItem("Cameracheck", this.Cameracheck);
localStorage.setItem("AIcheck", this.AIcheck);
localStorage.setItem("MCUcheck", this.MCUcheck);
localStorage.setItem("freecheck", this.freecheck);
this.adjustTableHeight();
},
loadLocalStorage() {
this.checkAllKXT = localStorage.getItem("checkAllKXT", this.checkAllKXT)
? JSON.parse(localStorage.getItem("checkAllKXT"))
: false;
this.checkAllYW = localStorage.getItem("checkAllYW", this.checkAllYW)
? JSON.parse(localStorage.getItem("checkAllYW"))
: false;
this.gycheck = localStorage.getItem("gycheck")
? JSON.parse(localStorage.getItem("gycheck"))
: true;
this.dccheck = localStorage.getItem("dccheck")
? JSON.parse(localStorage.getItem("dccheck"))
: false;
this.xtcheck = localStorage.getItem("xtcheck")
? JSON.parse(localStorage.getItem("xtcheck"))
: false;
// this.xtcs = localStorage.getItem("xtcs")
// ? JSON.parse(localStorage.getItem("xtcs"))
// : false;
// this.xtzq = localStorage.getItem("xtzq")
// ? JSON.parse(localStorage.getItem("xtzq"))
// : false;
this.pzcheck = localStorage.getItem("pzcheck")
? JSON.parse(localStorage.getItem("pzcheck"))
: false;
this.wlcheck = localStorage.getItem("wlcheck")
? JSON.parse(localStorage.getItem("wlcheck"))
: false;
this.cqcheck = localStorage.getItem("cqcheck")
? JSON.parse(localStorage.getItem("cqcheck"))
: false;
this.simcheck = localStorage.getItem("simcheck")
? JSON.parse(localStorage.getItem("simcheck"))
: false;
this.cmacheck = localStorage.getItem("cmacheck")
? JSON.parse(localStorage.getItem("cmacheck"))
: true;
this.i1check = localStorage.getItem("i1check")
? JSON.parse(localStorage.getItem("i1check"))
: true;
this.ywbbcheck = localStorage.getItem("ywbbcheck")
? JSON.parse(localStorage.getItem("ywbbcheck"))
: true;
this.Cameracheck = localStorage.getItem("Cameracheck")
? JSON.parse(localStorage.getItem("Cameracheck"))
: false;
this.AIcheck = localStorage.getItem("AIcheck")
? JSON.parse(localStorage.getItem("AIcheck"))
: false;
this.MCUcheck = localStorage.getItem("MCUcheck")
? JSON.parse(localStorage.getItem("MCUcheck"))
: false;
this.freecheck = localStorage.getItem("freecheck")
? JSON.parse(localStorage.getItem("freecheck"))
: false;
console.log(
"规约:" + this.gycheck,
"电池:" + this.dccheck,
"心跳:" + this.xtcheck,
"拍照:" + this.pzcheck,
"网络信号:" + this.wlcheck,
"重启次数:" + this.cqcheck,
"sim卡" + this.simcheck,
"cma服务器" + this.cmacheck,
"版本:" + this.bbcheck
);
},
adjustTableHeight() {
// 通过调用 window.resize 事件重新触发表格布局和渲染
const resizeEvent = new Event("resize");
window.dispatchEvent(resizeEvent);
// 或者使用 Vue 的 nextTick 方法来确保 DOM 更新完成后再执行调整操作
this.$nextTick(() => {
this.$refs.ywMultipleTable.doLayout(); // 调用 el-table 的 doLayout 方法重新布局
});
},
startCountdown() {
this.newupdatatime = new Date().getTime(); // 更新当前时间
// 清空之前可能存在的定时器
if (this.intervalId) {
clearInterval(this.intervalId);
}
// 开始倒计时每秒执行一次remainingTime方法
this.intervalId = setInterval(() => {
this.newupdatatime = new Date().getTime(); // 更新当前时间
this.tableData.forEach((item) => {
//console.log(item);
if (item.list) {
this.remainingTime(item.list[0]);
}
// let params = item.list[0];
// this.remainingTime(params); // 重新计算每个项目的剩余时间
});
}, 1000); // 每秒执行一次
},
remainingTime(item) {
if (!this.newupdatatime) {
// 更新时间尚未设置,返回默认的倒计时时间或者不执行任何操作
return "计算中...";
}
const estimatedPublishTime = item.estimatedPublishTime * 1000;
const difference = estimatedPublishTime - this.newupdatatime;
const minutes = Math.floor(difference / 60000);
const seconds = Math.floor((difference % 60000) / 1000);
if (minutes == 0 && seconds == 0) {
this.$parent.fetchData();
return `命令已下发`;
} else {
if (minutes < 10 && seconds < 10) {
return ` 0${minutes} : 0${seconds} `;
} else if (minutes < 10) {
return ` 0${minutes} : ${seconds} `;
} else {
return ` ${minutes} : ${seconds} `;
}
}
},
},
};
</script>
<style lang="less">
.tableContain {
width: 100%;
height: 100%;
.headTitle {
display: flex;
align-items: center;
margin-bottom: 8px;
.xfMl {
.el-form-item--small.el-form-item {
margin-bottom: 0px;
}
}
.zzMsg {
display: flex;
margin-left: auto;
margin-right: 48px;
.total {
margin-left: 8px;
//width: 100%;
height: 32px;
line-height: 32px;
font-size: 14px;
color: #333;
span {
margin-right: 12px;
}
.el-tag--info {
color: #333;
}
}
.drawBox {
//margin-left: auto;
}
}
}
.ywTableBox {
color: #333;
.el-table__cell {
text-align: center;
.cell {
padding: 0px;
}
}
.bbStyle {
text-align: left;
.cell {
display: flex;
p {
display: inline;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
b {
margin-left: 4px;
}
}
}
}
.hbClass {
.cell {
cursor: pointer;
&:hover {
color: #169e8c;
text-decoration: underline;
}
}
}
.has-color {
background: #f5dab1;
}
.has-color td.el-table__cell {
background: #f5dab1 !important;
}
.el-table--scrollable-y .el-table__body-wrapper {
height: calc(100% - 40px) !important;
}
.el-table__row .picBg {
background: #169e8c !important;
color: #fff;
}
th.el-table__cell {
background: #d3d3d3;
}
.noClass {
color: #333;
font-size: 12px;
line-height: 12px;
}
.redClass {
color: red;
font-weight: 700;
line-height: 12px;
span {
color: #333;
}
}
thead.is-group th.el-table__cell {
background: #d3d3d3;
}
tr {
background: #fff;
}
.el-table--striped
.el-table__body
tr.el-table__row--striped
td.el-table__cell {
background: #e9e9e8;
}
.el-table__body tr:hover > td.el-table__cell {
background: #e9e9e9;
}
thead {
color: #333;
}
.el-table--scrollable-y .el-table__body-wrapper {
height: 100% !important;
}
}
.el-table--small .el-table__cell {
padding: 4px 0px;
}
.el-table .caret-wrapper {
height: 24px;
width: 10px;
margin-left: 4px;
}
.el-table .sort-caret.ascending {
border-bottom-color: #666;
top: 0px;
left: 0px;
}
.el-table .ascending .sort-caret.ascending {
border-bottom-color: #169e8c;
}
.el-table .sort-caret.descending {
border-top-color: #666;
bottom: 2px;
left: 0px;
}
.el-table .descending .sort-caret.descending {
border-top-color: #169e8c;
}
//半选
.is-indeterminate .el-checkbox__input .el-checkbox__inner {
background-color: #169e8c;
border-color: #169e8c;
}
.is-indeterminate .el-checkbox__input .el-checkbox__inner:before {
content: "";
position: absolute;
display: block;
background-color: #fff;
height: 2px;
transform: scale(0.5);
left: 0;
right: 0;
top: 5px;
}
.drawerBox {
.el-drawer {
width: 240px !important;
.el-drawer__body {
padding: 16px;
color: #333;
.drawerSelect {
h3 {
font-size: 14px;
color: #333;
//font-weight: normal;
margin-bottom: 12px;
}
.selectBox {
display: flex;
flex-direction: column;
height: 32px;
line-height: 32px;
}
}
}
}
}
.upDialogBox {
.el-dialog {
.el-select {
width: 100%;
}
}
}
.frpcDialogBox {
.el-dialog__body {
.el-button--small {
padding: 5px 15px;
}
.el-form {
margin-top: 12px;
}
}
.el-select {
width: 100%;
}
}
.taskMask {
position: fixed;
bottom: 50%;
right: 0px;
z-index: 2;
.el-button {
border-radius: 50%;
padding: 10px;
}
}
.taskDrawDialog {
.commandList {
width: 100%;
height: calc(100% - 32px);
//background: #fcc;
overflow: auto;
p {
background: #fdf6ec;
margin-bottom: 8px;
line-height: 24px;
color: #333;
font-size: 14px;
padding: 6px;
cursor: pointer;
display: flex;
align-items: center;
&:hover {
background: #faecd8;
}
.indexClass {
padding: 4px;
font-size: 14px;
color: #000;
background: #d3d3d3;
min-width: 18px;
text-align: center;
margin-right: 8px;
}
.normalClass {
background: #d3d3d3;
}
.cancelClass {
background: #fde2e2;
}
.comMsg {
display: flex;
flex-wrap: wrap;
b {
font-weight: normal;
margin-right: 12px;
}
}
}
}
}
.redMlxf {
color: #f00;
b {
font-size: 12px;
font-weight: normal;
}
}
}
.contenBoxMsg {
p {
color: #333;
line-height: 24px;
font-size: 14px;
}
}
.el-select-dropdown__item {
i {
margin-left: 8px;
font-size: 12px;
font-style: normal;
}
}
</style>