hejianhao
2026-01-13 d54f63cfaf4d9130c804b8a3854bdf8680e688ac
feat(首页): 添加事故简讯模块和样式优化

- 新增事故简讯模块,包含无缝滚动功能
- 添加新字体文件并配置相关样式
- 优化页面布局和交互样式
- 重构搜索框为el-select组件
2个文件已添加
3个文件已修改
491 ■■■■■ 已修改文件
screen/src/assets/app.css 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/font/Source Han Sans CN Normal.ttf 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/font/font.css 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/font/zihunxingmouhei_trial.ttf 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/view/home/index.vue 449 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
screen/src/assets/app.css
@@ -94,6 +94,26 @@
    position: absolute;
}
.z-10 {
    z-index: 10;
}
.top0 {
    top: 0;
}
.right0 {
    right: 0;
}
.left0 {
    left: 0;
}
.bottom0 {
    bottom: 0;
}
.h100 {
    height: 100%;
}
@@ -166,4 +186,12 @@
.SHSM {
    font-family: 'Source Han Sans CN Medium';
}
.SHSN {
    font-family: 'Source Han Sans CN Normal';
}
.zh_tr {
    font-family: 'zihunxingmouhei_trial';
}
screen/src/assets/font/Source Han Sans CN Normal.ttf
Binary files differ
screen/src/assets/font/font.css
@@ -34,6 +34,13 @@
}
@font-face {
  font-family: 'Source Han Sans CN Normal';
  src: url('./Source Han Sans CN Normal.ttf');
  font-weight: normal;
  font-style: normal;
}
@font-face {
  font-family: 'Alibaba-PuHuiTi-R';
  src: url('./Alibaba-PuHuiTi-R.ttf');
  font-weight: normal;
@@ -80,4 +87,11 @@
  src: url('./D\ DIN-PRO-900-Heavy.ttf');
  font-weight: normal;
  font-style: normal;
}
@font-face {
  font-family: 'zihunxingmouhei_trial';
  src: url('./zihunxingmouhei_trial.ttf');
  font-weight: normal;
  font-style: normal;
}
screen/src/assets/font/zihunxingmouhei_trial.ttf
Binary files differ
screen/src/view/home/index.vue
@@ -2,10 +2,50 @@
  <div class="relative">
    <HeaderBox />
    <div id="mapcontainer" style="width: 1920px; height: 995px"></div>
    <div
      class="flex a-center absolute postion-center top--109 br--16 c-fff fs--14 bgcolor4 SSHR"
    >
      <div @click="activeTab = 1" class="lh--32 px--20 cursor-pointer z-10">
        在建工程
      </div>
      <div @click="activeTab = 2" class="lh--32 px--20 cursor-pointer z-10">
        固定资产
      </div>
      <div class="activeBox" :class="activeTab == 2 && 'activeBox2'">
        在建工程
      </div>
    </div>
    <div class="flex a-center absolute left--14 bottom--14">
      <img
        src="../../assets/img/home/Group@2x (4).png"
        class="w--110 h--110 mr--9 shrink0"
      />
      <div class="bgimg4 pt--10 c-fff">
        <div class="flex a-center ml--14">
          <div class="ripple">
            <div class="ripple-wave wave-1"></div>
            <div class="ripple-wave wave-2"></div>
            <div class="ripple-wave wave-3"></div>
          </div>
          <div class="fs--15 lh--15 ml--10">重大隐患数</div>
          <div class="color5 ml--13 fs--30 lh--30 zh_tr">16</div>
        </div>
        <div class="flex a-center j-center gap--52 mt--11">
          <div class="flex a-center">
            <div class="fs--14 lh--14 ml--10">未整改</div>
            <div class="color6 ml--13 fs--20 lh--24 zh_tr">14</div>
          </div>
          <div class="flex a-center">
            <div class="fs--14 lh--14 ml--10">已整改</div>
            <div class="color7 ml--13 fs--20 lh--24 zh_tr">2</div>
          </div>
        </div>
      </div>
    </div>
    <div class="leftBox">
      <div
        @click="handleClick"
        class="flex a-center j-between w100 px--20 h--40 relative bgcolor1"
        class="flex a-center j-between w100 px--20 h--40 relative bgcolor1 picker"
      >
        <el-date-picker
          v-model="dateRange"
