vue 点击滚动时间轴

复制代码
<template>
  <div class="background">
    <div class="sjz">
      <div class="iconDiv">
        <a-icon
          :class="showMonth[0].yearsMonth == startTime ? 'disabledIcon' : 'sjzIcon'"
          type="up-circle"
          @click="upSjz"
          theme="filled"
        />
      </div>
      <!-- 中间月份 -->
      <div class="monthList">
        <div v-for="(item, index) in showMonth" :key="index" class="monthItem">
          <span v-if="item.yearsMonth.indexOf('01') != -1">
            <!-- 年份显示 -->
            <div class="yearClass">
              <div>{{ item.yearsMonth.substring(0, 4) }}年</div>
              <img src="~@/assets/yeardown.png" alt="" class="yeardown" />
            </div>
            <!-- 判断是否可以点击 -->
            <span v-if="!item.clickMark">
              <div class="disabledCorsor">
                <span>
                  {{
                    item.yearsMonth.substring(5, 6) == 0
                      ? item.yearsMonth.substring(6, 7) + '月'
                      : item.yearsMonth.substring(5, 7) + '月'
                  }}
                </span>
              </div>
            </span>
            <span v-else>
              <div
                :class="item.yearsMonth == selectMonth ? 'selectMonth' : 'monthText'"
                @click="selectClick(item.yearsMonth)"
              >
                <span v-if="item.yearsMonth == selectMonth">
                  {{ item.yearsMonth }}
                </span>
                <span v-else>
                  {{
                    item.yearsMonth.substring(5, 6) == 0
                      ? item.yearsMonth.substring(6, 7) + '月'
                      : item.yearsMonth.substring(5, 7) + '月'
                  }}
                </span>
              </div>
            </span>
          </span>
          <span v-else>
            <!-- 判断是否可以点击 -->
            <span v-if="!item.clickMark">
              <div class="disabledCorsor">
                <span>
                  {{
                    item.yearsMonth.substring(5, 6) == 0
                      ? item.yearsMonth.substring(6, 7) + '月'
                      : item.yearsMonth.substring(5, 7) + '月'
                  }}
                </span>
              </div>
            </span>
            <span v-else>
              <div
                :class="item.yearsMonth == selectMonth ? 'selectMonth' : 'monthText'"
                @click="selectClick(item.yearsMonth)"
              >
                <span v-if="item.yearsMonth == selectMonth">
                  {{ item.yearsMonth }}
                </span>
                <span v-else>
                  {{
                    item.yearsMonth.substring(5, 6) == 0
                      ? item.yearsMonth.substring(6, 7) + '月'
                      : item.yearsMonth.substring(5, 7) + '月'
                  }}
                </span>
              </div>
            </span>
          </span>
        </div>
      </div>
      <div class="iconDiv">
        <a-icon
          :class="showMonth[showMonth.length - 1].yearsMonth == lastMonth ? 'disabledIcon' : 'sjzIcon'"
          class="sjzIcon"
          type="down-circle"
          @click="downSjz"
          theme="filled"
        />
      </div>
    </div>
  </div>
</template>

<script>
import moment from 'moment'

