AaronBruin 2 months ago
parent
commit
05875630c3

+ 0 - 16
src/views/system/broadcast/modules/eventList.vue

@@ -1,22 +1,6 @@
 <template>
     <div class="_eventList">
         <HeadlineTag type="right" value="终端日志" style="flex-shrink: 0;"></HeadlineTag>
-        <!-- <div class="_eventList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
-            <div :style="{ transform: `translateY(${scrollY}px)` }">
-                <div class="_eventList_mains_item" v-for="(item, index) in eventList.concat(eventList)" :key="index">
-                    <div class="_eventList_mains_item_text">
-                        <div :class="item.store === 'on' ? '_warning' : '_success'"
-                            class="_eventList_mains_item_text_flag"></div>
-                        <el-text class="w-150px mb-2" truncated style="color: white;margin-left: 10px;">
-                            {{ index + 1 }}#{{ item.TerminalLog }}
-                        </el-text>
-                    </div>
-                    <div class="_eventList_mains_item_btn">
-                        {{ item.TerminalTime }}
-                    </div>
-                </div>
-            </div>
-        </div> -->
         <div class="scroll-view" ref="scrollViewRef" @mouseenter="onMouseenter" @mouseleave="onMouseleave">
             <div ref="listRef" class="list" v-for="(p, n) in count" :key="n">
                 <div class="item" v-for="(item, index) in data" :key="index">

+ 1 - 1
src/views/system/building/equipment.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="page">
         <div class="header-view">
-            <div class="view_item" v-for="item in headerList">{{ item }}</div>
+            <div class="view_item" v-for="(item, index) in headerList">{{ item }}</div>
         </div>
         <div class="warning-view">
             <div class="scroll-view" ref="scrollViewRef" @mouseenter="onMouseenter" @mouseleave="onMouseleave">

+ 141 - 86
src/views/system/intruderalarm/alarm.vue

@@ -1,24 +1,16 @@
 <template>
     <div class="_eventList">
-        <!-- 绑定鼠标移入移出事件 -->
-        <div class="_eventList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
-            <!-- 复制一份数据用于无缝滚动 -->
-            <div :style="{ transform: `translateY(${scrollY}px)` }">
-                <div class="_eventList_mains_item" v-for="(item, index) in eventList" :key="index">
+        <div class="scroll-view" ref="scrollViewRef" @mouseenter="onMouseenter" @mouseleave="onMouseleave">
+            <div ref="listRef" class="list" v-for="(p, n) in count" :key="n">
+                <div class="item" v-for="(item, index) in data" :key="index">
                     <div class="_eventList_mains_item_text">
-                        <div :class="item.Name === 0 ? '_warning' : '_success'" class="_eventList_mains_item_text_flag">
+                        <div :class="item.State === 0 ? '_warning' : '_success'" class="_eventList_mains_item_text_flag">
                         </div>
                         <el-text class="w-150px mb-2" truncated style="color: white;margin-left: 10px;">
                             {{ item.Name }}
                         </el-text>
                     </div>
                     <el-text class="w-150px mb-2" truncated style="color: white;">
-                        {{ item.Phone }}
-                    </el-text>
-                    <el-text class="w-150px mb-2" truncated style="color: white;">
-                        {{ item.Location }}
-                    </el-text>
-                    <el-text class="w-150px mb-2" truncated style="color: white;">
                         {{ item.Date }}
                     </el-text>
                 </div>
@@ -35,87 +27,73 @@ const props = defineProps({
         default: {}
     }
 })
-// const eventList = ref([{
-//     name: '张史蒂',
-//     phone: '17231123222',
-//     address: '1号门',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     name: '张史蒂',
-//     phone: '17231123222',
-//     address: '1号门',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     name: '张史蒂',
-//     phone: '17231123222',
-//     address: '1号门',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     name: '张史蒂',
-//     phone: '17231123222',
-//     address: '1号门',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     name: '张史蒂',
-//     phone: '17231123222',
-//     address: '1号门',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     name: '张史蒂',
-//     phone: '17231123222',
-//     address: '1号门',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     name: '张史蒂',
-//     phone: '17231123222',
-//     address: '1号门',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     name: '张史蒂',
-//     phone: '17231123222',
-//     address: '1号门',
-//     time: '2025-04-15 10:20:00'
-// }])
-
-const eventList = ref([])
+
+const data = ref(); //列表数据
+const listRef = ref(); //列表dom
+const scrollViewRef = ref(); //滚动区域dom
+const count = ref(1); //列表个数
+
+let intervalId = null;
+let isAutoScrolling = true; //是否自动滚动标识
+
+//获取列表数据
+const getData = () => {
+    //模拟接口请求列表数据
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            //生成10条数据
+            let list = new Array(30).fill().map((item, index) => index);
+            resolve(list);
+        }, 100);
+    });
+};
+
 watch(() => props.resultData, (newVal) => {
     if (newVal) {
-        eventList.value = []
-        eventList.value = newVal.realTime
+        // data.value = await getData();
+        data.value = newVal;
+        intervalId && clearInterval(intervalId);
+        nextTick(() => {
+            //判断列表是否生成滚动条
+            count.value = hasScrollBar() ? 2 : 1;
+            //有滚动条开始自动滚动
+            if (count.value == 2) {
+                autoScrolling();
+            }
+        });
     }
 }, { deep: true, immediate: true } // 开启深度监听
 )
