设备列表

This commit is contained in:
磷叶 2025-04-30 18:22:56 +08:00
parent afa8e07964
commit 5d96ed97ba
12 changed files with 777 additions and 46 deletions

View File

@ -27,8 +27,6 @@
"lib": ["dom", "esnext"],
"types": ["@types/node"],
"sourceMap": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noEmit": true,
"isolatedModules": true,

View File

@ -107,4 +107,11 @@ export function unbindDeviceArea(ids) {
})
}
// 查询全部设备列表
export function listAllDevice(query) {
return request({
url: '/bst/device/all',
method: 'get',
params: query
})
}

View File

@ -23,7 +23,7 @@
<el-card v-if="detail.id" class="card-box">
<el-tabs>
<el-tab-pane label="电子围栏" lazy v-if="checkPermi(['bst:areaSub:list'])">
<area-sub :area-id="detail.id"/>
<area-sub :area-id="detail.id" :enable-edit="false"/>
</el-tab-pane>
<el-tab-pane label="车辆列表" lazy v-if="checkPermi(['bst:device:list'])">
<device :query="{areaId: detail.id}" />

View File

@ -90,7 +90,7 @@ export const DEVICE_STATUS_ICONS = {
};
// SN标签样式
export function getSnLabel(AMap, sn, position) {
export function getSnLabel(AMap, sn, position, color = '#409EFF') {
return new AMap.Text({
text: sn,
position: position,
@ -98,10 +98,10 @@ export function getSnLabel(AMap, sn, position) {
anchor: 'center',
style: {
background: '#fff',
border: '1px solid #409EFF',
border: `1px solid ${color}`,
borderRadius: '4px',
padding: '2px 8px',
color: '#409EFF',
color: color,
fontSize: '12px',
whiteSpace: 'nowrap',
textAlign: 'center',
@ -110,6 +110,25 @@ export function getSnLabel(AMap, sn, position) {
});
}
// 获取设备图标
export function getDeviceIcon(AMap, status) {
return new AMap.Icon({
image: DEVICE_STATUS_ICONS[status],
size: new AMap.Size(32, 36),
imageSize: new AMap.Size(32, 36),
anchor: 'bottom-center'
});
}
// 获取设备标记
export function getDeviceMaker(AMap, icon, position) {
return new AMap.Marker({
position: position,
offset: new AMap.Pixel(-16, -36),
icon: icon
});
}
// 公共方法
export const mapMethods = {
// 开始绘制(不管是那种边界)

View File

@ -23,4 +23,10 @@
color: #66b1ff;
}
}
}
.device-list {
position: absolute;
top: 10px;
left: 10px;
}

View File

@ -6,6 +6,11 @@
<!-- 地址搜索组件 -->
<address-search :map="map" :AMap="AMap" v-if="map && enableEdit" />
<!-- 车辆 -->
<div v-if="!enableEdit && deviceList && map" class="device-list">
<device-list :device-list="deviceList" :map="map" :AMap="AMap" ref="deviceList"/>
</div>
<!-- 地图工具栏 -->
<div class="map-tools">
<el-button-group>
@ -13,7 +18,8 @@
<el-button size="mini" id="area-edit" type="warning" icon="el-icon-edit" @click="startAreaBoundaryEdit" v-if="enableEdit" :disabled="isEditing">电子围栏</el-button>
<el-button size="mini" icon="el-icon-full-screen" @click="setFitView">全局查看</el-button>
<el-button size="mini" icon="el-icon-picture" @click="toggleMapStyle">切换样式</el-button>
<el-button size="mini" icon="el-icon-document" @click="toggleLabels">{{ showLabels ? '隐藏' : '显示' }}标签</el-button>
<el-button size="mini" icon="el-icon-view" @click="toggleLabels">{{ showLabels ? '隐藏' : '显示' }}标签</el-button>
<el-button size="mini" icon="el-icon-view" v-if="deviceList && deviceList.length > 0" @click="toggleDeviceShow">切换车辆展示</el-button>
<el-button size="mini" icon="el-icon-video-play" v-if="locationLogList && locationLogList.length > 0" @click="togglePlaybackPanel">{{ isPlaybackVisible ? '隐藏' : '显示' }}轨迹控制台</el-button>
</el-button-group>
</div>
@ -59,15 +65,16 @@ import AddressSearch from '@/views/bst/areaSub/components/AddressSearch.vue';
import OperationArea from './mixins/OperationArea';
import SubArea from './mixins/SubArea';
import LocationLog from './mixins/LocationLog';
import DeviceList from '@/views/bst/areaSub/components/DeviceList.vue'
export default {
name: 'AreaMap',
components: {
PlaybackPanel,
AddressSearch
AddressSearch,
DeviceList
},
mixins: [OperationArea, SubArea, LocationLog],
dicts: ['device_status', 'device_lock_status', 'device_quality'],
mixins: [OperationArea, SubArea, LocationLog], // DeviceList
props: {
//
area: {
@ -88,6 +95,10 @@ export default {
enableEdit: {
type: Boolean,
default: true
},
deviceList: {
type: Array,
default: () => []
}
},
data() {
@ -153,6 +164,8 @@ export default {
contextMenu: true
});
this.map.on('click', this.onCickMap);
//
this.polygonEditor = new this.AMap.PolygonEditor(this.map);
@ -163,6 +176,12 @@ export default {
console.error('地图初始化失败:', error);
}
},
onCickMap() {
this.closeAreaSubInfoWindow();
if (this.$refs.deviceList) {
this.$refs.deviceList.closeDeviceInfoWindow();
}
},
handlePolygonAdd({target}) {
this.editingPolygon = target;
},
@ -280,6 +299,11 @@ export default {
this.map = null;
}
},
toggleDeviceShow() {
if (this.$refs.deviceList) {
this.$refs.deviceList.toggleDeviceShow();
}
}
}
};

View File

@ -0,0 +1,480 @@
<template>
<div class="device-list" :class="{ 'is-collapsed': isCollapsed }">
<!-- 标题栏 -->
<div class="device-list-header" @click="toggleCollapse">
<span class="title">车辆列表</span>
<i class="collapse-icon" :class="isCollapsed ? 'el-icon-arrow-right' : 'el-icon-arrow-left'"></i>
</div>
<!-- 内容区域 -->
<div class="device-list-content">
<div class="filter-container">
<el-slider
v-model="filterForm.powerRange"
range
:min="0"
:max="100"
:marks="powerMarks"
@change="handleFilterChange"
/>
</div>
<el-table
:data="filteredDeviceList"
style="width: 100%"
height="400px"
size="mini"
@row-click="handleRowClick"
:header-cell-style="{ background: '#f5f7fa', color: '#606266', fontWeight: '500' }"
>
<el-table-column prop="vehicleNum" label="车辆" width="180" align="left" show-overflow-tooltip sortable>
<template slot-scope="scope">
<div class="table-cell">{{ scope.row.vehicleNum || '--' }}{{ scope.row.sn }}</div>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" sortable>
<template slot-scope="scope">
<dict-tag :options="dict.type.device_status" :value="scope.row.status" size="mini"/>
</template>
</el-table-column>
<el-table-column prop="remainingPower" label="电量" sortable>
<template slot-scope="scope">
<div class="power-progress">
<div
class="power-bar"
:style="{
width: `${scope.row.remainingPower}%`,
backgroundColor: getPowerColor(scope.row.remainingPower)
}"
></div>
<span class="power-text">{{ scope.row.remainingPower | fix2 }}%</span>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
import { getDeviceIcon, getDeviceMaker, getSnLabel } from "./AreaMap.js";
export default {
name: 'DeviceList',
dicts: ['device_status', 'device_lock_status', 'device_quality'],
props: {
deviceList: {
type: Array,
default: () => []
},
map: {
type: Object,
required: true
},
AMap: {
type: Object,
required: true
}
},
data() {
return {
infoWindow: null,
currentDevice: null,
deviceOverlays: new Map(),
deviceLabelOverlays: new Map(),
showDevice: true,
isCollapsed: true,
filterForm: {
powerRange: [0, 100],
sn: '',
vehicleNum: ''
},
powerMarks: {
0: '0%',
20: '20%',
40: '40%',
60: '60%',
80: '80%',
100: '100%'
}
}
},
computed: {
filteredDeviceList() {
return this.deviceList.filter(device => {
const powerMatch = device.remainingPower >= this.filterForm.powerRange[0] &&
device.remainingPower <= this.filterForm.powerRange[1];
const snMatch = !this.filterForm.sn ||
(device.sn && device.sn.toLowerCase().includes(this.filterForm.sn.toLowerCase()));
const vehicleNumMatch = !this.filterForm.vehicleNum ||
(device.vehicleNum && device.vehicleNum.toLowerCase().includes(this.filterForm.vehicleNum.toLowerCase()));
return powerMatch && snMatch && vehicleNumMatch;
});
}
},
watch: {
deviceList: {
handler(nv) {
this.renderDeviceMarkers(nv);
},
immediate: true
}
},
methods: {
//
renderDeviceMarkers(devices) {
this.clearOverlays(this.deviceOverlays);
this.clearOverlays(this.deviceLabelOverlays);
if (!devices) return;
devices.forEach(device => {
const position = [device.longitude, device.latitude];
const icon = getDeviceIcon(this.AMap, device.status);
const marker = getDeviceMaker(this.AMap, icon, position);
const color = this.getPowerColor(device.remainingPower);
const snLabel = getSnLabel(this.AMap, `${device.vehicleNum || ''} ${device.remainingPower}%`, position, color);
marker.on('click', () => {
this.showDeviceInfo(device, position);
});
this.deviceOverlays.set(device.id, marker);
this.deviceLabelOverlays.set(device.id, snLabel);
this.map.add([marker, snLabel]);
});
},
//
clearOverlays(overlays) {
overlays.forEach(overlay => {
this.map.remove(overlay);
});
overlays.clear();
},
//
getPowerColor(power) {
if (power <= 20) return '#F56C6C';
if (power <= 40) return '#E6A23C';
if (power <= 60) return '#409EFF';
if (power <= 80) return '#67C23A';
return '#2ecc71';
},
//
getStatusType(status) {
const statusMap = {
'online': 'success',
'offline': 'info',
'fault': 'danger',
'maintenance': 'warning'
};
return statusMap[status] || 'info';
},
//
handleFilterChange() {
this.renderDeviceMarkers(this.filteredDeviceList);
},
//
handleRowClick(row) {
const position = [row.longitude, row.latitude];
this.map.setCenter(position);
this.map.setZoom(15);
this.showDeviceInfo(row, position);
},
//
showDeviceInfo(device, position) {
if (!this.infoWindow) {
this.infoWindow = new this.AMap.InfoWindow({
isCustom: true,
offset: new this.AMap.Pixel(0, -30),
autoMove: true
});
}
this.currentDevice = device;
const content = this.createInfoWindowContent(device);
this.infoWindow.setContent(content);
this.infoWindow.open(this.map, position);
},
//
createInfoWindowContent(device) {
const content = document.createElement('div');
content.className = 'device-info-window';
content.style.padding = '10px';
content.style.minWidth = '300px';
content.style.backgroundColor = 'rgba(255, 255, 255, 0.9)';
content.style.borderRadius = '4px';
content.style.boxShadow = '0 2px 12px 0 rgba(0, 0, 0, 0.1)';
const infoItems = [
{ label: '车牌号', value: device.vehicleNum || '--' },
{ label: '状态', value: this.getDictLabel('device_status', device.status) },
{ label: 'SN', value: device.sn },
{ label: 'MAC', value: device.mac },
{ label: '电压', value: `${device.voltage || 0} V` },
{ label: '电量', value: `${device.remainingPower}%` },
{ label: '信号', value: device.signal || '-' },
{ label: '卫星', value: device.satellites || '-' },
{ label: '锁状态', value: this.getDictLabel('device_lock_status', device.lockStatus) },
{ label: '电门', value: this.getDictLabel('device_quality', device.quality) },
{ label: '速度', value: `${device.speed || 0} KM/h` },
];
const gridContainer = document.createElement('div');
gridContainer.style.display = 'grid';
gridContainer.style.gridTemplateColumns = 'repeat(2, 1fr)';
gridContainer.style.gap = '8px';
gridContainer.style.fontSize = '12px';
infoItems.forEach(item => {
const itemContainer = document.createElement('div');
itemContainer.style.display = 'flex';
itemContainer.style.alignItems = 'center';
itemContainer.style.marginBottom = '4px';
const label = document.createElement('span');
label.style.color = '#606266';
label.style.marginRight = '4px';
label.textContent = `${item.label}`;
const value = document.createElement('span');
value.style.color = '#303133';
value.style.fontWeight = '500';
value.textContent = item.value;
itemContainer.appendChild(label);
itemContainer.appendChild(value);
gridContainer.appendChild(itemContainer);
});
content.appendChild(gridContainer);
const buttonContainer = document.createElement('div');
buttonContainer.style.marginTop = '10px';
buttonContainer.style.textAlign = 'center';
const detailButton = document.createElement('button');
detailButton.textContent = '查看详情';
detailButton.style.padding = '6px 12px';
detailButton.style.backgroundColor = '#409EFF';
detailButton.style.color = '#fff';
detailButton.style.border = 'none';
detailButton.style.borderRadius = '4px';
detailButton.style.cursor = 'pointer';
detailButton.style.fontSize = '12px';
detailButton.onclick = () => {
this.closeDeviceInfoWindow();
this.$router.push(`/view/device/${device.id}`);
};
buttonContainer.appendChild(detailButton);
content.appendChild(buttonContainer);
return content;
},
//
closeDeviceInfoWindow() {
if (this.infoWindow) {
this.infoWindow.close();
this.currentDevice = null;
}
},
//
getDictLabel(dictType, value) {
const dict = this.dict.type[dictType];
if (!dict) return value;
const item = dict.find(item => item.value === value);
return item ? item.label : value;
},
//
toggleDeviceShow() {
this.showDevice = !this.showDevice;
this.deviceOverlays.forEach(item => {
item.setMap(this.showDevice ? this.map : null);
});
this.deviceLabelOverlays.forEach(item => {
item.setMap(this.showDevice ? this.map : null);
});
},
//
toggleCollapse() {
this.isCollapsed = !this.isCollapsed;
}
}
}
</script>
<style lang="scss" scoped>
.device-list {
position: relative;
width: 400px;
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
overflow: hidden;
&.is-collapsed {
width: 40px;
.device-list-content {
display: none;
}
.device-list-header {
.title {
display: none;
}
.collapse-icon {
margin: 0 auto;
}
}
}
.device-list-header {
height: 38px;
line-height: 38px;
padding: 0 8px;
background-color: #f5f7fa;
border-bottom: 1px solid #e4e7ed;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
.title {
font-size: 14px;
color: #303133;
transition: opacity 0.3s;
}
.collapse-icon {
font-size: 16px;
color: #909399;
transition: transform 0.3s;
}
}
.device-list-content {
padding: 15px;
}
.filter-container {
margin-bottom: 15px;
.filter-title {
font-size: 14px;
color: #606266;
margin-bottom: 10px;
}
.filter-form {
.filter-item {
width: 100%;
margin-bottom: 15px;
.filter-label {
font-size: 13px;
color: #606266;
margin-bottom: 8px;
}
}
}
}
.el-slider {
width: 100%;
}
::v-deep .el-table {
border: 1px solid #ebeef5;
border-radius: 4px;
.el-table__body-wrapper {
.el-table__row {
cursor: pointer;
&:hover {
background-color: #f5f7fa;
}
}
}
.table-cell {
padding: 0 10px;
font-size: 13px;
color: #606266;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.status-tag {
display: inline-block;
padding: 2px 6px;
border-radius: 4px;
font-size: 12px;
color: #fff;
&.success {
background-color: #67c23a;
}
&.info {
background-color: #909399;
}
&.danger {
background-color: #f56c6c;
}
&.warning {
background-color: #e6a23c;
}
}
.power-progress {
position: relative;
height: 20px;
line-height: 20px;
background-color: #ebeef5;
border-radius: 4px;
overflow: hidden;
margin: 0 10px;
.power-bar {
position: absolute;
top: 0;
left: 0;
height: 100%;
transition: width 0.3s;
}
.power-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 12px;
color: #fff;
text-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
line-height: 1;
white-space: nowrap;
}
}
//
.el-table__cell {
padding: 8px 0;
}
}
}
</style>

