feat:添加现场大屏整体框架,完成现场大屏承包商项目信息、AI报警情况以及特殊作业情况的静态页面绘画
This commit is contained in:
parent
809e3a1f34
commit
c908c79e55
31
package-lock.json
generated
31
package-lock.json
generated
@ -56,6 +56,7 @@
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.0.1",
|
||||
"@commitlint/config-conventional": "^17.0.0",
|
||||
"@types/echarts": "^4.9.22",
|
||||
"@types/node": "^17.0.31",
|
||||
"@types/sortablejs": "^1.15.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.22.0",
|
||||
@ -3186,6 +3187,15 @@
|
||||
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.4.tgz",
|
||||
"integrity": "sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ=="
|
||||
},
|
||||
"node_modules/@types/echarts": {
|
||||
"version": "4.9.22",
|
||||
"resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/echarts/-/echarts-4.9.22.tgz",
|
||||
"integrity": "sha512-7Fo6XdWpoi8jxkwP7BARUOM7riq8bMhmsCtSG8gzUcJmFhLo387tihoBYS/y5j7jl3PENT5RxeWZdN9RiwO7HQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/zrender": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "8.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.40.0.tgz",
|
||||
@ -3287,6 +3297,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
|
||||
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
|
||||
},
|
||||
"node_modules/@types/zrender": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/zrender/-/zrender-4.0.6.tgz",
|
||||
"integrity": "sha512-1jZ9bJn2BsfmYFPBHtl5o3uV+ILejAtGrDcYSpT4qaVKEI/0YY+arw3XHU04Ebd8Nca3SQ7uNcLaqiL+tTFVMg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.59.7",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz",
|
||||
@ -18822,6 +18838,15 @@
|
||||
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.4.tgz",
|
||||
"integrity": "sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ=="
|
||||
},
|
||||
"@types/echarts": {
|
||||
"version": "4.9.22",
|
||||
"resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/echarts/-/echarts-4.9.22.tgz",
|
||||
"integrity": "sha512-7Fo6XdWpoi8jxkwP7BARUOM7riq8bMhmsCtSG8gzUcJmFhLo387tihoBYS/y5j7jl3PENT5RxeWZdN9RiwO7HQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/zrender": "*"
|
||||
}
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "8.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.40.0.tgz",
|
||||
@ -18923,6 +18948,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
|
||||
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
|
||||
},
|
||||
"@types/zrender": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://mirrors.huaweicloud.com/repository/npm/@types/zrender/-/zrender-4.0.6.tgz",
|
||||
"integrity": "sha512-1jZ9bJn2BsfmYFPBHtl5o3uV+ILejAtGrDcYSpT4qaVKEI/0YY+arw3XHU04Ebd8Nca3SQ7uNcLaqiL+tTFVMg==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "5.59.7",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz",
|
||||
|
||||
@ -68,6 +68,7 @@
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.0.1",
|
||||
"@commitlint/config-conventional": "^17.0.0",
|
||||
"@types/echarts": "^4.9.22",
|
||||
"@types/node": "^17.0.31",
|
||||
"@types/sortablejs": "^1.15.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.22.0",
|
||||
|
||||
@ -28,6 +28,7 @@ export const BASE_IMAGE_URL = import.meta.env.VITE_BASE_IMAGE_URL;
|
||||
// export const COMPANY: string = "zsbf"; //中水北方
|
||||
// export const COMPANY: string = "as"; //鞍山项目
|
||||
// export const COMPANY: string = "agjt"; //鞍钢集团
|
||||
export const COMPANY: string = "agjtLive"; //鞍钢集团现场大屏
|
||||
// export const COMPANY: string = "agjtCommand"; //鞍钢集团指挥部大屏
|
||||
// export const COMPANY: string = "slx"; //苏立信项目
|
||||
// export const COMPANY: string = "hfqc"; //合肥启程项目
|
||||
@ -37,4 +38,4 @@ export const BASE_IMAGE_URL = import.meta.env.VITE_BASE_IMAGE_URL;
|
||||
// export const COMPANY: string = "phmw"; //鄱湖美湾医疗、医美产业集群项目 (需要去src\routers\modules\staticRouter.ts更换首页)
|
||||
// export const COMPANY: string = "xjnb"; // 新建宁波项目
|
||||
// export const COMPANY: string = "ahsa"; // 安徽水安项目
|
||||
export const COMPANY: string = "zkax"; // 中科安信项目
|
||||
// export const COMPANY: string = "zkax"; // 中科安信项目
|
||||
|
||||
@ -1321,7 +1321,7 @@ export const ZHZRFMenu: Array<any> = [
|
||||
},
|
||||
|
||||
]; //中海·臻如府
|
||||
// 中科安信大屏
|
||||
|
||||
export const ZKAXMenu: Array<any> = [
|
||||
{
|
||||
moduleName: "首页概览",
|
||||
@ -1343,4 +1343,4 @@ export const ZKAXMenu: Array<any> = [
|
||||
moduleName: "进度计划",
|
||||
modulePath: "/schedulePlan"
|
||||
}
|
||||
];
|
||||
]; //中科安信大屏
|
||||
@ -24,8 +24,8 @@ export const staticRouter: RouteRecordRaw[] = [
|
||||
{
|
||||
path: "/large",
|
||||
name: "大屏",
|
||||
component: () => import("@/views/sevenLargeScreen/indexL.vue"), //七参数标准版
|
||||
// component: () => import("@/views/commandScreen/indexCommand.vue"), //指挥部大屏
|
||||
// component: () => import("@/views/sevenLargeScreen/indexL.vue"), //七参数标准版
|
||||
component: () => import("@/views/commandScreen/indexCommand.vue"), //指挥部大屏
|
||||
// component: () => import("@/views/sevenLargeScreen/indexL_syhy.vue"), // 只有一级路由(盘锦、嘉兴、鄱湖美湾医疗项目需切换至该首页)
|
||||
children: [
|
||||
{
|
||||
@ -269,6 +269,11 @@ export const staticRouter: RouteRecordRaw[] = [
|
||||
path: "/commandScreen",
|
||||
name: "指挥部大屏",
|
||||
component: () => import("@/views/commandScreen/commandCenter/index.vue")
|
||||
},
|
||||
{
|
||||
path: "/liveScreen",
|
||||
name: "现场大屏",
|
||||
component: () => import("@/views/commandScreen/liveScreen/index.vue")
|
||||
}
|
||||
],
|
||||
meta: {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
<div class="header">
|
||||
<span class="projectTitle">
|
||||
<p v-if="COMPANY === 'agjtCommand'">指挥部大屏</p>
|
||||
<p v-if="COMPANY === 'agjtLive'">现场大屏</p>
|
||||
</span>
|
||||
<div class="leftIcon">
|
||||
<div class="info">数字化项目监管平台</div>
|
||||
@ -69,6 +70,13 @@ let agjtCommandList = ref([
|
||||
modulePath: "/commandScreen"
|
||||
}
|
||||
]);
|
||||
// 鞍山现场大屏
|
||||
let agjtLiveList = ref([
|
||||
{
|
||||
moduleName: "现场大屏",
|
||||
modulePath: "/liveScreen"
|
||||
}
|
||||
]);
|
||||
|
||||
const itemList = ref([]);
|
||||
const activeTab = ref(0);
|
||||
@ -100,6 +108,10 @@ onMounted(async () => {
|
||||
// menuList.value = AGJTCommandMenu;
|
||||
menuList.value = agjtCommandList.value;
|
||||
}
|
||||
if (COMPANY === "agjtLive") {
|
||||
// menuList.value = AGJTCommandMenu;
|
||||
menuList.value = agjtLiveList.value;
|
||||
}
|
||||
//这里是跳转过来后免登录的操作,接收token 登录 懂了
|
||||
//数据看板跳转免登录
|
||||
if (window.location.href.indexOf("token") != -1) {
|
||||
@ -194,6 +206,9 @@ function jumpBgd() {
|
||||
if(COMPANY === "agjtCommand"){
|
||||
window.location.replace("http://47.93.215.234:9809" + "/#/login?token=" + store.token);
|
||||
}
|
||||
if(COMPANY === "agjtLive"){
|
||||
window.location.replace("http://47.93.215.234:9809" + "/#/login?token=" + store.token);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
40
src/views/commandScreen/liveScreen/centerBottomLeft.vue
Normal file
40
src/views/commandScreen/liveScreen/centerBottomLeft.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="centerBottomLeft">
|
||||
<Card title="劳务实名制">
|
||||
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Card from "@/components/card.vue";
|
||||
import { ref, watch, onMounted } from "vue";
|
||||
import { getStageOption } from "@/api/modules/projectOverview";
|
||||
import { GlobalStore } from "@/stores";
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.centerBottomLeft {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
::v-deep .h-card .content {
|
||||
height: 80%;
|
||||
margin-top: 4%;
|
||||
}
|
||||
.notoDta {
|
||||
bottom: 10%;
|
||||
width: 20%;
|
||||
left: 35%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
img {
|
||||
width: 40%;
|
||||
}
|
||||
div {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
40
src/views/commandScreen/liveScreen/centerBottomRight.vue
Normal file
40
src/views/commandScreen/liveScreen/centerBottomRight.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="centerBottomRight">
|
||||
<Card title="质量待办">
|
||||
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Card from "@/components/card.vue";
|
||||
import { ref, watch, onMounted } from "vue";
|
||||
import { getStageOption } from "@/api/modules/projectOverview";
|
||||
import { GlobalStore } from "@/stores";
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.centerBottomRight {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
::v-deep .h-card .content {
|
||||
height: 80%;
|
||||
margin-top: 4%;
|
||||
}
|
||||
.notoDta {
|
||||
bottom: 10%;
|
||||
width: 20%;
|
||||
left: 35%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
img {
|
||||
width: 40%;
|
||||
}
|
||||
div {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
374
src/views/commandScreen/liveScreen/centerTop.vue
Normal file
374
src/views/commandScreen/liveScreen/centerTop.vue
Normal file
@ -0,0 +1,374 @@
|
||||
<template>
|
||||
<div class="centerTop">
|
||||
<Card title="安全教育">
|
||||
<div class="top-tab" v-if="COMPANY === 'agjt'">
|
||||
<div
|
||||
class="tab-box"
|
||||
:style="boxStyle(item)"
|
||||
v-for="(item, index) in topText2"
|
||||
:key="item.id"
|
||||
@click="activeBtn(item, index)"
|
||||
>
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-tab" v-else>
|
||||
<div
|
||||
class="tab-box"
|
||||
:style="boxStyle(item)"
|
||||
v-for="(item, index) in topText"
|
||||
:key="item.id"
|
||||
@click="activeBtn(item, index)"
|
||||
>
|
||||
{{ item.title }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="href-content" v-if="showVideo == 1">
|
||||
<el-carousel indicator-position="none" height="450px" style="width: 76%;">
|
||||
<el-carousel-item v-for="(item, index) in videoList" :key="item.id">
|
||||
<ckplayerComp
|
||||
:name="index"
|
||||
:poster="''"
|
||||
:deviceIp="`http://${item.account}:${item.password}`"
|
||||
:videoUrls="item.serialNumber"
|
||||
:autoPlay="true"
|
||||
></ckplayerComp>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
<div class="videoBox" v-if="showVideo == 2" @mouseenter="showChangeVideo = true" @mouseleave="showChangeVideo = false">
|
||||
<el-upload
|
||||
:action="BASEURL + '/upload/image'"
|
||||
:on-success="file => handleSuccessTwo(file, 1)"
|
||||
:on-error="file => handleError(file, 1)"
|
||||
:beforeUpload="file => handleBeforeUploadVideo(file, 1)"
|
||||
name="files"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<!-- 更换视频 -->
|
||||
<span class="change-video" v-if="showChangeVideo">更换视频</span>
|
||||
</el-upload>
|
||||
<video :src="BASEURL + '/image/' + projectData.videoUrl" class="videos" autoplay controls loop></video>
|
||||
</div>
|
||||
<div class="imgBox" v-if="showVideo == 3">
|
||||
<div class="imgs" @mouseenter="showChangeImg = true" @mouseleave="showChangeImg = false">
|
||||
<el-upload
|
||||
:action="BASEURL + '/upload/image'"
|
||||
:on-success="file => handleSuccess(file, 1)"
|
||||
:on-error="file => handleError(file, 1)"
|
||||
:beforeUpload="file => handleBeforeUploadPic(file, 1)"
|
||||
name="files"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<!-- 更换图片 -->
|
||||
<span class="change-video" v-if="showChangeImg">更换图片</span>
|
||||
</el-upload>
|
||||
<img :src="BASEURL + '/image/' + picUrl" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Card from "@/components/card.vue";
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
import { editProjectInfo, eidtProjectShowConfig, queryBySnData } from "@/api/modules/projectOverview";
|
||||
import { selectLiveVideoListApi } from "@/api/modules/video";
|
||||
import ckplayerComp from "./ckplayerComp.vue";
|
||||
import { COMPANY } from "@/config/config";
|
||||
|
||||
const store = GlobalStore();
|
||||
const videoList = ref([] as any);
|
||||
// ts
|
||||
type Props = {
|
||||
projectData?: any; // 传入项目信息
|
||||
};
|
||||
// withDefaults 定义默认值(传入的数据类型同默认值)
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
projectData: {}
|
||||
});
|
||||
// 项目信息
|
||||
const projectData = ref({} as any);
|
||||
|
||||
watch(
|
||||
() => props.projectData,
|
||||
newVal => {
|
||||
if (newVal) {
|
||||
// props.xData = newVal;
|
||||
projectData.value = newVal;
|
||||
}
|
||||
}
|
||||
);
|
||||
//效果图
|
||||
const picUrl = ref("" as any);
|
||||
|
||||
const BASEURL = import.meta.env.VITE_API_URL;
|
||||
// 显示视频
|
||||
const showVideo = ref(1 as any);
|
||||
|
||||
// 显示更换图片
|
||||
const showChangeImg = ref(false as any);
|
||||
|
||||
// 显示更换视频
|
||||
const showChangeVideo = ref(false as any);
|
||||
|
||||
let topText2 = ref([
|
||||
{ id: 1, title: "现场视频", isActive: true },
|
||||
{ id: 2, title: "宣传视频", isActive: false },
|
||||
{ id: 3, title: "效果图", isActive: false }
|
||||
]);
|
||||
let topText = ref([
|
||||
// { id: 1, title: "现场视频", isActive: true },
|
||||
{ id: 2, title: "宣传视频", isActive: true },
|
||||
{ id: 3, title: "效果图", isActive: false }
|
||||
]);
|
||||
const getVideoList = async (showLoading: boolean) => {
|
||||
let res: any = await selectLiveVideoListApi({
|
||||
projectSn: store.sn
|
||||
},showLoading);
|
||||
if(res.result && res.result.extend1){
|
||||
videoList.value = JSON.parse(res.result.extend1).result.videoList;
|
||||
// 为了解决视频播放器渲染,第二个总是会默认显示一半,我动态设置样式让视图刷新,只要设置百分百就有问题,所以只能使用此方法
|
||||
setTimeout(() => {
|
||||
// 获取所有的 video 元素
|
||||
var videos = document.querySelectorAll(".href-content video")
|
||||
// var videos = document.getElementsByTagName("video");
|
||||
// 遍历所有的 video 元素
|
||||
for (var i = 0; i < videos.length; i++) {
|
||||
// 修改视频元素的样式
|
||||
videos[i].style.width = "99.9%";
|
||||
videos[i].style.height = "99.9%";
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
|
||||
function boxStyle(item: any) {
|
||||
if (item.isActive) {
|
||||
let choiseStyle = {
|
||||
color: "#fff"
|
||||
};
|
||||
return choiseStyle;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
let tabIndex = ref(1 as any);
|
||||
function activeBtn(item: any) {
|
||||
let currentState = item.isActive;
|
||||
if (!currentState) {
|
||||
topText.value.forEach(el => {
|
||||
el.isActive = false;
|
||||
});
|
||||
item.isActive = !currentState;
|
||||
tabIndex.value = item.id;
|
||||
}
|
||||
showVideo.value = item.id;
|
||||
}
|
||||
|
||||
const uploadFail = () => {
|
||||
ElMessage({
|
||||
showClose: true,
|
||||
message: "上传失败,请重试",
|
||||
type: "warning"
|
||||
});
|
||||
};
|
||||
|
||||
const fileTypeFail = (text: any) => {
|
||||
ElMessage({
|
||||
showClose: true,
|
||||
message: text,
|
||||
type: "warning"
|
||||
});
|
||||
};
|
||||
|
||||
const uploadSuccess = () => {
|
||||
ElMessage({
|
||||
showClose: true,
|
||||
message: "上传成功",
|
||||
type: "success"
|
||||
});
|
||||
};
|
||||
|
||||
// 视频文件上传 之前
|
||||
function handleBeforeUploadVideo(file: any) {
|
||||
let fileType = file.type.split("/")[0];
|
||||
if (fileType == "video") {
|
||||
return true;
|
||||
} else {
|
||||
fileTypeFail("请选择正确的视频文件"); //"请选择正确的文件"
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 图片文件上传 之前
|
||||
function handleBeforeUploadPic(file: any) {
|
||||
let fileType = file.type.split("/")[0];
|
||||
if (fileType == "image") {
|
||||
return true;
|
||||
} else {
|
||||
fileTypeFail("请选择正确的图片文件"); //"请选择正确的文件"
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//上传失败
|
||||
function handleError(file: any) {
|
||||
uploadFail(); //"上传失败,请重试"
|
||||
}
|
||||
// 效果图上传成功
|
||||
function handleSuccess(file: any) {
|
||||
if (file.code == 200 || file.status == "SUCCESS") {
|
||||
let url = file.data[0].imageUrl;
|
||||
saveEffectData(url);
|
||||
}
|
||||
}
|
||||
|
||||
// 视频上传成功
|
||||
function handleSuccessTwo(file: any) {
|
||||
if (file.code == 200 || file.status == "SUCCESS") {
|
||||
let url = file.data[0].imageUrl;
|
||||
// this.imgUrl = url;
|
||||
saveOrDeleteVideo(url);
|
||||
}
|
||||
}
|
||||
//效果图 保存
|
||||
function saveEffectData(url: any) {
|
||||
// let configValue = JSON.stringify(url);
|
||||
let data = {
|
||||
projectSn: store.sn,
|
||||
showType: 3,
|
||||
showTitle: "效果图", //'效果图'
|
||||
configValue: url
|
||||
};
|
||||
eidtProjectShowConfig(data).then((res: any) => {
|
||||
if (res.code == 200) {
|
||||
getQueryBySnData();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 查询效果图
|
||||
function getQueryBySnData() {
|
||||
queryBySnData({
|
||||
projectSn: store.sn,
|
||||
showType: 3
|
||||
}).then((res: any) => {
|
||||
if (res.result) {
|
||||
picUrl.value = res.result.configValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
// //保存或删除宣传视频
|
||||
function saveOrDeleteVideo(url) {
|
||||
editProjectInfo({
|
||||
projectSn: store.sn,
|
||||
videoUrl: url
|
||||
}).then(res => {
|
||||
uploadSuccess(); //"上传成功"
|
||||
projectData.value.videoUrl = url;
|
||||
});
|
||||
}
|
||||
//将方法暴露给父组件
|
||||
defineExpose({
|
||||
getQueryBySnData
|
||||
})
|
||||
onMounted(async () => {
|
||||
if(COMPANY !== 'agjt') showVideo.value = 2
|
||||
await getVideoList();
|
||||
getQueryBySnData();
|
||||
if(COMPANY != 'agjt'){
|
||||
showVideo.value = 2;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.centerTop {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.videoBox {
|
||||
width: 100%;
|
||||
height: 92%;
|
||||
margin-top: 8%;
|
||||
background: url("@/assets/images/comprehensiveManage/project10.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.videos {
|
||||
width: 78%;
|
||||
height: 90%;
|
||||
margin-left: 11%;
|
||||
margin-top: 1%;
|
||||
}
|
||||
}
|
||||
.imgBox {
|
||||
width: 100%;
|
||||
height: 92%;
|
||||
margin-top: 8%;
|
||||
background: url("@/assets/images/comprehensiveManage/project10.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.imgs {
|
||||
width: 78%;
|
||||
height: 82%;
|
||||
margin: 3% 11%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-top: 5%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.href-content {
|
||||
width: 100%;
|
||||
height: 92%;
|
||||
margin-top: 8%;
|
||||
background: url("@/assets/images/comprehensiveManage/project10.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
// .href-content {
|
||||
// width: 95%;
|
||||
// height: 92%;
|
||||
// margin: 0 auto;
|
||||
// margin-top: 8%;
|
||||
// }
|
||||
|
||||
.change-video {
|
||||
position: absolute;
|
||||
background: url("@/assets/images/cardImg.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #fff;
|
||||
padding: 1% 2%;
|
||||
font-size: 16px;
|
||||
left: 45%;
|
||||
top: 55%;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.top-tab {
|
||||
position: absolute;
|
||||
top: 12%;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 30%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
.tab-box {
|
||||
font-size: 16px;
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .h-card .content {
|
||||
background: none;
|
||||
}
|
||||
</style>
|
||||
41
src/views/commandScreen/liveScreen/ckplayerComp.vue
Normal file
41
src/views/commandScreen/liveScreen/ckplayerComp.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<!--ckplayer 视频播放-->
|
||||
<template>
|
||||
<div style="width: 100%;height: 100%">
|
||||
<video :id="'videoItem' + name" muted controls autoplay style="width: 100%;height: 100%;object-fit: fill;" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Srs from "@/assets/js/srs.sdk";
|
||||
export default {
|
||||
props: ["videoUrls", "autoPlay", "poster", "deviceIp", "name"],
|
||||
data() {
|
||||
return {
|
||||
player: "",
|
||||
rtcPlayer: null
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
this.player = document.getElementById("videoItem" + this.name);
|
||||
//方法一:使用srs.sdk.js
|
||||
this.rtcPlayer = new Srs.SrsRtcWhipWhepAsync();
|
||||
this.rtcPlayer.play(this.videoUrls);
|
||||
// video标签
|
||||
this.player.srcObject = this.rtcPlayer.stream;
|
||||
// 方法二:使用jswebrtc.min.js
|
||||
// new JSWebrtc.Player(this.url, { video: player, autoplay: true, });
|
||||
},
|
||||
beforeDestroy: function () {
|
||||
this.rtcPlayer.close();
|
||||
},
|
||||
watch: {
|
||||
// watch第一次绑定值的时候不会执行监听,修改数据才会触发函数
|
||||
videoUrls(newVal,oldVal) {
|
||||
this.rtcPlayer = new Srs.SrsRtcWhipWhepAsync();
|
||||
this.rtcPlayer.play(newVal);
|
||||
this.player.srcObject = this.rtcPlayer.stream;
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
146
src/views/commandScreen/liveScreen/index.vue
Normal file
146
src/views/commandScreen/liveScreen/index.vue
Normal file
@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="projectContent">
|
||||
<div class="left">
|
||||
<leftTop :projectData="projectData" class="leftTop" ref="leftTopRef"></leftTop>
|
||||
<leftCenter :statisticsCount="statisticsCount" class="leftCenter"></leftCenter>
|
||||
<leftBottom :statisticsCount="statisticsCount" class="leftBottom"></leftBottom>
|
||||
</div>
|
||||
<div class="center">
|
||||
<centerTop :projectData="projectData" class="centerTop" ref="centerTopRef"></centerTop>
|
||||
<div class="centerBottom">
|
||||
<centerBottomLeft :projectData="projectData" class="centerBottomLeft" ref="centerBottomLeftRef"></centerBottomLeft>
|
||||
<centerBottomRight :projectData="projectData" class="centerBottomRight" ref="centerBottomRightRef"></centerBottomRight>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<rightTop class="rightTop" ref="rightTopRef"></rightTop>
|
||||
<rightBottom class="rightBottom" ref="rightBottomRef"></rightBottom>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import leftTop from "@/views/commandScreen/liveScreen/leftTop.vue";
|
||||
import leftCenter from "@/views/commandScreen/liveScreen/leftCenter.vue";
|
||||
import leftBottom from "@/views/commandScreen/liveScreen/leftBottom.vue";
|
||||
import centerTop from "@/views/commandScreen/liveScreen/centerTop.vue";
|
||||
import centerBottomLeft from "@/views/commandScreen/liveScreen/centerBottomLeft.vue";
|
||||
import centerBottomRight from "@/views/commandScreen/liveScreen/centerBottomRight.vue";
|
||||
import rightTop from "@/views/commandScreen/liveScreen/rightTop.vue";
|
||||
import rightBottom from "@/views/commandScreen/liveScreen/rightBottom.vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
const store = GlobalStore();
|
||||
import { getWorkerStatisticsCountApi, getProjectDetail } from "@/api/modules/projectOverview";
|
||||
import { ref, onMounted, onBeforeUnmount,nextTick } from "vue";
|
||||
const statisticsCount = ref(null as any);
|
||||
|
||||
const projectData = ref(null as any);
|
||||
//获取项目信息
|
||||
const getProjectInfo = async (showLoading: boolean) => {
|
||||
const res = await getProjectDetail({ projectSn: store.sn },showLoading);
|
||||
projectData.value = res.result;
|
||||
};
|
||||
|
||||
//获取人员概览
|
||||
const getPersonDetail = async () => {
|
||||
const res = await getWorkerStatisticsCountApi({ sn: store.sn });
|
||||
statisticsCount.value = res.result;
|
||||
};
|
||||
|
||||
const leftTopRef = ref();
|
||||
const centerTopRef = ref();
|
||||
const centerBottomLeftRef = ref();
|
||||
const rightTopRef = ref();
|
||||
const rightBottomRef = ref();
|
||||
const callChildFn = async () => {
|
||||
nextTick( async ()=>{
|
||||
leftTopRef.value.projectTypeEnum()
|
||||
centerTopRef.value.getQueryBySnData()
|
||||
centerBottomLeftRef.value.getProgressOption()
|
||||
rightTopRef.value.getSafeInfo()
|
||||
rightBottomRef.value.getList()
|
||||
})
|
||||
}
|
||||
//定时器
|
||||
const interval = ref(null as any);
|
||||
//定时调用
|
||||
const startInterval = async () => {
|
||||
interval.value= setInterval(() => {
|
||||
getPersonDetail();
|
||||
getProjectInfo();
|
||||
callChildFn();
|
||||
}, 30 * 1000);
|
||||
}
|
||||
// 在组件销毁时清除 interval
|
||||
const destroyInterval = () => {
|
||||
if (interval.value) {
|
||||
clearInterval(interval.value);
|
||||
}
|
||||
}
|
||||
// 在组件销毁时调用 destroyInterval 方法清除 interval
|
||||
onBeforeUnmount(() => {
|
||||
destroyInterval();
|
||||
})
|
||||
window.onbeforeunload = (e) => {
|
||||
destroyInterval();
|
||||
}
|
||||
onMounted( async () => {
|
||||
getPersonDetail();
|
||||
getProjectInfo();
|
||||
startInterval();
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.projectContent {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
.left {
|
||||
width: 26%;
|
||||
.leftTop {
|
||||
height: 32%;
|
||||
}
|
||||
.leftCenter {
|
||||
height: 33%;
|
||||
margin: 3% 0 3% 0;
|
||||
}
|
||||
.leftBottom {
|
||||
height: 35.25%;
|
||||
}
|
||||
}
|
||||
.center {
|
||||
width: 46%;
|
||||
margin: 0 1%;
|
||||
|
||||
.centerTop {
|
||||
height: 66%;
|
||||
margin-bottom: 2.1%;
|
||||
}
|
||||
.centerBottom{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.centerBottomLeft {
|
||||
width: 49%;
|
||||
height: 35.23%;
|
||||
}
|
||||
.centerBottomRight {
|
||||
width: 49%;
|
||||
height: 35.23%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.right {
|
||||
width: 26%;
|
||||
|
||||
.rightTop {
|
||||
height: 32%;
|
||||
}
|
||||
.rightBottom {
|
||||
height: 78.636%;
|
||||
margin: 3% 0 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
136
src/views/commandScreen/liveScreen/leftBottom.vue
Normal file
136
src/views/commandScreen/liveScreen/leftBottom.vue
Normal file
@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div class="leftBottom">
|
||||
<Card title="特殊作业情况">
|
||||
<div class="mainContainer">
|
||||
<div id="pieEchart" style="width:100%;height:100%"></div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Card from "@/components/card.vue";
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
function drawPie(){
|
||||
type EChartsOption = echarts.EChartsOption;
|
||||
|
||||
var chartDom = document.getElementById('pieEchart')!;
|
||||
var myChart = echarts.init(chartDom);
|
||||
var option: EChartsOption;
|
||||
|
||||
option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
data: [ 'Direct', 'Marketing', 'Search Engine', 'Email', 'Union Ads', 'Video Ads', 'Baidu', 'Google', 'Bing', 'Others' ]
|
||||
},
|
||||
|
||||
series: [
|
||||
{
|
||||
grid:{
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: '5%',
|
||||
containLabel:true
|
||||
},
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
selectedMode: 'single',
|
||||
radius: [0, '30%'],
|
||||
label: {
|
||||
position: 'inner',
|
||||
fontSize: 14
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{ value: 1548, name: 'Search Engine' },
|
||||
{ value: 775, name: 'Direct' },
|
||||
{ value: 679, name: 'Marketing', selected: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Access From',
|
||||
type: 'pie',
|
||||
radius: ['45%', '60%'],
|
||||
labelLine: {
|
||||
length: 1
|
||||
},
|
||||
label: {
|
||||
formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ',
|
||||
backgroundColor: '#F6F8FC',
|
||||
borderColor: '#8C8D8E',
|
||||
borderWidth: 1,
|
||||
borderRadius: 3,
|
||||
|
||||
rich: {
|
||||
a: {
|
||||
color: '#6E7079',
|
||||
lineHeight: 10,
|
||||
align: 'center'
|
||||
},
|
||||
hr: {
|
||||
borderColor: '#8C8D8E',
|
||||
width: '100%',
|
||||
borderWidth: 1,
|
||||
height: 0
|
||||
},
|
||||
b: {
|
||||
color: '#4C5058',
|
||||
fontSize: 10,
|
||||
fontWeight: 'bold',
|
||||
lineHeight: 12
|
||||
},
|
||||
per: {
|
||||
color: '#fff',
|
||||
backgroundColor: '#4C5058',
|
||||
padding: [1, 1],
|
||||
borderRadius: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
{ value: 1048, name: 'Baidu' },
|
||||
{ value: 335, name: 'Direct' },
|
||||
{ value: 310, name: 'Email' },
|
||||
{ value: 251, name: 'Google' },
|
||||
{ value: 234, name: 'Union Ads' },
|
||||
{ value: 147, name: 'Bing' },
|
||||
{ value: 135, name: 'Video Ads' },
|
||||
{ value: 102, name: 'Others' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
};
|
||||
|
||||
option && myChart.setOption(option);
|
||||
}
|
||||
|
||||
onMounted( async () => {
|
||||
drawPie()
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.leftBottom {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.mainContainer{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
}
|
||||
::v-deep .h-card .content {
|
||||
height: 80%;
|
||||
}
|
||||
</style>
|
||||
58
src/views/commandScreen/liveScreen/leftCenter.vue
Normal file
58
src/views/commandScreen/liveScreen/leftCenter.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="leftCenter">
|
||||
<Card title="AI报警情况">
|
||||
<div class="mainContainer">
|
||||
<div class="imgBox"><img src="@\assets\images\vehicleManagement\goCar.png"/></div>
|
||||
<div class="textBox">
|
||||
<div>报警位置:东南口</div>
|
||||
<div>报警事件:2024-03-01 12:00:00</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Card from "@/components/card.vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
import { COMPANY } from "@/config/config";
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { getPersonTypeAndEduStatisticsApi } from "@/api/modules/labor";
|
||||
const store = GlobalStore();
|
||||
// ts
|
||||
|
||||
onMounted( async () => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.leftCenter {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.mainContainer{
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 20px);
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
.imgBox{
|
||||
width: 100%;
|
||||
height: 85%;
|
||||
img{
|
||||
width: 100%;
|
||||
height:100%;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
.textBox{
|
||||
height: 15%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
::v-deep .h-card .content {
|
||||
height: 80%;
|
||||
}
|
||||
</style>
|
||||
140
src/views/commandScreen/liveScreen/leftTop.vue
Normal file
140
src/views/commandScreen/liveScreen/leftTop.vue
Normal file
@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<div class="leftTop">
|
||||
<Card title="承包商项目信息">
|
||||
<!-- <div class="projectInfo">
|
||||
<div><span>项目名称:</span> {{ projectData.projectName || "" }}</div>
|
||||
<div :title="projectLocal"><span>项目地址:</span> {{ projectLocal }}</div>
|
||||
<div><span>项目经理:</span> {{ projectData.projectManage || "" }}</div>
|
||||
<div><span>联系电话:</span> {{ projectData.projectTel || "" }}</div>
|
||||
<div><span>建筑面积:</span> {{ projectData.projectAcreage || "" }} ㎡</div>
|
||||
<div><span>开工日期:</span> {{ projectData.startWorkDate || "" }}</div>
|
||||
<div><span>项目编号:</span> {{ projectData.projectNumber || "" }}</div>
|
||||
<div><span>工程类别:</span> {{ projectData.projectType && projectTypeEnumList.length > 0 ? projectTypeEnumList[projectData.projectType - 1].name : "" }}</div>
|
||||
</div> -->
|
||||
<div class="mainContainer">
|
||||
<div>承包商名称:辽宁五瞏</div>
|
||||
<div class="lineBox"><div class="boxInner1">施工区域:东北角一区</div> <div class="boxInner2">项目编号:002</div></div>
|
||||
<div class="lineBox"><div class="boxInner1">项目经理:王海龙</div> <div class="boxInner2">项目类型:epc总承包</div></div>
|
||||
<div class="lineBox"><div class="boxInner1">联系电话:13312545623</div> <div class="boxInner2">竣工日期:2024-03-01</div></div>
|
||||
<div class="lineBox"><div class="boxInner1">建筑面积:12457㎡</div> <div class="boxInner2">合同总额:230万元</div></div>
|
||||
<div class="lineBox"><div class="boxInner1">投资总额:12457万元</div> <div class="boxInner2">工程类别:矿山</div></div>
|
||||
<div class="lineBox"><div class="boxInner1">开工日期:2024-03-01</div> <div class="boxInner2">结构类型:混合结构</div></div>
|
||||
<div class="lineBox"><div class="boxInner1">项目编号:鞍高开项备[2021]23号)</div> <div class="boxInner2">施工阶段:主体施工</div></div>
|
||||
<div class="lineBox"><div class="boxInner1">工程类别:矿山</div> <div class="boxInner2">工程状态</div></div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Card from "@/components/card.vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { getStageOption } from "@/api/modules/projectOverview";
|
||||
|
||||
// ts
|
||||
type Props = {
|
||||
projectData?: any; // 传入项目信息
|
||||
};
|
||||
// withDefaults 定义默认值(传入的数据类型同默认值)
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
projectData: {}
|
||||
});
|
||||
// 项目信息
|
||||
const projectData = ref({} as any);
|
||||
|
||||
const projectLocal = ref("" as any);
|
||||
const store = GlobalStore();
|
||||
const projectTypeEnumList:any = ref([]); //工程类别
|
||||
// 工程类别字典数据
|
||||
const projectTypeEnum = async () => {
|
||||
const res: any = await getStageOption({ dictionaryEncoding: "project_type", projectSn: store.sn });
|
||||
if (res.result.length > 0) {
|
||||
let newArray = res.result.map((item: any) => {
|
||||
return {
|
||||
name: item.name,
|
||||
id: Number(item.data)
|
||||
};
|
||||
});
|
||||
projectTypeEnumList.value = newArray
|
||||
} else {
|
||||
projectTypeEnumList.value = []
|
||||
}
|
||||
};
|
||||
//将方法暴露给父组件
|
||||
defineExpose({
|
||||
projectTypeEnum
|
||||
})
|
||||
onMounted( async () => {
|
||||
await projectTypeEnum();
|
||||
})
|
||||
watch(
|
||||
() => props.projectData,
|
||||
newVal => {
|
||||
if (newVal) {
|
||||
// props.xData = newVal;
|
||||
projectData.value = newVal;
|
||||
projectLocal.value =
|
||||
projectData.value.provinceName +
|
||||
projectData.value.cityName +
|
||||
projectData.value.areaName +
|
||||
projectData.value.projectAddress;
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.leftTop {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.mainContainer{
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
.lineBox{
|
||||
// background-color: #fff;
|
||||
line-height: 18px;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
.boxInner1{
|
||||
// width: 60%;
|
||||
width: 50%;
|
||||
}
|
||||
.boxInner2{
|
||||
// width: 40%;
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// .projectInfo {
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// color: #fff;
|
||||
// padding: 2% 0 0 4%;
|
||||
|
||||
// div {
|
||||
// width: 95%;
|
||||
// height: 12%;
|
||||
// font-size: 15px;
|
||||
// white-space: nowrap; //单行
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// span {
|
||||
// margin-right: 3%;
|
||||
// color: #ccc;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
::v-deep .h-card .content {
|
||||
height: 80%;
|
||||
}
|
||||
::v-deep .h-card {
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
30
src/views/commandScreen/liveScreen/rightBottom.vue
Normal file
30
src/views/commandScreen/liveScreen/rightBottom.vue
Normal file
@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class="rightBottom">
|
||||
<Card title="安全待办">
|
||||
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { GlobalStore } from "@/stores";
|
||||
import { getCurrentDayAirQualityApi } from "@/api/modules/projectOverview";
|
||||
import { ref, onMounted, reactive } from "vue";
|
||||
// import * as echarts from "echarts";
|
||||
import Card from "@/components/card.vue";
|
||||
const store = GlobalStore();
|
||||
|
||||
onMounted( async () => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.rightBottom {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
::v-deep .h-card .content {
|
||||
height: 80%;
|
||||
}
|
||||
</style>
|
||||
31
src/views/commandScreen/liveScreen/rightTop.vue
Normal file
31
src/views/commandScreen/liveScreen/rightTop.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="rightTop">
|
||||
<Card title="应急记录">
|
||||
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Card from "@/components/card.vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { GlobalStore } from "@/stores";
|
||||
const store = GlobalStore();
|
||||
import * as echarts from "echarts";
|
||||
|
||||
onMounted(async () => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.rightTop {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
::v-deep .h-card .content {
|
||||
height: 80%;
|
||||
}
|
||||
::v-deep .h-card {
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user