-const mainsRef = ref(null)
-const scrollY = ref(0)
-let intervalId = null
-const scrollSpeed = 1 // 滚动速度
-
-const startCarousel = () => {
+onMounted(() => {
+})
+//判断列表是否有滚动条
+const hasScrollBar = () => {
+    return scrollViewRef.value.scrollHeight > scrollViewRef.value.clientHeight;
+};
+//设置自动滚动
+const autoScrolling = () => {
     intervalId = setInterval(() => {
-        const itemHeight = mainsRef.value.querySelector('._eventList_mains_item').offsetHeight
-        scrollY.value -= scrollSpeed
-        if (Math.abs(scrollY.value) >= itemHeight * eventList.value.length) {
-            scrollY.value = 0
+        if (scrollViewRef.value.scrollTop < listRef.value[0].clientHeight) {
+            scrollViewRef.value.scrollTop += isAutoScrolling ? 1 : 0;
+        } else {
+            scrollViewRef.value.scrollTop = 0;
         }
-    }, 20)
-}
-
-const pauseCarousel = () => {
-    clearInterval(intervalId)
-}
-
-const resumeCarousel = () => {
-    startCarousel()
-}
-
-onMounted(async () => {
-    await nextTick();
-    startCarousel()
-})
-
-onUnmounted(() => {
-    clearInterval(intervalId)
-})
+    }, 20);
+};
+
+onBeforeUnmount(() => {
+    //离开页面清理定时器
+    intervalId && clearInterval(intervalId);
+});
+
+//鼠标进入,停止滚动
+const onMouseenter = () => {
+    isAutoScrolling = false;
+};
+//鼠标移出,继续滚动
+const onMouseleave = () => {
+    isAutoScrolling = true;
+};
 </script>
 
 <style lang="scss" scoped>
@@ -168,4 +146,81 @@ onUnmounted(() => {
         }
     }
 }
+
+.header-view {
+    margin-top: 10px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10px 10px 10px 20px;
+    background-color: rgba(16, 40, 92, 1);
+}
+
+.view_item {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+}
+
+.warning-view {
+    width: 100%;
+    height: calc(100% - 51px);
+    display: flex;
+    flex-direction: column;
+}
+
+.label {
+    color: #fff;
+    padding: 20px;
+    font-size: 22px;
+}
+
+.scroll-view {
+    flex: 1;
+    height: 0;
+    width: 100%;
+    overflow-y: auto;
+}
+
+.list {
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.item {
+    padding: 0px 10px 0px 20px;
+    width: 100%;
+    height: 50px;
+    min-height: 50px;
+    font-size: 15px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: #eee;
+}
+
+.item:nth-child(even) {
+    background: rgba(16, 40, 92, 0.4);
+}
+
+.item:hover {
+    cursor: pointer;
+    background-image: linear-gradient(to right, #168cdb, transparent);
+}
+
+/*隐藏滚动条
+ */
+::-webkit-scrollbar {
+    display: none;
+}
+
+.blue_title {
+    color: #67C23A;
+}
+
+.red_title {
+    color: #F56C6C;
+}
 </style>

+ 5 - 34
src/views/system/intruderalarm/index.vue

@@ -15,7 +15,7 @@
                             <div class="point_box" style="margin-top: 10px;margin-left: 15px;">
                                 <el-input v-model="input" placeholder="按报警名称搜索" />
                             </div>
-                            <alarm :resultData="leftData"></alarm>
+                            <alarm :resultData="leftData.realTime"></alarm>
                             <!-- <div style="height: calc(100% - 160px);">
                                 <Empty></Empty>
                             </div>
@@ -64,11 +64,10 @@
                             <div ref="chartRouting" style="width: 100%;height: 100%;"></div>
                         </div>
                     </div>
-                    <div class="flex_spection">
-                        <HeadlineTag type="right" value="实时巡检"></HeadlineTag>
+                    <div class="flex_spection" style="height: 33%;">
+                        <HeadlineTag type="right" value="实时监控"></HeadlineTag>
                         <div class="box_arch">
-                            <dv-scroll-board :config="config"
-                                style="width:100%;height:calc(100% - 10px);margin-top: 10px;" />
+                            <inspection :resultData="leftData.realTime"></inspection>
                         </div>
                     </div>
                 </div>
@@ -84,6 +83,7 @@ import layout from "@/components/layout_/index.vue";
 import HeadlineTag from '@/components/HeadlineTag'
 import Empty from '@/components/Empty'
 import alarm from './alarm.vue'
+import inspection from './inspection.vue'
 import * as echarts from 'echarts'
 import 'echarts-liquidfill';
 const total = ref(0);
@@ -92,25 +92,6 @@ const queryParams = ref({
     pageSize: 10,
 });
 const input = ref('')
-const config = ref({
-    headerBGC: '#10285c',
-    oddRowBGC: '#10285c7f',
-    evenRowBGC: '#10285c00',
-    header: ['名称', '位置', '列3'],
-    data: [
-        // ['行1列1', '行1列2', '行1列3'],
-        // ['行2列1', '行2列2', '行2列3'],
-        // ['行3列1', '行3列2', '行3列3'],
-        // ['行4列1', '行4列2', '行4列3'],
-        // ['行5列1', '行5列2', '行5列3'],
-        // ['行6列1', '行6列2', '行6列3'],
-        // ['行7列1', '行7列2', '行7列3'],
-        // ['行8列1', '行8列2', '行8列3'],
-        // ['行9列1', '行9列2', '行9列3'],
-        // ['行10列1', '行10列2', '行10列3']
-    ]
-})
-
 /** 查询列表 */
 function getList() {
 };
@@ -564,16 +545,6 @@ watch(() => leftData.value, (newVal) => {
                 data: Object.entries(newVal.AlarmTrend24Hour),
             }],
         })