View File

@ -0,0 +1,182 @@
import { getDeviceIcon, getDeviceMaker, getSnLabel } from "@/views/bst/areaSub/components/AreaMap.js";
export const $deviceList = {
props: {
deviceList: {
type: Array,
default: () => []
},
},
data() {
return {
infoWindow: null,
currentDevice: null,
deviceOverlays: new Map(),
deviceLabelOverlays: new Map(),
showDevice: true,
}
},
watch: {
deviceList(nv, ov) {
this.renderDeviceMarkers(nv);
}
},
methods: {
// 新增方法,用于在地图上渲染设备标记
renderDeviceMarkers() {
this.clearOverlays(this.deviceOverlays);
this.clearOverlays(this.deviceLabelOverlays);
if (this.deviceList == null) {
return;
}
this.deviceList.forEach(device => {
const position = [device.longitude, device.latitude];
const icon = getDeviceIcon(this.AMap, device.status);
const marker = getDeviceMaker(this.AMap, icon, position);
let color = '#409EFF';
// 根据电量设置不同颜色
if (device.remainingPower <= 20) {
color = '#F56C6C'; // 红色 - 严重不足
} else if (device.remainingPower <= 40) {
color = '#E6A23C'; // 橙色 - 电量不足
} else if (device.remainingPower <= 60) {
color = '#409EFF'; // 蓝色 - 一般
} else if (device.remainingPower <= 80) {
color = '#67C23A'; // 绿色 - 充足
} else {
color = '#2ecc71'; // 深绿色 - 非常充足
}
const snLabel = getSnLabel(this.AMap, `${device.vehicleNum || ''} ${device.remainingPower}%`, position, color);
// 添加点击事件
marker.on('click', (e) => {
this.showDeviceInfo(device, position);
});
this.deviceOverlays.set(device.id, marker);
this.deviceLabelOverlays.set(device.id, snLabel);
this.map.add([marker, snLabel]);
});
},
// 关闭信息弹窗
closeDeviceInfoWindow() {
if (this.infoWindow) {
this.infoWindow.close();
this.currentDevice = null;
}
},
// 显示设备信息弹窗
showDeviceInfo(device, position) {
if (!this.infoWindow) {
this.infoWindow = new this.AMap.InfoWindow({
isCustom: true,
offset: new this.AMap.Pixel(0, -30),
autoMove: true
});
}
this.currentDevice = device;
const content = this.createInfoWindowContent(device);
this.infoWindow.setContent(content);
this.infoWindow.open(this.map, position);
},
// 创建信息弹窗内容
createInfoWindowContent(device) {
const content = document.createElement('div');
content.className = 'device-info-window';
content.style.padding = '10px';
content.style.minWidth = '300px';
content.style.backgroundColor = 'rgba(255, 255, 255, 0.9)';
content.style.borderRadius = '4px';
content.style.boxShadow = '0 2px 12px 0 rgba(0, 0, 0, 0.1)';
const infoItems = [
{ label: '车牌号', value: device.vehicleNum || '--' },
{ label: '状态', value: this.getDictLabel('device_status', device.status) },
{ label: 'SN', value: device.sn },
{ label: 'MAC', value: device.mac },
{ label: '电压', value: `${device.voltage || 0} V` },
{ label: '电量', value: `${device.remainingPower}%` },
{ label: '信号', value: device.signal || '-' },
{ label: '卫星', value: device.satellites || '-' },
{ label: '锁状态', value: this.getDictLabel('device_lock_status', device.lockStatus) },
{ label: '电门', value: this.getDictLabel('device_quality', device.quality) },
{ label: '速度', value: `${device.speed || 0} KM/h` },
];
// 创建网格容器
const gridContainer = document.createElement('div');
gridContainer.style.display = 'grid';
gridContainer.style.gridTemplateColumns = 'repeat(2, 1fr)';
gridContainer.style.gap = '8px';
gridContainer.style.fontSize = '12px';
infoItems.forEach(item => {
const itemContainer = document.createElement('div');
itemContainer.style.display = 'flex';
itemContainer.style.alignItems = 'center';
itemContainer.style.marginBottom = '4px';
const label = document.createElement('span');
label.style.color = '#606266';
label.style.marginRight = '4px';
label.textContent = `${item.label}`;
const value = document.createElement('span');
value.style.color = '#303133';
value.style.fontWeight = '500';
value.textContent = item.value;
itemContainer.appendChild(label);
itemContainer.appendChild(value);
gridContainer.appendChild(itemContainer);
});
content.appendChild(gridContainer);
// 添加查看详情按钮
const buttonContainer = document.createElement('div');
buttonContainer.style.marginTop = '10px';
buttonContainer.style.textAlign = 'center';
const detailButton = document.createElement('button');
detailButton.textContent = '查看详情';
detailButton.style.padding = '6px 12px';
detailButton.style.backgroundColor = '#409EFF';
detailButton.style.color = '#fff';
detailButton.style.border = 'none';
detailButton.style.borderRadius = '4px';
detailButton.style.cursor = 'pointer';
detailButton.style.fontSize = '12px';
detailButton.onclick = () => {
this.closeDeviceInfoWindow();
this.$router.push(`/view/device/${device.id}`);
};
buttonContainer.appendChild(detailButton);
content.appendChild(buttonContainer);
return content;
},
// 获取字典标签
getDictLabel(dictType, value) {
const dict = this.dict.type[dictType];
if (!dict) return value;
const item = dict.find(item => item.value === value);
return item ? item.label : value;
},
toggleDeviceShow() {
this.showDevice = !this.showDevice;
this.deviceOverlays.forEach(item => {
item.setMap(this.showDevice ? this.map : null);
});
this.deviceLabelOverlays.forEach(item => {
item.setMap(this.showDevice ? this.map : null);
});
}
}
}

