874 lines
26 KiB
Vue
874 lines
26 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="app-container">
|
|||
|
|
<el-row :gutter="10" class="mb12">
|
|||
|
|
<el-col :span="1.5">
|
|||
|
|
<el-button
|
|||
|
|
type="primary"
|
|||
|
|
plain
|
|||
|
|
icon="el-icon-plus"
|
|||
|
|
size="mini"
|
|||
|
|
@click="handleAdd"
|
|||
|
|
>新增</el-button>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="1.5">
|
|||
|
|
<el-button
|
|||
|
|
type="success"
|
|||
|
|
plain
|
|||
|
|
icon="el-icon-edit"
|
|||
|
|
size="mini"
|
|||
|
|
:disabled="single"
|
|||
|
|
@click="handleUpdate"
|
|||
|
|
>修改</el-button>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="1.5">
|
|||
|
|
<el-button
|
|||
|
|
type="danger"
|
|||
|
|
plain
|
|||
|
|
icon="el-icon-delete"
|
|||
|
|
size="mini"
|
|||
|
|
:disabled="multiple"
|
|||
|
|
@click="handleDelete"
|
|||
|
|
>删除</el-button>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="1.5">
|
|||
|
|
<el-button
|
|||
|
|
type="warning"
|
|||
|
|
plain
|
|||
|
|
icon="el-icon-download"
|
|||
|
|
size="mini"
|
|||
|
|
@click="handleExport"
|
|||
|
|
>导出</el-button>
|
|||
|
|
</el-col>
|
|||
|
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|||
|
|
</el-row>
|
|||
|
|
|
|||
|
|
<el-row :gutter="10" class="mb12">
|
|||
|
|
<el-col :span="24">
|
|||
|
|
<el-card class="box-card">
|
|||
|
|
<div slot="header" class="clearfix">
|
|||
|
|
<span>终端统计</span>
|
|||
|
|
</div>
|
|||
|
|
<el-row :gutter="20">
|
|||
|
|
<el-col :span="8">
|
|||
|
|
<el-statistic title="终端总数" :value="statistics.total || 0" />
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="8">
|
|||
|
|
<el-statistic title="在线终端" :value="statistics.onlineCount || 0">
|
|||
|
|
<template slot="suffix">
|
|||
|
|
<el-tag size="mini" type="success">在线</el-tag>
|
|||
|
|
</template>
|
|||
|
|
</el-statistic>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="8">
|
|||
|
|
<el-statistic title="离线终端" :value="statistics.offlineCount || 0">
|
|||
|
|
<template slot="suffix">
|
|||
|
|
<el-tag size="mini" type="danger">离线</el-tag>
|
|||
|
|
</template>
|
|||
|
|
</el-statistic>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
</el-card>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
|
|||
|
|
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px" class="search-form">
|
|||
|
|
<el-form-item label="手机号" prop="phoneNumber">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.phoneNumber"
|
|||
|
|
placeholder="请输入手机号"
|
|||
|
|
clearable
|
|||
|
|
size="small"
|
|||
|
|
style="width: 140px"
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="IMEI号" prop="imei">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.imei"
|
|||
|
|
placeholder="请输入IMEI号"
|
|||
|
|
clearable
|
|||
|
|
size="small"
|
|||
|
|
style="width: 140px"
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="车牌号" prop="plateNumber">
|
|||
|
|
<el-input
|
|||
|
|
v-model="queryParams.plateNumber"
|
|||
|
|
placeholder="请输入车牌号"
|
|||
|
|
clearable
|
|||
|
|
size="small"
|
|||
|
|
style="width: 140px"
|
|||
|
|
@keyup.enter.native="handleQuery"
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="省份" prop="provinceId">
|
|||
|
|
<el-select
|
|||
|
|
v-model="queryParams.provinceId"
|
|||
|
|
placeholder="请选择省份"
|
|||
|
|
clearable
|
|||
|
|
size="small"
|
|||
|
|
@change="handleQueryProvinceChange"
|
|||
|
|
style="width: 120px"
|
|||
|
|
>
|
|||
|
|
<el-option
|
|||
|
|
v-for="item in provinceOptions"
|
|||
|
|
:key="item.areaCode"
|
|||
|
|
:label="item.name"
|
|||
|
|
:value="item.areaCode"
|
|||
|
|
/>
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="城市" prop="cityId">
|
|||
|
|
<el-select
|
|||
|
|
v-model="queryParams.cityId"
|
|||
|
|
placeholder="请选择城市"
|
|||
|
|
clearable
|
|||
|
|
size="small"
|
|||
|
|
:disabled="!queryParams.provinceId"
|
|||
|
|
style="width: 120px"
|
|||
|
|
>
|
|||
|
|
<el-option
|
|||
|
|
v-for="item in queryCityOptions"
|
|||
|
|
:key="item.areaCode"
|
|||
|
|
:label="item.name"
|
|||
|
|
:value="item.areaCode"
|
|||
|
|
/>
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="在线状态" prop="onlineStatus">
|
|||
|
|
<el-select v-model="queryParams.onlineStatus" placeholder="在线状态" clearable size="small" style="width: 100px">
|
|||
|
|
<el-option label="在线" :value="1" />
|
|||
|
|
<el-option label="离线" :value="0" />
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item>
|
|||
|
|
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|||
|
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-form>
|
|||
|
|
|
|||
|
|
<el-table v-loading="loading" :data="terminalList" @selection-change="handleSelectionChange">
|
|||
|
|
<el-table-column type="selection" width="55" align="center" />
|
|||
|
|
<el-table-column label="终端ID" align="center" prop="terminalId" width="80" />
|
|||
|
|
<el-table-column label="手机号" align="center" prop="phoneNumber" width="120" />
|
|||
|
|
<el-table-column label="IMEI号" align="center" prop="imei" width="150" />
|
|||
|
|
<el-table-column label="省份" align="center" prop="provinceName" width="100" />
|
|||
|
|
<el-table-column label="城市" align="center" prop="cityName" width="100" />
|
|||
|
|
<el-table-column label="终端型号" align="center" prop="terminalModel" />
|
|||
|
|
<el-table-column label="车牌号" align="center" prop="plateNumber" width="120">
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<span>{{ scope.row.plateNumber }}</span>
|
|||
|
|
<el-tag v-if="scope.row.plateColor === 1" size="mini" type="primary">蓝</el-tag>
|
|||
|
|
<el-tag v-else-if="scope.row.plateColor === 2" size="mini" type="warning">黄</el-tag>
|
|||
|
|
<el-tag v-else-if="scope.row.plateColor === 3" size="mini" type="info">黑</el-tag>
|
|||
|
|
<el-tag v-else-if="scope.row.plateColor === 4" size="mini">白</el-tag>
|
|||
|
|
<el-tag v-else-if="scope.row.plateColor === 9" size="mini" type="success">新能源</el-tag>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column label="在线状态" align="center" prop="onlineStatus" width="80">
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<el-tag v-if="scope.row.onlineStatus === 1" type="success">在线</el-tag>
|
|||
|
|
<el-tag v-else type="danger">离线</el-tag>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column label="最后心跳" align="center" prop="lastHeartbeatTime" width="150">
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<span>{{ parseTime(scope.row.lastHeartbeatTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column label="客户端IP" align="center" prop="clientIp" width="120" />
|
|||
|
|
<el-table-column label="注册时间" align="center" prop="registerTime" width="150">
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<span>{{ parseTime(scope.row.registerTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<el-button
|
|||
|
|
size="mini"
|
|||
|
|
type="text"
|
|||
|
|
icon="el-icon-edit"
|
|||
|
|
@click="handleUpdate(scope.row)"
|
|||
|
|
>修改</el-button>
|
|||
|
|
<el-button
|
|||
|
|
size="mini"
|
|||
|
|
type="text"
|
|||
|
|
icon="el-icon-delete"
|
|||
|
|
@click="handleDelete(scope.row)"
|
|||
|
|
>删除</el-button>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
</el-table>
|
|||
|
|
|
|||
|
|
<pagination
|
|||
|
|
v-show="total>0"
|
|||
|
|
:total="total"
|
|||
|
|
:page.sync="queryParams.pageNum"
|
|||
|
|
:limit.sync="queryParams.pageSize"
|
|||
|
|
@pagination="getList"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<!-- 添加或修改终端设备对话框 -->
|
|||
|
|
<el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
|
|||
|
|
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
|||
|
|
<el-row>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="手机号" prop="phoneNumber">
|
|||
|
|
<el-input v-model="form.phoneNumber" placeholder="请输入终端手机号" maxlength="20" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="IMEI号" prop="imei">
|
|||
|
|
<el-input v-model="form.imei" placeholder="请输入设备IMEI号(15位)" maxlength="15" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
<el-row>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="省份" prop="provinceId">
|
|||
|
|
<el-select
|
|||
|
|
v-model="form.provinceId"
|
|||
|
|
placeholder="请选择省份"
|
|||
|
|
clearable
|
|||
|
|
@change="handleFormProvinceChange"
|
|||
|
|
style="width: 100%"
|
|||
|
|
>
|
|||
|
|
<el-option
|
|||
|
|
v-for="item in provinceOptions"
|
|||
|
|
:key="item.areaCode"
|
|||
|
|
:label="item.name"
|
|||
|
|
:value="item.areaCode"
|
|||
|
|
/>
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="城市" prop="cityId">
|
|||
|
|
<el-select
|
|||
|
|
v-model="form.cityId"
|
|||
|
|
placeholder="请选择城市"
|
|||
|
|
clearable
|
|||
|
|
:disabled="!form.provinceId"
|
|||
|
|
style="width: 100%"
|
|||
|
|
>
|
|||
|
|
<el-option
|
|||
|
|
v-for="item in formCityOptions"
|
|||
|
|
:key="item.areaCode"
|
|||
|
|
:label="item.name"
|
|||
|
|
:value="item.areaCode"
|
|||
|
|
/>
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
<el-row>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="制造商ID" prop="manufacturerId">
|
|||
|
|
<el-input v-model="form.manufacturerId" placeholder="请输入制造商ID" maxlength="20" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="终端型号" prop="terminalModel">
|
|||
|
|
<el-input v-model="form.terminalModel" placeholder="请输入终端型号" maxlength="30" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
<el-row>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="设备ID" prop="terminalDeviceId">
|
|||
|
|
<el-input v-model="form.terminalDeviceId" placeholder="请输入终端设备ID" maxlength="30" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="车牌颜色" prop="plateColor">
|
|||
|
|
<el-select v-model="form.plateColor" placeholder="请选择车牌颜色" style="width: 100%">
|
|||
|
|
<el-option label="其他" :value="0" />
|
|||
|
|
<el-option label="蓝色" :value="1" />
|
|||
|
|
<el-option label="黄色" :value="2" />
|
|||
|
|
<el-option label="黑色" :value="3" />
|
|||
|
|
<el-option label="白色" :value="4" />
|
|||
|
|
<el-option label="新能源" :value="9" />
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
<el-row>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="车牌号" prop="plateNumber">
|
|||
|
|
<el-input v-model="form.plateNumber" placeholder="请输入车牌号" maxlength="20" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="鉴权码" prop="authCode">
|
|||
|
|
<el-input v-model="form.authCode" placeholder="请输入鉴权码" maxlength="50" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
<el-row>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="在线状态" prop="onlineStatus">
|
|||
|
|
<el-radio-group v-model="form.onlineStatus">
|
|||
|
|
<el-radio :label="1">在线</el-radio>
|
|||
|
|
<el-radio :label="0">离线</el-radio>
|
|||
|
|
</el-radio-group>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="客户端IP" prop="clientIp">
|
|||
|
|
<el-input v-model="form.clientIp" placeholder="请输入客户端IP地址" maxlength="50" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
<el-row>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="注册时间" prop="registerTime">
|
|||
|
|
<el-date-picker
|
|||
|
|
v-model="form.registerTime"
|
|||
|
|
type="datetime"
|
|||
|
|
placeholder="选择注册时间"
|
|||
|
|
value-format="yyyy-MM-dd HH:mm:ss"
|
|||
|
|
style="width: 100%"
|
|||
|
|
>
|
|||
|
|
</el-date-picker>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
<el-col :span="12">
|
|||
|
|
<el-form-item label="最后鉴权时间" prop="lastAuthTime">
|
|||
|
|
<el-date-picker
|
|||
|
|
v-model="form.lastAuthTime"
|
|||
|
|
type="datetime"
|
|||
|
|
placeholder="选择最后鉴权时间"
|
|||
|
|
value-format="yyyy-MM-dd HH:mm:ss"
|
|||
|
|
style="width: 100%"
|
|||
|
|
>
|
|||
|
|
</el-date-picker>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-col>
|
|||
|
|
</el-row>
|
|||
|
|
</el-form>
|
|||
|
|
<div slot="footer" class="dialog-footer">
|
|||
|
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
|||
|
|
<el-button @click="cancel">取 消</el-button>
|
|||
|
|
</div>
|
|||
|
|
</el-dialog>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { listTerminal, getTerminal, delTerminal, addTerminal, updateTerminal, exportTerminal, getTerminalStatistics } from "@/api/base/terminal";
|
|||
|
|
import { listProvinces, listCities } from "@/api/base/area";
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
name: "Terminal",
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
// 遮罩层
|
|||
|
|
loading: true,
|
|||
|
|
// 选中数组
|
|||
|
|
ids: [],
|
|||
|
|
// 非单个禁用
|
|||
|
|
single: true,
|
|||
|
|
// 非多个禁用
|
|||
|
|
multiple: true,
|
|||
|
|
// 显示搜索条件
|
|||
|
|
showSearch: true,
|
|||
|
|
// 总条数
|
|||
|
|
total: 0,
|
|||
|
|
// 终端设备表格数据
|
|||
|
|
terminalList: [],
|
|||
|
|
// 弹出层标题
|
|||
|
|
title: "",
|
|||
|
|
// 是否显示弹出层
|
|||
|
|
open: false,
|
|||
|
|
// 查询参数
|
|||
|
|
queryParams: {
|
|||
|
|
pageNum: 1,
|
|||
|
|
pageSize: 10,
|
|||
|
|
phoneNumber: null,
|
|||
|
|
imei: null,
|
|||
|
|
provinceId: null,
|
|||
|
|
cityId: null,
|
|||
|
|
plateNumber: null,
|
|||
|
|
onlineStatus: null,
|
|||
|
|
},
|
|||
|
|
// 表单参数
|
|||
|
|
form: {
|
|||
|
|
terminalId: null,
|
|||
|
|
phoneNumber: null,
|
|||
|
|
imei: null,
|
|||
|
|
provinceId: null,
|
|||
|
|
cityId: null,
|
|||
|
|
manufacturerId: null,
|
|||
|
|
terminalModel: null,
|
|||
|
|
terminalDeviceId: null,
|
|||
|
|
plateColor: 0,
|
|||
|
|
plateNumber: null,
|
|||
|
|
authCode: null,
|
|||
|
|
registerTime: null,
|
|||
|
|
lastAuthTime: null,
|
|||
|
|
onlineStatus: 0,
|
|||
|
|
lastHeartbeatTime: null,
|
|||
|
|
clientIp: null
|
|||
|
|
},
|
|||
|
|
// 表单校验
|
|||
|
|
rules: {
|
|||
|
|
phoneNumber: [
|
|||
|
|
{ required: true, message: "手机号不能为空", trigger: "blur" },
|
|||
|
|
{ pattern: /^[0-9]{11,20}$/, message: "手机号格式不正确", trigger: "blur" }
|
|||
|
|
],
|
|||
|
|
imei: [
|
|||
|
|
{ pattern: /^[0-9]{15}$/, message: "IMEI号必须为15位数字", trigger: "blur" }
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
// 省份选项
|
|||
|
|
provinceOptions: [],
|
|||
|
|
// 查询表单城市选项
|
|||
|
|
queryCityOptions: [],
|
|||
|
|
// 编辑表单城市选项
|
|||
|
|
formCityOptions: [],
|
|||
|
|
// 统计信息
|
|||
|
|
statistics: {}
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
created() {
|
|||
|
|
this.getList();
|
|||
|
|
this.getStatistics();
|
|||
|
|
this.getProvinceList();
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
/** 查询终端设备列表 */
|
|||
|
|
getList() {
|
|||
|
|
this.loading = true;
|
|||
|
|
listTerminal(this.queryParams).then(response => {
|
|||
|
|
this.terminalList = response.rows || [];
|
|||
|
|
this.total = response.total || 0;
|
|||
|
|
this.loading = false;
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error("获取终端列表失败:", error);
|
|||
|
|
this.loading = false;
|
|||
|
|
this.terminalList = [];
|
|||
|
|
this.total = 0;
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 获取终端统计信息 */
|
|||
|
|
getStatistics() {
|
|||
|
|
getTerminalStatistics().then(response => {
|
|||
|
|
this.statistics = response.data || {};
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error("获取统计信息失败:", error);
|
|||
|
|
this.statistics = {};
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 查询省份列表 */
|
|||
|
|
getProvinceList() {
|
|||
|
|
listProvinces().then(response => {
|
|||
|
|
console.log("省份列表响应:", response);
|
|||
|
|
// 处理不同的响应结构
|
|||
|
|
let provinceData = [];
|
|||
|
|
if (response && response.data) {
|
|||
|
|
provinceData = Array.isArray(response.data) ? response.data : [];
|
|||
|
|
} else if (Array.isArray(response)) {
|
|||
|
|
provinceData = response;
|
|||
|
|
} else if (response && response.rows) {
|
|||
|
|
provinceData = response.rows;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.provinceOptions = provinceData.map(item => ({
|
|||
|
|
areaCode: item.areaCode || item.area_code || item.id,
|
|||
|
|
name: item.name || item.areaName || item.area_name
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
console.log("处理后的省份列表:", this.provinceOptions);
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error("获取省份列表失败:", error);
|
|||
|
|
this.provinceOptions = [];
|
|||
|
|
this.$modal.msgError("获取省份列表失败");
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 查询表单省份变化 */
|
|||
|
|
handleQueryProvinceChange(value) {
|
|||
|
|
console.log("查询表单选择的省份ID:", value);
|
|||
|
|
|
|||
|
|
// 清空城市选择
|
|||
|
|
this.queryParams.cityId = null;
|
|||
|
|
this.queryCityOptions = [];
|
|||
|
|
|
|||
|
|
if (value) {
|
|||
|
|
// 直接使用 value,不进行 Number 转换,保持原始类型
|
|||
|
|
listCities(value).then(response => {
|
|||
|
|
console.log("查询表单城市列表响应:", response);
|
|||
|
|
// 处理不同的响应结构
|
|||
|
|
let cityData = [];
|
|||
|
|
if (response && response.data) {
|
|||
|
|
cityData = Array.isArray(response.data) ? response.data : [];
|
|||
|
|
} else if (Array.isArray(response)) {
|
|||
|
|
cityData = response;
|
|||
|
|
} else if (response && response.rows) {
|
|||
|
|
cityData = response.rows;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.queryCityOptions = cityData.map(item => ({
|
|||
|
|
areaCode: item.areaCode || item.area_code || item.id,
|
|||
|
|
name: item.name || item.areaName || item.area_name
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
console.log("处理后的城市列表:", this.queryCityOptions);
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error("获取查询表单城市列表失败:", error);
|
|||
|
|
this.queryCityOptions = [];
|
|||
|
|
this.$modal.msgError("获取城市列表失败");
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 编辑表单省份变化 */
|
|||
|
|
handleFormProvinceChange(value) {
|
|||
|
|
console.log("编辑表单选择的省份ID:", value);
|
|||
|
|
|
|||
|
|
// 清空城市选择
|
|||
|
|
this.form.cityId = null;
|
|||
|
|
this.formCityOptions = [];
|
|||
|
|
|
|||
|
|
if (value) {
|
|||
|
|
// 直接使用 value,不进行 Number 转换,保持原始类型
|
|||
|
|
listCities(value).then(response => {
|
|||
|
|
console.log("编辑表单城市列表响应:", response);
|
|||
|
|
// 处理不同的响应结构
|
|||
|
|
let cityData = [];
|
|||
|
|
if (response && response.data) {
|
|||
|
|
cityData = Array.isArray(response.data) ? response.data : [];
|
|||
|
|
} else if (Array.isArray(response)) {
|
|||
|
|
cityData = response;
|
|||
|
|
} else if (response && response.rows) {
|
|||
|
|
cityData = response.rows;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.formCityOptions = cityData.map(item => ({
|
|||
|
|
areaCode: item.areaCode || item.area_code || item.id,
|
|||
|
|
name: item.name || item.areaName || item.area_name
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
console.log("处理后的城市列表:", this.formCityOptions);
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error("获取编辑表单城市列表失败:", error);
|
|||
|
|
this.formCityOptions = [];
|
|||
|
|
this.$modal.msgError("获取城市列表失败");
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 取消按钮
|
|||
|
|
cancel() {
|
|||
|
|
this.open = false;
|
|||
|
|
this.reset();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 表单重置
|
|||
|
|
reset() {
|
|||
|
|
this.form = {
|
|||
|
|
terminalId: null,
|
|||
|
|
phoneNumber: null,
|
|||
|
|
imei: null,
|
|||
|
|
provinceId: null,
|
|||
|
|
cityId: null,
|
|||
|
|
manufacturerId: null,
|
|||
|
|
terminalModel: null,
|
|||
|
|
terminalDeviceId: null,
|
|||
|
|
plateColor: 0,
|
|||
|
|
plateNumber: null,
|
|||
|
|
authCode: null,
|
|||
|
|
registerTime: null,
|
|||
|
|
lastAuthTime: null,
|
|||
|
|
onlineStatus: 0,
|
|||
|
|
lastHeartbeatTime: null,
|
|||
|
|
clientIp: null
|
|||
|
|
};
|
|||
|
|
this.formCityOptions = []; // 清空编辑表单的城市选项
|
|||
|
|
// 清空表单验证
|
|||
|
|
if (this.$refs.form) {
|
|||
|
|
this.$refs.form.clearValidate();
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 搜索按钮操作 */
|
|||
|
|
handleQuery() {
|
|||
|
|
this.queryParams.pageNum = 1;
|
|||
|
|
this.getList();
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 重置按钮操作 */
|
|||
|
|
resetQuery() {
|
|||
|
|
// 使用$nextTick确保DOM更新后再重置
|
|||
|
|
this.$nextTick(() => {
|
|||
|
|
this.queryParams = {
|
|||
|
|
pageNum: 1,
|
|||
|
|
pageSize: 10,
|
|||
|
|
phoneNumber: null,
|
|||
|
|
imei: null,
|
|||
|
|
provinceId: null,
|
|||
|
|
cityId: null,
|
|||
|
|
plateNumber: null,
|
|||
|
|
onlineStatus: null,
|
|||
|
|
};
|
|||
|
|
this.queryCityOptions = []; // 清空查询表单的城市选项
|
|||
|
|
this.getList();
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 多选框选中数据
|
|||
|
|
handleSelectionChange(selection) {
|
|||
|
|
this.ids = selection.map(item => item.terminalId);
|
|||
|
|
this.single = selection.length !== 1;
|
|||
|
|
this.multiple = !selection.length;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 新增按钮操作 */
|
|||
|
|
handleAdd() {
|
|||
|
|
this.reset();
|
|||
|
|
this.open = true;
|
|||
|
|
this.title = "添加终端设备";
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 修改按钮操作 */
|
|||
|
|
handleUpdate(row) {
|
|||
|
|
this.reset();
|
|||
|
|
const terminalId = row.terminalId || this.ids[0];
|
|||
|
|
getTerminal(terminalId).then(response => {
|
|||
|
|
this.form = { ...response.data };
|
|||
|
|
console.log("编辑表单数据:", this.form);
|
|||
|
|
|
|||
|
|
// 如果省份ID存在,加载对应的城市列表到编辑表单
|
|||
|
|
if (this.form.provinceId) {
|
|||
|
|
listCities(this.form.provinceId).then(cityResponse => {
|
|||
|
|
console.log("编辑时城市列表响应:", cityResponse);
|
|||
|
|
// 处理不同的响应结构
|
|||
|
|
let cityData = [];
|
|||
|
|
if (cityResponse && cityResponse.data) {
|
|||
|
|
cityData = Array.isArray(cityResponse.data) ? cityResponse.data : [];
|
|||
|
|
} else if (Array.isArray(cityResponse)) {
|
|||
|
|
cityData = cityResponse;
|
|||
|
|
} else if (cityResponse && cityResponse.rows) {
|
|||
|
|
cityData = cityResponse.rows;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.formCityOptions = cityData.map(item => ({
|
|||
|
|
areaCode: item.areaCode || item.area_code || item.id,
|
|||
|
|
name: item.name || item.areaName || item.area_name
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
this.open = true;
|
|||
|
|
this.title = "修改终端设备";
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error("加载城市列表失败:", error);
|
|||
|
|
this.formCityOptions = [];
|
|||
|
|
this.open = true;
|
|||
|
|
this.title = "修改终端设备";
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
this.open = true;
|
|||
|
|
this.title = "修改终端设备";
|
|||
|
|
}
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error("获取终端信息失败:", error);
|
|||
|
|
this.$modal.msgError("获取终端信息失败");
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 提交按钮 */
|
|||
|
|
submitForm() {
|
|||
|
|
this.$refs["form"].validate(valid => {
|
|||
|
|
if (valid) {
|
|||
|
|
if (this.form.terminalId != null) {
|
|||
|
|
// 修改操作
|
|||
|
|
updateTerminal(this.form).then(response => {
|
|||
|
|
this.$modal.msgSuccess("修改成功");
|
|||
|
|
this.open = false;
|
|||
|
|
this.getList();
|
|||
|
|
this.getStatistics();
|
|||
|
|
}).catch(error => {
|
|||
|
|
this.$modal.msgError(error.message || "修改失败");
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
// 新增操作
|
|||
|
|
addTerminal(this.form).then(response => {
|
|||
|
|
this.$modal.msgSuccess("新增成功");
|
|||
|
|
this.open = false;
|
|||
|
|
this.getList();
|
|||
|
|
this.getStatistics();
|
|||
|
|
}).catch(error => {
|
|||
|
|
this.$modal.msgError(error.message || "新增失败");
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 删除按钮操作 */
|
|||
|
|
handleDelete(row) {
|
|||
|
|
const terminalIds = row.terminalId || this.ids;
|
|||
|
|
this.$modal.confirm('是否确认删除终端设备编号为"' + terminalIds + '"的数据项?').then(() => {
|
|||
|
|
return delTerminal(terminalIds);
|
|||
|
|
}).then(() => {
|
|||
|
|
this.getList();
|
|||
|
|
this.getStatistics();
|
|||
|
|
this.$modal.msgSuccess("删除成功");
|
|||
|
|
}).catch(() => {
|
|||
|
|
// 用户取消操作
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 导出按钮操作 */
|
|||
|
|
handleExport() {
|
|||
|
|
const queryParams = { ...this.queryParams };
|
|||
|
|
this.$modal.confirm('是否确认导出所有终端设备数据项?').then(() => {
|
|||
|
|
return exportTerminal(queryParams);
|
|||
|
|
}).then(response => {
|
|||
|
|
this.$download.name(response, '终端设备.xlsx');
|
|||
|
|
}).catch(() => {
|
|||
|
|
// 用户取消操作
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.app-container {
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mb12 {
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mb20 {
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.box-card {
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.text-center {
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.clearfix:before,
|
|||
|
|
.clearfix:after {
|
|||
|
|
display: table;
|
|||
|
|
content: "";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.clearfix:after {
|
|||
|
|
clear: both;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.statistic-item {
|
|||
|
|
text-align: center;
|
|||
|
|
padding: 10px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.statistic-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #666;
|
|||
|
|
margin-bottom: 5px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.statistic-value {
|
|||
|
|
font-size: 24px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.text-success {
|
|||
|
|
color: #67c23a;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.text-danger {
|
|||
|
|
color: #f56c6c;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 表单样式优化 */
|
|||
|
|
.el-form-item {
|
|||
|
|
margin-bottom: 18px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-select {
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-input {
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-date-picker {
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 表格样式优化 */
|
|||
|
|
.el-table {
|
|||
|
|
margin-top: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-table__header {
|
|||
|
|
background-color: #f5f7fa;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-table th {
|
|||
|
|
background-color: #f5f7fa;
|
|||
|
|
color: #333;
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-table td {
|
|||
|
|
padding: 8px 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 操作按钮样式 */
|
|||
|
|
.small-padding .cell {
|
|||
|
|
padding-left: 5px;
|
|||
|
|
padding-right: 5px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 分页样式 */
|
|||
|
|
.pagination-container {
|
|||
|
|
margin-top: 20px;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 对话框样式 */
|
|||
|
|
.el-dialog__body {
|
|||
|
|
max-height: 70vh;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-dialog__footer {
|
|||
|
|
padding: 10px 20px;
|
|||
|
|
border-top: 1px solid #ebeef5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 搜索表单样式优化 - 确保一行显示 */
|
|||
|
|
.search-form {
|
|||
|
|
white-space: nowrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.search-form .el-form-item {
|
|||
|
|
margin-bottom: 10px;
|
|||
|
|
margin-right: 10px;
|
|||
|
|
display: inline-block;
|
|||
|
|
vertical-align: top;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.search-form .el-form-item__label {
|
|||
|
|
padding-right: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.search-form .el-form-item__content {
|
|||
|
|
display: inline-block;
|
|||
|
|
}
|
|||
|
|
</style>
|