-        let arrData = []
-        let arrData1 = newVal.realTime
-        arrData1.forEach(item => {
-            let arrData2 = []
-            arrData2.push(item.Name)
-            arrData2.push(item.Location)
-            arrData2.push(item.Event)
-            arrData.push(arrData2)
-        })
-        config.value.data = arrData
     }
 }, { deep: true, immediate: true } // 开启深度监听
 )

+ 190 - 0
src/views/system/intruderalarm/inspection.vue

@@ -0,0 +1,190 @@
+<template>
+    <div class="page">
+        <div class="header-view">
+            <div class="view_item" v-for="item in headerList">{{ item }}</div>
+        </div>
+        <div class="warning-view">
+            <div class="scroll-view" ref="scrollViewRef" @mouseenter="onMouseenter" @mouseleave="onMouseleave">
+                <div ref="listRef" class="list" v-for="(p, n) in count" :key="n">
+                    <div class="item" v-for="(item, index) in data" :key="index">
+                        <div class="content view_item">{{ item.Name }}</div>
+                        <div class="time view_item">
+                            {{ item.Name }}
+                        </div>
+                        <div class="time view_item">{{ item.Date }}</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref, onBeforeMount, onMounted, onBeforeUnmount, nextTick } from "vue";
+const props = defineProps({
+    resultData: {
+        type: Array,
+        default: []
+    }
+})
+const headerList = ref(['名称', '位置', '时间'])
+const data = ref([]); //列表数据
+const listRef = ref(); //列表dom
+const scrollViewRef = ref(); //滚动区域dom
+const count = ref(1); //列表个数
+
+let intervalId = null;
+let isAutoScrolling = true; //是否自动滚动标识
+
+//获取列表数据
+const getData = () => {
+    //模拟接口请求列表数据
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            //生成10条数据
+            let list = new Array(30).fill().map((item, index) => index);
+            resolve(list);
+        }, 100);
+    });
+};
+
+watch(() => props.resultData, (newVal) => {
+    if (newVal) {
+        // data.value = await getData();
+        data.value = newVal;
+        intervalId && clearInterval(intervalId);
+        nextTick(() => {
+            //判断列表是否生成滚动条
+            count.value = hasScrollBar() ? 2 : 1;
+            //有滚动条开始自动滚动
+            if (count.value == 2) {
+                autoScrolling();
+            }
+        });
+    }
+}, { deep: true, immediate: true } // 开启深度监听
+)
+onMounted(() => {
+})
+//判断列表是否有滚动条
+const hasScrollBar = () => {
+    return scrollViewRef.value.scrollHeight > scrollViewRef.value.clientHeight;
+};
+//设置自动滚动
+const autoScrolling = () => {
+    intervalId = setInterval(() => {
+        if (scrollViewRef.value.scrollTop < listRef.value[0].clientHeight) {
+            scrollViewRef.value.scrollTop += isAutoScrolling ? 1 : 0;
+        } else {
+            scrollViewRef.value.scrollTop = 0;
+        }
+    }, 20);
+};
+
+onBeforeUnmount(() => {
+    //离开页面清理定时器
+    intervalId && clearInterval(intervalId);
+});
+
+//鼠标进入,停止滚动
+const onMouseenter = () => {
+    isAutoScrolling = false;
+};
+//鼠标移出,继续滚动
+const onMouseleave = () => {
+    isAutoScrolling = true;
+};
+</script>
+
+<style scoped lang="scss">
+.page {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    overflow: hidden;
+}
+
+.header-view {
+    margin-top: 10px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10px 10px 10px 20px;
+    background-color: rgba(16, 40, 92, 1);
+}
+
+.view_item {
+    // flex: 1;
+    // display: flex;
+    // align-items: center;
+    // justify-content: flex-start;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    max-width: 33%;
+}
+
+.warning-view {
+    width: 100%;
+    height: calc(100% - 51px);
+    display: flex;
+    flex-direction: column;
+}
+
+.label {
+    color: #fff;
+    padding: 20px;
+    font-size: 22px;
+}
+
+.scroll-view {
+    flex: 1;
+    height: 0;
+    width: 100%;
+    overflow-y: auto;
+}
+
+.list {
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.item {
+    padding: 0px 10px 0px 20px;
+    width: 100%;
+    height: 50px;
+    min-height: 50px;
+    font-size: 15px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: #eee;
+}
+
+.item:nth-child(even) {
+    background: rgba(16, 40, 92, 0.4);
+}
+
+.item:hover {
+    cursor: pointer;
+    background-image: linear-gradient(to right, #168cdb, transparent);
+}
+
+/*隐藏滚动条
+ */
+::-webkit-scrollbar {
+    display: none;
+}
+
+.blue_title {
+    color: #67C23A;
+}
+
+.red_title {
+    color: #F56C6C;
+}
+</style>

+ 157 - 65
src/views/system/lighting/modules/deviceList.vue

@@ -4,7 +4,29 @@
         <div class="point_box" style="margin-top: 10px;">
             <el-input v-model="value" placeholder="按巡查点名称搜索" />
         </div>
-        <div class="_deviceList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
+        <div class="scroll-view" ref="scrollViewRef" @mouseenter="onMouseenter" @mouseleave="onMouseleave">
+            <div ref="listRef" class="list" v-for="(p, n) in count" :key="n">
+                <div class="item" v-for="(item, index) in data" :key="index">
+                    <el-text class="w-150px mb-2 _table_row1" truncated style="color: white;flex: .4;">
+                        <el-icon color="#168cdb">
+                            <el-icon>
+                                <Opportunity />
+                            </el-icon>
+                        </el-icon>
+                        {{ item.DeviceName }}
+                    </el-text>
+                    <el-text class="w-150px mb-2" truncated :class="item.SwitchStatus == 0 ? 'blue_title' : 'red_title'"
+                        style="flex: .2;">
+                        {{ item.SwitchStatus == 0 ? '开启' : '关闭' }}
+                    </el-text>
+                    <el-text class="w-150px mb-2" truncated
+                        :class="item.OnlinePresence == 0 ? 'blue_title' : 'red_title'" style="flex: .2">
+                        {{ item.OnlinePresence == 0 ? '在线' : '离线' }}
+                    </el-text>
+                </div>
+            </div>
+        </div>
+        <!-- <div class="_deviceList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
             <div :style="{ transform: `translateY(${scrollY}px)` }">
                 <div class="_deviceList_mains_item" v-for="(item, index) in eventList" :key="index">
                     <el-text class="w-150px mb-2 _table_row1" truncated style="color: white;flex: .4;">
@@ -28,7 +50,7 @@
                     </el-icon>
                 </div>
             </div>
-        </div>
+        </div> -->
     </div>
 </template>
 
@@ -44,81 +66,74 @@ const props = defineProps({
 })
 
 const value = ref('')
-// const eventList = ref([
-//     { name: '回路1', state: '开启', flag: '在线' },
-//     { name: '回路2', state: '关闭', flag: '离线' },
-//     { name: '回路3', state: '开启', flag: '在线' },
-//     { name: '回路4', state: '关闭', flag: '离线' },
-//     { name: '回路5', state: '开启', flag: '在线' },
-//     { name: '回路6', state: '关闭', flag: '离线' },
-//     { name: '回路7', state: '开启', flag: '在线' },
-//     { name: '回路8', state: '关闭', flag: '离线' },
-//     { name: '回路9', state: '开启', flag: '在线' },
-//     { name: '回路10', state: '关闭', flag: '离线' },
-//     { name: '回路11', state: '开启', flag: '在线' },
-//     { name: '回路12', state: '关闭', flag: '离线' },
-//     { name: '回路13', state: '开启', flag: '在线' },
-//     { name: '回路14', state: '关闭', flag: '离线' },
-//     { name: '回路15', state: '开启', flag: '在线' },
-//     { name: '回路16', state: '关闭', flag: '离线' },
-//     { name: '回路17', state: '开启', flag: '在线' },
-//     { name: '回路18', state: '关闭', flag: '离线' },
-//     { name: '回路19', state: '开启', flag: '在线' },
-//     { name: '回路20', state: '关闭', flag: '离线' },
-//     { name: '回路21', state: '开启', flag: '在线' },
-//     { name: '回路22', state: '关闭', flag: '离线' },
-//     { name: '回路23', state: '开启', flag: '在线' },
-//     { name: '回路24', state: '关闭', flag: '离线' }
-// ])
-
-const eventList = ref([])
+
+const headerList = ref(['名称', '状态', '时间'])
+const data = ref(); //列表数据
+const listRef = ref(); //列表dom
+const scrollViewRef = ref(); //滚动区域dom
+const count = ref(1); //列表个数
+
+let intervalId = null;
+let isAutoScrolling = true; //是否自动滚动标识
+
+//获取列表数据
+const getData = () => {
+    //模拟接口请求列表数据
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            //生成10条数据
+            let list = new Array(30).fill().map((item, index) => index);
+            resolve(list);
+        }, 100);
+    });
+};
+
 watch(() => props.resultData, (newVal) => {
     if (newVal) {
-        eventList.value = []
-        eventList.value = newVal
+        // data.value = await getData();
+        data.value = newVal;
+        intervalId && clearInterval(intervalId);
+        nextTick(() => {
+            //判断列表是否生成滚动条
+            count.value = hasScrollBar() ? 2 : 1;
+            //有滚动条开始自动滚动
+            if (count.value == 2) {
+                autoScrolling();
+            }
+        });
     }
 }, { deep: true, immediate: true } // 开启深度监听
 )
