src/Pool/VideoRuleData.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/camera.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/canvas/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/cameraAccess/components/SeparateRules.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/Pool/VideoRuleData.ts
@@ -1,164 +1,160 @@ import { getCameraInfo,getGB28181CameraInfo } from "@/api/camera"; import { getAllPolygon } from "@/api/polygon"; import { getDirDetails, findAllFileByStackId } from "@/api/localVedio"; import { getCameraSceneRule } from '@/api/scene' import { getCameraInfo, getGB28181CameraInfo } from "@/api/camera" import { getAllPolygon } from "@/api/polygon" import { getDirDetails, findAllFileByStackId } from "@/api/localVedio" import { getCameraSceneRule } from "@/api/scene" export default class VideoRuleData { public selectTask: Array<object>; public rules: Array<object>; public polygonData: Array<object>; public cameraId: string = ""; public canvasData: object; public baseImg: string; public cameraName: string; public camearInfo: object; public selectTask: Array<object> public rules: Array<object> public polygonData: Array<object> public cameraId: string = "" public canvasData: object public baseImg: string public cameraName: string public camearInfo: object public loading: boolean; public loading: boolean public analytics: boolean; public dealWay: boolean; public runServerName: string; public analytics: boolean public dealWay: boolean public runServerName: string public resolutionOption: Array<any>; public selectResolution: string; public hasCtrlC: boolean; public resolutionOption: Array<any> public selectResolution: string public hasCtrlC: boolean public gb28181: boolean constructor(id: string,isGB:boolean) { this.loading = false; this.baseImg = ""; this.cameraId = id ? id : ""; this.cameraName = ""; this.selectTask = []; this.polygonData = []; constructor(id: string, isGB: boolean) { this.loading = false this.baseImg = "" this.cameraId = id ? id : "" this.cameraName = "" this.selectTask = [] this.polygonData = [] this.canvasData = { line: [], arrow: [], polygon: [], rect: [] }; } this.camearInfo = {}; this.analytics = false; this.dealWay = false; this.runServerName = ""; this.rules = []; this.camearInfo = {} this.analytics = false this.dealWay = false this.runServerName = "" this.rules = [] if (id && id !== "") { this.update(isGB); this.update(isGB) } this.resolutionOption = [ { value: '1001', label: '1280*720' value: "1001", label: "1280*720" }, { value: '1002', label: '1920*1080' value: "1002", label: "1920*1080" }, { value: '1003', label: '2560*1440' value: "1003", label: "2560*1440" } ] this.selectResolution = '1002' this.selectResolution = "1002" this.hasCtrlC = false this.gb28181 = isGB ? isGB : false } public async update(isGB) { await this.getInfo(isGB); await this.getSceneRule(); await this.getPolygon(); await this.getInfo(isGB) await this.getSceneRule() await this.getPolygon() } public async getInfo(isGB) { // 判断选中的是摄像机还是数据栈 if (this.cameraId.indexOf("stack") === -1) { //处理国标摄像机 if(isGB) { if (isGB) { try { const rsp: any = await getGB28181CameraInfo(this.cameraId); if (rsp.success) { this.cameraName = rsp.data.name ? rsp.data.name : ""; } } catch { this.cameraName = ""; } } else { try { const rsp: any = await getCameraInfo(this.cameraId); if (rsp.success) { this.cameraName = rsp.data.name ? rsp.data.name : ""; } const rsp: any = await getGB28181CameraInfo(this.cameraId) if (rsp.success) { this.cameraName = rsp.data.name ? rsp.data.name : "" } } catch { this.cameraName = ""; this.cameraName = "" } } else { try { const rsp: any = await getCameraInfo(this.cameraId) if (rsp.success) { this.cameraName = rsp.data.name ? rsp.data.name : "" } } catch { this.cameraName = "" } } } else { const rsp: any = await findAllFileByStackId({ stackId: this.cameraId }); const rsp: any = await findAllFileByStackId({ stackId: this.cameraId }) if (rsp.success && rsp.data.dataList.length) { let snapshots = rsp.data.dataList.map(obj => { return obj.snapshot_url; let snapshots = rsp.data.dataList.map((obj) => { return obj.snapshot_url }) this.baseImg = snapshots[0]; this.baseImg = snapshots[0] // console.log(snapshots) } } } public async getPolygon() { this.polygonData = []; this.polygonData = [] const rsp: any = await getAllPolygon({ cameraId: this.cameraId }); const rsp: any = await getAllPolygon({ cameraId: this.cameraId }) if (rsp && rsp.success) { this.canvasData = { line: rsp.data.line, arrow: rsp.data.arrow, polygon: rsp.data.polygon, rect: rsp.data.rect }; } // 只对摄像机数据底图进行处理 if (this.cameraId.indexOf("stack") < 0) { this.baseImg = rsp.data.snapshot_url ? rsp.data.snapshot_url : ""; this.baseImg = rsp.data.snapshot_url ? rsp.data.snapshot_url : "" if (!this.baseImg) { this.loading = true; this.loading = true } else { this.loading = false; this.loading = false } } const newObj = item => { const newObj = (item) => { return { id: item.id, name: item.name, defence_state: item.defence_state }; }; } } let line = rsp.data.line.map(newObj); let polygon = rsp.data.polygon.map(newObj); let rect = rsp.data.rect.map(newObj); let line = rsp.data.line.map(newObj) let polygon = rsp.data.polygon.map(newObj) let rect = rsp.data.rect.map(newObj) if (line.length !== 0 || polygon.length !== 0 || rect.length !== 0) { this.polygonData = [...polygon, ...line, ...rect]; this.polygonData = [...polygon, ...line, ...rect] } } } public async getSceneRule() { const rsp: any = await getCameraSceneRule({ cameraId: this.cameraId }); const rsp: any = await getCameraSceneRule({ cameraId: this.cameraId }) if (rsp && rsp.success) { let rspData = rsp.data.taskList ? rsp.data.taskList : [] this.rules = rsp.data.rules ? rsp.data.rules : [] this.camearInfo = rsp.data.cameraInfo ? rsp.data.cameraInfo : {}; this.camearInfo = rsp.data.cameraInfo ? rsp.data.cameraInfo : {} this.analytics = rsp.data.cameraInfo.run_type !== -1 ? true : false this.dealWay = rsp.data.cameraInfo.run_type === 1 ? true : false this.runServerName = rsp.data.cameraInfo.runServerName src/api/camera.ts
@@ -1,118 +1,119 @@ import request from "@/scripts/httpRequest"; import qs from "qs"; import request from "@/scripts/httpRequest" import qs from "qs" export const createCamera = (camera: any) => { return request({ url: "/data/api-v/camera/add", method: "post", data: camera }); }; }) } export const updateCameraInfo = (camera: any) => { return request({ url: "/data/api-v/camera/update", method: "put", data: camera }); }; }) } export const getCameraInfo = (id: string) => { return request({ url: "/data/api-v/camera/show", method: "get", params: { id: id } }); }; }) } export const getGB28181CameraInfo = (id: string) => { return request({ url: "/data/api-v/gb28181/camera/show", method: "get", params: { cid: id } }); }; }) } export const delCamera = (id: string) => { return request({ url: "/data/api-v/camera/del", method: "get", params: { id: id } }); }; }) } export const saveCameraRules = (query: any) => { return request({ url: "/data/api-v/camera/saveTask", method: "post", data: query }); }; }) } export const deleteCameraRules = (query: any) => { return request({ url: "/data/api-v/cameraTaskArgs/deleteByGroup", method: "get", params: query }); }; }) } export const getLinkRules = (query: any) => { return request({ url: "/data/api-v/cameraTaskArgs/getLinkRulesByCameraIds", method: "post", data: query }); }; }) } export const saveLinkRule = (query: any) => { return request({ url: "/data/api-v/cameraTaskArgs/saveLinkRulesByGroup", method: "post", data: query }); }; }) } export const updateSnapshot = (cameraId: string) => { export const updateSnapshot = (cameraId: string, isGB: boolean) => { let api = isGB ? "/data/api-v/gb28181/camera/updateSnapshotUrl" : "/data/api-v/camera/updateSnapshotUrl" return request({ url: "/data/api-v/camera/updateSnapshotUrl", url: api, method: "get", params: { cameraId: cameraId } }); }; }) } export const updateCameraTask = (params: any) => { return request({ url: "/data/api-v/cameraTask/updateCameraTaskStatus", method: "post", data: params }); }; }) } export const updateRuleDefence = (params: any) => { return request({ url: "/data/api-v/cameraTaskArgs/updateDefenceStateByGroup", method: "post", data: qs.stringify(params) }); }; }) } export const updateAlarmLevel = (params: any) => { return request({ url: "/data/api-v/cameraTask/saveAlarmLevelByGroup", method: "post", data: params }); }; }) } export const addCameraTask = (params: any) => { return request({ url: "/data/api-v/cameraTask/addTask", method: "post", data: qs.stringify(params) }); }; }) } // 云台 export const ptzControl = (params: any) => { @@ -120,8 +121,8 @@ url: "/data/api-v/camera/ptzControl", method: "post", data: params }); }; }) } // //查找所有(多边形)区域 export const findAllPolygons = () => { @@ -158,7 +159,7 @@ //获取摄像机的坐标标定信息 export const getCameraMarks = (query: any) => { return request({ url: '/data/api-v/camera/coord', url: "/data/api-v/camera/coord", method: "get", params: query }) @@ -167,8 +168,8 @@ //更新摄像机的坐标标定信息 export const updateCameraMarks = (data: any) => { return request({ url: '/data/api-v/camera/updateCoord', method: 'post', url: "/data/api-v/camera/updateCoord", method: "post", data }) } @@ -176,8 +177,8 @@ //保存摄像机分组 export const saveCameraGroupInfo = (data: any) => { return request({ url: '/data/api-v/camera/group/save', method: 'post', url: "/data/api-v/camera/group/save", method: "post", data }) } @@ -185,15 +186,14 @@ //查询摄像机分组信息 export const findCameraGroups = () => { return request({ url: '/data/api-v/camera/group/findAll', method: 'get' url: "/data/api-v/camera/group/findAll", method: "get" }) } export const delCameraGroup = (groupId: string) => { return request({ url: '/data/api-v/camera/group/del?groupId=' + groupId, method: 'post' url: "/data/api-v/camera/group/del?groupId=" + groupId, method: "post" }) } src/components/canvas/index.vue
@@ -1,23 +1,21 @@ <template> <div class="s-cavas" :style="{width:canvasWidth+'px',height:canvasHeight+'px'}"> <div class="s-cavas" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"> <canvas ref="myCanvas" :width="canvasWidth" :height="canvasHeight" :style="`background:url(${canvasBg}) center / ${canvasWidth}px ${canvasHeight}px no-repeat; background-size: contain;`" :style=" `background:url(${canvasBg}) center / ${canvasWidth}px ${canvasHeight}px no-repeat; background-size: contain;` " ></canvas> <el-tooltip content="刷新底图" placement="bottom" popper-class="atooltip" v-if="isShowRefresh"> <span class="iconfont icongengxin" @click="refresh"></span> </el-tooltip> <p class="tip" :style="disabled ? `display:block;` : `display:none;`">批量配置方式不允许绘制区域,请选择摄像机进行区域绘制</p> <el-dialog title :visible.sync="visible" width="1150px" append-to-body :before-close="cancelFunc" > <p class="tip" :style="disabled ? `display:block;` : `display:none;`"> 批量配置方式不允许绘制区域,请选择摄像机进行区域绘制 </p> <el-dialog title :visible.sync="visible" width="1150px" append-to-body :before-close="cancelFunc"> <canvas-dialog ref="bigCanvas" :canvasDataToChild="canvasData" @@ -32,8 +30,8 @@ </div> </template> <script> import canvasDialog from "./Dialog"; import { updateSnapshot } from "@/api/camera"; import canvasDialog from "./Dialog" import { updateSnapshot } from "@/api/camera" export default { name: "myCanvas", components: { @@ -66,7 +64,7 @@ }, canvasDataShow: { default: () => { return { line: [], rect: [], arrow: [], polygon: [] }; return { line: [], rect: [], arrow: [], polygon: [] } }, type: Object }, @@ -104,17 +102,16 @@ if (this.snapshot_url) { // 数据栈自动上传处理 if (this.snapshot_url.indexOf("/opt/vasystem") == 0) { return this.snapshot_url.replace("/opt/vasystem", ""); return this.snapshot_url.replace("/opt/vasystem", "") } if (this.sourceType == 2) { return `${this.snapshot_url}`; return `${this.snapshot_url}` } else { return `/httpImage/${this.snapshot_url}`; return `/httpImage/${this.snapshot_url}` } } else { return this.blackImg; return this.blackImg } } }, @@ -133,17 +130,17 @@ c: null, ctx: null, visible: false, baseImg: undefined, baseImg: undefined //showProportion: 1.666 }; } }, watch: { loading: { handler(newVal, oldVal) { // console.log(newVal,'loading') if (newVal) { this.baseImg = ""; this.refresh(); this.baseImg = "" this.refresh() } }, deep: true @@ -151,11 +148,11 @@ canvasDataShow: { handler(newVal, oldVal) { // console.log(newVal, "canvasDataShow newVal"); this.canvasData.line = newVal.line; this.canvasData.rect = newVal.rect; this.canvasData.arrow = newVal.arrow; this.canvasData.polygon = newVal.polygon; this.clickSelect(this.canvasData); this.canvasData.line = newVal.line this.canvasData.rect = newVal.rect this.canvasData.arrow = newVal.arrow this.canvasData.polygon = newVal.polygon this.clickSelect(this.canvasData) }, deep: true } @@ -163,156 +160,139 @@ mounted() { this.$nextTick(() => { // this.c = document.querySelector("#" + this.divId); this.c = this.$refs.myCanvas; this.ctx = this.c.getContext("2d"); this.canvasData = JSON.parse(JSON.stringify(this.canvasDataShow)); this.clickSelect(this.canvasData); }); this.c = this.$refs.myCanvas this.ctx = this.c.getContext("2d") this.canvasData = JSON.parse(JSON.stringify(this.canvasDataShow)) this.clickSelect(this.canvasData) }) }, methods: { // 获取canvas底图 async getCanvasPic() { // this.$emit('changeBaseImg',this.currentCameraId) this.$emit('changeLoading', true) this.$emit("changeLoading", true) if (this.currentCameraId) { let _this = this; await updateSnapshot(this.currentCameraId) .then(res => { let _this = this await updateSnapshot(this.currentCameraId, this.isGB28181) .then((res) => { if (res.data.cameraId === _this.currentCameraId) { this.baseImg = res.data.snapshotUrl; this.$emit('refresh', res.data.snapshotUrl, _this.currentCameraId) this.baseImg = res.data.snapshotUrl this.$emit("refresh", res.data.snapshotUrl, _this.currentCameraId) this.$forceUpdate() this.$notify({ type: "success", message: "底图已刷新" }); }) } }) .catch(err => { .catch((err) => { this.$notify({ type: "error", message: "底图刷新失败" }); }); this.$emit('changeLoading', false) }) }) this.$emit("changeLoading", false) } }, showModal() { // console.log(this.canvasData, "点击绘制的时候传递过去的数据"); this.visible = true; this.visible = true this.$nextTick(() => { // this.$refs.bigCanvas.delCursor = {} }) }, cancelFunc() { this.visible = false; this.$refs.bigCanvas.cancel(); this.visible = false this.$refs.bigCanvas.cancel() // console.log("关闭了"); }, handleOk() { // 判断图形的名字是否重复 // console.log("ok"); this.$refs.bigCanvas.changeType('0') let repeatName = this.isRepeat(); this.$refs.bigCanvas.changeType("0") let repeatName = this.isRepeat() if (repeatName !== "") { this.$notify({ type: "error", message: repeatName + "图形名称重复,请更正!" }); return; }) return } this.$notify({ type: "success", message: "已保存绘制!" }); }) // 每次保存关闭模态窗时都要把模态窗的数据写到父组件里来 this.canvasData = this.$refs.bigCanvas.canvasData; this.canvasData = this.$refs.bigCanvas.canvasData // 顺便甩到更外层去 this.$emit("fromCanvas", this.$refs.bigCanvas.canvasData); this.$emit("fromCanvas", this.$refs.bigCanvas.canvasData) // console.log("你好", this.canvasData); this.clickSelect(this.canvasData); this.visible = false; this.clickSelect(this.canvasData) this.visible = false }, // 回显cavas数据 // 点击选中变色 将当前页面所有路径重绘判断当前鼠标的坐标在哪个图形内 如果不传坐标参数就是回显的方法 clickSelect(e) { this.ctx.clearRect(0, 0, this.c.width, this.c.height); let _this = this; // 集合中遍历需要将this转存一下使用 _this.canvasData.line.forEach(function (v, i) { _this.ctx.strokeStyle = "yellow"; _this.ctx.beginPath(); _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion); _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion); _this.ctx.stroke(); _this.showRemarks( v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name ); _this.c.style.cursor = "default"; this.ctx.clearRect(0, 0, this.c.width, this.c.height) let _this = this // 集合中遍历需要将this转存一下使用 _this.canvasData.line.forEach(function(v, i) { _this.ctx.strokeStyle = "yellow" _this.ctx.beginPath() _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion) _this.ctx.stroke() _this.showRemarks(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name) _this.c.style.cursor = "default" if (e && _this.ctx.isPointInStroke(e.offsetX, e.offsetY)) { // 如果传入了事件坐标,就用isPointInStroke判断一下 // 如果当前环境覆盖了该坐标,就将图形的index放到数组里 // 当鼠标移入之后将当前的模式切换为选中模式 _this.type = "0"; _this.delCursor.type = "1"; _this.delCursor.index = i; _this.type = "0" _this.delCursor.type = "1" _this.delCursor.index = i // 将当前元素标红 _this.ctx.strokeStyle = "red"; _this.ctx.beginPath(); _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion); _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion); _this.ctx.stroke(); _this.showRemarks( v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name ); _this.c.style.cursor = "pointer"; _this.ctx.strokeStyle = "red" _this.ctx.beginPath() _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion) _this.ctx.stroke() _this.showRemarks(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name) _this.c.style.cursor = "pointer" } }); _this.canvasData.rect.forEach(function (v, i) { _this.ctx.strokeStyle = "yellow"; _this.ctx.beginPath(); _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion); _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion); _this.ctx.lineTo(v.location[2].x / _this.showProportion, v.location[2].y / _this.showProportion); _this.ctx.lineTo(v.location[3].x / _this.showProportion, v.location[3].y / _this.showProportion); _this.ctx.lineTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion); _this.ctx.stroke(); _this.showRemarks( v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name ); _this.c.style.cursor = "default"; }) _this.canvasData.rect.forEach(function(v, i) { _this.ctx.strokeStyle = "yellow" _this.ctx.beginPath() _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion) _this.ctx.lineTo(v.location[2].x / _this.showProportion, v.location[2].y / _this.showProportion) _this.ctx.lineTo(v.location[3].x / _this.showProportion, v.location[3].y / _this.showProportion) _this.ctx.lineTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) _this.ctx.stroke() _this.showRemarks(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name) _this.c.style.cursor = "default" if (e && _this.ctx.isPointInPath(e.offsetX, e.offsetY)) { // 如果传入了事件坐标,就用isPointInStroke判断一下 // 当鼠标移入之后将当前的模式切换为选中模式 _this.type = "0"; _this.delCursor.type = "2"; _this.delCursor.index = i; _this.type = "0" _this.delCursor.type = "2" _this.delCursor.index = i // 将当前元素标红 _this.ctx.strokeStyle = "red"; _this.ctx.beginPath(); _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion); _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion); _this.ctx.lineTo(v.location[2].x / _this.showProportion, v.location[2].y / _this.showProportion); _this.ctx.lineTo(v.location[3].x / _this.showProportion, v.location[3].y / _this.showProportion); _this.ctx.lineTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion); _this.ctx.stroke(); _this.showRemarks( v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name ); _this.c.style.cursor = "pointer"; _this.ctx.strokeStyle = "red" _this.ctx.beginPath() _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion) _this.ctx.lineTo(v.location[2].x / _this.showProportion, v.location[2].y / _this.showProportion) _this.ctx.lineTo(v.location[3].x / _this.showProportion, v.location[3].y / _this.showProportion) _this.ctx.lineTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) _this.ctx.stroke() _this.showRemarks(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name) _this.c.style.cursor = "pointer" } }); _this.canvasData.arrow.forEach(function (v, i) { _this.ctx.strokeStyle = "yellow"; }) _this.canvasData.arrow.forEach(function(v, i) { _this.ctx.strokeStyle = "yellow" // _this.ctx.beginPath() // _this.ctx.moveTo(v.location[0].x / 2, v.location[0].y / 2) // _this.ctx.lineTo(v.location[1].x / 2, v.location[1].y / 2) @@ -326,22 +306,18 @@ 20, 30, "yellow" ); // 绘制方法 _this.showRemarks( v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name ); _this.c.style.cursor = "default"; ) // 绘制方法 _this.showRemarks(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name) _this.c.style.cursor = "default" if (e && _this.ctx.isPointInStroke(e.offsetX, e.offsetY)) { // 如果传入了事件坐标,就用isPointInStroke判断一下 // 如果当前环境覆盖了该坐标,就将图形的index放到数组里 // 当鼠标移入之后将当前的模式切换为选中模式 _this.type = "0"; _this.delCursor.type = "4"; _this.delCursor.index = i; _this.type = "0" _this.delCursor.type = "4" _this.delCursor.index = i // 将当前元素标红 _this.ctx.strokeStyle = "red"; _this.ctx.strokeStyle = "red" // _this.ctx.beginPath() // _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) // _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion) @@ -355,66 +331,62 @@ 20, 30, "red" ); // 绘制方法 _this.showRemarks( v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name ); _this.c.style.cursor = "pointer"; ) // 绘制方法 _this.showRemarks(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion, v.name) _this.c.style.cursor = "pointer" } }); _this.canvasData.polygon.forEach(function (v, i) { }) _this.canvasData.polygon.forEach(function(v, i) { if (v.location.length === 0) { return; return } _this.ctx.strokeStyle = "yellow"; _this.ctx.beginPath(); _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion); _this.ctx.strokeStyle = "yellow" _this.ctx.beginPath() _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) for (let i = 1; i < v.location.length; i++) { _this.ctx.lineTo(v.location[i].x / _this.showProportion, v.location[i].y / _this.showProportion); _this.ctx.lineTo(v.location[i].x / _this.showProportion, v.location[i].y / _this.showProportion) } _this.ctx.closePath(); _this.ctx.stroke(); _this.ctx.closePath() _this.ctx.stroke() _this.showRemarks( v.location[v.location.length - 1].x / _this.showProportion, v.location[v.location.length - 1].y / _this.showProportion, v.name ); _this.c.style.cursor = "default"; ) _this.c.style.cursor = "default" if (e && _this.ctx.isPointInPath(e.offsetX, e.offsetY)) { // 如果传入了事件坐标,就用isPointInStroke判断一下 // 如果当前环境覆盖了该坐标,就将图形的index放到数组里 // 当鼠标移入之后将当前的模式切换为选中模式 _this.type = "0"; _this.delCursor.type = "5"; _this.delCursor.index = i; _this.type = "0" _this.delCursor.type = "5" _this.delCursor.index = i // 将当前元素标红 _this.ctx.strokeStyle = "red"; _this.ctx.beginPath(); _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion); _this.ctx.strokeStyle = "red" _this.ctx.beginPath() _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) for (let i = 1; i < v.location.length; i++) { _this.ctx.lineTo(v.location[i].x / _this.showProportion, v.location[i].y / _this.showProportion); _this.ctx.lineTo(v.location[i].x / _this.showProportion, v.location[i].y / _this.showProportion) } _this.ctx.closePath(); _this.ctx.stroke(); _this.ctx.closePath() _this.ctx.stroke() _this.showRemarks( v.location[v.location.length - 1].x / _this.showProportion, v.location[v.location.length - 1].y / _this.showProportion, v.name ); _this.c.style.cursor = "pointer"; ) _this.c.style.cursor = "pointer" } }); }) }, // 回显图形备注 showRemarks(x, y, remarks) { this.ctx.moveTo(x, y - 10); // 因为放大之后是y-20,所以缩小版的为y-10 this.ctx.fillStyle = "green"; // 设置填充颜色为绿色 this.ctx.font = '10px "微软雅黑"'; // 设置字体 this.ctx.textBaseline = "bottom"; // 设置字体底线对齐绘制基线 this.ctx.textAlign = "left"; // 设置字体对齐的方式 this.ctx.fillText(remarks, x, y - 10); // 填充文字 this.ctx.moveTo(x, y - 10) // 因为放大之后是y-20,所以缩小版的为y-10 this.ctx.fillStyle = "green" // 设置填充颜色为绿色 this.ctx.font = '10px "微软雅黑"' // 设置字体 this.ctx.textBaseline = "bottom" // 设置字体底线对齐绘制基线 this.ctx.textAlign = "left" // 设置字体对齐的方式 this.ctx.fillText(remarks, x, y - 10) // 填充文字 }, // 箭头绘制函数 drawArrow(ctx, fromX, fromY, toX, toY, theta, headlen, width, color) { @@ -425,86 +397,86 @@ // headlen:三角斜边长度 // width:箭头线宽度 // color:箭头颜色 theta = typeof theta !== "undefined" ? theta : 30; headlen = typeof theta !== "undefined" ? headlen : 10; width = typeof width !== "undefined" ? width : 1; color = typeof color !== "undefined" ? color : "yellow"; theta = typeof theta !== "undefined" ? theta : 30 headlen = typeof theta !== "undefined" ? headlen : 10 width = typeof width !== "undefined" ? width : 1 color = typeof color !== "undefined" ? color : "yellow" // 计算各角度和对应的P2,P3坐标 let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI; let angle1 = ((angle + theta) * Math.PI) / 180; let angle2 = ((angle - theta) * Math.PI) / 180; let topX = headlen * Math.cos(angle1); let topY = headlen * Math.sin(angle1); let botX = headlen * Math.cos(angle2); let botY = headlen * Math.sin(angle2); let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI let angle1 = ((angle + theta) * Math.PI) / 180 let angle2 = ((angle - theta) * Math.PI) / 180 let topX = headlen * Math.cos(angle1) let topY = headlen * Math.sin(angle1) let botX = headlen * Math.cos(angle2) let botY = headlen * Math.sin(angle2) ctx.save(); ctx.beginPath(); let arrowX = fromX - topX; let arrowY = fromY - topY; ctx.moveTo(arrowX, arrowY); ctx.moveTo(fromX, fromY); ctx.lineTo(toX, toY); arrowX = toX + topX; arrowY = toY + topY; ctx.moveTo(arrowX, arrowY); ctx.lineTo(toX, toY); arrowX = toX + botX; arrowY = toY + botY; ctx.lineTo(arrowX, arrowY); ctx.strokeStyle = color; ctx.lineWidth = width; ctx.stroke(); ctx.restore(); ctx.save() ctx.beginPath() let arrowX = fromX - topX let arrowY = fromY - topY ctx.moveTo(arrowX, arrowY) ctx.moveTo(fromX, fromY) ctx.lineTo(toX, toY) arrowX = toX + topX arrowY = toY + topY ctx.moveTo(arrowX, arrowY) ctx.lineTo(toX, toY) arrowX = toX + botX arrowY = toY + botY ctx.lineTo(arrowX, arrowY) ctx.strokeStyle = color ctx.lineWidth = width ctx.stroke() ctx.restore() }, async refresh() { // console.log(this.loading,'刷新底图',this.snapshot_url) if (!this.currentCameraId) { return false; return false } // await this.$emit('changeLoading', true) this.getCanvasPic(); this.getCanvasPic() }, // 判断图形名称是否重复 isRepeat() { let _this = this; // 集合中遍历需要将this转存一下使用 let nameArray = []; let _this = this // 集合中遍历需要将this转存一下使用 let nameArray = [] for (const v of _this.$refs.bigCanvas.canvasData.line) { for (const item of nameArray) { if (v.name === item) { return v.name; return v.name } } nameArray.push(v.name); nameArray.push(v.name) } for (const v of _this.$refs.bigCanvas.canvasData.arrow) { for (const item of nameArray) { if (v.name === item) { return v.name; return v.name } } nameArray.push(v.name); nameArray.push(v.name) } for (const v of _this.$refs.bigCanvas.canvasData.rect) { for (const item of nameArray) { if (v.name === item) { return v.name; return v.name } } nameArray.push(v.name); nameArray.push(v.name) } for (const v of _this.$refs.bigCanvas.canvasData.polygon) { for (const item of nameArray) { if (v.name === item) { return v.name; return v.name } } nameArray.push(v.name); nameArray.push(v.name) } return ""; return "" } } }; } </script> <style lang="scss" scoped> canvas { src/pages/cameraAccess/components/SeparateRules.vue
@@ -15,11 +15,7 @@ </span> </div> <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'" > <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'"> <span class="label">处理方式</span> <toggle-button :value="Camera.dealWay" @@ -28,29 +24,20 @@ :color="{ checked: '#3D68E1', unchecked: '#FF7733', disabled: '#CCCCCC', disabled: '#CCCCCC' }" :sync="true" @change="changePoll" /> </div> <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'" > <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'"> <span class="label">处理状态: {{ camStatus }}</span> </div> <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'" > <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'"> <span class="label" >分辨率: {{ Camera.camearInfo.resolution_width == 0 || Camera.camearInfo.resolution_height == 0 Camera.camearInfo.resolution_width == 0 || Camera.camearInfo.resolution_height == 0 ? "本机分辨率" : `${Camera.camearInfo.resolution_width} * ${Camera.camearInfo.resolution_height}` }}</span @@ -64,12 +51,7 @@ <div v-if="Camera.analytics" class="flex-box"> <span class="label">算法快速通道</span> <div class="channel flex-box"> <el-tooltip effect="dark" content="复制此摄像机算法规则" placement="bottom" popper-class="atooltip" > <el-tooltip effect="dark" content="复制此摄像机算法规则" placement="bottom" popper-class="atooltip"> <span style="color: #3d68e1; cursor: pointer; font-size: 23px" @click="ctrlC" @@ -79,9 +61,7 @@ <el-tooltip effect="dark" :content=" !TreeDataPool.ctrlCameraId ? '粘贴算法规则' : `粘贴算法规则,来源:${TreeDataPool.ctrlCameraName}` !TreeDataPool.ctrlCameraId ? '粘贴算法规则' : `粘贴算法规则,来源:${TreeDataPool.ctrlCameraName}` " placement="bottom" popper-class="atooltip" @@ -128,19 +108,13 @@ <div class="draw-box"> <div class="draw-box-title"> <b style="font-size: 14px">绘制区域</b> <span class="el-dropdown-link" @click="drawBaseImg" style="position: relative; top: 5px; cursor: pointer" > <span class="el-dropdown-link" @click="drawBaseImg" style="position: relative; top: 5px; cursor: pointer"> <i class="iconfont iconbianji1" style="font-size: 28px"></i> </span> </div> <div style="width: 590px; height: 16px"> <b style="font-size: 14px">{{ Camera.camearInfo.alias ? Camera.camearInfo.alias : Camera.camearInfo.name Camera.camearInfo.alias ? Camera.camearInfo.alias : Camera.camearInfo.name }}</b> </div> <div class="img-box"> @@ -160,6 +134,7 @@ :loading="Camera.loading" :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :isGB28181="Camera.gb28181" @fromCanvas="getCanvasData" @changeLoading="changeLoading" @refresh="refresh" @@ -175,16 +150,9 @@ class="swiper-box-container2" style="width: 100%" > <swiper-slide v-for="(data, index) in swipercanvasData" :key="index" > <swiper-slide v-for="(data, index) in swipercanvasData" :key="index"> <div> <b class="video-title" style="font-size: 14px; margin-top: -10px" >{{ data.name }}</b > <b class="video-title" style="font-size: 14px; margin-top: -10px">{{ data.name }}</b> <polygon-canvas class="cavas" ref="canvas" @@ -208,20 +176,12 @@ </div> </swiper-slide> </swiper> <div class="swiper-local-prev" v-show="swipercanvasData.length > 1" @click="prevClick" > <div class="swiper-local-prev" v-show="swipercanvasData.length > 1" @click="prevClick"> <div class="icon-btn" slot="button-prev"> <i class="iconfont iconzuo"></i> </div> </div> <div class="swiper-local-next" v-show="swipercanvasData.length > 1" @click="nextClick" > <div class="swiper-local-next" v-show="swipercanvasData.length > 1" @click="nextClick"> <div class="icon-btn" slot="button-next"> <i class="iconfont iconyou1"></i> </div> @@ -259,21 +219,21 @@ </template> <script> import { savePolygon } from "@/api/polygon"; import { savePolygon } from "@/api/polygon" import { pasteRules } from "@/api/task"; import { getCameraInfo } from "@/api/camera"; import { saveCameraScene } from "@/api/scene"; import { pasteRules } from "@/api/task" import { getCameraInfo } from "@/api/camera" import { saveCameraScene } from "@/api/scene" import { changeRunType } from "@/api/pollConfig"; import { findAllFileByStackId } from "@/api/localVedio"; import VideoRuleData from "@/Pool/VideoRuleData"; import { changeRunType } from "@/api/pollConfig" import { findAllFileByStackId } from "@/api/localVedio" import VideoRuleData from "@/Pool/VideoRuleData" import TimeSlider from "./TimeSlider"; import polygonCanvas from "@/components/canvas"; import Sysinfo from "@/components/subComponents/SystemInfo"; import SceneRule from "./SceneRule"; import SlideScene from "./scene/SlideScene"; import TimeSlider from "./TimeSlider" import polygonCanvas from "@/components/canvas" import Sysinfo from "@/components/subComponents/SystemInfo" import SceneRule from "./SceneRule" import SlideScene from "./scene/SlideScene" export default { components: { @@ -281,21 +241,19 @@ polygonCanvas, Sysinfo, SceneRule, SlideScene, SlideScene }, directives: { focus: { inserted: function (el) { el.querySelector("input").focus(); }, }, inserted: function(el) { el.querySelector("input").focus() } } }, computed: { cameraType() { return this.TreeDataPool.treeActiveName === "camera" ? "camera" : "dataStack"; }, return this.TreeDataPool.treeActiveName === "camera" ? "camera" : "dataStack" } }, data() { return { @@ -308,15 +266,15 @@ grabCursor: true, pagination: { el: ".swiper-pagination", type: "fraction", type: "fraction" }, navigation: { nextEl: ".swiper-local-next", prevEl: ".swiper-local-prev", }, prevEl: ".swiper-local-prev" } }, tableRuleList: [], camStatus:'', camStatus: "", cameraId: "", showSysInfo: false, showCanvas: true, @@ -326,29 +284,28 @@ swiperIndex: 0, swipercanvasData: [], stackFilesPage: 1, stackFilesSize: 5, }; stackFilesSize: 5 } }, mounted() { this.mockAsync(); this.PollData.statistics(); this.PollData.statistics() }, watch: { "Camera.cameraId": { handler(n, o) { if (n) { if (this.TreeDataPool.treeActiveName == "dataStack") { this.stackFilesPage = 1; this.stackFilesSize = 5; this.stackId = n; this.stackFilesPage = 1 this.stackFilesSize = 5 this.stackId = n if (this.stackId) { this.swipercanvasData = []; this.getStackFiles(); this.swipercanvasData = [] this.getStackFiles() } } } }, }, } } }, methods: { getStatus() { @@ -356,336 +313,296 @@ if (res.success) { switch (res.data.status) { case 0: this.camStatus = "未配规则"; return this.camStatus = "未配规则" return case 1: this.camStatus = "等待轮询处理"; return this.camStatus = "等待轮询处理" return case 2: this.camStatus = "正在执行分析处理"; return this.camStatus = "正在执行分析处理" return case -1: this.camStatus = "其他情况导致未处理"; this.camStatus = "其他情况导致未处理" return case -2: this.camStatus = "故障导致未处理"; this.camStatus = "故障导致未处理" return } } }); }) }, prevClick() { if (this.swiperIndex == 0) { if (this.stackFilesPage > 1) { this.stackFilesPage--; this.getStackFiles(true); this.stackFilesPage-- this.getStackFiles(true) } else { this.$message({ type: "info", message: "当前已是第一页", }); message: "当前已是第一页" }) } } }, nextClick() { if (this.swiperIndex == this.swipercanvasData.length - 1) { this.stackFilesPage++; this.getStackFiles(true); this.stackFilesPage++ this.getStackFiles(true) } }, getStackFiles(onClick = false) { this.getStackFileLoading = true; let _this = this; this.getStackFileLoading = true let _this = this findAllFileByStackId({ name: "", stackId: this.stackId, page: this.stackFilesPage, size: this.stackFilesSize, type: 0, type: 0 }) .then((res) => { if (res && res.success) { if (res.data.dataList.length > 0) { this.swipercanvasData = []; this.swipercanvasData = [] this.swipercanvasData = res.data.dataList.map((item) => { return { name: item.name, stackId: item.stack_id, baseImg: item.type == 2 ? `/files/${item.path.substr( item.path.lastIndexOf("/") + 1 )}` : item.snapshot_url, item.type == 2 ? `/files/${item.path.substr(item.path.lastIndexOf("/") + 1)}` : item.snapshot_url, type: item.type, id: item.id, loading: false, }; }); this.swiperIndex = 0; this.$refs.swiper.swiper.activeIndex = 0; loading: false } }) this.swiperIndex = 0 this.$refs.swiper.swiper.activeIndex = 0 } else { if (onClick) { this.$message({ type: "warning", message: "已无更多数据!", }); message: "已无更多数据!" }) } } } else { this.$message({ type: "error", message: "数据请求失败,请稍后重试!", }); message: "数据请求失败,请稍后重试!" }) } this.getStackFileLoading = false; this.getStackFileLoading = false }) .catch((e) => { this.getStackFileLoading = false; }); this.getStackFileLoading = false }) }, swiperSlideChange() { this.swiperIndex = this.$refs.swiper.swiper.activeIndex; }, mockAsync() { setTimeout(() => { this.mockSceneData = [ { scenename: "name1", id: 1, icon: ["iconrenlianjiance", "icongetijingzhi"], }, { scenename: "name2", id: 2, icon: ["iconchouyan-copy"] }, { scenename: "name3", id: 3, icon: [ "iconrenshukouzhao", "iconchouyan-copy", "iconrenlianjiance", "icongetijingzhi", ], }, { scenename: "name4", id: 4, icon: ["iconchouyan-copy", "iconrenlianjiance", "icongetijingzhi"], }, { scenename: "name5", id: 5, icon: ["icongetijingzhi"] }, { scenename: "name6", id: 6, icon: ["iconrenshukouzhao", "icongetijingzhi"], }, { scenename: "name7", id: 7, icon: ["iconrenlianjiance"] }, ]; }, 3000); this.swiperIndex = this.$refs.swiper.swiper.activeIndex }, drawBaseImg() { if (Array.isArray(this.$refs.canvas)) { if (this.$refs.canvas.length > 0) { this.$refs.canvas[0].showModal(); this.$refs.canvas[0].showModal() } } else { this.$refs.canvas.showModal(); this.$refs.canvas.showModal() } }, getCanvasData(data) { let polyon = { ...data }; polyon.camera_id = this.Camera.cameraId; let polyon = { ...data } polyon.camera_id = this.Camera.cameraId savePolygon(polyon).then((rsp) => { this.Camera.getPolygon(); this.Camera.getPolygon() //this.Camera.getCameraTask(); }); }) }, refresh(url) { this.Camera.baseImg = url; this.Camera.baseImg = url }, // 初始化摄像机信息,父组件调用 async initCameraData(id, type) { this.Camera = new VideoRuleData(); console.log("121212"); console.log(type); this.Camera = new VideoRuleData() if (id && id !== "") { this.loading = false; this.Camera.cameraId = id; this.loading = false this.Camera.cameraId = id this.Camera.gb28181 = type === 1 if (type === 1) { await this.Camera.update(true); await this.Camera.update(true) } else { await this.Camera.update(); await this.Camera.update() } } this.$refs.timeSlider.activeTab = this.VideoManageData.TimeRules[0].id; this.showSysInfo = true; this.$refs.timeSlider.activeTab = this.VideoManageData.TimeRules[0].id this.showSysInfo = true // 判断正在执行实时或者轮询任务 this.PollData.CameraList.forEach((element) => { if (element.id === this.Camera.cameraId) { this.runType = element.run_type; this.runType = element.run_type } }); }) }, saveSceneRule(groupRule) { const payload = { ...groupRule }; payload.cameraIds = [this.Camera.cameraId]; let _this = this; const payload = { ...groupRule } payload.cameraIds = [this.Camera.cameraId] let _this = this saveCameraScene(payload).then((rsp) => { if (rsp && rsp.success) { this.Camera.update(); this.Camera.update() this.$notify({ type: "success", message: "策略保存成功!", }); message: "策略保存成功!" }) //刷新左侧树 _this.$root.$children[0].$children[0].querySearchAsync("camera"); _this.$root.$children[0].$children[0].querySearchAsync("camera") } }); }) }, delScenRule() { this.Camera.update(); this.Camera.update() }, changeLoading(params) { this.loading = params; this.loading = params }, //是否进行视频分析处理 pollEnable(row) { let val = 0; let val = 0 if (row) { if (this.PollData.RealTimeSum < this.PollData.channelTotal) { this.Camera.dealWay = true; val = 1; this.Camera.dealWay = true val = 1 } else { this.Camera.dealWay = false; val = 0; this.Camera.dealWay = false val = 0 } } else { this.Camera.dealWay = false; val = -1; this.Camera.dealWay = false val = -1 } if (this.Camera.cameraId && this.Camera.cameraId !== undefined) { changeRunType({ camera_ids: [this.Camera.cameraId], run_type: val, run_type: val }).then((rsp) => { this.getStatus() if (rsp && rsp.success) { this.$notify({ type: "success", message: "配置成功", }); message: "配置成功" }) } else { this.$notify({ type: "error", message: "配置失败", }); message: "配置失败" }) } this.TreeDataPool.fetchTreeData(); }); this.TreeDataPool.fetchTreeData() }) } this.PollData.statisticTaskInfo(); this.PollData.statisticTaskInfo() }, //实时、轮询切换 changePoll(row) { //判断是新增还是更新 debugger; debugger if (this.Camera.cameraId && this.Camera.cameraId !== undefined) { if (this.PollData.RealTimeSum < this.PollData.channelTotal) { if (row.value) { this.Camera.dealWay = true; this.Camera.dealWay = true } else { this.Camera.dealWay = false; this.Camera.dealWay = false } debugger; debugger changeRunType({ camera_ids: [this.Camera.cameraId], run_type: this.Camera.dealWay ? 1 : 0, run_type: this.Camera.dealWay ? 1 : 0 }).then((rsp) => { if (rsp && rsp.success) { this.$notify({ type: "success", message: "配置成功", }); message: "配置成功" }) } else { this.$notify({ type: "error", message: "配置失败", }); message: "配置失败" }) } }); }) } else { if (this.Camera.dealWay) { this.Camera.dealWay = false; debugger; this.Camera.dealWay = false debugger changeRunType({ camera_ids: [this.Camera.cameraId], run_type: this.Camera.dealWay ? 1 : 0, run_type: this.Camera.dealWay ? 1 : 0 }).then((rsp) => { if (rsp && rsp.success) { this.$notify({ type: "success", message: "配置成功", }); message: "配置成功" }) } else { this.$notify({ type: "error", message: "配置失败", }); message: "配置失败" }) } }); }) } } this.TreeDataPool.fetchTreeData(); this.PollData.statisticTaskInfo(); this.TreeDataPool.fetchTreeData() this.PollData.statisticTaskInfo() } }, //复制 ctrlC() { this.TreeDataPool.ctrlCameraId = this.Camera.cameraId; this.TreeDataPool.ctrlCameraName = this.Camera.cameraName; this.TreeDataPool.ctrlCameraId = this.Camera.cameraId this.TreeDataPool.ctrlCameraName = this.Camera.cameraName this.$notify({ type: "success", message: "复制算法成功!", }); message: "复制算法成功!" }) }, ctrlV() { if (this.Camera.cameraId === this.TreeDataPool.ctrlCameraId) { this.$notify({ type: "warning", message: "不能粘贴本摄像机的算法到本摄像机!", }); return false; message: "不能粘贴本摄像机的算法到本摄像机!" }) return false } pasteRules({ sourceId: this.TreeDataPool.ctrlCameraId, targetIds: [this.Camera.cameraId], targetIds: [this.Camera.cameraId] }) .then((res) => { if (res && res.success) { this.$notify({ type: "success", message: "粘贴算法成功!", }); this.initCameraData(this.Camera.cameraId); message: "粘贴算法成功!" }) this.initCameraData(this.Camera.cameraId) } else { this.$notify({ type: "error", message: "粘贴算法失败!", }); message: "粘贴算法失败!" }) } }) .catch((err) => { this.$notify({ type: "error", message: "粘贴算法失败!", }); }); }, }, }; message: "粘贴算法失败!" }) }) } } } </script> <style lang="scss"> .el-message--info .el-message__content {