export default {
  data() {
    return {
      // 时间轴
      monthList: [],
      showMonth: [],
      minMonthNum: 0,
      maxMonthNum: 0,
      selectMonth: '',
      // 最终日期
      lastMonth: '',
      startTime:'',
      endTime:'',
    }
  },
  created() {
    var that = this
    that.startTime = '2020-10'
    that.endTime = '2024-12'
    // 时间轴
    that.monthList = that.timeline([that.startTime, that.endTime])  //传入两个时间端,计算出所有的月份
    if (that.monthList.length >= 12) {
      that.minMonthNum = that.monthList.length - 12
      that.maxMonthNum = that.monthList.length
    } else {
      that.minMonthNum = 0
      that.maxMonthNum = that.monthList.length
    }
    that.showMonth = that.monthList.slice(that.minMonthNum, that.maxMonthNum)
    that.selectMonth = that.endTime
    that.lastMonth = that.monthList[that.monthList.length - 1].yearsMonth
  },
  methods: {
    moment,
    // 时间轴
    timeline(date) {
      const startDate = new Date(date[0])
      const endDate = new Date(date[1])
      const result = []
      while (startDate <= endDate) {
        result.push({ yearsMonth: moment(startDate).format('YYYY-MM'), clickMark: true })
        startDate.setMonth(startDate.getMonth() + 1)
      }
      return result
    },
    // 向上
    upSjz() {
      if (this.showMonth[0].yearsMonth != this.startTime) {
        this.minMonthNum = this.minMonthNum - 1
        this.maxMonthNum = this.maxMonthNum - 1
        this.showMonth = this.monthList.slice(this.minMonthNum, this.maxMonthNum)
      }
    },
    // 向下
    downSjz() {
      if (this.showMonth[this.showMonth.length - 1].yearsMonth != this.lastMonth) {
        this.minMonthNum = this.minMonthNum + 1
        this.maxMonthNum = this.maxMonthNum + 1
        this.showMonth = this.monthList.slice(this.minMonthNum, this.maxMonthNum)
      }
    },
    // 选择月份
    selectClick(item) {
      this.selectMonth = item
    },
  },
}
</script>

<style lang="less" scoped>
.sjz {
  width: 72px;
  border: 1px solid #e8e8e8;
  margin-left: 10px;
}

.iconDiv {
  text-align: center;
}

.sjzIcon {
  font-size: 16px;
  font-style: normal;
  // cursor: pointer;
  color: #1677ff;
  margin: 8px 0;
}

.disabledIcon {
  font-size: 16px;
  font-style: normal;
  // cursor: pointer;
  color: #cccccc;
  margin: 8px 0;
}

.yearClass {
  font-size: 13px;
  // font-weight: 700;
  display: inline-block;
  text-align: center;
  width: 100%;
  color: #1677ff;
  font-weight: bold;
  position: relative;
}

.monthText {
  cursor: pointer;
  color: #333;
}

.monthList {
  text-align: center;
  // color: #333;
  // font-weight: 700;
  line-height: 26px;
  font-size: 12px;
}

.selectMonth {
  background: #1677ff;
  color: #fff;
  cursor: pointer;
  // border-radius: 18px;
  display: block;
  margin: auto;
  // width: 92%;
  line-height: 26px;
}

.yeardown {
  position: absolute;
  right: 31px;
  top: 20px;
  width: 8px;
}

.disabledCorsor {
  color: #e5e5e5;
  cursor: not-allowed;
}
</style>

展示的样式

注意:引入 moment 插件

相关推荐
阿猫的故乡11 分钟前
Vue过渡动画从入门到装X:淡入淡出、滑动、列表动画、第三方库全搞定
前端·javascript·vue.js
裕波25 分钟前
Vue&ViteConf 2026 将于 7 月 18 日在上海举办,尤雨溪将现场发表主题演讲
vue.js·vite
IManiy26 分钟前
总结之Vibe Coding前端骨架
前端
小和尚敲木头30 分钟前
vue3 vite动态拼接图片路径
javascript
JS菌33 分钟前
AI Agent 沙箱双层防护体系:从权限过滤到内核隔离的完整实现
前端·人工智能·后端
Aphasia31143 分钟前
从输入URL到页面展示全流程
前端·面试
我叫黑大帅1 小时前
前端如何竖屏固定视口背景
前端·javascript·面试
abcy0712131 小时前
python pandas csv异步后台清洗前端优先返回成功信息
前端·python·pandas
不会敲代码12 小时前
我花了三天时间,终于把 Cookie、XSS、CSRF 和浏览器存储给整明白了
javascript·面试
IT_陈寒2 小时前
Vite这个坑我帮你踩了,动态导入居然这样才生效
前端·人工智能·后端