-const mainsRef = ref(null)
-const scrollY = ref(0)
-let intervalId = null
-const scrollSpeed = 1 // 滚动速度
-
-const startCarousel = () => {
+onMounted(() => {
+})
+//判断列表是否有滚动条
+const hasScrollBar = () => {
+    return scrollViewRef.value.scrollHeight > scrollViewRef.value.clientHeight;
+};
+//设置自动滚动
+const autoScrolling = () => {
     intervalId = setInterval(() => {
-        const itemHeight = mainsRef.value?.querySelector('._deviceList_mains_item')?.offsetHeight;
-        if (!itemHeight) return;
-        scrollY.value -= scrollSpeed;
-        // 检查第一个元素是否完全离开视口
-        if (Math.abs(scrollY.value) >= itemHeight) {
-            // 将第一个元素移到列表末尾
-            const firstItem = eventList.value.shift();
-            if (firstItem) {
-                eventList.value.push(firstItem);
-            }
-            // 调整滚动位置
-            scrollY.value += itemHeight;
+        if (scrollViewRef.value.scrollTop < listRef.value[0].clientHeight) {
+            scrollViewRef.value.scrollTop += isAutoScrolling ? 1 : 0;
+        } else {
+            scrollViewRef.value.scrollTop = 0;
         }
     }, 20);
 };
 
-const pauseCarousel = () => {
-    clearInterval(intervalId);
-};
-
-const resumeCarousel = () => {
-    startCarousel();
-};
-
-onMounted(() => {
-    nextTick(() => {
-        startCarousel();
-    })
+onBeforeUnmount(() => {
+    //离开页面清理定时器
+    intervalId && clearInterval(intervalId);
 });
 
-onUnmounted(() => {
-    clearInterval(intervalId);
-});
+//鼠标进入,停止滚动
+const onMouseenter = () => {
+    isAutoScrolling = false;
+};
+//鼠标移出,继续滚动
+const onMouseleave = () => {
+    isAutoScrolling = true;
+};
 </script>
 
 <style lang="scss">
@@ -144,6 +159,83 @@ onUnmounted(() => {
         }
     }
 }
+
+.header-view {
+    margin-top: 10px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10px 10px 10px 20px;
+    background-color: rgba(16, 40, 92, 1);
+}
+
+.view_item {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+}
+
+.warning-view {
+    width: 100%;
+    height: calc(100% - 51px);
+    display: flex;
+    flex-direction: column;
+}
+
+.label {
+    color: #fff;
+    padding: 20px;
+    font-size: 22px;
+}
+
+.scroll-view {
+    flex: 1;
+    height: 0;
+    width: 100%;
+    overflow-y: auto;
+}
+
+.list {
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.item {
+    padding: 0px 10px 0px 20px;
+    width: 100%;
+    height: 50px;
+    min-height: 50px;
+    font-size: 15px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: #eee;
+}
+
+.item:nth-child(even) {
+    background: rgba(16, 40, 92, 0.4);
+}
+
+.item:hover {
+    cursor: pointer;
+    background-image: linear-gradient(to right, #168cdb, transparent);
+}
+
+/*隐藏滚动条
+ */
+::-webkit-scrollbar {
+    display: none;
+}
+
+.blue_title {
+    color: #67C23A;
+}
+
+.red_title {
+    color: #F56C6C;
+}
 </style>
 
 <style lang="scss" scoped>

+ 152 - 75
src/views/system/lighting/modules/eventList.vue

@@ -2,8 +2,7 @@
     <div class="_eventList">
         <HeadlineTag type="right" value="事件列表" style="flex-shrink: 0;"></HeadlineTag>
         <!-- 绑定鼠标移入移出事件 -->
-        <div class="_eventList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
-            <!-- 复制一份数据用于无缝滚动 -->
+        <!-- <div class="_eventList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
             <div :style="{ transform: `translateY(${scrollY}px)` }">
                 <div class="_eventList_mains_item" v-for="(item, index) in eventList.concat(eventList)" :key="index">
                     <div class="_eventList_mains_item_text">
@@ -18,6 +17,22 @@
                     </el-text>
                 </div>
             </div>
+        </div> -->
+        <div class="scroll-view" ref="scrollViewRef" @mouseenter="onMouseenter" @mouseleave="onMouseleave">
+            <div ref="listRef" class="list" v-for="(p, n) in count" :key="n">
+                <div class="item" v-for="(item, index) in data" :key="index">
+                    <div class="_eventList_mains_item_text">
+                        <div :class="item.DeviceStatus === 0 ? '_success' : '_warning'"
+                            class="_eventList_mains_item_text_flag"></div>
+                        <el-text class="w-150px mb-2" truncated style="color: white;margin-left: 10px;">
+                            {{ item.DeviceName }}
+                        </el-text>
+                    </div>
+                    <el-text class="w-150px mb-2" truncated style="color: white;">
+                        {{ item.EventDate }}
+                    </el-text>
+                </div>
+            </div>
         </div>
     </div>
 </template>
@@ -31,86 +46,72 @@ const props = defineProps({
         default: []
     }
 })
-// const eventList = ref([{
-//     store: 'on',
-//     color: 'rgb(82.4, 155.2, 46.4)',
-//     name: '设备启动1',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'on',
-//     color: 'rgb(82.4, 155.2, 46.4)',
-//     name: '设备启动2',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'off',
-//     color: 'red',
-//     name: '设备停止3',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'on',
-//     color: 'rgb(82.4, 155.2, 46.4)',
-//     name: '设备启动4',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'off',
-//     color: 'red',
-//     name: '设备停止5',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'off',
-//     color: 'red',
-//     name: '设备停止6',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'on',
-//     color: 'rgb(82.4, 155.2, 46.4)',
-//     name: '设备启动7',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'off',
-//     color: 'red',
-//     name: '设备停止8',
-//     time: '2025-04-15 10:20:00'
-// }])
-
-const eventList = ref([])
+const data = ref(); //列表数据
+const listRef = ref(); //列表dom
+const scrollViewRef = ref(); //滚动区域dom
+const count = ref(1); //列表个数
+
+let intervalId = null;
+let isAutoScrolling = true; //是否自动滚动标识
+
+//获取列表数据
+const getData = () => {
+    //模拟接口请求列表数据
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            //生成10条数据
+            let list = new Array(30).fill().map((item, index) => index);
+            resolve(list);
+        }, 100);
+    });
+};
+
 watch(() => props.resultData, (newVal) => {
     if (newVal) {
-        eventList.value = []
-        eventList.value = newVal
+        // data.value = await getData();
+        data.value = newVal;
+        intervalId && clearInterval(intervalId);
+        nextTick(() => {
+            //判断列表是否生成滚动条
+            count.value = hasScrollBar() ? 2 : 1;
+            //有滚动条开始自动滚动
+            if (count.value == 2) {
+                autoScrolling();
+            }
+        });
     }
 }, { deep: true, immediate: true } // 开启深度监听
 )
