瀏覽代碼

新增布局页面;新增日期组件;新增天气组件;添加新的字体;

画安 3 天之前
父節點
當前提交
ad3806dd21

二進制
src/assets/fonts/YouSheBiaoTiHei_Regular.ttf


二進制
src/assets/images/layout-left.png


二進制
src/assets/images/layout-right.png


二進制
src/assets/images/layout-top.png


+ 88 - 0
src/components/ui/DateTimeWidget.vue

@@ -0,0 +1,88 @@
+<template>
+  <div class="datetime-widget">
+    <div class="time-display">{{ currentTime }}</div>
+    
+    <div class="date-display">
+      <span class="weekday">{{ currentWeekday }}</span>
+      <span class="date">{{ currentDate }}</span>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'DateTimeWidget',
+  data() {
+    return {
+      currentTime: '00:00:00',
+      currentDate: '2023.01.01',
+      currentWeekday: '周一',
+      timer: null
+    }
+  },
+  mounted() {
+    this.updateDateTime();
+    // 每秒更新一次时间
+    this.timer = setInterval(this.updateDateTime, 1000);
+  },
+  beforeDestroy() {
+    // 组件销毁前必须清除定时器,防止内存泄漏
+    if (this.timer) {
+      clearInterval(this.timer);
+    }
+  },
+  methods: {
+    updateDateTime() {
+      const now = new Date();
+      
+      // 格式化时间 HH:mm:ss
+      const hh = String(now.getHours()).padStart(2, '0');
+      const mm = String(now.getMinutes()).padStart(2, '0');
+      const ss = String(now.getSeconds()).padStart(2, '0');
+      this.currentTime = `${hh}:${mm}:${ss}`;
+      
+      // 格式化日期 YYYY.M.D (根据你的设计图,月份和日期似乎没有补0)
+      const year = now.getFullYear();
+      const month = now.getMonth() + 1;
+      const date = now.getDate();
+      this.currentDate = `${year}.${month}.${date}`;
+      
+      // 格式化星期
+      const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
+      this.currentWeekday = weekdays[now.getDay()];
+    }
+  }
+}
+</script>
+
+<style scoped>
+.datetime-widget {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  color: #ffffff;
+}
+
+.time-display {
+  font-size: 24px;
+  line-height: 28px;
+  font-weight: 500;
+  letter-spacing: 2px;
+  font-family: "Arial", sans-serif; 
+}
+
+.date-display {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: flex-start;
+  gap: 2px;
+}
+
+.weekday, .date {
+  font-size: 12px;
+  line-height: 12px;
+  color: rgba(255,255,255,0.8);
+  line-height: 1.2;
+}
+</style>

+ 56 - 0
src/components/ui/WeatherWidget.vue

@@ -0,0 +1,56 @@
+<template>
+  <div class="weather-widget">
+    <span class="text">
+      <span class="icon">{{ icon }}</span>{{ text }}
+    </span>
+    <span class="temp">{{ temperature }}</span>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'WeatherWidget',
+  props: {
+    icon: {
+      type: String,
+      default: '☀️'
+    },
+    text: {
+      type: String,
+      default: '晴'
+    },
+    temperature: {
+      type: String,
+      default: '32/17℃'
+    }
+  }
+}
+</script>
+
+<style scoped>
+.weather-widget {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  color: #ffffff;
+  font-family: var(--font-family, sans-serif);
+}
+
+.icon {
+  font-size: 22px;
+}
+
+.text {
+  font-size: 24px;
+  line-height: 26px;
+  font-weight: 500;
+  letter-spacing: 2px;
+}
+
+.temp {
+  font-size: 16px;
+  line-height: 24px;
+  font-family: PingFangSC, PingFang SC;
+  color: rgba(255,255,255,0.8);
+}
+</style>

+ 204 - 0
src/layouts/DashboardLayout.vue

