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 pagination = ref({ currentPage: 1, pageSize: 10, total: 0 });
const listData = ref([]); // const listData = ref([]); //
const currentRow = ref<Record<string, any>>({}); // 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({ const searchForm = reactive({
train_number: "", train_number: "",
@ -307,7 +308,6 @@ onMounted(() => {
:row-class-name="handleRowClassName" :row-class-name="handleRowClassName"
@row-click="handleRowClick" @row-click="handleRowClick"
> >
<template v-slot:actionBar="{ row }"> <template v-slot:actionBar="{ row }">
<ul class="flex table_action_box"> <ul class="flex table_action_box">
<li <li
@ -335,13 +335,13 @@ onMounted(() => {
<li> <li>
<div class="fg-footer-charts-title">日检出量</div> <div class="fg-footer-charts-title">日检出量</div>
<div class="fg-footer-charts-content"> <div class="fg-footer-charts-content">
<PoleDailyDetectionChart :data="dailyDetectionData" /> <!-- <PoleDailyDetectionChart :data="dailyDetectionData" /> -->
</div> </div>
</li> </li>
<li> <li>
<div class="fg-footer-charts-title">日告警分类</div> <div class="fg-footer-charts-title">日告警分类</div>
<div class="fg-footer-charts-content"> <div class="fg-footer-charts-content">
<PoleDailyAlertChart :data="dailyDetectionData" /> <!-- <PoleDailyAlertChart :data="dailyDetectionData" /> -->
</div> </div>
</li> </li>
</ul> </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"> <script setup lang="tsx">
import { BaseTable } from "@/components/CustomTable"; import { BaseTable } from "@/components/CustomTable";
import ContentHeader from "@/components/ContentHeader.vue"; import ContentHeader from "@/components/ContentHeader.vue";
@ -258,6 +199,64 @@ onMounted(() => {
getList(); getList();
}); });
</script> </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"> <style lang="scss">
@import url("./DeviceStatus.scss"); @import url("./DeviceStatus.scss");

@ -1,122 +1,38 @@
.digger-monitor-warp { .digger-monitor-main-content {
box-sizing: border-box; background-image: url("@/assets/diggerMonitor/diggerMonitor-main-bg.png");
padding-top: 32px; background-size: 100% 100%;
width: 100%; background-position: bottom;
height: 100%; background-repeat: no-repeat;
display: flex; height: 586px;
justify-content: space-between; margin-top: 20px;
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-search-box { .digger-monitor-body {
display: flex; padding: 0 24px;
align-items: center; }
gap: 12px; .digger-monitor-search-box {
margin: 16px 0; display: flex;
} align-items: center;
.right-panel{ gap: 12px;
.el-scrollbar__view { margin: 24px 0 16px;;
background: transparent !important; }
height: 600px; .right-panel {
} width: calc(
.fixed_pagination{ 100% - var(--fg-swiper-monitor-slide-iamge-width) -
padding: 12px 20px 15px; var(--fg-swiper-monitor-main-iamge-width) - var(--fg-box-margin) * 2
} );
.el-scrollbar__view {
background: transparent !important;
height: 360px;
} }
}
.digger-monitor-banner {
.digger-monitor-left { .left-panel {
width: 49%; width: calc(
background-image: url("@/assets/common/boderBg.png"); var(--fg-swiper-monitor-slide-iamge-width) +
background-size: 100% 100%; var(--fg-swiper-monitor-main-iamge-width) + var(--fg-box-margin)
background-position: center; );
background-repeat: no-repeat; max-height: 480px;
.monitor-left-top { margin-right: 16px;
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;
}
} }
} }
}

@ -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> <script lang="ts" setup>
import Player from "@/components/videoPlayer/Player.vue"; import { onBeforeRouteLeave } from "vue-router";
import SwiperPlayer from "./components/SwiperPlayer.vue";
import ContentHeader from "@/components/ContentHeader.vue";
import { BaseDelete, BaseTable } from "@/components/CustomTable"; import { BaseDelete, BaseTable } from "@/components/CustomTable";
import { Swiper, SwiperSlide } from "swiper/vue"; import DiggerAlarmModal from "./components/DiggerAlarmModal.vue";
import { Navigation, Scrollbar } from "swiper/modules";
import { import {
getAppearanceMonitorApi, getAppearanceMonitorApi,
getAppearanceMonitorDetailApi, getAppearanceMonitorDetailApi,
@ -131,17 +9,8 @@ import {
deleteAppearanceMonitorApi, deleteAppearanceMonitorApi,
} from "@/api/dashboard"; } from "@/api/dashboard";
import { isSuccessApi } from "@/utils/forApi"; import { isSuccessApi } from "@/utils/forApi";
import DiggerAlarmModal from "./components/DiggerAlarmModal.vue";
import { useWebSocketStore } from "@/stores/websocketStore"; 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 isAlarmOpen = ref<Boolean>(false); //
const isDeleteOpen = ref<Boolean>(false); // const isDeleteOpen = ref<Boolean>(false); //
const websocketStore = useWebSocketStore(); const websocketStore = useWebSocketStore();
@ -149,15 +18,6 @@ const websocketStore = useWebSocketStore();
watch( watch(
() => websocketStore.messages, () => websocketStore.messages,
(newMessages: string[], oldMessages: string[]) => { (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) { if (newMessages?.length > 0 && !isAlarmOpen.value) {
console.log( console.log(
newMessages[newMessages?.length - 1], newMessages[newMessages?.length - 1],
@ -222,76 +82,15 @@ const columns = [
property: "created_at", property: "created_at",
}, },
{ {
slot: "operation", type: "action",
label: "操作", label: "操作",
width: 140, width: 170,
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;
},
},
"删除"
),
]
),
]
);
},
}, },
]; ];
const listData = ref([]); // const listData = ref([]); //
const currentRow = ref<Record<string, any>>({}); // 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 currFile = ref<Record<string, any>>({}); //
// //
const searchForm = reactive({ const searchForm = reactive({
train_number: "", train_number: "",
@ -300,7 +99,6 @@ const searchForm = reactive({
station: "", station: "",
type: "distance", // TODO distance type: "distance", // TODO distance
}); });
const dataLoading = ref(true);
// //
const getFileList = async () => { const getFileList = async () => {
try { try {
@ -312,53 +110,15 @@ const getFileList = async () => {
console.log(res.data, "getDetailList_data"); console.log(res.data, "getDetailList_data");
if (isSuccessApi(res)) { if (isSuccessApi(res)) {
currFileList.value = res.data.data; currFileList.value = res.data.data;
currFile.value = res.data.data[0];
activeIndex.value = 0;
} }
} catch (error) { } catch (error) {
console.log(error, "getDetailList_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() { function loadDetail() {
currentRow.value = listData.value[0]; currentRow.value = listData.value[0];
console.log(currentRow.value, "currentRow"); console.log(currentRow.value, "currentRow");
getFileList(); getFileList();
getBeforeFileList();
} }
// //
@ -426,11 +186,23 @@ const handleRowClassName = ({ row }) => {
return row.id === currentRow.value.id ? "selected-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) => { const handleRowClick = (row, event, rowIndex) => {
currentRow.value = row; currentRow.value = row;
getFileList(); getFileList();
getBeforeFileList();
}; };
onBeforeRouteLeave(() => { onBeforeRouteLeave(() => {
@ -443,6 +215,144 @@ onMounted(() => {
getList(); getList();
}); });
</script> </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"> <style lang="scss">
@import url("./DiggerMonitor.scss"); @import url("./DiggerMonitor.scss");
</style> </style>

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

@ -1,12 +1,14 @@
<template> <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 }"> <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="flex items-center justify-center header-left">
<div class="header-icon mr-[12px]"></div> <div class="header-icon mr-[12px]"></div>
<p class="overflow-hidden whitespace-nowrap text-ellipsis max-w-[650px]">{{ <p class="overflow-hidden whitespace-nowrap text-ellipsis max-w-[650px]">故障提示</p>
"故障提示" }}</p> </div>
<div class="fg-dialog-header-close" @click="close">
</div> </div>
</div> </div>
</template> </template>
@ -17,10 +19,10 @@
<img :src="item.image_url" alt="" v-if="index < 4"></img> <img :src="item.image_url" alt="" v-if="index < 4"></img>
</template> --> </template> -->
<div class="appearanceAlarm-content-top-left"> <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-left-img">
<div class="appearanceAlarm-content-top-img"> <div class="appearanceAlarm-content-top-img">
<img :src="imageBefore" alt=""></img> <img :src="imageBefore" alt="" />
</div> </div>
<div class="appearanceAlarm-content-top-img-slider"> <div class="appearanceAlarm-content-top-img-slider">
<swiper ref="swiperModalRef" :modules="modules" :slides-per-view="3" :space-between="10" navigation <swiper ref="swiperModalRef" :modules="modules" :slides-per-view="3" :space-between="10" navigation
@ -35,7 +37,7 @@
</div> </div>
</div> </div>
<div class="appearanceAlarm-content-top-right"> <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-right-img">
<div class="appearanceAlarm-content-top-img"> <div class="appearanceAlarm-content-top-img">
<img :src="imageAfter" alt=""></img> <img :src="imageAfter" alt=""></img>
@ -53,18 +55,20 @@
</div> </div>
</div> </div>
</div> </div>
<div class="appearanceAlarm-content-bottom"> <div class="appearanceAlarm-content-info mt-[16px]">
<span class="appearanceAlarm-content-bottom-title">列车信息:</span> <div class="font-bold appearanceAlarm-content-info-title mb-[12px]">列车信息:</div>
<div class="appearanceAlarm-content-bottom-info"> <ul class="appearanceAlarm-content-info-list">
<li>
<span class="mr-8">列车编号: <i>{{ info.train_number }}</i></span> <span class="mr-8">列车编号: <i>{{ info.train_number }}</i></span>
<span class="mr-8">车型: <i>{{ info.train_model }}</i></span> <span class="mr-8">车型: <i>{{ info.train_model }}</i></span>
<span>发生时间: <i>{{ info.created_at }}</i></span> <span>发生时间: <i>{{ info.created_at }}</i></span>
</div> </li>
<div class="appearanceAlarm-content-bottom-info"> <li>
<span class="mr-8">告警类型: <i>{{ info.alarm_type }}</i></span> <span class="mr-8">告警类型: <i>{{ info.alarm_type }}</i></span>
<span>故障类型: <i>{{ info.fault_type }}</i></span> <span>故障类型: <i>{{ info.fault_type }}</i></span>
</div> </li>
<div class="appearanceAlarm-content-bottom-btn"> </ul>
<div class="appearanceAlarm-content-info-btn">
<el-button type="primary" @click="exportToExcel" class="appearanceAlarm-btn"> <el-button type="primary" @click="exportToExcel" class="appearanceAlarm-btn">
<span class="icon"></span> 导出 <span class="icon"></span> 导出
</el-button> </el-button>
@ -215,37 +219,9 @@ onMounted(() => {
<style lang="scss"> <style lang="scss">
.appearanceAlarmModal.el-dialog { .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 { .appearanceAlarm-dialog-header {
color: white; color: white;
padding: 0; padding: 0;
padding-top: 8px;
margin-bottom: 10px;
.header-left { .header-left {
padding: 0 24px; padding: 0 24px;
font-weight: bold; font-weight: bold;
@ -280,7 +256,26 @@ onMounted(() => {
// width: 368px; // width: 368px;
// height: 216px; // 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; display: inline-block;
width: 42px; width: 42px;
height: 20px; height: 20px;
@ -345,7 +340,7 @@ onMounted(() => {
position: absolute; position: absolute;
top: 0; top: 0;
left: -16px; left: -16px;
border-left: 2px dashed rgba(255,255,255,0.6); border-left: 1px dashed rgba(255,255,255,0.6);
// width: 2px; /* 线 */ // width: 2px; /* 线 */
height: 100%; /* 分割线高度,根据需要调整 */ height: 100%; /* 分割线高度,根据需要调整 */
// margin-right: 10px; /* 线 */ // margin-right: 10px; /* 线 */
@ -392,10 +387,8 @@ onMounted(() => {
} }
} }
} }
.appearanceAlarm-content-bottom { .appearanceAlarm-content-info {
box-sizing: border-box; .appearanceAlarm-content-info-title {
margin-top: 12px;
.appearanceAlarm-content-bottom-title {
box-sizing: border-box; box-sizing: border-box;
padding-left: 8px; padding-left: 8px;
height: 22px; height: 22px;
@ -406,20 +399,25 @@ onMounted(() => {
line-height: 22px; 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; font-size: 14px;
color: #FFFFFF; color: #FFFFFF;
i { i {
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
} }
}
} }
.appearanceAlarm-content-bottom-info:nth-of-type(1) { .appearanceAlarm-content-info-list:nth-of-type(1) {
margin: 4px 0; margin: 4px 0;
} }
.appearanceAlarm-content-bottom-btn { .appearanceAlarm-content-info-btn {
margin-top: 24px; margin-top: 32px;
text-align: end; text-align: end;
.appearanceAlarm-btn { .appearanceAlarm-btn {
width: 96px; width: 96px;

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

@ -1,9 +1,15 @@
<template> <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 }"> <template #header="{ close, titleId, titleClass }">
<div <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="flex items-center justify-center header-left">
<div class="header-icon mr-[12px]"></div> <div class="header-icon mr-[12px]"></div>
@ -13,6 +19,7 @@
钩机详情 钩机详情
</p> </p>
</div> </div>
<div class="fg-dialog-header-close" @click="close"></div>
</div> </div>
</template> </template>
<!-- 图片区域 --> <!-- 图片区域 -->
@ -45,7 +52,7 @@ interface Emits {
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
value: false, value: false,
info: {}, info: {},
fileList: [] fileList: [],
}); });
const emit = defineEmits<Emits>(); const emit = defineEmits<Emits>();
@ -66,44 +73,14 @@ const show = computed({
<style lang="scss"> <style lang="scss">
.digger-alarm-modal.el-dialog { .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 { .digger-detail-dialog-header {
color: white;
padding: 0;
padding-top: 8px;
margin-bottom: 10px;
.header-left { .header-left {
padding: 0 24px; padding: 0 24px;
font-weight: bold; font-weight: bold;
font-size: 18px; font-size: 18px;
.header-icon { .header-icon {
margin-top: 4px;
width: 24px; width: 24px;
height: 48px; height: 48px;
background-image: url("@/assets/common/alarm_title.png"); background-image: url("@/assets/common/alarm_title.png");
@ -116,13 +93,13 @@ const show = computed({
.digger-detail-content { .digger-detail-content {
box-sizing: border-box; box-sizing: border-box;
padding: 0 24px; padding: 8px 24px;
width: 100%; width: 100%;
height: 500px; height: 529px;
img{ img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
} }
</style> </style>

@ -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> <script lang="ts" setup>
import Player from '@/components/videoPlayer/Player.vue' import Player from "@/components/videoPlayer/Player.vue";
import { ElMessage } from 'element-plus'; import { ElMessage } from "element-plus";
import { extractUniqueDatesWithMoment, filterDataByDate } from '@/utils/array'; import { extractUniqueDatesWithMoment, filterDataByDate } from "@/utils/array";
interface Props { interface Props {
value: boolean; /** 弹窗显隐 */ value: boolean /** 弹窗显隐 */;
info: Record<string, any>; /** 设备信息 */ info: Record<string, any> /** 设备信息 */;
historyVideos: Record<string, any>[]; /** 历史视频列表 */ historyVideos: Record<string, any>[] /** 历史视频列表 */;
} }
interface Emits { interface Emits {
(e: "update:value", val: boolean): void; (e: "update:value", val: boolean): void;
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
value: false, value: false,
info: {}, info: {},
historyVideos: [] historyVideos: [],
}); });
const emit = defineEmits<Emits>(); const emit = defineEmits<Emits>();
@ -67,219 +22,270 @@ const emit = defineEmits<Emits>();
const dateList = ref<string[]>([]); const dateList = ref<string[]>([]);
const selectedDate = ref(); // const selectedDate = ref(); //
const recordList = ref([]); const recordList = ref([]);
const currentVideo = ref<Record<string, any>>({}) const currentVideo = ref<Record<string, any>>({});
const isPlaying = ref(false); const isPlaying = ref(false);
const togglePlay = () => { const togglePlay = () => {
isPlaying.value = !isPlaying.value; isPlaying.value = !isPlaying.value;
}; };
// TODO 使 // TODO 使
const handleProgress = (data: { currentTime: number, duration: number }) => { const handleProgress = (data: { currentTime: number; duration: number }) => {
console.log((data.currentTime / data.duration) * 100, "handleProgress") console.log((data.currentTime / data.duration) * 100, "handleProgress");
const progressVal = (data.currentTime / data.duration) * 100 const progressVal = (data.currentTime / data.duration) * 100;
} };
// TODO 使 // TODO 使
const handleDuration = (newDuration: number) => { const handleDuration = (newDuration: number) => {
// duration.value = newDuration // duration.value = newDuration
} };
// //
const loadData = () => { const loadData = () => {
recordList.value = props.historyVideos recordList.value = props.historyVideos;
dateList.value = extractUniqueDatesWithMoment(recordList.value); dateList.value = extractUniqueDatesWithMoment(recordList.value);
currentVideo.value = props.historyVideos[0]; // currentVideo.value = props.historyVideos[0]; //
}; };
// //
const handleDateChange = (date) => { const handleDateChange = (date) => {
console.log(date, "handleDateChange_date"); console.log(date, "handleDateChange_date");
if (date) { if (date) {
selectedDate.value = date; selectedDate.value = date;
recordList.value = filterDataByDate(toRaw(props.historyVideos), date); recordList.value = filterDataByDate(toRaw(props.historyVideos), date);
currentVideo.value = recordList.value[0]; // currentVideo.value = recordList.value[0]; //
} else { } else {
loadData() loadData();
} }
}; };
// //
const handleItemClick = (item) => { const handleItemClick = (item) => {
if (currentVideo.value?.id === item.id) { if (currentVideo.value?.id === item.id) {
togglePlay() // togglePlay(); //
} else { } else {
currentVideo.value = item; currentVideo.value = item;
} }
}; };
// //
const handleVideoEnd = () => { const handleVideoEnd = () => {
// currentIndex.value = -1; // currentIndex.value = -1;
}; };
// //
const formatTime = (timeStr) => { const formatTime = (timeStr) => {
return timeStr.split(' ')[1].substring(0, 5); // return timeStr.split(" ")[1].substring(0, 5); //
}; };
// //
const handleClose = () => { const handleClose = () => {
emits('close'); emits("close");
}; };
const show = computed({ const show = computed({
get() { get() {
return props.value; return props.value;
}, },
set(val: boolean) { set(val: boolean) {
emit("update:value", val); emit("update:value", val);
} },
}); });
// TODO // TODO
defineExpose({ loadData }) defineExpose({ loadData });
</script> </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"> <style lang="scss">
.historyVideoModal-wrap.el-dialog { .historyVideoModal-wrap.el-dialog {
border: none; .video-dialog-header {
overflow: hidden; color: white;
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;
padding: 0; padding: 0;
margin-top: calc(50vh - 316px); padding-top: 4px;
.el-dialog__header.show-close { .header-left {
padding: 0; 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; .main-content {
height: 56px; padding: 8px 24px 24px;
color: white;
font-size: 18px; // background: red;
padding-top: 4px; .video-player-box {
padding-right: 20px; border-radius: 0px 0px 4px 4px;
overflow: hidden;
width: 752px;
height: 502px;
.video-element {
width: 100%;
height: 100%;
}
} }
.video-dialog-header { .video-record-list {
color: white; flex-direction: column;
padding: 0; flex: 1;
padding-top: 4px; color: white;
.header-left { .record_date_select {
padding: 0 18px; width: 100%;
font-weight: bold; display: flex;
font-size: 18px; flex: 1;
border-radius: 2px;
.header-icon { // border: none;
margin-top: 8px; border: 1px solid rgba(8, 139, 214, 0.4);
width: 48px;
height: 48px; .el-select__wrapper {
background-image: url("@/assets/common/dialog_title_icon.png"); width: 100%;
background-size: contain;
background-position: center; &.is-focused {
background-repeat: no-repeat; box-shadow: none;
} }
&.is-hovering {
border: none;
}
&:hover {
border: none;
}
} }
} }
.main-content { .record-list-box {
padding-left: 24px; margin-top: 12px;
padding-top: 24px; display: grid;
gap: 12px;
// background: red; li {
.video-player-box { color: white;
border-radius: 0px 0px 4px 4px; height: 32px;
overflow: hidden; cursor: pointer;
width: 752px; padding-left: 16px;
height: 502px; padding-right: 24px;
// margin: 6px 0;
.video-element { background: rgba(9, 82, 129, 0.6);
width: 100%; border-radius: 2px;
height: 100%; border: 1px solid rgba(22, 139, 202, 0.3);
} &.active,
} &:hover {
background: rgba(9, 82, 129, 0.6);
.video-record-list { box-shadow: inset 2px 2px 4px 0px rgba(51, 178, 185, 0.6),
flex-direction: column; 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; flex: 1;
color: white; font-size: 14px;
}
.record_date_select {
width: 100%; .play-btn {
display: flex; width: 20px;
flex: 1; height: 20px;
border-radius: 2px; background: url("@/assets/common/player_icon.png") no-repeat center
// border: none; center;
border: 1px solid rgba(8, 139, 214, 0.4); background-size: contain;
}
.playing {
.el-select__wrapper { background: url("@/assets/common/pause_icon.png") no-repeat center
width: 100%; center;
background-size: contain;
&.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;
}
}
}
} }
}
} }
}
} }
</style> </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> <template>
<el-dialog class="vehiclModal-wrap fg-dialog fg-dialog2" v-model="show" @close="handleClose" align-center :show-close="false" > <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"> <div class="vehicl-content-bottom">
<!-- //TODO --> <!-- //TODO -->
<span class="vehicl-content-bottom-title">列车与车厢号</span> <span class="vehicl-content-bottom-title">列车与车厢号</span>
<div class="vehicl-content-bottom-vehicl"> <div class="flex items-center vehicl-content-bottom-vehicl">
<div class="vehicl-content-bottom-vehicl-header"></div> <div class="train-card-item mb-[8px] mr-[8px] flex items-center justify-center ">
<div :class="['vehicl-content-bottom-vehicl-body-box', { 'high-height': info?.data?.train_data?.length > 15 }]"> <div class="train_head_icon"></div>
<div class="vehicl-content-bottom-vehicl-body" v-for="(item, index) in info?.data?.train_data" :key="index"> </div>
<div>{{ item.model }}</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> <div>
<!-- <span class="mr-3">04</span> --> <!-- <span class="mr-3">04</span> -->
<span>{{ item.carriage_number }}</span> <span>{{ item.carriage_number }}</span>
</div> </div>
</div> </div>
</div> </li>
</ul>
</div> </div>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
</template> </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"> <style lang="scss">
.vehiclModal-wrap.el-dialog { .vehiclModal-wrap.el-dialog {
@ -96,7 +101,6 @@ const itemCount = 16; // 这里可以根据实际需求动态设置
font-weight: bold; font-weight: bold;
font-size: 18px; font-size: 18px;
.header-icon { .header-icon {
margin-top: 4px;
width: 24px; width: 24px;
height: 48px; height: 48px;
background-image: url("@/assets/common/alarm_title.png"); background-image: url("@/assets/common/alarm_title.png");
@ -134,23 +138,33 @@ const itemCount = 16; // 这里可以根据实际需求动态设置
.vehicl-content-bottom { .vehicl-content-bottom {
box-sizing: border-box; box-sizing: border-box;
margin-top: 12px; margin-top: 12px;
.vehicl-content-bottom-vehicl { .vehicl-content-bottom-vehicl {
box-sizing: border-box; box-sizing: border-box;
padding-top: 16px; padding-top: 16px;
display: flex; display: flex;
// align-items: flex-end;
width: 100%; width: 100%;
height: 98px; height: 98px;
.vehicl-content-bottom-vehicl-header { .train-card-item {
margin-right: 8px; width: 80px;
width: 82px; height: 56px;
height: 82px; background-image: url("@/assets/vehicleManage/train_card_bg.png");
background-image: url("@/assets/common/vehicl_header.png");
background-size: 100% 100%; background-size: 100% 100%;
background-position: center; background-position: center;
background-repeat: no-repeat; 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 { .high-height {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
@ -161,6 +175,7 @@ const itemCount = 16; // 这里可以根据实际需求动态设置
// background-color: #003366; /* */ // background-color: #003366; /* */
padding: 0; /* 去除默认内边距 */ padding: 0; /* 去除默认内边距 */
margin: 0; /* 去除默认外边距 */ margin: 0; /* 去除默认外边距 */
gap: 8px; /* 车厢之间的间距 */
/* 自定义滚动条样式 */ /* 自定义滚动条样式 */
&::-webkit-scrollbar { &::-webkit-scrollbar {
height: 8px; /* 滚动条高度 */ height: 8px; /* 滚动条高度 */
@ -170,23 +185,7 @@ const itemCount = 16; // 这里可以根据实际需求动态设置
background-color: #003366; /* 滚动条滑块颜色 */ background-color: #003366; /* 滚动条滑块颜色 */
border-radius: 4px; /* 滑块圆角 */ 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