-const mainsRef = ref(null)
-const scrollY = ref(0)
-let intervalId = null
-const scrollSpeed = 1 // 滚动速度
-
-const startCarousel = () => {
-    intervalId = setInterval(() => {
-        const itemHeight = mainsRef.value.querySelector('._eventList_mains_item').offsetHeight
-        scrollY.value -= scrollSpeed
-        if (Math.abs(scrollY.value) >= itemHeight * eventList.value.length) {
-            scrollY.value = 0
-        }
-    }, 20)
-}
-
-const pauseCarousel = () => {
-    clearInterval(intervalId)
-}
-
-const resumeCarousel = () => {
-    startCarousel()
-}
-
 onMounted(() => {
-    startCarousel()
-})
-
-onUnmounted(() => {
-    clearInterval(intervalId)
 })
+//判断列表是否有滚动条
+const hasScrollBar = () => {
+    return scrollViewRef.value.scrollHeight > scrollViewRef.value.clientHeight;
+};
+//设置自动滚动
+const autoScrolling = () => {
+    intervalId = setInterval(() => {
+        if (scrollViewRef.value.scrollTop < listRef.value[0].clientHeight) {
+            scrollViewRef.value.scrollTop += isAutoScrolling ? 1 : 0;
+        } else {
+            scrollViewRef.value.scrollTop = 0;
+        }
+    }, 20);
+};
+
+onBeforeUnmount(() => {
+    //离开页面清理定时器
+    intervalId && clearInterval(intervalId);
+});
+
+//鼠标进入,停止滚动
+const onMouseenter = () => {
+    isAutoScrolling = false;
+};
+//鼠标移出,继续滚动
+const onMouseleave = () => {
+    isAutoScrolling = true;
+};
 </script>
 
 <style lang="scss" scoped>