@@ -30,7 +70,7 @@
      <div
        class="flex a-center j-between w100 pl--20 mt--13 h--40 relative bgcolor1 searchBox"
      >
        <input placeholder="请输入项目名称" />
        <el-select filterable placeholder="请输入项目名称" />
        <div class="btn">搜索</div>
      </div>
      <div class="mt--33">
@@ -139,31 +179,78 @@
        </TitleBox>
      </div>
    </div>
    <div class="flex a-center absolute left--14 bottom--14">
      <img
        src="../../assets/img/home/Group@2x (4).png"
        class="w--110 h--110 mr--9 shrink0"
      />
      <div class="bgimg4 pt--10 c-fff">
        <div class="flex a-center ml--14">
          <div class="ripple">
            <div class="ripple-wave wave-1"></div>
            <div class="ripple-wave wave-2"></div>
            <div class="ripple-wave wave-3"></div>
          </div>
          <div class="fs--15 lh--15 ml--10">重大隐患数</div>
          <div class="color5 ml--13 fs--30 lh--30">16</div>
        </div>
        <div class="flex a-center j-center gap--52 mt--11">
          <div class="flex a-center">
            <div class="fs--14 lh--14 ml--10">未整改</div>
            <div class="color6 ml--13 fs--20 lh--24">14</div>
          </div>
          <div class="flex a-center">
            <div class="fs--14 lh--14 ml--10">已整改</div>
            <div class="color7 ml--13 fs--20 lh--24">2</div>
          </div>
        </div>
    <div class="rightBox">
      <div class="mt--33">
        <TitleBox>
          <template #title> 事故简讯 </template>
          <template #right>
            <div
              class="flex a-center py--6 pl--10 pr--8 br--4 bgcolor5 cursor-pointer"
            >
              <div class="fs--12 lh--12 c-fff mr--4 SHSR">详情</div>
              <img
                src="../../assets/img/home/13@2x.png"
                class="w--14 h--14 shrink0"
              />
            </div>
          </template>
          <template #content>
            <div
              ref="scrollContainer"
              class="scroll-container"
              style="height: 408px"
              @mouseenter="handleMouseEnter"
              @mouseleave="handleMouseLeave"
              @wheel="handleWheel"
            >
              <div>
                <div
                  v-for="(item, index) in scrollData"
                  :key="`${item.id}-${index}`"
                  :class="(index + 1) % 2 === 0 ? 'bgcolor7' : ''"
                  class="relative py--20 pl--20 pr--32 c-fff"
                >
                  <div
                    class="absolute lh--20 fs--12 SHSBold bgcolor6 px--6 top0 right0"
                  >
                    {{ item.type }}
                  </div>
                  <div class="fs--16 lh--16 SHSBold">
                    {{ item.title }}
                  </div>
                  <div class="flex a-center mt--14">
                    <img
                      src="../../assets/img/home/Shape@2x (2).png"
                      class="w--8 h--10 shrink0 mr--7"
                    />
                    <div class="SHSN fs--12 lh--12">{{ item.location }}</div>
                  </div>
                  <div class="flex a-center j-between mt--8 pr--76">
                    <div class="flex a-center">
                      <img
                        src="../../assets/img/home/Shape@2x (3).png"
                        class="w--10 h--9 shrink0 mr--7"
                      />
                      <div class="SHSN fs--12 lh--12">{{ item.date }}</div>
                    </div>
                    <div class="flex a-center">
                      <img
                        src="../../assets/img/home/Shape@2x (1).png"
                        class="w--9 h--10 shrink0 mr--7"
                      />
                      <div class="SHSN fs--12 lh--12">
                        伤亡:造成
                        <span class="SHSBold fs--12">{{
                          item.casualties
                        }}</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </template>
        </TitleBox>
      </div>
    </div>
  </div>
