feat: 初步完成各模块静态样式调整

dev
donghao 4 weeks ago
parent 1c20ab4c0c
commit 301da206e9

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

@ -84,7 +84,8 @@ const columns = [
const pagination = ref({ currentPage: 1, pageSize: 10, total: 0 });
const listData = ref([]); //
const currentRow = ref<Record<string, any>>({}); //
const currFileList = ref<Record<string, any>[]>([]); //
const currFileList = ref<Record<string, any>[]>([]); //
const currBeforeFileList = ref<Record<string, any>[]>([]); //
//
const searchForm = reactive({
train_number: "",
@ -307,7 +308,6 @@ onMounted(() => {
:row-class-name="handleRowClassName"
@row-click="handleRowClick"
>
<template v-slot:actionBar="{ row }">
<ul class="flex table_action_box">
<li
@ -335,13 +335,13 @@ onMounted(() => {
<li>
<div class="fg-footer-charts-title">日检出量</div>
<div class="fg-footer-charts-content">
<PoleDailyDetectionChart :data="dailyDetectionData" />
<!-- <PoleDailyDetectionChart :data="dailyDetectionData" /> -->
</div>
</li>
<li>
<div class="fg-footer-charts-title">日告警分类</div>
<div class="fg-footer-charts-content">
<PoleDailyAlertChart :data="dailyDetectionData" />
<!-- <PoleDailyAlertChart :data="dailyDetectionData" /> -->
</div>
</li>
</ul>

@ -1,62 +1,3 @@
<template>
<div class="bg-basic-content">
<div class="device-status-wrap">
<div class="device-status-header mt-[32px]">
<div class="mt-[24px] py-[16px] pl-[69px] flex items-center">
<div class="fg-title">设备状态</div>
</div>
</div>
<div class="px-[24px] device-status-content-box">
<div class="mt-[16px] bg-transparent baseTable_wrap full_table">
<BaseTable
class="bg-transparent baseTable_box"
:total="pagination.total"
:pageSize="pagination.pageSize"
:dataSource="listData"
:isFixedPagination="true"
:columns="columns"
:page="pagination.currentPage"
@change="handleTableChange"
>
<template v-slot:actionBar="{ row }">
<ul class="flex table_action_box">
<li
class="flex items-center mr-[12px]"
@click="openCurrent(row)"
>
<div class="fg-button-primary1">即时视频</div>
</li>
<li class="flex items-center" @click="openHistory(row)">
<div class="fg-button-primary">查看详情</div>
</li>
</ul>
</template>
</BaseTable>
</div>
</div>
<RealVideoModal
v-model:value="isRealOpen"
:info="currentRow"
@close="isRealOpen = false"
/>
<HistoryVideoModal
ref="historyModalRef"
v-model:value="isHistoryOpen"
:info="currentRow"
:historyVideos="historyVideos"
@close="isHistoryOpen = false"
/>
<AlarmModal
v-model:value="isAlarmOpen"
:info="currentDetailRow"
:image="currFileList"
@close="isAlarmOpen = false"
/>
</div>
</div>
</template>
<script setup lang="tsx">
import { BaseTable } from "@/components/CustomTable";
import ContentHeader from "@/components/ContentHeader.vue";
@ -258,6 +199,64 @@ onMounted(() => {
getList();
});
</script>
<template>
<div class="bg-basic-content">
<div class="device-status-wrap">
<div class="device-status-header mt-[32px]">
<div class="mt-[24px] py-[16px] pl-[69px] flex items-center">
<div class="fg-title">设备状态</div>
</div>
</div>
<div class="px-[24px] device-status-content-box">
<div class="mt-[16px] bg-transparent baseTable_wrap full_table">
<BaseTable
class="bg-transparent baseTable_box"
:total="pagination.total"
:pageSize="pagination.pageSize"
:dataSource="listData"
:isFixedPagination="true"
:columns="columns"
:page="pagination.currentPage"
@change="handleTableChange"
>
<template v-slot:actionBar="{ row }">
<ul class="flex table_action_box">
<li
class="flex items-center mr-[12px]"
@click="openCurrent(row)"
>
<div class="fg-button-primary1">即时视频</div>
</li>
<li class="flex items-center" @click="openHistory(row)">
<div class="fg-button-primary">查看详情</div>
</li>
</ul>
</template>
</BaseTable>
</div>
</div>
<RealVideoModal
v-model:value="isRealOpen"
:info="currentRow"
@close="isRealOpen = false"
/>
<HistoryVideoModal
ref="historyModalRef"
v-model:value="isHistoryOpen"
:info="currentRow"
:historyVideos="historyVideos"
@close="isHistoryOpen = false"
/>
<AlarmModal
v-model:value="isAlarmOpen"
:info="currentDetailRow"
:image="currFileList"
@close="isAlarmOpen = false"
/>
</div>
</div>
</template>
<style lang="scss">
@import url("./DeviceStatus.scss");

@ -1,122 +1,38 @@
.digger-monitor-warp {
box-sizing: border-box;
padding-top: 32px;
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
gap: 20px;
// align-items: center;
.digger-monitor-right {
box-sizing: border-box;
width:970px;
// display: flex;
background-image: url("@/assets/common/diggerMonitor-main-bg.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
.digger-monitor-main-content {
background-image: url("@/assets/diggerMonitor/diggerMonitor-main-bg.png");
background-size: 100% 100%;
background-position: bottom;
background-repeat: no-repeat;
height: 586px;
margin-top: 20px;
.digger-monitor-search-box {
display: flex;
align-items: center;
gap: 12px;
margin: 16px 0;
}
.right-panel{
.el-scrollbar__view {
background: transparent !important;
height: 600px;
}
.fixed_pagination{
padding: 12px 20px 15px;
}
.digger-monitor-body {
padding: 0 24px;
}
.digger-monitor-search-box {
display: flex;
align-items: center;
gap: 12px;
margin: 24px 0 16px;;
}
.right-panel {
width: calc(
100% - var(--fg-swiper-monitor-slide-iamge-width) -
var(--fg-swiper-monitor-main-iamge-width) - var(--fg-box-margin) * 2
);
.el-scrollbar__view {
background: transparent !important;
height: 360px;
}
.digger-monitor-left {
width: 49%;
background-image: url("@/assets/common/boderBg.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
.monitor-left-top {
box-sizing: border-box;
padding: 32px 16px 20px;
min-height: 600px;
.file-preview-screen {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
height: 492px;
// background-color: red;
img {
max-width: 100%;
max-height: 100%;
object-fit: cover;
}
video {
width: 100%;
max-height: calc(100%);
}
}
}
.monitor-left-bottom {
width: 100%;
padding: 0 16px;
margin-bottom: 29px;
overflow: visible;
.swiper {
width: 100%;
height: 100%;
.swiper-slide {
width: 20%;
border-radius:4px;
height: 144px;
img {
width: 100%;
height: 144px;
border-radius:4px;
object-fit: cover
}
}
.active-slide img,
.active-slide video {
border-radius:4px;
border: 2px solid #2ECCE0;
}
.swiper-button-prev,
.swiper-button-next {
background-color: rgba(0, 0, 0, 0.5);
color: white;
width: 32px;
height: 32px;
border-radius: 50%;
}
.swiper-button-prev::after,
.swiper-button-next::after {
font-size: 12px ;
color: #FFF;
}
/* 修改按钮悬停样式 */
.swiper-button-prev:hover,
.swiper-button-next:hover {
background-color: rgba(0, 0, 0, 0.8);
}
}
}
.empty-bg {
box-sizing: border-box;
width: 892px;
height: 815px;
background-image: url("@/assets/common/emptyBg.png");
background-size: 156px 102px;
background-position: center;
background-repeat: no-repeat;
}
}
.digger-monitor-banner {
.left-panel {
width: calc(
var(--fg-swiper-monitor-slide-iamge-width) +
var(--fg-swiper-monitor-main-iamge-width) + var(--fg-box-margin)
);
max-height: 480px;
margin-right: 16px;
}
}
}

@ -1,129 +1,7 @@
<template>
<div class="digger-monitor-warp">
<div class="digger-monitor-left">
<template v-if="currFileList?.length">
<div class="flex items-center justify-center h-full monitor-left-top">
<div class="file-preview-screen">
<!-- // TODO -->
<img :src="currFileList?.[0]?.image_url" v-if="currFileList?.[0]?.image_url" />
<div v-else class="w-full h-full bg-error-picture"></div>
</div>
</div>
</template>
<div class="empty-bg" v-else></div>
</div>
<div class="digger-monitor-right h-[100%]">
<div class="module-header">
<ContentHeader bgLayout="918">
<template #title>
<div class="w-[200px] bg_title bg_title_8"></div>
</template>
<template #extra>
<div></div>
</template>
</ContentHeader>
</div>
<!-- 表格区域 -->
<!-- 搜索区域 -->
<div class="px-[16px]">
<div class="digger-monitor-search-box">
<!-- <el-select
v-model="searchForm.station"
placeholder="钩机编号"
class="custom-select"
>
<el-option label="小觉站" value="小觉站"></el-option>
<el-option label="东西站" value="东西站"></el-option>
<el-option label="立杆区" value="立杆区"></el-option>
</el-select> -->
<el-input
v-model="searchForm.train_number"
placeholder="请输入列车号"
class="custom-input"
clearable
/>
<el-input
v-model="searchForm.train_carriage_number"
placeholder="请输入车厢号"
class="custom-input"
clearable
/>
<!-- <el-select
v-model="searchForm.fault_type"
placeholder="故障类型"
class="custom-select"
>
<el-option label="下侧门板缺失" value="下侧门板缺失"></el-option>
<el-option label="门折页座脱落" value="门折页座脱落"></el-option>
<el-option label="小门塔扣丢失" value="小门塔扣丢失"></el-option>
<el-option label="小窗裂纹" value="小窗裂纹"></el-option>
<el-option label="搭扣未搭" value="搭扣未搭"></el-option>
<el-option label="小门外胀" value="小门外胀"></el-option>
</el-select> -->
<el-button
type="primary"
@click="handleQuery"
class="basic-btn query-btn"
>
<span class="icon"></span> 查询
</el-button>
<el-button @click="handleReset" class="basic-btn reset-btn">
<span class="icon"></span> 重置
</el-button>
</div>
<!-- 右侧表格区域 -->
<div class="w-full right-panel">
<div class="bg-transparent baseTable_wrap">
<template v-if="pagination.total > 0">
<BaseTable
class="bg-transparent baseTable_box"
:total="pagination.total"
:pageSize="pagination.pageSize"
:dataSource="listData"
:isFixedPagination="true"
:columns="columns"
:page="pagination.currentPage"
@change="handleTableChange"
:row-class-name="handleRowClassName"
@row-click="handleRowClick"
>
<template #created_at="{ row }">
<div>{{ row }}</div>
</template>
</BaseTable>
</template>
</div>
</div>
</div>
</div>
<DiggerAlarmModal
v-model:value="isAlarmOpen"
:info="currentRow"
:fileList="currFileList"
@close="isAlarmOpen = false"
/>
<BaseDelete
v-model:value="isDeleteOpen"
:deleteContent="`
<p>
确定删除
<span>${currentRow?.alarm_type}</span>
相关告警记录吗删除后将找不到此记录请谨慎操作.
</p>
`"
@delete-confirm="handleDeleteConfirm"
:info="currentRow"
@close="isDeleteOpen = false"
/>
</div>
</template>
<script lang="ts" setup>
import Player from "@/components/videoPlayer/Player.vue";
import SwiperPlayer from "./components/SwiperPlayer.vue";
import ContentHeader from "@/components/ContentHeader.vue";
import { onBeforeRouteLeave } from "vue-router";
import { BaseDelete, BaseTable } from "@/components/CustomTable";
import { Swiper, SwiperSlide } from "swiper/vue";
import { Navigation, Scrollbar } from "swiper/modules";
import DiggerAlarmModal from "./components/DiggerAlarmModal.vue";
import {
getAppearanceMonitorApi,
getAppearanceMonitorDetailApi,
@ -131,17 +9,8 @@ import {
deleteAppearanceMonitorApi,
} from "@/api/dashboard";
import { isSuccessApi } from "@/utils/forApi";
import DiggerAlarmModal from "./components/DiggerAlarmModal.vue";
import { useWebSocketStore } from "@/stores/websocketStore";
import { onBeforeRouteLeave } from "vue-router";
import "swiper/css";
import "swiper/scss";
import "swiper/scss/navigation";
import { color } from "echarts";
const modules = [Navigation, Scrollbar];
const activeIndex = ref(-1);
const swiperRef = ref(null);
const isAlarmOpen = ref<Boolean>(false); //
const isDeleteOpen = ref<Boolean>(false); //
const websocketStore = useWebSocketStore();
@ -149,15 +18,6 @@ const websocketStore = useWebSocketStore();
watch(
() => websocketStore.messages,
(newMessages: string[], oldMessages: string[]) => {
// console.log(':', newMessages[newMessages?.length - 1].content);
// console.log(':', oldMessages);
// if (newMessages?.length > oldMessages?.length) {
// //
// const newMessage = newMessages[newMessages?.length - 1];
// // console.log(' WebSocket :', newMessage);
// //
// }
if (newMessages?.length > 0 && !isAlarmOpen.value) {
console.log(
newMessages[newMessages?.length - 1],
@ -222,76 +82,15 @@ const columns = [
property: "created_at",
},
{
slot: "operation",
type: "action",
label: "操作",
width: 140,
formatter: (row) => {
return h(
"div",
{
style: {
fontSize: "14px",
color: "#37EBFF",
},
},
[
h(
"span",
{
fontSize: "14px",
class: "pf-1",
},
[
h(
"i",
{
style: {
fontSize: "14px",
letterSpacing: "2px",
marginRight: "4px",
color: "#009DFF",
},
onClick: (row) => {
console.log("row.id");
//
isAlarmOpen.value = true;
console.log(isAlarmOpen.value);
currentRow.value = row;
},
},
"详情"
),
h(
"i",
{
style: {
fontSize: "14px",
letterSpacing: "2px",
marginRight: "4px",
color: "#FF2727",
},
onClick: (row) => {
// console.log(row.id);
//
isDeleteOpen.value = true;
currentRow.value = row;
},
},
"删除"
),
]
),
]
);
},
width: 170,
},
];
const listData = ref([]); //
const currentRow = ref<Record<string, any>>({}); //
const currFileList = ref<Record<string, any>[]>([]); //
const currBeforeFileList = ref<Record<string, any>[]>([]); //
const currFile = ref<Record<string, any>>({}); //
//
const searchForm = reactive({
train_number: "",
@ -300,7 +99,6 @@ const searchForm = reactive({
station: "",
type: "distance", // TODO distance
});
const dataLoading = ref(true);
//
const getFileList = async () => {
try {
@ -312,53 +110,15 @@ const getFileList = async () => {
console.log(res.data, "getDetailList_data");
if (isSuccessApi(res)) {
currFileList.value = res.data.data;
currFile.value = res.data.data[0];
activeIndex.value = 0;
}
} catch (error) {
console.log(error, "getDetailList_error");
}
};
//
const getBeforeFileList = async () => {
try {
const res = await getBeforeMonitorDetailApi({
id: currentRow.value?.id,
current: 1,
pageSize: 1000,
});
console.log(res.data, "getDetailList_data");
if (isSuccessApi(res)) {
currBeforeFileList.value = res.data.data;
}
} catch (error) {
console.log(error, "getDetailList_error");
}
};
// TODO mock
// const getFileList = async () => {
// try {
// const resAll = await fetch('/api/v1/record/record_detail_list/', {
// method: 'POST'
// })
// const res = await resAll.json()
// if (isSuccessApi(res)) {
// currFileList.value = res.data.data;
// currFile.value = res.data.data[0];
// activeIndex.value = 0;
// }
// } catch (error) {
// console.error(':', error)
// }
// }
function loadDetail() {
currentRow.value = listData.value[0];
console.log(currentRow.value, "currentRow");
getFileList();
getBeforeFileList();
}
//
@ -426,11 +186,23 @@ const handleRowClassName = ({ row }) => {
return row.id === currentRow.value.id ? "selected-row" : "";
};
/**查看详情 */
function openCurrent(row) {
console.log(row, "openCurrent");
currentRow.value = row;
isAlarmOpen.value = true;
}
//
function deleteCurrent(row) {
isDeleteOpen.value = true;
currentRow.value = row;
}
//
const handleRowClick = (row, event, rowIndex) => {
currentRow.value = row;
getFileList();
getBeforeFileList();
};
onBeforeRouteLeave(() => {
@ -443,6 +215,144 @@ onMounted(() => {
getList();
});
</script>
<template>
<div class="digger-monitor-warp">
<div class="digger-monitor-main-content">
<div class="module-header">
<div class="fg-title pl-[32px] pt-[23px]">
<span class="text-[18px]">钩机监测</span>
</div>
</div>
<div class="digger-monitor-body">
<!-- 搜索区域 -->
<div class="digger-monitor-search-box">
<!-- <el-select
v-model="searchForm.station"
placeholder="钩机编号"
class="custom-select"
>
<el-option label="小觉站" value="小觉站"></el-option>
<el-option label="东西站" value="东西站"></el-option>
<el-option label="立杆区" value="立杆区"></el-option>
</el-select> -->
<el-input
v-model="searchForm.train_number"
placeholder="请输入列车号"
class="custom-input"
clearable
/>
<el-input
v-model="searchForm.train_carriage_number"
placeholder="请输入车厢号"
class="custom-input"
clearable
/>
<!-- <el-select
v-model="searchForm.fault_type"
placeholder="故障类型"
class="custom-select"
>
<el-option label="下侧门板缺失" value="下侧门板缺失"></el-option>
<el-option label="门折页座脱落" value="门折页座脱落"></el-option>
<el-option label="小门塔扣丢失" value="小门塔扣丢失"></el-option>
<el-option label="小窗裂纹" value="小窗裂纹"></el-option>
<el-option label="搭扣未搭" value="搭扣未搭"></el-option>
<el-option label="小门外胀" value="小门外胀"></el-option>
</el-select> -->
<el-button
type="primary"
@click="handleQuery"
class="basic-btn query-btn"
>
<span class="icon"></span> 查询
</el-button>
<el-button @click="handleReset" class="basic-btn reset-btn">
<span class="icon"></span> 重置
</el-button>
</div>
<!-- 主体内容区域 -->
<div class="flex justify-between digger-monitor-banner">
<div class="left-panel">
<template v-if="currFileList?.length">
<div
class="flex items-center justify-center h-full monitor-left-top"
>
<!-- // TODO -->
<img
class="w-full h-full"
:src="currFileList?.[0]?.image_url"
v-if="currFileList?.[0]?.image_url"
/>
<div v-else class="w-full h-full fg-empty-image"></div>
</div>
</template>
<div class="empty-bg" v-else></div>
</div>
<!-- 表格区域 -->
<!-- 搜索区域 -->
<!-- 右侧表格区域 -->
<div class="right-panel">
<div class="bg-transparent baseTable_wrap">
<template v-if="pagination.total > 0">
<BaseTable
class="bg-transparent baseTable_box"
:total="pagination.total"
:pageSize="pagination.pageSize"
:dataSource="listData"
:isFixedPagination="true"
:columns="columns"
:page="pagination.currentPage"
@change="handleTableChange"
:row-class-name="handleRowClassName"
@row-click="handleRowClick"
>
<template v-slot:actionBar="{ row }">
<ul class="flex table_action_box">
<li
class="flex items-center mr-[8px]"
@click="openCurrent(row)"
>
<div class="fg-button-primary">详情</div>
</li>
<li
class="flex items-center mr-[8px]"
@click="deleteCurrent(row)"
>
<div class="fg-button-primary-danger">删除</div>
</li>
</ul>
</template>
</BaseTable>
</template>
</div>
</div>
</div>
</div>
</div>
<DiggerAlarmModal
v-model:value="isAlarmOpen"
:info="currentRow"
:fileList="currFileList"
@close="isAlarmOpen = false"
/>
<BaseDelete
v-model:value="isDeleteOpen"
:deleteContent="`
<p>
确定删除
<span>${currentRow?.alarm_type}</span>
相关告警记录吗删除后将找不到此记录请谨慎操作.
</p>
`"
@delete-confirm="handleDeleteConfirm"
:info="currentRow"
@close="isDeleteOpen = false"
/>
</div>
</template>
<style lang="scss">
@import url("./DiggerMonitor.scss");
</style>

@ -5,9 +5,7 @@
background-repeat: no-repeat;
height: 586px;
margin-top: 20px;
.search-section {
padding: 16px 0;
}
.pole-monitor-body {
padding: 0 24px;
}

@ -1,12 +1,14 @@
<template>
<el-dialog class="appearanceAlarmModal" v-model="show" @close="handleClose">
<el-dialog class="appearanceAlarmModal fg-dialog" v-model="show" @close="handleClose" align-center :show-close="false" >
<!-- 自定义标题栏 -->
<template #header="{ close, titleId, titleClass }">
<div class="flex items-center justify-between appearanceAlarm-dialog-header">
<div class="flex items-center justify-between appearanceAlarm-dialog-header fg-dialog-header">
<div class="flex items-center justify-center header-left">
<div class="header-icon mr-[12px]"></div>
<p class="overflow-hidden whitespace-nowrap text-ellipsis max-w-[650px]">{{
"故障提示" }}</p>
<p class="overflow-hidden whitespace-nowrap text-ellipsis max-w-[650px]">故障提示</p>
</div>
<div class="fg-dialog-header-close" @click="close">
</div>
</div>
</template>
@ -17,10 +19,10 @@
<img :src="item.image_url" alt="" v-if="index < 4"></img>
</template> -->
<div class="appearanceAlarm-content-top-left">
<span class="appearanceAlarm-content-top-title">故障前</span>
<div class="appearanceAlarm-error-title-before appearanceAlarm-error-title">故障前</div>
<div class="appearanceAlarm-content-top-left-img">
<div class="appearanceAlarm-content-top-img">
<img :src="imageBefore" alt=""></img>
<img :src="imageBefore" alt="" />
</div>
<div class="appearanceAlarm-content-top-img-slider">
<swiper ref="swiperModalRef" :modules="modules" :slides-per-view="3" :space-between="10" navigation
@ -35,7 +37,7 @@
</div>
</div>
<div class="appearanceAlarm-content-top-right">
<span class="appearanceAlarm-content-top-title">故障后</span>
<div class="appearanceAlarm-error-title-after appearanceAlarm-error-title">故障后</div>
<div class="appearanceAlarm-content-top-right-img">
<div class="appearanceAlarm-content-top-img">
<img :src="imageAfter" alt=""></img>
@ -53,18 +55,20 @@
</div>
</div>
</div>
<div class="appearanceAlarm-content-bottom">
<span class="appearanceAlarm-content-bottom-title">列车信息:</span>
<div class="appearanceAlarm-content-bottom-info">
<div class="appearanceAlarm-content-info mt-[16px]">
<div class="font-bold appearanceAlarm-content-info-title mb-[12px]">列车信息:</div>
<ul class="appearanceAlarm-content-info-list">
<li>
<span class="mr-8">列车编号: <i>{{ info.train_number }}</i></span>
<span class="mr-8">车型: <i>{{ info.train_model }}</i></span>
<span>发生时间: <i>{{ info.created_at }}</i></span>
</div>
<div class="appearanceAlarm-content-bottom-info">
</li>
<li>
<span class="mr-8">告警类型: <i>{{ info.alarm_type }}</i></span>
<span>故障类型: <i>{{ info.fault_type }}</i></span>
</div>
<div class="appearanceAlarm-content-bottom-btn">
</li>
</ul>
<div class="appearanceAlarm-content-info-btn">
<el-button type="primary" @click="exportToExcel" class="appearanceAlarm-btn">
<span class="icon"></span> 导出
</el-button>
@ -215,37 +219,9 @@ onMounted(() => {
<style lang="scss">
.appearanceAlarmModal.el-dialog {
border: none;
overflow: hidden;
box-shadow: none;
background-color: transparent;
background-image: url("@/assets/common/bg_real_dialog.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
width: 816px;
height:609px;
padding: 0;
// margin-top: calc(50vh - 316px);
.el-dialog__header.show-close {
padding: 0;
}
.el-dialog__close {
width: 56px;
height: 56px;
color: white;
font-size: 18px;
padding-top: 4px;
padding-right: 20px;
}
.appearanceAlarm-dialog-header {
color: white;
padding: 0;
padding-top: 8px;
margin-bottom: 10px;
.header-left {
padding: 0 24px;
font-weight: bold;
@ -280,7 +256,26 @@ onMounted(() => {
// width: 368px;
// height: 216px;
// }
.appearanceAlarm-content-top-title {
.appearanceAlarm-error-title{
width: 100px;
height: 36px;
background-image: url("@/assets/appearanceMonitor/beforeError.png");
background-size: 100%;
background-position: center;
background-repeat: no-repeat;
color: #FFFFFF;
text-align: center;
line-height: 36px;
font-size: 14px;
font-weight: 700;
margin-bottom: 12px;
&.appearanceAlarm-error-title-after{
background-image: url("@/assets/appearanceMonitor/afterError.png");
}
}
.appearanceAlarm-error-title
.appearanceAlarm-error-title-before {
display: inline-block;
width: 42px;
height: 20px;
@ -345,7 +340,7 @@ onMounted(() => {
position: absolute;
top: 0;
left: -16px;
border-left: 2px dashed rgba(255,255,255,0.6);
border-left: 1px dashed rgba(255,255,255,0.6);
// width: 2px; /* 线 */
height: 100%; /* 分割线高度,根据需要调整 */
// margin-right: 10px; /* 线 */
@ -392,10 +387,8 @@ onMounted(() => {
}
}
}
.appearanceAlarm-content-bottom {
box-sizing: border-box;
margin-top: 12px;
.appearanceAlarm-content-bottom-title {
.appearanceAlarm-content-info {
.appearanceAlarm-content-info-title {
box-sizing: border-box;
padding-left: 8px;
height: 22px;
@ -406,20 +399,25 @@ onMounted(() => {
line-height: 22px;
}
.appearanceAlarm-content-bottom-info {
box-sizing: border-box;
.appearanceAlarm-content-info-list {
display: grid;
gap: 12px;
&>li{
box-sizing: border-box;
font-size: 14px;
color: #FFFFFF;
i {
font-style: normal;
font-weight: bold;
}
}
}
.appearanceAlarm-content-bottom-info:nth-of-type(1) {
.appearanceAlarm-content-info-list:nth-of-type(1) {
margin: 4px 0;
}
.appearanceAlarm-content-bottom-btn {
margin-top: 24px;
.appearanceAlarm-content-info-btn {
margin-top: 32px;
text-align: end;
.appearanceAlarm-btn {
width: 96px;

@ -106,7 +106,7 @@ const show = computed({
background-color: transparent;
width: 573px;
height: 248px;
padding: 0;
padding: 0;
.el-dialog__close {
width: 32px;
height: 32px;

@ -1,9 +1,15 @@
<template>
<el-dialog class="digger-alarm-modal fg-dialog" v-model="show" @close="handleClose">
<el-dialog
class="digger-alarm-modal fg-dialog"
v-model="show"
@close="handleClose"
align-center
:show-close="false"
>
<!-- 自定义标题栏 -->
<template #header="{ close, titleId, titleClass }">
<div
class="flex items-center justify-between digger-detail-dialog-header"
class="flex items-center justify-between digger-detail-dialog-header fg-dialog-header"
>
<div class="flex items-center justify-center header-left">
<div class="header-icon mr-[12px]"></div>
@ -13,6 +19,7 @@
钩机详情
</p>
</div>
<div class="fg-dialog-header-close" @click="close"></div>
</div>
</template>
<!-- 图片区域 -->
@ -45,7 +52,7 @@ interface Emits {
const props = withDefaults(defineProps<Props>(), {
value: false,
info: {},
fileList: []
fileList: [],
});
const emit = defineEmits<Emits>();
@ -66,44 +73,14 @@ const show = computed({
<style lang="scss">
.digger-alarm-modal.el-dialog {
border: none;
overflow: hidden;
box-shadow: none;
background-color: transparent;
background-image: url("@/assets/common/bg_real_dialog.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
width: 816px;
height: 609px;
padding: 0;
// margin-top: calc(50vh - 316px);
.el-dialog__header.show-close {
padding: 0;
}
.el-dialog__close {
width: 56px;
height: 56px;
color: white;
font-size: 18px;
padding-top: 4px;
padding-right: 20px;
}
.digger-detail-dialog-header {
color: white;
padding: 0;
padding-top: 8px;
margin-bottom: 10px;
.header-left {
padding: 0 24px;
font-weight: bold;
font-size: 18px;
.header-icon {
margin-top: 4px;
width: 24px;
height: 48px;
background-image: url("@/assets/common/alarm_title.png");
@ -116,10 +93,10 @@ const show = computed({
.digger-detail-content {
box-sizing: border-box;
padding: 0 24px;
padding: 8px 24px;
width: 100%;
height: 500px;
img{
height: 529px;
img {
width: 100%;
height: 100%;
}

@ -1,64 +1,19 @@
<template>
<el-dialog class="historyVideoModal-wrap" v-model="show" @close="handleClose">
<!-- 自定义标题栏 -->
<template #header="{ close, titleId, titleClass }">
<div class="flex items-center justify-between video-dialog-header">
<div class="flex items-center justify-center header-left">
<div class="header-icon mr-[12px]"></div>
<p class="overflow-hidden whitespace-nowrap text-ellipsis max-w-[650px]">{{
info.device_name }}</p>
</div>
</div>
</template>
<div class="flex main-content">
<!-- 播放器 -->
<Player :src="currentVideo.video_url" :is-playing="isPlaying" @update:progress="handleProgress"
@update:duration="handleDuration" @play="isPlaying = true" @pause="isPlaying = false" />
<div class="flex video-record-list">
<!-- 日期筛选 -->
<div class="flex pl-[16px] pr-[24px] items-center">
<span>时间</span>
<el-select v-model="selectedDate" placeholder="请选择" class="custom-select record_date_select"
clearable @change="handleDateChange" @clear="handleClear">
<el-option v-for="(item, index) in dateList" :key="item" :label="item"
:value="item"></el-option>
</el-select>
<!-- <el-date-picker v-model="selectedDate" type="date" placeholder="选择日期"
@change="handleDateChange"></el-date-picker> -->
</div>
<!-- 记录列表 -->
<el-scrollbar style="height: calc(100% - 80px)">
<ul class="record-list-box">
<li v-for="(item, index) in recordList" :key="item.id"
:class="{ active: currentVideo?.id === item.id }" @click="handleItemClick(item)"
class="flex items-center justify-between">
<span class="time">{{ item.created_at }}</span>
<div :class="{ 'play-btn': true, 'playing': isPlaying && currentVideo?.id === item.id }">
</div>
</li>
</ul>
</el-scrollbar>
</div>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import Player from '@/components/videoPlayer/Player.vue'
import { ElMessage } from 'element-plus';
import { extractUniqueDatesWithMoment, filterDataByDate } from '@/utils/array';
import Player from "@/components/videoPlayer/Player.vue";
import { ElMessage } from "element-plus";
import { extractUniqueDatesWithMoment, filterDataByDate } from "@/utils/array";
interface Props {
value: boolean; /** 弹窗显隐 */
info: Record<string, any>; /** 设备信息 */
historyVideos: Record<string, any>[]; /** 历史视频列表 */
value: boolean /** 弹窗显隐 */;
info: Record<string, any> /** 设备信息 */;
historyVideos: Record<string, any>[] /** 历史视频列表 */;
}
interface Emits {
(e: "update:value", val: boolean): void;
(e: "update:value", val: boolean): void;
}
const props = withDefaults(defineProps<Props>(), {
value: false,
info: {},
historyVideos: []
value: false,
info: {},
historyVideos: [],
});
const emit = defineEmits<Emits>();
@ -67,219 +22,270 @@ const emit = defineEmits<Emits>();
const dateList = ref<string[]>([]);
const selectedDate = ref(); //
const recordList = ref([]);
const currentVideo = ref<Record<string, any>>({})
const currentVideo = ref<Record<string, any>>({});
const isPlaying = ref(false);
const togglePlay = () => {
isPlaying.value = !isPlaying.value;
isPlaying.value = !isPlaying.value;
};
// TODO 使
const handleProgress = (data: { currentTime: number, duration: number }) => {
console.log((data.currentTime / data.duration) * 100, "handleProgress")
const progressVal = (data.currentTime / data.duration) * 100
}
const handleProgress = (data: { currentTime: number; duration: number }) => {
console.log((data.currentTime / data.duration) * 100, "handleProgress");
const progressVal = (data.currentTime / data.duration) * 100;
};
// TODO 使
const handleDuration = (newDuration: number) => {
// duration.value = newDuration
}
// duration.value = newDuration
};
//
const loadData = () => {
recordList.value = props.historyVideos
dateList.value = extractUniqueDatesWithMoment(recordList.value);
currentVideo.value = props.historyVideos[0]; //
recordList.value = props.historyVideos;
dateList.value = extractUniqueDatesWithMoment(recordList.value);
currentVideo.value = props.historyVideos[0]; //
};
//
const handleDateChange = (date) => {
console.log(date, "handleDateChange_date");
if (date) {
selectedDate.value = date;
recordList.value = filterDataByDate(toRaw(props.historyVideos), date);
currentVideo.value = recordList.value[0]; //
} else {
loadData()
}
console.log(date, "handleDateChange_date");
if (date) {
selectedDate.value = date;
recordList.value = filterDataByDate(toRaw(props.historyVideos), date);
currentVideo.value = recordList.value[0]; //
} else {
loadData();
}
};
//
const handleItemClick = (item) => {
if (currentVideo.value?.id === item.id) {
togglePlay() //
} else {
currentVideo.value = item;
}
if (currentVideo.value?.id === item.id) {
togglePlay(); //
} else {
currentVideo.value = item;
}
};
//
const handleVideoEnd = () => {
// currentIndex.value = -1;
// currentIndex.value = -1;
};
//
const formatTime = (timeStr) => {
return timeStr.split(' ')[1].substring(0, 5); //
return timeStr.split(" ")[1].substring(0, 5); //
};
//
const handleClose = () => {
emits('close');
emits("close");
};
const show = computed({
get() {
return props.value;
},
set(val: boolean) {
emit("update:value", val);
}
get() {
return props.value;
},
set(val: boolean) {
emit("update:value", val);
},
});
// TODO
defineExpose({ loadData })
defineExpose({ loadData });
</script>
<template>
<el-dialog
class="historyVideoModal-wrap fg-dialog fg-dialog2"
v-model="show"
@close="handleClose"
align-center
:show-close="false"
>
<!-- 自定义标题栏 -->
<template #header="{ close, titleId, titleClass }">
<div
class="flex items-center justify-between video-dialog-header fg-dialog-header"
>
<div class="flex items-center justify-center header-left">
<div class="header-icon mr-[12px]"></div>
<p
class="overflow-hidden whitespace-nowrap text-ellipsis max-w-[650px]"
>
{{ info.device_name }}
</p>
</div>
<div class="fg-dialog-header-close" @click="close"></div>
</div>
</template>
<div class="flex main-content">
<!-- 播放器 -->
<Player
:src="currentVideo.video_url"
:is-playing="isPlaying"
@update:progress="handleProgress"
@update:duration="handleDuration"
@play="isPlaying = true"
@pause="isPlaying = false"
/>
<div class="flex video-record-list pl-[24px]">
<!-- 日期筛选 -->
<div class="flex items-center">
<span>时间</span>
<el-select
v-model="selectedDate"
placeholder="请选择"
class="custom-select record_date_select"
clearable
@change="handleDateChange"
@clear="handleClear"
>
<el-option
v-for="(item, index) in dateList"
:key="item"
:label="item"
:value="item"
></el-option>
</el-select>
<!-- <el-date-picker v-model="selectedDate" type="date" placeholder="选择日期"
@change="handleDateChange"></el-date-picker> -->
</div>
<!-- 记录列表 -->
<el-scrollbar style="height: calc(100% - 80px)">
<ul class="record-list-box">
<li
v-for="(item, index) in recordList"
:key="item.id"
:class="{ active: currentVideo?.id === item.id }"
@click="handleItemClick(item)"
class="flex items-center justify-between"
>
<span class="time">{{ item.created_at }}</span>
<div
:class="{
'play-btn': true,
playing: isPlaying && currentVideo?.id === item.id,
}"
></div>
</li>
</ul>
</el-scrollbar>
</div>
</div>
</el-dialog>
</template>
<style lang="scss">
.historyVideoModal-wrap.el-dialog {
border: none;
overflow: hidden;
box-shadow: none;
background-color: transparent;
background-image: url("@/assets/common/bg_player_dialog.png");
background-size: contain;
background-position: center;
background-repeat: no-repeat;
width: 1100px;
height: 612px;
.video-dialog-header {
color: white;
padding: 0;
margin-top: calc(50vh - 316px);
.el-dialog__header.show-close {
padding: 0;
padding-top: 4px;
.header-left {
padding: 0 24px;
font-weight: bold;
font-size: 18px;
.header-icon {
width: 48px;
height: 48px;
background-image: url("@/assets/common/dialog_title_icon.png");
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
}
.el-dialog__close {
width: 56px;
height: 56px;
color: white;
font-size: 18px;
padding-top: 4px;
padding-right: 20px;
}
.video-dialog-header {
color: white;
padding: 0;
padding-top: 4px;
.header-left {
padding: 0 18px;
font-weight: bold;
font-size: 18px;
.header-icon {
margin-top: 8px;
width: 48px;
height: 48px;
background-image: url("@/assets/common/dialog_title_icon.png");
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
}
}
.main-content {
padding: 8px 24px 24px;
// background: red;
.video-player-box {
border-radius: 0px 0px 4px 4px;
overflow: hidden;
width: 752px;
height: 502px;
.video-element {
width: 100%;
height: 100%;
}
}
.main-content {
padding-left: 24px;
padding-top: 24px;
// background: red;
.video-player-box {
border-radius: 0px 0px 4px 4px;
overflow: hidden;
width: 752px;
height: 502px;
.video-element {
width: 100%;
height: 100%;
}
.video-record-list {
flex-direction: column;
flex: 1;
color: white;
.record_date_select {
width: 100%;
display: flex;
flex: 1;
border-radius: 2px;
// border: none;
border: 1px solid rgba(8, 139, 214, 0.4);
.el-select__wrapper {
width: 100%;
&.is-focused {
box-shadow: none;
}
&.is-hovering {
border: none;
}
&:hover {
border: none;
}
}
.video-record-list {
flex-direction: column;
}
.record-list-box {
margin-top: 12px;
display: grid;
gap: 12px;
li {
color: white;
height: 32px;
cursor: pointer;
padding-left: 16px;
padding-right: 24px;
// margin: 6px 0;
background: rgba(9, 82, 129, 0.6);
border-radius: 2px;
border: 1px solid rgba(22, 139, 202, 0.3);
&.active,
&:hover {
background: rgba(9, 82, 129, 0.6);
box-shadow: inset 2px 2px 4px 0px rgba(51, 178, 185, 0.6),
inset -2px -2px 4px 0px rgba(51, 178, 185, 0.6);
border-radius: 2px 2px 2px 2px;
border: 1px solid #29cfe2;
color: #37dbff;
}
.time {
flex: 1;
color: white;
.record_date_select {
width: 100%;
display: flex;
flex: 1;
border-radius: 2px;
// border: none;
border: 1px solid rgba(8, 139, 214, 0.4);
.el-select__wrapper {
width: 100%;
&.is-focused {
box-shadow: none;
}
&.is-hovering {
border: none;
}
&:hover {
border: none;
}
}
}
.record-list-box {
margin-top: 12px;
li {
color: white;
height: 32px;
cursor: pointer;
padding-left: 16px;
padding-right: 24px;
// margin: 6px 0;
&.active,
&:hover {
background: linear-gradient(90deg, rgba(30, 54, 88, 0) 0%, #0C4FAD 53%, rgba(65, 117, 190, 0) 100%);
color: #37DBFF;
border-radius: 2px;
border: 1px solid;
border-image: linear-gradient(90deg, rgba(12, 24, 64, 0), rgba(69, 174, 250, 1), rgba(102, 102, 102, 0)) 1 1;
}
.time {
flex: 1;
font-size: 14px;
}
.play-btn {
width: 20px;
height: 20px;
background: url("@/assets/common/player_icon.png") no-repeat center center;
background-size: contain;
}
.playing {
background: url("@/assets/common/pause_icon.png") no-repeat center center;
background-size: contain;
}
}
}
font-size: 14px;
}
.play-btn {
width: 20px;
height: 20px;
background: url("@/assets/common/player_icon.png") no-repeat center
center;
background-size: contain;
}
.playing {
background: url("@/assets/common/pause_icon.png") no-repeat center
center;
background-size: contain;
}
}
}
}
}
}
</style>

@ -1,3 +1,40 @@
<script lang="ts" setup>
import { ref } from 'vue';
interface Props {
/** 弹窗显隐 */
value: boolean;
info: Record<string, any>;
image: any;
}
interface Emits {
(e: "update:value", val: boolean): void;
}
const props = withDefaults(defineProps<Props>(), {
value: false,
info: {},
image: []
});
const emit = defineEmits<Emits>();
//
const handleClose = () => {
// emits('close');
};
const show = computed({
get() {
return props.value;
},
set(val: boolean) {
emit("update:value", val);
}
});
//
const itemCount = 16; //
</script>
<template>
<el-dialog class="vehiclModal-wrap fg-dialog fg-dialog2" v-model="show" @close="handleClose" align-center :show-close="false" >
<!-- 自定义标题栏 -->
@ -29,60 +66,28 @@
<div class="vehicl-content-bottom">
<!-- //TODO -->
<span class="vehicl-content-bottom-title">列车与车厢号</span>
<div class="vehicl-content-bottom-vehicl">
<div class="vehicl-content-bottom-vehicl-header"></div>
<div :class="['vehicl-content-bottom-vehicl-body-box', { 'high-height': info?.data?.train_data?.length > 15 }]">
<div class="vehicl-content-bottom-vehicl-body" v-for="(item, index) in info?.data?.train_data" :key="index">
<div>{{ item.model }}</div>
<div class="flex items-center vehicl-content-bottom-vehicl">
<div class="train-card-item mb-[8px] mr-[8px] flex items-center justify-center ">
<div class="train_head_icon"></div>
</div>
<ul :class="['train-card-item-list', { 'high-height': info?.data?.train_data?.length > 15 }]">
<li class="flex flex-1 train-card-item" v-for="(item, index) in info?.data?.train_data" :key="index">
<div class="w-[80px] px-[8px] flex flex-col justify-center">
<div>{{ item.model }}</div>
<div>
<!-- <span class="mr-3">04</span> -->
<span>{{ item.carriage_number }}</span>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
interface Props {
/** 弹窗显隐 */
value: boolean;
info: Record<string, any>;
image: any;
}
interface Emits {
(e: "update:value", val: boolean): void;
}
const props = withDefaults(defineProps<Props>(), {
value: false,
info: {},
image: []
});
const emit = defineEmits<Emits>();
//
const handleClose = () => {
// emits('close');
};
const show = computed({
get() {
return props.value;
},
set(val: boolean) {
emit("update:value", val);
}
});
//
const itemCount = 16; //
</script>
<style lang="scss">
.vehiclModal-wrap.el-dialog {
@ -96,7 +101,6 @@ const itemCount = 16; // 这里可以根据实际需求动态设置
font-weight: bold;
font-size: 18px;
.header-icon {
margin-top: 4px;
width: 24px;
height: 48px;
background-image: url("@/assets/common/alarm_title.png");
@ -134,23 +138,33 @@ const itemCount = 16; // 这里可以根据实际需求动态设置
.vehicl-content-bottom {
box-sizing: border-box;
margin-top: 12px;
.vehicl-content-bottom-vehicl {
box-sizing: border-box;
padding-top: 16px;
display: flex;
// align-items: flex-end;
width: 100%;
height: 98px;
.vehicl-content-bottom-vehicl-header {
margin-right: 8px;
width: 82px;
height: 82px;
background-image: url("@/assets/common/vehicl_header.png");
.train-card-item {
width: 80px;
height: 56px;
background-image: url("@/assets/vehicleManage/train_card_bg.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
font-weight: 500;
font-size: 12px;
color: #37DBFF;
.train_head_icon{
width: 48px;
height: 48px;
background-image: url("@/assets/vehicleManage/train_head.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
}
.vehicl-content-bottom-vehicl-body-box,
.train-card-item-list,
.high-height {
box-sizing: border-box;
width: 100%;
@ -161,6 +175,7 @@ const itemCount = 16; // 这里可以根据实际需求动态设置
// background-color: #003366; /* */
padding: 0; /* 去除默认内边距 */
margin: 0; /* 去除默认外边距 */
gap: 8px; /* 车厢之间的间距 */
/* 自定义滚动条样式 */
&::-webkit-scrollbar {
height: 8px; /* 滚动条高度 */
@ -170,23 +185,7 @@ const itemCount = 16; // 这里可以根据实际需求动态设置
background-color: #003366; /* 滚动条滑块颜色 */
border-radius: 4px; /* 滑块圆角 */
}
.vehicl-content-bottom-vehicl-body {
box-sizing: border-box;
margin-right: 8px;
padding: 12px 8px;
width: 80px;
height: 66px;
background-image: url("@/assets/common/vehicl_body.png");
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
font-weight: 500;
font-size: 12px;
color: #154DDD;
}
}
.high-height {
height: 90px;
}
}
}

Loading…
Cancel
Save