场景
若依前后端分离版手把手教你本地搭建环境并运行项目:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108465662
Vue中使用Openlayers加载Geoserver发布的ImageWMS:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/115867709
在上面搭建起来Vue+SpringBoot的前后端分离的项目的基础上,并且加载显示地图之后。
要实现在地图上显示所有摄像头的位置,并且可以新增时在地图上选择坐标,以及修改时可以在地图上回显坐标。
实现效果如下
新增摄像头
修改摄像头
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。
实现
1、mysql设计数据库如下
建表语句
DROP TABLE IF EXISTS `bus_surveillance_video`;
CREATE TABLE `bus_surveillance_video` (
`id` int(0) NOT NULL AUTO_INCREMENT COMMENT '序号',
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '摄像头IP',
`port` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '摄像头端口号',
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '登录账号',
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '登录密码',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '名称',
`area_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '区域位置',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
2、然后使用代码生成工具,生成相应的各层代码。
数据库设计主要使用area_name用来存取坐标,但是坐标是分x,y的,所以在实体类中再多加两个属性x和y,在新增和编辑的接口中进行
坐标的转换。
实体类代码:
package com.ruoyi.system.domain;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import java.math.BigDecimal;
import java.util.List;
public class BusSurveillanceVideo extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 序号 */
private Long id;
/** 摄像头IP */
@Excel(name = "摄像头IP")
private String ip;
/** 摄像头端口号 */
@Excel(name = "摄像头端口号")
private String port;
/** 登录账号 */
@Excel(name = "登录账号")
private String username;
/** 登录密码 */
@Excel(name = "登录密码")
private String password;
/** 摄像头通道 */
@Excel(name = "摄像头通道")
private List channels;
/** 名称 */
@Excel(name = "名称")
private String name;
/** 位置x坐标 */
private BigDecimal siteX;
/** 位置y坐标 */
private BigDecimal siteY;
/** 区域名称 */
@Excel(name = "区域位置")
private String areaName;
public BigDecimal getSiteX() {
return siteX;
}
public void setSiteX(BigDecimal siteX) {
this.siteX = siteX;
}
public BigDecimal getSiteY() {
return siteY;
}
public void setSiteY(BigDecimal siteY) {
this.siteY = siteY;
}
public String getAreaName() {
return areaName;
}
public void setAreaName(String areaName) {
this.areaName = areaName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setIp(String ip)
{
this.ip = ip;
}
public String getIp()
{
return ip;
}
public void setPort(String port)
{
this.port = port;
}
public String getPort()
{
return port;
}
public void setUsername(String username)
{
this.username = username;
}
public String getUsername()
{
return username;
}
public void setPassword(String password)
{
this.password = password;
}
public String getPassword()
{
return password;
}
public List getChannels() {
return channels;
}
public void setChannels(List channels) {
this.channels = channels;
}
@Override
public String toString() {
return "BusSurveillanceVideo{" +
"id=" + id +
", ip='" + ip + '\'' +
", port='" + port + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
", channels=" + channels +
'}';
}
}
Mapper代码:
package com.ruoyi.system.mapper;
import com.ruoyi.system.domain.BusSurveillanceVideo;
import java.util.List;
public interface BusSurveillanceVideoMapper
{
/**
* 查询摄像头参数
*
* @param id 摄像头参数ID
* @return 摄像头参数
*/
public BusSurveillanceVideo selectBusSurveillanceVideoById(Long id);
/**
* 查询摄像头参数列表
*
* @param busSurveillanceVideo 摄像头参数
* @return 摄像头参数集合
*/
public List<BusSurveillanceVideo> selectBusSurveillanceVideoList(BusSurveillanceVideo busSurveillanceVideo);
/**
* 新增摄像头参数
*
* @param busSurveillanceVideo 摄像头参数
* @return 结果
*/
public int insertBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo);
/**
* 修改摄像头参数
*
* @param busSurveillanceVideo 摄像头参数
* @return 结果
*/
public int updateBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo);
/**
* 删除摄像头参数
*
* @param id 摄像头参数ID
* @return 结果
*/
public int deleteBusSurveillanceVideoById(Long id);
/**
* 批量删除摄像头参数
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteBusSurveillanceVideoByIds(Long[] ids);
}
mapper.xml代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.BusSurveillanceVideoMapper">
<resultMap type="BusSurveillanceVideo" id="BusSurveillanceVideoResult">
<result property="id" column="id"/>
<result property="ip" column="ip"/>
<result property="port" column="port"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="name" column="name"/>
<result property="areaName" column="area_name"/>
</resultMap>
<sql id="selectBusSurveillanceVideoVo">
select id, ip, port, username, password, name,area_name
from bus_surveillance_video
</sql>
<select id="selectBusSurveillanceVideoList" parameterType="BusSurveillanceVideo"
resultMap="BusSurveillanceVideoResult">
<include refid="selectBusSurveillanceVideoVo"/>
<where>
<if test="ip != null and ip != ''">and ip = #{ip}</if>
<if test="port != null and port != ''">and port = #{port}</if>
<if test="username != null and username != ''">and username like concat('%', #{username}, '%')</if>
<if test="password != null and password != ''">and password = #{password}</if>
<if test="name != null and name != ''">and name = #{name}</if>
<if test="areaName!=null and areaName != ''">and area_name = #{areaName}</if>
</where>
</select>
<select id="selectBusSurveillanceVideoById" parameterType="Long" resultMap="BusSurveillanceVideoResult">
<include refid="selectBusSurveillanceVideoVo"/>
where id = #{id}
</select>
<insert id="insertBusSurveillanceVideo" parameterType="BusSurveillanceVideo">
insert into bus_surveillance_video
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="ip != null">ip,</if>
<if test="port != null">port,</if>
<if test="username != null">username,</if>
<if test="password != null">password,</if>
<if test="name != null">name,</if>
<if test="areaName !=null ">area_name,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="ip != null">#{ip},</if>
<if test="port != null">#{port},</if>
<if test="username != null">#{username},</if>
<if test="password != null">#{password},</if>
<if test="name != null">#{name},</if>
<if test="areaName!=null">#{areaName}</if>
</trim>
</insert>
<update id="updateBusSurveillanceVideo" parameterType="BusSurveillanceVideo">
update bus_surveillance_video
<trim prefix="SET" suffixOverrides=",">
<if test="ip != null">ip = #{ip},</if>
<if test="port != null">port = #{port},</if>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
<if test="name != null">name = #{name},</if>
<if test="areaName!=null">area_name =#{areaName}</if>
</trim>
where id = #{id}
</update>
<delete id="deleteBusSurveillanceVideoById" parameterType="Long">
delete
from bus_surveillance_video
where id = #{id}
</delete>
<delete id="deleteBusSurveillanceVideoByIds" parameterType="String">
delete from bus_surveillance_video where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
Service接口代码
package com.ruoyi.system.service;
import com.ruoyi.system.domain.BusSurveillanceVideo;
import java.util.List;
public interface IBusSurveillanceVideoService
{
/**
* 查询摄像头参数
*
* @param id 摄像头参数ID
* @return 摄像头参数
*/
public BusSurveillanceVideo selectBusSurveillanceVideoById(Long id);
/**
* 查询摄像头参数列表
*
* @param busSurveillanceVideo 摄像头参数
* @return 摄像头参数集合
*/
public List<BusSurveillanceVideo> selectBusSurveillanceVideoList(BusSurveillanceVideo busSurveillanceVideo);
/**
* 新增摄像头参数
*
* @param busSurveillanceVideo 摄像头参数
* @return 结果
*/
public int insertBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo);
/**
* 修改摄像头参数
*
* @param busSurveillanceVideo 摄像头参数
* @return 结果
*/
public int updateBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo);
/**
* 批量删除摄像头参数
*
* @param ids 需要删除的摄像头参数ID
* @return 结果
*/
public int deleteBusSurveillanceVideoByIds(Long[] ids);
/**
* 删除摄像头参数信息
*
* @param id 摄像头参数ID
* @return 结果
*/
public int deleteBusSurveillanceVideoById(Long id);
}
ServiceImpl代码
package com.ruoyi.system.service.impl;
import com.ruoyi.system.domain.BusSurveillanceVideo;
import com.ruoyi.system.mapper.BusSurveillanceVideoMapper;
import com.ruoyi.system.service.IBusSurveillanceVideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Service
public class BusSurveillanceVideoServiceImpl implements IBusSurveillanceVideoService {
@Autowired
private BusSurveillanceVideoMapper busSurveillanceVideoMapper;
/**
* 查询摄像头参数
*
* @param id 摄像头参数ID
* @return 摄像头参数
*/
@Override
public BusSurveillanceVideo selectBusSurveillanceVideoById(Long id) {
return busSurveillanceVideoMapper.selectBusSurveillanceVideoById(id);
}
/**
* 查询摄像头参数列表
*
* @param busSurveillanceVideo 摄像头参数
* @return 摄像头参数
*/
@Override
public List<BusSurveillanceVideo> selectBusSurveillanceVideoList(BusSurveillanceVideo busSurveillanceVideo) {
List<BusSurveillanceVideo> busSurveillanceVideos = busSurveillanceVideoMapper.selectBusSurveillanceVideoList(busSurveillanceVideo);
busSurveillanceVideos.forEach(videos -> {
videos.setChannels(new ArrayList());
if (videos.getAreaName() != null) {
String[] point = videos.getAreaName().substring(1, videos.getAreaName().length() - 1).split(",");
if (!point[0].equals("null") && !point[1].equals("null")) {
videos.setSiteX(new BigDecimal(point[0]));
videos.setSiteY(new BigDecimal(point[1]));
}
}
});
return busSurveillanceVideos;
}
/**
* 新增摄像头参数
*
* @param busSurveillanceVideo 摄像头参数
* @return 结果
*/
@Override
public int insertBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo) {
String area = "[" + busSurveillanceVideo.getSiteX() + "," + busSurveillanceVideo.getSiteY() + "]";
busSurveillanceVideo.setAreaName(area);
return busSurveillanceVideoMapper.insertBusSurveillanceVideo(busSurveillanceVideo);
}
/**
* 修改摄像头参数
*
* @param busSurveillanceVideo 摄像头参数
* @return 结果
*/
@Override
public int updateBusSurveillanceVideo(BusSurveillanceVideo busSurveillanceVideo) {
String area = "[" + busSurveillanceVideo.getSiteX() + "," + busSurveillanceVideo.getSiteY() + "]";
busSurveillanceVideo.setAreaName(area);
return busSurveillanceVideoMapper.updateBusSurveillanceVideo(busSurveillanceVideo);
}
/**
* 批量删除摄像头参数
*
* @param ids 需要删除的摄像头参数ID
* @return 结果
*/
@Override
public int deleteBusSurveillanceVideoByIds(Long[] ids) {
return busSurveillanceVideoMapper.deleteBusSurveillanceVideoByIds(ids);
}
/**
* 删除摄像头参数信息
*
* @param id 摄像头参数ID
* @return 结果
*/
@Override
public int deleteBusSurveillanceVideoById(Long id) {
return busSurveillanceVideoMapper.deleteBusSurveillanceVideoById(id);
}
}
注意在这层实现的坐标x和坐标y的拆分显示给前端以及组合存储更新到数据库。
Controller层代码
package com.ruoyi.web.controller.system;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.BusSurveillanceVideo;
import com.ruoyi.system.service.IBusSurveillanceVideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/surveillanceVideo")
public class BusSurveillanceVideoController extends BaseController
{
@Autowired
private IBusSurveillanceVideoService busSurveillanceVideoService;
/**
* 查询摄像头参数列表
*/
@GetMapping("/getVideoInfo")
public TableDataInfo list(BusSurveillanceVideo busSurveillanceVideo)
{
startPage();
List<BusSurveillanceVideo> list = busSurveillanceVideoService.selectBusSurveillanceVideoList(busSurveillanceVideo);
return getDataTable(list);
}
/**
* 获取摄像头参数详细信息
*/
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return AjaxResult.success(busSurveillanceVideoService.selectBusSurveillanceVideoById(id));
}
/**
* 新增摄像头参数
*/
@Log(title = "摄像头参数", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(BusSurveillanceVideo busSurveillanceVideo)
{
return toAjax(busSurveillanceVideoService.insertBusSurveillanceVideo(busSurveillanceVideo));
}
/**
* 修改摄像头参数
*/
@Log(title = "摄像头参数", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody BusSurveillanceVideo busSurveillanceVideo)
{
return toAjax(busSurveillanceVideoService.updateBusSurveillanceVideo(busSurveillanceVideo));
}
/**
* 删除摄像头参数
*/
@Log(title = "摄像头参数", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(busSurveillanceVideoService.deleteBusSurveillanceVideoByIds(ids));
}
}
3、前端代码结构
前端代码实现结构
其中Index.vue是主页面,实现如下显示所有摄像头数据。
lampMap.vue是地图显示摄像头页面实现如下效果
videoMap.vue是点击新增或者编辑时点击选择摄像头时的弹窗
4、index.vue代码
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryForm"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="摄像头ip" prop="ip">
<el-input
v-model="queryParams.ip"
placeholder="请输入摄像头ip"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" 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-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['runcontrolmange:surveillanceVideo:add']"
>新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['runcontrolmange:surveillanceVideo:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['runcontrolmange:surveillanceVideo:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="primary"
icon="el-icon-map-location"
size="mini"
@click="showLampPointData"
>地图
</el-button>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="videoList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column show-overflow-tooltip label="名称" align="center" prop="name" />
<el-table-column show-overflow-tooltip label="摄像头ip" align="center" prop="ip" />
<el-table-column
show-overflow-tooltip
label="账号"
align="center"
prop="username"
/>
<el-table-column
show-overflow-tooltip
label="密码"
align="center"
prop="password"
/>
<el-table-column show-overflow-tooltip label="端口" align="center" prop="port" />
<el-table-column
show-overflow-tooltip
label="摄像头坐标"
align="center"
prop="areaName"
/>
<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)"
v-hasPermi="['runcontrolmange:surveillanceVideo:edit']"
>修改</el-button
>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['runcontrolmange:surveillanceVideo:remove']"
>删除</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="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="摄像头ip" prop="ip">
<el-input v-model="form.ip" placeholder="请输入摄像头ip" />
</el-form-item>
<el-form-item label="账号" prop="username">
<el-input v-model="form.username" placeholder="请输入账号" />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="form.password" placeholder="请输入密码" />
</el-form-item>
<el-form-item label="端口" prop="port">
<el-input v-model="form.port" placeholder="请输入端口" />
</el-form-item>
<el-form-item label="摄像头位置" prop="coordinate">
<el-input v-model="lightPoint" placeholder="点击新增/更改摄像头坐标" @focus="onMap" />
</el-form-item>
</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>
<!-- 地图 -->
<videoMap ref="videoMap" @childEvent="parentEvent"></videoMap>
<lampMap ref="lampMap"></lampMap>
</div>
</template>
<script>
import {
VideoInfoList,
addVideo,
updateVideo,
delVideo,
} from "@/api/system/carVideo";
import videoMap from "./component/videoMap";
import lampMap from "./component/lampMap";
export default {
name: "OpUser",
components: {
videoMap,
lampMap,
},
data() {
return {
// 遮罩层
loading: false,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 识别用户表格数据
videoList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
},
// 表单参数
form: {
coordinate: "",
},
// 表单校验
rules: {},
dialogVisible: false,
// 摄像头的参数
lightPoint: [],
};
},
created() {
this.getList();
},
mounted() {},
destroyed() {},
methods: {
parentEvent(data) {
this.form.siteX = data[0];
this.form.siteY = data[1];
this.lightPoint = `${this.form.siteX},${this.form.siteY}`;
this.form.coordinate = this.lightPoint;
},
onMap() {
this.$refs.videoMap.dialogVisible = true;
this.$refs.videoMap.init();
this.$refs.videoMap.coordinate = this.form.coordinate;
this.$refs.videoMap.drawPoint([this.form.siteX, this.form.siteY]);
},
// 所有摄像头地图
showLampPointData(data) {
this.$refs.lampMap.dialogVisible = true;
this.$refs.lampMap.init();
this.$refs.lampMap.drawPoint(this.videoList);
},
getList() {
VideoInfoList(this.queryParams).then((res) => {
this.videoList = res.rows;
this.total = res.total;
this.loading = false;
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
handleAdd() {
this.reset();
this.open = true;
this.lightPoint = "";
this.title = "新增摄像头";
},
handleUpdate(row) {
this.reset();
this.title = "修改";
this.open = true;
let id;
if(row.id){
id = row.id
this.videoList.forEach((item) => {
if (item.id == id) {
this.form = JSON.parse(JSON.stringify(item));
this.lightPoint = item.areaName;
}
});
}else{
id = this.ids;
this.videoList.forEach((item) => {
if (item.id == id[0]) {
this.form = JSON.parse(JSON.stringify(item));
this.lightPoint = item.areaName;
}
});
}
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.form.id != null) {
updateVideo(this.form).then((response) => {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addVideo(this.form).then((response) => {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
handleDelete(row) {
const ids = row.id || this.ids;
this.$confirm("是否确认删除该条数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return delVideo(ids);
})
.then(() => {
this.getList();
this.msgSuccess("删除成功");
});
},
cancel() {
this.open = false;
this.reset();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.openVideoData = [];
this.openVideoData = selection;
this.ids = selection.map((item) => item.id);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
reset() {
this.form = {
ip: null,
name: null,
username: null,
password: null,
port: null,
coordinate:''
};
this.resetForm("form");
},
},
};
</script>
<style scoped>
</style>
其中调用增删改查后台接口的代码
import request from '@/utils/request'
export function VideoInfoList(query) {
return request({
url: '/surveillanceVideo/getVideoInfo',
method: 'get',
params: query
})
}
// 新增
export function addVideo(query) {
return request({
url: '/surveillanceVideo',
method: 'post',
params: query
})
}
// 修改
export function updateVideo(query) {
return request({
url: '/surveillanceVideo',
method: 'put',
data: query
})
}
// 删除
export function delVideo(id) {
return request({
url: '/surveillanceVideo/' + id,
method: 'delete'
})
}
5、index.vue关键代码
点击地图按钮
<el-button
type="primary"
icon="el-icon-map-location"
size="mini"
@click="showLampPointData"
>地图
</el-button>
显示所有摄像头地图
// 所有摄像头地图
showLampPointData(data) {
this.$refs.lampMap.dialogVisible = true;
this.$refs.lampMap.init();
this.$refs.lampMap.drawPoint(this.videoList);
},
首先显示lampMap组件的弹窗,其次初始化地图,然后调用地图画点的方法,并传递所有摄像头的坐标的list。
其中所有摄像头坐标的list是页面初始化请求接口获取的。
created() {
this.getList();
},
然后是新增和编辑页面点击摄像头位置时
<el-form-item label="摄像头位置" prop="coordinate">
<el-input v-model="lightPoint" placeholder="点击新增/更改摄像头坐标" @focus="onMap" />
</el-form-item>
注意这里的onMap方法
onMap() {
this.$refs.videoMap.dialogVisible = true;
this.$refs.videoMap.init();
this.$refs.videoMap.coordinate = this.form.coordinate;
this.$refs.videoMap.drawPoint([this.form.siteX, this.form.siteY]);
},
首先是显示页面,其次是地图初始化,然后是获取form对象的coordinate属性并传递给videoMap子组件的coordinate属性
用来在地图上进行回显摄像头位置。最后执行画点的方法,参数为form表单的x坐标与y坐标。
注意这里的表单中的prop是是coordinate,但是输入框的v-model却是lightPoint。
这样做才能实现弹窗之后回传的属性为x和y,然后表单需要提交给后台的是拼接后的单个字符串的格式。
6.lampMap代码
<template>
<div class="cont">
<el-dialog
title="摄像头"
:visible.sync="dialogVisible"
width="70%"
:modal="false"
v-loading="loading"
>
<div id="xhdMap" v-if="dialogVisible"></div>
</el-dialog>
</div>
</template>
<script>
import Map from "ol/Map";
import View from "ol/View";
import Feature from "ol/Feature";
import { Point, LineString } from "ol/geom";
import { Image as ImageLayer, Vector as VectorLayer, Tile as TileLayer } from "ol/layer";
import { Circle, Fill, Icon, Stroke, Style, Text } from "ol/style";
import { Cluster, OSM, Vector as VectorSource, XYZ, ImageWMS, TileWMS } from "ol/source";
export default {
data() {
return {
dialogVisible: false,
loading: false,
layers: null,
map: null,
zoom: null,
lightLayer: null,
lightData: [],
};
},
mounted() {},
beforeDestroy() {},
methods: {
// 初始化地图
init() {
let self = this;
this.wsIsRun = true;
self.$nextTick(() => {
self.layers = new ImageLayer({
extent: [911908.3769988124, 110617.87078181792,1596307.9757537232, 420506.5270969288], // 边界,
source: new ImageWMS({
url: "http://127.0.0.1:8000/geoserver/nyc/wms",
// Layers需要指定要显示的图层名
params: {
LAYERS: "nyc:nyc_roads",
exceptions: "application/vnd.ogc.se_inimage",
FORMAT: "image/png",
},
serverType: "geoserver",
}),
});
this.lightLayer = new VectorLayer({
source: new VectorSource({ features: [] }),
});
// 绘制线的图层
this.map = new Map({
layers: [this.layers,this.lightLayer],
target: "xhdMap",
view: new View({
center: [987701, 213364.299370935],
zoom: 12, // 放大级数
maxZoom: 20,
minZoom: 4,
}),
});
});
},
// 画点
drawPoint(data) {
let url = "";
this.lightData = data;
url = "/images/video.png";
this.$nextTick(() => {
data.forEach((item, index) => {
let feature = new Feature({
// geometry 几何图形
geometry: new Point([Number(item.siteX), Number(item.siteY)]),
});
feature.setId(item.id);
let style = new Style({
image: new Icon({
scale: 0.3,
src: url,
anchor: [0.48, 0.52],
}),
});
feature.setStyle(style);
// getSource() 获得目前事件的事件源
this.lightLayer.getSource().addFeature(feature);
});
});
},
},
};
</script>
<style>
#xhdMap {
width: 100%;
height: 80vh;
}
.el-dialog__header {
background-color: #409eff;
}
.el-dialog__title,
.el-dialog__close {
color: #fff !important;
}
.el-dialog__body {
padding: 5px;
}
</style>
<style scoped>
.popup {
position: absolute;
height: 40%;
width: 30%;
right: 10px;
bottom: 10px;
z-index: 999;
color: #fff;
padding: 0 15px;
background: url("~@/assets/home/lamp_bg.png") no-repeat center;
background-size: 100% 100%;
}
.msg_box {
position: relative;
top: calc(50% - 124px);
}
.msg_box div {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 4px;
}
.show_label {
font-size: 16px;
color: #ffffff;
font-family: 时尚中黑;
width: 150px;
}
.popup .msg_box /deep/ .el-input__inner {
display: inline-block;
color: #ffffff;
background: url("~@/assets/home/input_bg.png") no-repeat;
border: none;
background-size: 100% 100%;
width: calc(100% - 5px);
}
.popup .el-select {
width: calc(100% - 10px);
}
.ol-popup-closer {
text-decoration: none;
position: absolute;
top: -13px;
right: 9px;
z-index: 2001;
}
.ol-popup-closer:after {
content: "✖";
font-size: 20px;
}
.xhd .title {
line-height: 40px !important;
text-indent: 0.6rem !important;
}
.online_state {
display: inline-block;
width: 10px;
height: 10px;
margin-right: 6px;
border-radius: 50%;
}
.online_state_red {
background: red;
}
.online_state_green {
background: green;
}
</style>
7、lampMap关键代码
这里绘制map时分两个图层,一个是显示地图线的图层layers,一个是显示摄像头的图层lightlayers
主要是上面点击地图按钮时将所有的摄像头的坐标数据传递给画摄像头位置的图层的实现
drawPoint(data) {
let url = "";
this.lightData = data;
url = "/images/video.png";
this.$nextTick(() => {
data.forEach((item, index) => {
let feature = new Feature({
// geometry 几何图形
geometry: new Point([Number(item.siteX), Number(item.siteY)]),
});
feature.setId(item.id);
let style = new Style({
image: new Icon({
scale: 0.3,
src: url,
anchor: [0.48, 0.52],
}),
});
feature.setStyle(style);
// getSource() 获得目前事件的事件源
this.lightLayer.getSource().addFeature(feature);
});
});
}
8、videoMap.vue代码
<template>
<div class="cont">
<el-dialog
title="选取摄像头位置"
:visible.sync="dialogVisible"
width="70%"
:modal="false"
v-loading="loading"
:before-close="handleClose"
>
<div id="pMap" v-if="dialogVisible"></div>
<p class="showPoint">经纬度:{{ coordinate }}</p>
<div class="dialogfooter">
<el-button type="primary" size="small" @click="submitForm">确 定</el-button>
<el-button size="small" @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import Map from "ol/Map";
import View from "ol/View";
import Feature from "ol/Feature";
import { Point, LineString } from "ol/geom";
import { Circle, Fill, Icon, Stroke, Style, Text } from "ol/style";
import { getVectorContext } from "ol/render";
import { easeOut } from "ol/easing";
import { Image as ImageLayer, Vector as VectorLayer, Tile as TileLayer } from "ol/layer";
import { Cluster, OSM, Vector as VectorSource, XYZ, ImageWMS, TileWMS } from "ol/source";
export default {
data() {
return {
dialogVisible: false,
loading: false,
layers: null,
map: null,
zoom: null,
lightLayer: null,
coordinate: null,
};
},
mounted() {
if (this.coordinate) {
this.drawPoint(this.coordinate);
}
},
watch: {},
methods: {
// 初始化地图
init() {
let self = this;
self.$nextTick(() => {
self.layers = new ImageLayer({
extent: [911908.3769988124, 110617.87078181792,1596307.9757537232, 420506.5270969288], // 边界,
source: new ImageWMS({
url: "http://127.0.0.1:8000/geoserver/nyc/wms",
// Layers需要指定要显示的图层名
params: {
LAYERS: "nyc:nyc_roads",
exceptions: "application/vnd.ogc.se_inimage",
FORMAT: "image/png",
},
serverType: "geoserver",
}),
});
// 摄像头位置所放的图层
this.lightLayer = new VectorLayer({
source: new VectorSource({ features: [] }),
});
// 绘制地图线的图层
this.map = new Map({
layers: [this.layers,this.lightLayer],
target: "pMap",
view: new View({
//地图中心点
center: [987777.93778, 213834.81024],
zoom: 12,
maxZoom: 20,
minZoom: 4,
}),
});
this.onPoint();
});
},
drawPoint(data, isTrue) {
let url = "";
url = "/images/video.png";
this.$nextTick(() => {
if (isTrue) {
this.removePoint();
}
let feature = new Feature({
// geometry 几何图形
geometry: new Point([Number(data[0]), Number(data[1])]),
});
let style = new Style({
image: new Icon({
scale: 0.3,
src: url,
anchor: [0.48, 0.52],
}),
});
feature.setStyle(style);
this.lightLayer.getSource().addFeature(feature);
});
},
removePoint() {
let self = this;
let allPointFeatures = self.lightLayer.getSource().getFeatures();
allPointFeatures.forEach((item) => {
self.lightLayer.getSource().removeFeature(item);
});
},
onPoint() {
// 监听singleclick事件
let _this = this;
this.map.on("singleclick", function (e) {
_this.coordinate = e.coordinate;
debugger
if (_this.coordinate) {
_this.drawPoint(_this.coordinate, true);
}
});
},
handleClose() {
this.dialogVisible = false;
},
submitForm() {
this.$emit("childEvent", this.coordinate);
this.dialogVisible = false;
},
cancel() {
this.dialogVisible = false;
},
},
};
</script>
<style>
#pMap {
width: 100%;
height: 80vh;
}
.el-dialog__header {
background-color: #409eff;
}
.el-dialog__title,
.el-dialog__close {
color: #fff !important;
}
.el-dialog__body {
padding: 5px;
}
.showPoint {
position: absolute;
top: 50px;
color: #070707;
z-index: 1;
left: 50px;
}
.dialogfooter {
position: absolute;
bottom: 10px;
right: 10px;
}
</style>
9、videoMap.vue关键代码
主要是监听地图的单击事件,在单击事件中获取坐标并赋值在左上角显示,然后再进行绘制摄像头图标图层。
onPoint() {
// 监听singleclick事件
let _this = this;
this.map.on("singleclick", function (e) {
_this.coordinate = e.coordinate;
debugger
if (_this.coordinate) {
_this.drawPoint(_this.coordinate, true);
}
});
},
这里的绘制的方法加了一个参数,用来作为页面上是否只留一个图标的限制。
如果传递true则先清理图层在重新绘制,保证只能有一个最新的摄像头位置。
if (isTrue) {
this.removePoint();
}
在removePoint中遍历所有摄像头图层然后删除掉
removePoint() {
let self = this;
let allPointFeatures = self.lightLayer.getSource().getFeatures();
allPointFeatures.forEach((item) => {
self.lightLayer.getSource().removeFeature(item);
});
},
最后是点击确定时
submitForm() {
this.$emit("childEvent", this.coordinate);
this.dialogVisible = false;
},
将选取的坐标值传递给父组件。在父组件通过
parentEvent(data) {
this.form.siteX = data[0];
this.form.siteY = data[1];
this.lightPoint = `${this.form.siteX},${this.form.siteY}`;
this.form.coordinate = this.lightPoint;
},
接受传值并分别赋值给输入框要回显的坐标值以及表单要提交绑定的值。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136174.html