@@ -162,4 +163,80 @@ onUnmounted(() => {
         }
     }
 }
+.header-view {
+    margin-top: 10px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10px 10px 10px 20px;
+    background-color: rgba(16, 40, 92, 1);
+}
+
+.view_item {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+}
+
+.warning-view {
+    width: 100%;
+    height: calc(100% - 51px);
+    display: flex;
+    flex-direction: column;
+}
+
+.label {
+    color: #fff;
+    padding: 20px;
+    font-size: 22px;
+}
+
+.scroll-view {
+    flex: 1;
+    height: 0;
+    width: 100%;
+    overflow-y: auto;
+}
+
+.list {
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.item {
+    padding: 0px 10px 0px 20px;
+    width: 100%;
+    height: 50px;
+    min-height: 50px;
+    font-size: 15px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: #eee;
+}
+
+.item:nth-child(even) {
+    background: rgba(16, 40, 92, 0.4);
+}
+
+.item:hover {
+    cursor: pointer;
+    background-image: linear-gradient(to right, #168cdb, transparent);
+}
+
+/*隐藏滚动条
+ */
+::-webkit-scrollbar {
+    display: none;
+}
+
+.blue_title {
+    color: #67C23A;
+}
+
+.red_title {
+    color: #F56C6C;
+}
 </style>

+ 0 - 21
src/views/system/tenement/modules/eventList.vue

@@ -1,27 +1,6 @@
 <template>
     <div class="_eventList">
         <HeadlineTag type="right" value="人员出入记录" style="flex-shrink: 0;"></HeadlineTag>
-        <!-- <div class="_eventList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
-            <div :style="{ transform: `translateY(${scrollY}px)` }">
-                <div class="_eventList_mains_item" v-for="(item, index) in eventList.concat(eventList)" :key="index">
-                    <div class="_eventList_mains_item_text">
-                        <div :class="item.State === 0 ? '_success' : '_warning'"
-                            class="_eventList_mains_item_text_flag">
-                            {{ item.State === 0 ? '进' : '出' }}
-                        </div>
-                        <el-text class="w-150px mb-2" truncated style="color: white;margin-left: 10px;">
-                            {{ item.Name }}
-                        </el-text>
-                    </div>
-                    <div :style="{ color: item.State === 0 ? '#15acaa' : '#FFC107', 'font-size': '12px' }">
-                        {{ item.State === 0 ? '进入' : '出入' }}
-                    </div>
-                    <div class="_eventList_mains_item_btn">
-                        {{ item.Date }}
-                    </div>
-                </div>
-            </div>
-        </div> -->
         <div class="scroll-view" ref="scrollViewRef" @mouseenter="onMouseenter" @mouseleave="onMouseleave">
             <div ref="listRef" class="list" v-for="(p, n) in count" :key="n">
                 <div class="item" v-for="(item, index) in data" :key="index">

+ 164 - 90
src/views/system/video/modules/eventList.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="_eventList">
         <HeadlineTag type="right" value="监控列表" style="flex-shrink: 0;"></HeadlineTag>
-        <div class="_eventList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
+        <!-- <div class="_eventList_mains" ref="mainsRef" @mouseenter="pauseCarousel" @mouseleave="resumeCarousel">
             <div :style="{ transform: `translateY(${scrollY}px)` }">
                 <div class="_eventList_mains_item" v-for="(item, index) in eventList.concat(eventList)" :key="index">
                     <div class="_eventList_mains_item_text">
@@ -22,6 +22,27 @@
                     </div>
                 </div>
             </div>
+        </div> -->
+        <div class="scroll-view" ref="scrollViewRef" @mouseenter="onMouseenter" @mouseleave="onMouseleave">
+            <div ref="listRef" class="list" v-for="(p, n) in count" :key="n">
+                <div class="item" v-for="(item, index) in data" :key="index">
+                    <div class="_eventList_mains_item_text">
+                        <div :class="item.Id === 'on' ? '_success' : '_warning'"
+                            class="_eventList_mains_item_text_flag"></div>
+                        <el-text class="w-150px mb-2" truncated style="color: white;margin-left: 10px;">
+                            {{ item.Name }}
+                        </el-text>
+                    </div>
+                    <div class="_eventList_mains_item_btn">
+                        <el-icon color="#44b0f9" size="18">
+                            <Download />
+                        </el-icon>
+                        <el-icon color="#44b0f9" size="18">
+                            <Bell />
+                        </el-icon>
+                    </div>
+                </div>
+            </div>
         </div>
     </div>
 </template>
@@ -35,105 +56,83 @@ const props = defineProps({
         default: []
     }
 })
-// const eventList = ref([{
-//     store: 'on',
-//     color: 'rgb(82.4, 155.2, 46.4)',
-//     name: '监控设备1',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'on',
-//     color: 'rgb(82.4, 155.2, 46.4)',
-//     name: '监控设备2',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'off',
-//     color: 'red',
-//     name: '监控设备3',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'on',
-//     color: 'rgb(82.4, 155.2, 46.4)',
-//     name: '监控设备4',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'off',
-//     color: 'red',
-//     name: '监控设备5',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'off',
-//     color: 'red',
-//     name: '监控设备6',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'on',
-//     color: 'rgb(82.4, 155.2, 46.4)',
-//     name: '监控设备7',
-//     time: '2025-04-15 10:20:00'
-// }, {
-//     store: 'off',
-//     color: 'red',
-//     name: '监控设备8',
-//     time: '2025-04-15 10:20:00'
-// }])
-
-const eventList = ref([])
+const data = ref(); //列表数据
+const listRef = ref(); //列表dom
+const scrollViewRef = ref(); //滚动区域dom
+const count = ref(1); //列表个数
+
+let intervalId = null;
+let isAutoScrolling = true; //是否自动滚动标识
+
+//获取列表数据
+const getData = () => {
+    //模拟接口请求列表数据
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            //生成10条数据
+            let list = new Array(30).fill().map((item, index) => index);
+            resolve(list);
+        }, 100);
+    });
+};
+
 watch(() => props.resultData, (newVal) => {
     if (newVal) {
-        eventList.value = []
-        eventList.value = newVal
+        // data.value = await getData();
+        data.value = newVal;
+        intervalId && clearInterval(intervalId);
+        nextTick(() => {
+            //判断列表是否生成滚动条
+            count.value = hasScrollBar() ? 2 : 1;
+            //有滚动条开始自动滚动
+            if (count.value == 2) {
+                autoScrolling();
+            }
+        });
     }
 }, { deep: true, immediate: true } // 开启深度监听
 )
