<template>
|
<div class="s-separate-rules">
|
<div class="top">
|
<div class="left">
|
<div class="left-top">
|
<!-- 场景及规则 -->
|
<div class="left-top-left">
|
<div class="title">场景</div>
|
<slide-scene :sceneData="Camera.rules"></slide-scene>
|
</div>
|
|
<!-- 算力信息进度条 -->
|
<div class="left-top-middle">
|
<div class="title">算力信息</div>
|
<sysinfo :stroke="20" v-if="showSysInfo" />
|
</div>
|
</div>
|
<div class="left-bottom">
|
<!-- 实时算力信息 -->
|
<HashrateCard
|
class="left-bottom-left"
|
title="实时算力"
|
:total="`${PollData.RealTimeValidCount}`"
|
:ValidCount="`${PollData.RealTimeSum}`"
|
:InValidCount="`${PollData.RealTimeInvalid}`"
|
:RunningCount="`${PollData.RealTimeRun}`"
|
:NoDeal="`${PollData.RealTimeNoDeal}`"
|
></HashrateCard>
|
|
<!-- 轮询算力信息 -->
|
<HashrateCard
|
class="left-bottom-middle"
|
title="轮询算力"
|
:total="`${PollData.PollValidCount}`"
|
:ValidCount="`${PollData.PollSum}`"
|
:InValidCount="`${PollData.PollInvalid}`"
|
:RunningCount="`${PollData.PollRun}`"
|
:NoDeal="`${PollData.PollNoDeal}`"
|
></HashrateCard>
|
</div>
|
</div>
|
|
<!-- 绘制区域canvas -->
|
<div class="right">
|
<div class="title">绘制区域</div>
|
<div class="button draw" @click="drawBaseImg">绘制区域</div>
|
<polygon-canvas
|
class="cavas"
|
ref="canvas"
|
v-if="showCanvas"
|
v-loading="loading"
|
element-loading-text="刷新中,请稍等..."
|
element-loading-background="rgba(0, 0, 0, 0.8)"
|
:isShowDrawArrow="false"
|
:disabled="false"
|
:snapshot_url="Camera.baseImg"
|
:canvasDataShow="Camera.canvasData"
|
:currentCameraId="Camera.cameraId"
|
:loading="Camera.loading"
|
:canvasWidth="canvasWidth"
|
:canvasHeight="canvasHeight"
|
@fromCanvas="getCanvasData"
|
@changeLoading="changeLoading"
|
@refresh="refresh"
|
></polygon-canvas>
|
</div>
|
</div>
|
|
<!-- 独立场景区域 -->
|
<div class="SeparateRules">
|
<div class="title">独立场景</div>
|
<div class="control">
|
<i class="iconfont" @click="showSdkBox = true"></i>
|
<i class="iconfont"></i>
|
<i class="iconfont"></i>
|
</div>
|
|
<div class="content">
|
<!-- 摄像机 -->
|
<CameraBox
|
:camera="Camera"
|
id="separate_camera"
|
@addSeparateRule="addSeparateRule"
|
></CameraBox>
|
|
<!-- 场景区域 -->
|
<div class="RuleArea">
|
<template v-if="SeparateRules.length > 0">
|
<RuleItem
|
v-for="(item, index) in SeparateRules"
|
:key="index"
|
:rule="item"
|
:id="'rule_' + index"
|
@edit="editSeparateRules(item, index)"
|
@addSdk="addSdk('separate', index)"
|
@backToOrigin="backToOrigin($event, item)"
|
></RuleItem>
|
</template>
|
|
<div class="empty" v-else>
|
<img src="/images/hashrate/独立场景空页面.png" alt="" />
|
<div class="des">暂无独立场景</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 添加场景弹窗 -->
|
<AddRuleBox
|
:type="ruleType"
|
:editData="editData"
|
v-if="showAddBox"
|
@close="showAddBox = false"
|
@save="getNewRule"
|
></AddRuleBox>
|
|
<SdkBox v-if="showSdkBox" @close="showSdkBox = false"> </SdkBox>
|
|
<SdkSettingBox
|
v-if="showSdkSettingBox"
|
@close="showSdkSettingBox = false"
|
@getNewSdk="getNewSdk"
|
:Cameras="[Camera]"
|
></SdkSettingBox>
|
|
<!-- 遮罩层 -->
|
<div class="mask" v-if="showAddBox || showSdkSettingBox"></div>
|
|
<div class="bottom" style="display: none">
|
<div class="devide"></div>
|
<div class="bottom-right">
|
<div class="draw-and-time-box">
|
<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"
|
>
|
<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
|
}}</b> -->
|
</div>
|
<div class="img-box">
|
<template v-if="TreeDataPool.treeActiveName == 'camera'">
|
<polygon-canvas
|
class="cavas"
|
ref="canvas"
|
v-if="showCanvas"
|
v-loading="loading"
|
element-loading-text="刷新中,请稍等..."
|
element-loading-background="rgba(0, 0, 0, 0.8)"
|
:isShowDrawArrow="false"
|
:disabled="false"
|
:snapshot_url="Camera.baseImg"
|
:canvasDataShow="Camera.canvasData"
|
:currentCameraId="Camera.cameraId"
|
:loading="Camera.loading"
|
:canvasWidth="canvasWidth"
|
:canvasHeight="canvasHeight"
|
@fromCanvas="getCanvasData"
|
@changeLoading="changeLoading"
|
@refresh="refresh"
|
></polygon-canvas>
|
</template>
|
<template v-else>
|
<div style="width: 100%" v-loading="getStackFileLoading">
|
<swiper
|
ref="swiper"
|
:auto-update="true"
|
:options="canvasSwiperOption"
|
@slideChange="swiperSlideChange"
|
class="swiper-box-container2"
|
style="width: 100%"
|
>
|
<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
|
>
|
<polygon-canvas
|
class="cavas"
|
ref="canvas"
|
v-if="showCanvas"
|
v-loading="loading"
|
element-loading-text="刷新中,请稍等..."
|
element-loading-background="rgba(0, 0, 0, 0.8)"
|
:isShowDrawArrow="false"
|
:isShowRefresh="false"
|
:sourceType="data.type"
|
:disabled="false"
|
:snapshot_url="data.baseImg"
|
:canvasDataShow="Camera.canvasData"
|
:currentCameraId="data.stackId"
|
:loading="data.loading"
|
:canvasWidth="canvasWidth"
|
:canvasHeight="canvasHeight"
|
@fromCanvas="getCanvasData"
|
@changeLoading="changeLoading"
|
></polygon-canvas>
|
</div>
|
</swiper-slide>
|
</swiper>
|
<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="icon-btn" slot="button-next">
|
<i class="iconfont iconyou1"></i>
|
</div>
|
</div>
|
</div>
|
</template>
|
</div>
|
</div>
|
<div style="float: left; width: calc(10% - 90px); height: 100%"></div>
|
<div
|
class="time-box"
|
style="
|
width: calc(90% + 90px - 576px);
|
overflow-x: auto;
|
overflow-y: hidden;
|
"
|
>
|
<p style="text-align: left; padding: 10px; box-sizing: border-box">
|
<b style="font-size: 14px">时间段</b>
|
</p>
|
<time-slider ref="timeSlider" :type="'sep'" />
|
</div>
|
</div>
|
|
<scene-rule
|
:seletedCameras="[Camera]"
|
:tableRuleList="Camera.rules"
|
:onSaveScene="saveSceneRule"
|
@delete-rule="delScenRule"
|
></scene-rule>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import { jsPlumb } from "jsplumb";
|
|
import { savePolygon } from "@/api/polygon";
|
|
import { pasteRules } from "@/api/task";
|
|
import { saveCameraScene, getLinkSceneRule } from "@/api/scene";
|
|
import { changeRunType } from "@/api/pollConfig";
|
import { findAllFileByStackId } from "@/api/localVedio";
|
import VideoRuleData from "@/Pool/VideoRuleData";
|
|
import TimeSlider from "./components/TimeSlider";
|
import polygonCanvas from "@/components/canvas";
|
import Sysinfo from "@/components/subComponents/SystemInfo";
|
import SceneRule from "./components/SceneRule";
|
import SlideScene from "./components/scene/SlideScene";
|
import HashrateCard from "@/views/hashrate/CameraManage/CameraRules/components/HashrateCard";
|
import CameraBox from "@/views/hashrate/CameraManage/CameraRules/components/CameraBox";
|
import RuleItem from "@/views/hashrate/CameraManage/CameraRules/components/RuleItem";
|
import AddRuleBox from "@/views/hashrate/CameraManage/CameraRules/components/AddRuleBox";
|
import SdkBox from "@/views/hashrate/CameraManage/CameraRules/components/SdkBox";
|
import SdkSettingBox from "@/views/hashrate/CameraManage/CameraRules/components/SdkSettingBox";
|
|
export default {
|
components: {
|
TimeSlider,
|
polygonCanvas,
|
Sysinfo,
|
SceneRule,
|
SlideScene,
|
HashrateCard,
|
CameraBox,
|
RuleItem,
|
AddRuleBox,
|
SdkBox,
|
SdkSettingBox,
|
},
|
directives: {
|
focus: {
|
inserted: function (el) {
|
el.querySelector("input").focus();
|
},
|
},
|
},
|
computed: {
|
cameraType() {
|
return this.TreeDataPool.treeActiveName === "camera"
|
? "camera"
|
: "dataStack";
|
},
|
selectedCameraIds() {
|
return this.TreeDataPool.selectedNodes;
|
},
|
},
|
data() {
|
return {
|
loading: false,
|
Camera: new VideoRuleData(),
|
Carmeras: [],
|
runType: -1,
|
getStackFileLoading: false,
|
canvasSwiperOption: {
|
grabCursor: true,
|
pagination: {
|
el: ".swiper-pagination",
|
type: "fraction",
|
},
|
navigation: {
|
nextEl: ".swiper-local-next",
|
prevEl: ".swiper-local-prev",
|
},
|
},
|
plumbIns: null,
|
showAddBox: false,
|
ruleType: "",
|
showSdkBox: false,
|
showSdkSettingBox: false,
|
editData: {},
|
addData: {},
|
// swiperOption: {
|
// slidesPerView: 5,
|
// spaceBetween: 8,
|
// pagination: {
|
// el: ".swiper-pagination",
|
// clickable: true
|
// },
|
// navigation: {
|
// nextEl: ".swiper-next-border",
|
// prevEl: ".swiper-pre-border"
|
// }
|
// },
|
tableRuleList: [],
|
SeparateRules: [], //独立场景
|
cameraId: "",
|
showSysInfo: false,
|
showCanvas: true,
|
canvasWidth: 568,
|
canvasHeight: 320,
|
stackId: "",
|
swiperIndex: 0,
|
swipercanvasData: [],
|
stackFilesPage: 1,
|
stackFilesSize: 5,
|
};
|
},
|
created() {
|
document.querySelector("html").style["min-width"] = "1920px";
|
// 初始化连线变量
|
this.plumbIns = jsPlumb.getInstance();
|
},
|
mounted() {
|
this.PollData.statistics();
|
},
|
destroyed() {
|
document.querySelector("html").style["min-width"] = "1280px";
|
},
|
watch: {
|
"Camera.cameraId": {
|
handler(n, o) {
|
if (n) {
|
if (this.TreeDataPool.treeActiveName == "dataStack") {
|
this.stackFilesPage = 1;
|
this.stackFilesSize = 5;
|
this.stackId = n;
|
if (this.stackId) {
|
this.swipercanvasData = [];
|
this.getStackFiles();
|
}
|
}
|
}
|
},
|
},
|
},
|
methods: {
|
prevClick() {
|
if (this.swiperIndex == 0) {
|
if (this.stackFilesPage > 1) {
|
this.stackFilesPage--;
|
this.getStackFiles(true);
|
} else {
|
this.$message({
|
type: "info",
|
message: "当前已是第一页",
|
});
|
}
|
}
|
},
|
nextClick() {
|
if (this.swiperIndex == this.swipercanvasData.length - 1) {
|
this.stackFilesPage++;
|
this.getStackFiles(true);
|
}
|
},
|
getStackFiles(onClick = false) {
|
this.getStackFileLoading = true;
|
let _this = this;
|
findAllFileByStackId({
|
name: "",
|
stackId: this.stackId,
|
page: this.stackFilesPage,
|
size: this.stackFilesSize,
|
type: 0,
|
})
|
.then((res) => {
|
if (res && res.success) {
|
if (res.data.dataList.length > 0) {
|
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,
|
type: item.type,
|
id: item.id,
|
loading: false,
|
};
|
});
|
this.swiperIndex = 0;
|
this.$refs.swiper.swiper.activeIndex = 0;
|
} else {
|
if (onClick) {
|
this.$message({
|
type: "warning",
|
message: "已无更多数据!",
|
});
|
}
|
}
|
} else {
|
this.$message({
|
type: "error",
|
message: "数据请求失败,请稍后重试!",
|
});
|
}
|
this.getStackFileLoading = false;
|
})
|
.catch((e) => {
|
this.getStackFileLoading = false;
|
});
|
},
|
swiperSlideChange() {
|
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();
|
}
|
} else {
|
this.$refs.canvas.showModal();
|
}
|
},
|
getCanvasData(data) {
|
let polyon = { ...data };
|
polyon.camera_id = this.Camera.cameraId;
|
savePolygon(polyon).then((rsp) => {
|
this.Camera.getPolygon();
|
//this.Camera.getCameraTask();
|
});
|
},
|
refresh(url) {
|
this.Camera.baseImg = url;
|
},
|
// 初始化摄像机信息,父组件调用
|
async initCameraData(id) {
|
//获取独立场景
|
let newCamera = new VideoRuleData();
|
if (id && id !== "") {
|
this.loading = false;
|
newCamera.cameraId = id;
|
await newCamera.update();
|
}
|
|
this.Camera = newCamera;
|
this.SeparateRules = this.Camera.rules;
|
|
this.$nextTick(() => {
|
this.connectLine();
|
});
|
|
this.$refs.timeSlider.activeTab = this.VideoManageData.TimeRules[0].id;
|
this.showSysInfo = true;
|
// 判断正在执行实时或者轮询任务
|
this.PollData.CameraList.forEach((element) => {
|
if (element.id === newCamera.cameraId) {
|
this.runType = element.run_type;
|
}
|
});
|
|
// 获取混合场景
|
this.showRules(id);
|
},
|
|
// 获取混合场景
|
showRules(id) {
|
let rules = [];
|
|
//多选摄像机模式
|
if (this.selectedCameraIds.length && this.TreeDataPool.multiple) {
|
getLinkSceneRule({ cameraIds: this.selectedCameraIds })
|
.then((rsp) => {
|
if (rsp && rsp.success) {
|
rules = rsp.data;
|
// 统一规则编辑的数据结构
|
for (let i = 0; i < rules.length; i++) {
|
rules[i].group_rules = rules[i].rules;
|
}
|
}
|
})
|
.catch(() => {});
|
|
//单选摄像机模式
|
} else if (id) {
|
getLinkSceneRule({ cameraIds: [id] })
|
.then((rsp) => {
|
if (rsp && rsp.success) {
|
rules = rsp.data;
|
// 统一规则编辑的数据结构
|
for (let i = 0; i < rules.length; i++) {
|
rules[i].group_rules = rules[i].rules;
|
}
|
|
this.$set(this.Camera, "rules", this.Camera.rules.concat(rules));
|
}
|
})
|
.catch(() => {});
|
}
|
},
|
|
saveSceneRule(groupRule) {
|
const payload = { ...groupRule };
|
payload.cameraIds = [this.Camera.cameraId];
|
let _this = this;
|
saveCameraScene(payload).then((rsp) => {
|
if (rsp && rsp.success) {
|
this.Camera.update();
|
this.$notify({
|
type: "success",
|
message: "策略保存成功!",
|
});
|
//刷新左侧树
|
|
_this.$root.$children[0].$children[0].querySearchAsync("camera");
|
}
|
});
|
},
|
delScenRule() {
|
this.Camera.update();
|
},
|
changeLoading(params) {
|
this.loading = params;
|
},
|
//是否进行视频分析处理
|
pollEnable(row) {
|
let val = 0;
|
if (row) {
|
if (this.PollData.RealTimeSum < this.PollData.channelTotal) {
|
this.Camera.dealWay = true;
|
val = 1;
|
} else {
|
this.Camera.dealWay = false;
|
val = 0;
|
}
|
} else {
|
this.Camera.dealWay = false;
|
val = -1;
|
}
|
if (this.Camera.cameraId && this.Camera.cameraId !== undefined) {
|
debugger;
|
changeRunType({
|
camera_ids: [this.Camera.cameraId],
|
run_type: val,
|
}).then((rsp) => {
|
if (rsp && rsp.success) {
|
this.$notify({
|
type: "success",
|
message: "配置成功",
|
});
|
} else {
|
this.$notify({
|
type: "error",
|
message: "配置失败",
|
});
|
}
|
this.TreeDataPool.fetchTreeData();
|
});
|
}
|
this.PollData.statisticTaskInfo();
|
},
|
//实时、轮询切换
|
changePoll(row) {
|
//判断是新增还是更新
|
debugger;
|
if (this.Camera.cameraId && this.Camera.cameraId !== undefined) {
|
if (this.PollData.RealTimeSum < this.PollData.channelTotal) {
|
if (row.value) {
|
this.Camera.dealWay = true;
|
} else {
|
this.Camera.dealWay = false;
|
}
|
debugger;
|
changeRunType({
|
camera_ids: [this.Camera.cameraId],
|
run_type: this.Camera.dealWay ? 1 : 0,
|
}).then((rsp) => {
|
if (rsp && rsp.success) {
|
this.$notify({
|
type: "success",
|
message: "配置成功",
|
});
|
} else {
|
this.$notify({
|
type: "error",
|
message: "配置失败",
|
});
|
}
|
});
|
} else {
|
if (this.Camera.dealWay) {
|
this.Camera.dealWay = false;
|
debugger;
|
changeRunType({
|
camera_ids: [this.Camera.cameraId],
|
run_type: this.Camera.dealWay ? 1 : 0,
|
}).then((rsp) => {
|
if (rsp && rsp.success) {
|
this.$notify({
|
type: "success",
|
message: "配置成功",
|
});
|
} else {
|
this.$notify({
|
type: "error",
|
message: "配置失败",
|
});
|
}
|
});
|
}
|
}
|
this.TreeDataPool.fetchTreeData();
|
this.PollData.statisticTaskInfo();
|
}
|
},
|
//复制
|
ctrlC() {
|
this.TreeDataPool.ctrlCameraId = this.Camera.cameraId;
|
this.TreeDataPool.ctrlCameraName = this.Camera.cameraName;
|
this.$notify({
|
type: "success",
|
message: "复制算法成功!",
|
});
|
},
|
ctrlV() {
|
if (this.Camera.cameraId === this.TreeDataPool.ctrlCameraId) {
|
this.$notify({
|
type: "warning",
|
message: "不能粘贴本摄像机的算法到本摄像机!",
|
});
|
return false;
|
}
|
pasteRules({
|
sourceId: this.TreeDataPool.ctrlCameraId,
|
targetIds: [this.Camera.cameraId],
|
})
|
.then((res) => {
|
if (res && res.success) {
|
this.$notify({
|
type: "success",
|
message: "粘贴算法成功!",
|
});
|
this.initCameraData(this.Camera.cameraId);
|
} else {
|
this.$notify({
|
type: "error",
|
message: "粘贴算法失败!",
|
});
|
}
|
})
|
.catch((err) => {
|
this.$notify({
|
type: "error",
|
message: "粘贴算法失败!",
|
});
|
});
|
},
|
|
//连接独立场景连线
|
connectLine() {
|
//清除之前的连线
|
this.plumbIns.deleteEveryConnection();
|
|
for (let index = 0; index < this.SeparateRules.length; index++) {
|
this.plumbIns.connect({
|
// 对应上述基本概念
|
source: "separate_camera",
|
target: `rule_${index}`,
|
anchor: ["Left", "Right"],
|
connector: index === 0 ? ["Straight"] : ["Bezier", { curviness: 60 }],
|
endpoints: [["Blank", { cssClass: "sourcePoint" }], "Blank"],
|
overlays: [["Arrow", { width: 8, length: 8, location: 1 }]], // overlay
|
// 添加样式
|
paintStyle: { stroke: "#0065FF", strokeWidth: 2 }, // connector
|
endpointStyle: {
|
fill: "#fff",
|
outlineStroke: "#0065FF",
|
}, // endpoint
|
});
|
}
|
},
|
|
//添加独立场景
|
addSeparateRule() {
|
this.ruleType = "separate";
|
this.showAddBox = true;
|
},
|
|
//回填新的独立场景
|
getNewRule(newRule) {
|
if (newRule.action === "add") {
|
this.SeparateRules.push(newRule.data);
|
this.showAddBox = false;
|
this.$nextTick(() => {
|
this.connectLine();
|
});
|
} else if (newRule.action === "edit") {
|
this.SeparateRules[newRule.data.index].alarm_level =
|
newRule.data.alarm_level;
|
this.SeparateRules[newRule.data.index].scene_name =
|
newRule.data.scene_name;
|
this.SeparateRules[newRule.data.index].desc = newRule.data.desc;
|
this.SeparateRules[newRule.data.index].template_id =
|
newRule.data.template_id;
|
this.SeparateRules[newRule.data.index].time_rule_id =
|
newRule.data.time_rule_id;
|
this.SeparateRules[newRule.data.index].voiceId = newRule.data.voiceId;
|
this.showAddBox = false;
|
}
|
},
|
|
//修改独立场景
|
editSeparateRules(item, index) {
|
this.editData = {
|
type: "separate",
|
rule: item,
|
index,
|
};
|
this.addSeparateRule();
|
},
|
|
//添加算法
|
addSdk(type, index) {
|
this.addData = {
|
type,
|
index,
|
};
|
this.showSdkBox = false;
|
this.showSdkSettingBox = true;
|
},
|
|
//添加算法回调
|
getNewSdk(newRule) {
|
if (this.addData.type === "separate") {
|
if (this.SeparateRules[this.addData.index].rules.length > 0) {
|
newRule.rule_with_pre = "&&";
|
}
|
this.SeparateRules[this.addData.index].rules.push(newRule);
|
}
|
this.addData = {};
|
},
|
|
backToOrigin(e, item) {
|
e = item;
|
console.log(e);
|
this.$forceUpdate();
|
},
|
},
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.s-separate-rules {
|
overflow-x: auto;
|
box-sizing: border-box;
|
padding: 13px 0 20px;
|
|
.title {
|
box-sizing: border-box;
|
margin-bottom: 20px;
|
padding-left: 10px;
|
border-left: 4px solid #0065ff;
|
font-size: 16px;
|
font-weight: 700;
|
}
|
|
.top {
|
display: flex;
|
|
.left-top {
|
display: flex;
|
margin-bottom: 24px;
|
|
.left-top-left {
|
box-sizing: border-box;
|
padding: 20px;
|
width: 608px;
|
height: 232px;
|
margin-right: 24px;
|
background-color: #fff;
|
}
|
|
.left-top-middle {
|
box-sizing: border-box;
|
padding: 20px;
|
flex: 1;
|
width: 292px;
|
height: 232px;
|
background-color: #fff;
|
|
.chart ::v-deep {
|
.row {
|
margin-bottom: 20px;
|
}
|
}
|
}
|
}
|
|
.left-bottom {
|
display: flex;
|
|
.left-bottom-left {
|
width: 450px;
|
height: 146px;
|
box-sizing: border-box;
|
margin-right: 24px;
|
background-color: #fff;
|
}
|
|
.left-bottom-middle {
|
flex: 1;
|
background-color: #fff;
|
}
|
}
|
|
.right {
|
position: relative;
|
box-sizing: border-box;
|
margin-left: 24px;
|
padding: 20px;
|
background: #fff;
|
flex: 1;
|
|
.draw {
|
position: absolute;
|
top: 20px;
|
right: 20px;
|
width: 64px;
|
height: 24px;
|
color: #fff;
|
text-align: center;
|
line-height: 24px;
|
font-size: 12px;
|
background-color: #0065ff;
|
}
|
}
|
}
|
|
.SeparateRules {
|
position: relative;
|
box-sizing: border-box;
|
padding: 20px;
|
margin: 24px 0;
|
background: rgba($color: #fff, $alpha: 0.9);
|
|
.control {
|
position: absolute;
|
display: flex;
|
justify-content: end;
|
top: 20px;
|
right: 20px;
|
|
i {
|
margin-left: 10px;
|
font-size: 24px;
|
color: #0065ff;
|
cursor: pointer;
|
|
&:hover {
|
color: rgb(0, 51, 255);
|
}
|
}
|
}
|
|
.content {
|
display: flex;
|
margin-top: 10px;
|
|
.empty {
|
margin-left: 60px;
|
width: 1220px;
|
height: 198px;
|
border: 1px solid #c0c5cc;
|
border-radius: 5px;
|
text-align: center;
|
background: #f0f5fa;
|
img {
|
margin-top: 14px;
|
width: 250px;
|
height: 150px;
|
}
|
|
.des {
|
margin-top: 2px;
|
color: #666;
|
}
|
}
|
}
|
|
::v-deep .sourcePoint {
|
margin-top: -4px;
|
margin-left: -6px;
|
width: 4px !important;
|
height: 4px !important;
|
border-radius: 50%;
|
border: 2px solid #0065ff;
|
}
|
}
|
|
.mask {
|
position: absolute;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
background: #000000;
|
opacity: 0.2;
|
z-index: 1;
|
}
|
}
|
</style>
|