View File

@ -1,5 +1,5 @@
import { isEmpty } from "@/utils/index";
import { DEVICE_STATUS_ICONS, getSnLabel } from "@/views/bst/areaSub/components/AreaMap";
import { DEVICE_STATUS_ICONS, getDeviceIcon, getDeviceMaker, getSnLabel } from "@/views/bst/areaSub/components/AreaMap";
export default {
data() {
@ -126,19 +126,10 @@ export default {
if (!this.currentDeviceMarker) {
// 创建图标对象
this.currentDeviceIcon = new this.AMap.Icon({
image: DEVICE_STATUS_ICONS[this.currentLog.status],
size: new this.AMap.Size(32, 36),
imageSize: new this.AMap.Size(32, 36),
anchor: 'bottom-center'
});
this.currentDeviceIcon = getDeviceIcon(this.AMap, this.currentLog.status);
// 首次创建设备标记
this.currentDeviceMarker = new this.AMap.Marker({
position: position,
offset: new this.AMap.Pixel(-16, -36),
icon: this.currentDeviceIcon
});
this.currentDeviceMarker = getDeviceMaker(this.AMap, this.currentDeviceIcon, position);
// 保存当前设备ID
this.currentDeviceMarker.deviceId = this.currentLog.deviceId;

View File

@ -50,17 +50,16 @@ export default {
methods: {
initSubArea() {
// 添加地图点击事件,关闭信息窗体和清除选中状态
this.map.on('click', () => {
if (this.currentInfoWindow) {
this.currentInfoWindow.close();
}
if (!this.isEditing) {
this.selectedAreaId = null;
}
});
this.renderSubAreas();
},
closeAreaSubInfoWindow() {
if (this.currentInfoWindow) {
this.currentInfoWindow.close();
}
if (!this.isEditing) {
this.selectedAreaId = null;
}
},
// 渲染子区域
renderSubAreas() {

View File

@ -38,17 +38,18 @@
</el-form>
<el-row :gutter="10" class="mb8">
<!-- <el-col :span="1.5">
<el-col :span="1.5" v-if="!enableEdit">
<el-button
type="primary"
plain
icon="el-icon-plus"
icon="el-icon-location"
size="mini"
@click="handleAdd"
v-has-permi="['bst:areaSub:add']"
>新增</el-button>
</el-col> -->
<el-col :span="1.5">
@click="$router.push(`/operate/areaSub/${area.id}`)"
v-show="!enableEdit"
v-has-permi="['bst:areaSub:list']"
>前往编辑</el-button>
</el-col>
<el-col :span="1.5" v-if="enableEdit">
<el-button
type="danger"
plain
@ -125,7 +126,7 @@
</template>
</el-table-column>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160" v-if="enableEdit">
<template slot-scope="scope">
<el-button
size="mini"
@ -158,11 +159,13 @@
ref="map"
:area="area"
:area-sub-list="areaSubList"
:device-list="deviceList"
@edit="handleUpdate"
@delete="handleDelete"
@add-boundary="handleAddBoundary"
@update-boundary="handleUpdateBoundary"
@update-area-boundary="handleUpdateAreaBoundary"
:enableEdit="enableEdit"
/>
</div>
@ -187,6 +190,7 @@ import { AreaSubStatus, AreaSubType } from '@/utils/enums';
import AreaMap from '@/views/bst/areaSub/components/AreaMap.vue';
import AreaSubEditDialog from '@/views/bst/areaSub/components/AreaSubEditDialog.vue';
import {startGuide} from "@/utils/guide"
import { listAllDevice } from '@/api/bst/device';
//
const defaultSort = {
@ -203,6 +207,11 @@ export default {
areaId: {
type: String,
default: null
},
//
enableEdit: {
type: Boolean,
default: true
}
},
data() {
@ -275,6 +284,7 @@ export default {
},
area: {},
loadingArea: false,
deviceList: []
};
},
created() {
@ -286,9 +296,11 @@ export default {
this.getArea();
this.getList();
this.$nextTick(()=> {
startGuide("AreaSub");
});
if (this.enableEdit) {
this.$nextTick(()=> {
startGuide("AreaSubEdit");
});
}
},
methods: {
handleRowClick(row) {
@ -298,7 +310,7 @@ export default {
handleStatusChange(row, val) {
updateAreaSub({id: row.id, status: val}).then(response => {
if (response.code == 200) {
this.$modal.msgSuccess("更新成功");
this.$modal.msgSuccess("更新成功");
}
}).catch(() => {
row.status = val == AreaSubStatus.NORMAL ? AreaSubStatus.DISABLED : AreaSubStatus.NORMAL;
@ -346,10 +358,23 @@ export default {
this.loadingArea = true;
getArea(this.queryParams.areaId).then(response => {
this.area = response.data;
if (!this.enableEdit) {
this.getDeviceList();
}
}).finally(() => {
this.loadingArea = false;
});
},
//
getDeviceList() {
if (this.area == null) {
return;
}
listAllDevice({areaId: this.area.id}).then(res => {
this.deviceList = res.data;
})
},
/** 当排序按钮被点击时触发 **/
onSortChange(column) {
if (column.order == null) {

View File

@ -36,8 +36,8 @@ module.exports = {
proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
target: `http://localhost:4101`,
// target: `https://ele.ccttiot.com/prod-api`,
// target: `http://localhost:4101`,
target: `https://ele.ccttiot.com/prod-api`,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''