-const mainsRef = ref(null)
-const scrollY = ref(0)
-let intervalId = null
-const scrollSpeed = 1 // 滚动速度
-
-const startCarousel = () => {
+onMounted(() => {
+})
+//判断列表是否有滚动条
+const hasScrollBar = () => {
+    return scrollViewRef.value.scrollHeight > scrollViewRef.value.clientHeight;
+};
+//设置自动滚动
+const autoScrolling = () => {
     intervalId = setInterval(() => {
-        const itemHeight = mainsRef.value?.querySelector('._eventList_mains_item')?.offsetHeight;
-        if (!itemHeight) return;
-
-        scrollY.value -= scrollSpeed;
-
-        // 检查第一个元素是否完全离开视口
-        if (Math.abs(scrollY.value) >= itemHeight) {
-            // 将第一个元素移到列表末尾
-            const firstItem = eventList.value.shift();
-            if (firstItem) {
-                eventList.value.push(firstItem);
-            }
-            // 调整滚动位置
-            scrollY.value += itemHeight;
+        if (scrollViewRef.value.scrollTop < listRef.value[0].clientHeight) {
+            scrollViewRef.value.scrollTop += isAutoScrolling ? 1 : 0;
+        } else {
+            scrollViewRef.value.scrollTop = 0;
         }
-    }, 50);
-};
-
-const pauseCarousel = () => {
-    clearInterval(intervalId);
-};
-
-const resumeCarousel = () => {
-    startCarousel();
+    }, 20);
 };
 