@@ -0,0 +1,204 @@
+<template>
+    <div class="fluid-dashboard">
+        <div class="frame-top">
+            <div class="title">{{ title }}</div>
+        </div>
+        <div class="frame-left"></div>
+        <div class="frame-right"></div>
+        <div class="frame-bottom"></div>
+
+        <slot name="map"></slot>
+
+        <div class="ui-layer">
+
+            <header class="top-header">
+                <div class="header-left">
+                    <slot name="header-left"></slot>
+                </div>
+                <div class="header-right">
+                    <slot name="header-right"></slot>
+                </div>
+            </header>
+
+            <main class="main-layout" :class="layoutClass">
+
+                <aside class="left-sidebar">
+                    <slot name="left"></slot>
+                </aside>
+
+                <section class="center-area">
+                    <slot name="center"></slot>
+                </section>
+
+                <aside class="right-sidebar">
+                    <slot name="right"></slot>
+                </aside>
+
+            </main>
+        </div>
+
+        <slot name="dialogs"></slot>
+
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'DashboardLayout',
+    props: {
+        // 接收外部传入的 class,用于动态切换 CSS 网格布局
+        // 例如传入 "special-situation-monitoring"
+        layoutClass: {
+            type: String,
+            default: ''
+        }
+    },
+    data() {
+        return {
+            title: '交通型号控制平台',
+        }
+    }
+}
+</script>
+
+<style scoped>
+/* ================= 根容器 ================= */
+.fluid-dashboard {
+    width: 100vw;
+    height: 100vh;
+    position: relative;
+    overflow: hidden;
+    background: #050a17;
+    /* 兜底深色背景 */
+}
+
+/* ================= 大屏装饰边框 ================= */
+.frame-top,
+.frame-left,
+.frame-right,
+.frame-bottom {
+    position: absolute;
+    pointer-events: none;
+    /* 【核心】鼠标事件穿透,不挡底层交互 */
+    z-index: 50;
+    /* 层级高于 UI,低于弹窗 */
+}
+
+.frame-top {
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100px;
+    background: url('@/assets/images/layout-top.png') no-repeat center top;
+    background-size: 100% 100%;
+}
+
+.frame-top .title {
+    font-family: var(--title-font-family);
+    font-size: 48px;
+    color: #707070;
+    line-height: 63px;
+    text-align: center;
+    font-style: normal;
+    text-transform: none;
+    background: linear-gradient(90deg, #9ED3FD 0%, #FFFFFF 100%);
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+}
+
+.frame-left {
+    top: 10px;
+    left: 0;
+    width: 16px;
+    height: calc(100% - 10px - 40px);
+    background: url('@/assets/images/layout-left.png') no-repeat left center;
+    background-size: 100% 100%;
+}
+
+.frame-right {
+    top: 10px;
+    right: 0;
+    width: 16px;
+    height: calc(100% - 10px - 40px);
+    background: url('@/assets/images/layout-right.png') no-repeat right center;
+    background-size: 100% 100%;
+}
+
+.frame-bottom {
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    height: 17px;
+    /* background: url('@/assets/images/layout-bottom.png') no-repeat center bottom; */ 
+    background-size: 100% 100%;
+}
+
+/* ================= UI 层与网格布局 ================= */
+.ui-layer {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 2;
+    pointer-events: none;
+    /* 让鼠标穿透点到下层的地图 */
+    display: grid;
+    grid-template-rows: 80px 1fr;
+    /* 头部 80px,其余给主体 */
+}
+
+/* 恢复具体功能区域的鼠标交互 */
+.top-header,
+.left-sidebar,
+.center-area,
+.right-sidebar {
+    pointer-events: auto;
+}
+
+/* --- 头部 --- */
+.top-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-end;
+    padding: 0 50px;
+    /* 左右内边距,避开边框图片 */
+    position: relative;
+}
+
+.header-right {
+    position: absolute;
+    right: 50px;
+    bottom: 0;
+}
+
+/* --- 主体网格 --- */
+.main-layout {
+    display: grid;
+    /* 默认网格:左320,中间自适应,右480 */
+    grid-template-columns: 320px 1fr 480px;
+    gap: 20px;
+    /* 【关键】给四周留出 padding,防止里面的图表被外围的装饰边框挡住! */
+    padding: 20px 50px 60px 50px;
+    height: 100%;
+    box-sizing: border-box;
+}
+
+/* 特殊模式下的网格变体 (通过 layoutClass 触发) */
+.main-layout.special-situation-monitoring {
+    grid-template-columns: 500px 1fr 480px;
+}
+
+/* --- 区域容器设定 --- */
+.left-sidebar,
+.right-sidebar {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+.center-area {
+    position: relative;
+    height: 100%;
+}
+</style>

+ 67 - 6
src/styles/base.css

@@ -1,3 +1,15 @@
+/* ==========================================
+   基础重置与全局变量
+========================================== */
+
+@font-face {
+  font-family: 'YouSheBiaoTiHei';
+  src: url('../assets/fonts/YouSheBiaoTiHei_Regular.ttf') format('truetype');
+  font-weight: normal;
+  font-style: normal;
+}
+
+
 html, body {
   width: 100%;
   height: 100%;
@@ -7,7 +19,9 @@ html, body {
   font-family: "Microsoft YaHei", "PingFang SC", Arial, sans-serif;
 }
 
-* { box-sizing: border-box; }
+* { 
+  box-sizing: border-box; 
+}
 
 #app {
   width: 100vw;
@@ -15,11 +29,58 @@ html, body {
   overflow: hidden;
 }
 
-:root{
-  --c-primary:#2bdcff;
-  --c-border:#3D72B8;
-  --c-btn:#06378E;
-  --radius:8px;
+:root {
+  --title-font-family: 'YouSheBiaoTiHei';
+  --c-primary: #2bdcff;
+  --c-border: #3D72B8;
+  --c-btn: #06378E;
+  --radius: 8px;
   --fs-title: clamp(18px, 1.4vw, 28px);
   --fs-base: clamp(12px, 0.95vw, 16px);
+}
+
+/* ==========================================
+   全局工具类 (Utility Classes)
+========================================== */
+/* 通用地图底层容器样式 */
+.map-layer {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 1;
+}
+
+/* ==========================================
+   全局滚动条美化 (大屏科技感风格)
+========================================== */
+::-webkit-scrollbar {
+  width: 0px;  /* 如果你想显示滚动条,可以改为 6px 或 8px */
+  height: 0px; 
+}
+
+::-webkit-scrollbar-track {
+  background: rgba(15, 34, 67, 0.3);
+  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.3); 
+}
+
+::-webkit-scrollbar-thumb {
+  background: linear-gradient(180deg, rgba(31, 206, 251, 0.2) 0%, rgba(0, 229, 255, 0.6) 100%);
+  border: 1px solid rgba(31, 206, 251, 0.4); 
+  border-radius: 4px; /* 建议加个圆角更美观 */
+}
+
+::-webkit-scrollbar-thumb:hover {
+  background: linear-gradient(180deg, rgba(31, 206, 251, 0.5) 0%, rgba(0, 229, 255, 0.9) 100%);
+  box-shadow: 0 0 10px rgba(0, 229, 255, 0.8); 
+  border-color: rgba(31, 206, 251, 0.8);
+}
+
+::-webkit-scrollbar-button {
+  display: none; 
+}
+
+::-webkit-scrollbar-corner {
+  background: transparent; 
 }

+ 3 - 3
src/styles/global.css

@@ -31,7 +31,7 @@
 }
 
 /* 恢复 UI 层交互 */
-.top-header,
+.top-header1,
 .left-sidebar,
 .right-sidebar,
 .float-video-panel,
@@ -41,7 +41,7 @@
 }
 
 /* --- 顶部 Header --- */
-.top-header {
+.top-header1 {
   display: flex;
   justify-content: space-between;
   align-items: center;
@@ -59,7 +59,7 @@
   letter-spacing: 4px;
 }
 
-.top-header .right-wrap {
+.top-header1 .right-wrap {
   position: absolute;
   right: 50px;
   bottom: 0;

File diff suppressed because it is too large
+ 1497 - 0
src/views/Home copy.vue


File diff suppressed because it is too large
+ 33 - 1481
src/views/Home.vue