@@ -181,6 +268,10 @@
      mapView: null,
      dateRange: [moment().startOf("month"), moment().endOf("month")], //默认本月
      dateTxt: "",
      activeTab: 1,
      scrollData: [], // 存储滚动数据
      scrollTimer: null, // 滚动定时器
      scrollContainer: null, // 滚动容器引用
    };
  },
  watch: {
@@ -199,11 +290,138 @@
  created() {},
  mounted() {
    this.setMapload();
    this.$nextTick(() => {
      this.scrollContainer = this.$refs.scrollContainer;
      this.initScrollData();
    });
  },
  beforeDestroy() {},
  beforeDestroy() {
    this.stopAutoScroll();
  },
  methods: {
    handleClick() {
      this.$refs.datePicker.focus();
    },
    // 初始化滚动数据
    initScrollData() {
      // 创建示例数据,模拟真实的事故简讯数据
      const sampleData = [
        {
          id: 1,
          type: "塔吊倒塌",
          title: "秦皇岛市钢铁厂发生塔吊倒塌事故",
          location: "河北省秦皇岛市昌黎县",
          date: "2025年11月10日",
          casualties: "造成 1 人死亡",
        },
        {
          id: 2,
          type: "脚手架坍塌",
          title: "广州市某工地脚手架坍塌事故",
          location: "广东省广州市白云区",
          date: "2025年11月9日",
          casualties: "造成 2 人受伤",
        },
        {
          id: 3,
          type: "高处坠落",
          title: "深圳市某建筑工地工人高处坠落",
          location: "广东省深圳市南山区",
          date: "2025年11月8日",
          casualties: "造成 1 人死亡,1 人重伤",
        },
        {
          id: 4,
          type: "物体打击",
          title: "成都市某工地发生物体打击事故",
          location: "四川省成都市武侯区",
          date: "2025年11月7日",
          casualties: "造成 1 人轻伤",
        },
        {
          id: 5,
          type: "触电事故",
          title: "杭州市某工地发生触电事故",
          location: "浙江省杭州市西湖区",
          date: "2025年11月6日",
          casualties: "造成 1 人死亡",
        },
        {
          id: 6,
          type: "机械伤害",
          title: "南京市某工地发生机械伤害事故",
          location: "江苏省南京市江宁区",
          date: "2025年11月5日",
          casualties: "造成 1 人重伤",
        },
        {
          id: 7,
          type: "坍塌事故",
          title: "武汉市某工地发生局部坍塌事故",
          location: "湖北省武汉市汉阳区",
          date: "2025年11月4日",
          casualties: "造成 1 人死亡,2 人受伤",
        },
      ];
      // 为了实现无缝滚动,复制2份数据
      this.scrollData = [...sampleData, ...sampleData];
      // 开始滚动
      this.startAutoScroll();
    },
    // 开始自动滚动
    startAutoScroll() {
      this.stopAutoScroll();
      if (!this.scrollContainer) return;
      const originalDataLength = this.scrollData.length / 2;
      const itemHeight = 80; // 每个项目高度
      const scroll = () => {
        // 获取当前滚动位置
        let currentScrollTop = this.scrollContainer.scrollTop;
        // 如果滚动到第二份数据的末尾,跳回第一份数据的开头
        if (currentScrollTop >= originalDataLength * itemHeight) {
          // 瞬间跳回第一份数据的位置,实现无缝滚动
          this.scrollContainer.scrollTop = 0;
        } else {
          // 正常向下滚动
          this.scrollContainer.scrollTop += 1;
        }
        this.scrollTimer = requestAnimationFrame(scroll);
      };
      // 开始滚动
      this.scrollTimer = requestAnimationFrame(scroll);
    },
    // 停止自动滚动
    stopAutoScroll() {
      if (this.scrollTimer) {
        cancelAnimationFrame(this.scrollTimer);
        this.scrollTimer = null;
      }
    },
    // 鼠标进入容器时暂停滚动
    handleMouseEnter() {
      this.stopAutoScroll();
    },
    // 鼠标离开容器时恢复滚动
    handleMouseLeave() {
      this.startAutoScroll();
    },
    // 处理滚轮事件
    handleWheel(event) {
      event.preventDefault();
      this.scrollContainer.scrollTop += event.deltaY;
    },
    setMapload() {
      AMapLoader.load({
@@ -228,6 +446,62 @@
</script>
<style lang="less" scoped>
.bgimg4 {
  background-image: url("../../assets/img/home/Group 24 Copy@2x.png");
  background-size: 100% 100%;
  width: 300px;
  height: 94px;
}
.color5 {
  color: #ff4d04;
}
.color6 {
  color: #fedb65;
}
.color7 {
  color: #47a1ff;
}
.bgcolor4 {
  background: #06175b;
  border-radius: 16px;
  border: 1px solid #204fb3;
}
.bgcolor5 {
  background: rgba(14, 93, 251, 0.5);
}
.bgcolor6 {
  background: linear-gradient(180deg, #ff4d4f 0%, #e5484d 100%);
  border-radius: 2px 0px 0px 10px;
  border: 1px solid #e5484d;
}
.bgcolor7 {
  background: rgba(14, 95, 255, 0.2);
}
.activeBox {
  position: absolute;
  top: 0;
  left: 0;
  padding: 0 20px;
  height: 32px;
  background: #0600e4;
  color: transparent;
  box-shadow: inset 0px 0px 20px 0px rgba(102, 255, 255, 0.52);
  border-radius: 20px;
  border: 1px solid rgba(50, 197, 255, 0.22);
  transition: all 0.3s ease-in-out;
}
.activeBox2 {
  left: 100px;
}
.leftBox {
  width: 380px;
  position: absolute;
@@ -295,35 +569,34 @@
  .color5 {
    color: rgba(204, 224, 248, 0.7);
  }
  .picker {
    ::v-deep .el-input__icon {
      display: none;
    }
  ::v-deep .el-input__icon {
    display: none;
  }
    ::v-deep .el-input__inner {
      background: transparent;
      border: none;
      color: transparent;
    }
  ::v-deep .el-input__inner {
    background: transparent;
    border: none;
    color: transparent;
  }
  ::v-deep .el-range-input {
    background: transparent;
    border: none;
    color: transparent;
    ::v-deep .el-range-input {
      background: transparent;
      border: none;
      color: transparent;
    }
  }
  .searchBox {
    input {
      background-color: transparent;
    ::v-deep .el-input__inner {
      background: transparent;
      border: none;
      color: #fff;
      padding: 0;
    }
    input::placeholder {
      color: rgba(255, 255, 255, 0.6);
    }
    input:focus {
      outline: none;
    ::v-deep .el-input__suffix {
      display: none;
    }
    .btn {
@@ -359,25 +632,6 @@
      text-align: center;
    }
  }
}
.bgimg4 {
  background-image: url("../../assets/img/home/Group 24 Copy@2x.png");
  background-size: 100% 100%;
  width: 300px;
  height: 94px;
}
.color5 {
  color: #ff4d04;
}
.color6 {
  color: #fedb65;
}
.color7 {
  color: #47a1ff;
}
.ripple {
@@ -422,27 +676,6 @@
  }
  20% {
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -50%) scale(1.4);
    opacity: 0;
  }
}
/* 兼容性前缀 */
.wave-2, .wave-3 {
  -webkit-animation-name: ripple-effect;
  -moz-animation-name: ripple-effect;
  -o-animation-name: ripple-effect;
  animation-name: ripple-effect;
}
@-webkit-keyframes ripple-effect {
  0% {
    -webkit-transform: translate(-50%, -50%) scale(0.7);
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
@@ -451,17 +684,37 @@
  }
}
@-moz-keyframes ripple-effect {
  0% {
    -moz-transform: translate(-50%, -50%) scale(0.7);
    opacity: 0;
.rightBox {
  width: 462px;
  position: absolute;
  top: 85px;
  right: 20px;
}
/* 无缝滚动容器 */
.scroll-container {
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
  -ms-overflow-style: none;
  scrollbar-width: none;
  &::-webkit-scrollbar {
    width: 6px;
  }
  20% {
    opacity: 1;
  &::-webkit-scrollbar-track {
    background: transparent;
  }
  100% {
    -moz-transform: translate(-50%, -50%) scale(1.4);
    opacity: 0;
  &::-webkit-scrollbar-thumb {
    background-color: rgba(255, 255, 255, 0.3);
    border-radius: 3px;
  }
  &::-webkit-scrollbar-thumb:hover {
    background-color: rgba(255, 255, 255, 0.5);
  }
}
</style>