-onMounted(() => {
-    startCarousel();
+onBeforeUnmount(() => {
+    //离开页面清理定时器
+    intervalId && clearInterval(intervalId);
 });
 
-onUnmounted(() => {
-    clearInterval(intervalId);
-});
+//鼠标进入,停止滚动
+const onMouseenter = () => {
+    isAutoScrolling = false;
+};
+//鼠标移出,继续滚动
+const onMouseleave = () => {
+    isAutoScrolling = true;
+};
 </script>
 
 <style lang="scss" scoped>
 ._success {
-    background: #15acaa;	
+    background: #15acaa;
 }
+
 ._warning {
-    background: #FFC107;	
+    background: #FFC107;
 }
+
 ._eventList {
     overflow: hidden;
     display: flex;
@@ -155,33 +154,108 @@ onUnmounted(() => {
                 display: flex;
                 justify-content: space-between;
                 align-items: center;
+
                 &_flag {
                     width: 10px;
                     height: 10px;
                     border-radius: 50%;
-                    margin-left: 10px; 
+                    margin-left: 10px;
                 }
+
                 &_p {
                     margin-left: 10px;
                 }
             }
-            &_btn{
+
+            &_btn {
                 color: red;
                 display: flex;
                 font-size: 14px;
                 gap: 20px;
+
                 &_item {
                     border-radius: 5px;
                     cursor: pointer;
                 }
             }
         }
-        &_item:nth-child(even){
-            background: rgba($color: #168cdb, $alpha: .05);
-        }
-        &_item:hover {
-            background-image: linear-gradient(to right, #168cdb, transparent); 
-        }
     }
 }
+
+.header-view {
+    margin-top: 10px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 10px 10px 10px 20px;
+    background-color: rgba(16, 40, 92, 1);
+}
+
+.view_item {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+}
+
+.warning-view {
+    width: 100%;
+    height: calc(100% - 51px);
+    display: flex;
+    flex-direction: column;
+}
+
+.label {
+    color: #fff;
+    padding: 20px;
+    font-size: 22px;
+}
+
+.scroll-view {
+    flex: 1;
+    height: 0;
+    width: 100%;
+    overflow-y: auto;
+}
+
+.list {
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.item {
+    padding: 0px 10px 0px 20px;
+    width: 100%;
+    height: 50px;
+    min-height: 50px;
+    font-size: 15px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: #eee;
+}
+
+.item:nth-child(even) {
+    background: rgba(16, 40, 92, 0.4);
+}
+
+.item:hover {
+    cursor: pointer;
+    background-image: linear-gradient(to right, #168cdb, transparent);
+}
+
+/*隐藏滚动条
+ */
+::-webkit-scrollbar {
+    display: none;
+}
+
+.blue_title {
+    color: #67C23A;
+}
+
+.red_title {
+    color: #F56C6C;
+}
 </style>