Commit 8738706d authored by ZiJian Zhang's avatar ZiJian Zhang
Browse files

New bus timer

parent 9f3c17d2
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
import { defineClientAppEnhance } from '@vuepress/client'

import BusTimer from "./components/BusTimer.vue";
import ObjectSelector from "./components/ObjectSelector.vue";
import DataRequest from "./components/DataRequest.vue";
import GridList from "./components/GridList.vue";

export default defineClientAppEnhance(({ app, router, siteData }) => {
    app.component("BusTimer",BusTimer)
    app.component("ObjectSelector",ObjectSelector)
    app.component("DataRequest",DataRequest)
    app.component("GridList",GridList)
})
 No newline at end of file
+58 −0
Original line number Diff line number Diff line
<template>
  <tr
    v-if="secondFromDispatch"
    :class="isWaiting ? 'bus-waiting' : 'bus-running'"
  >
    <td>{{ startTime }}</td>
    <td>
      {{ isWaiting ? "等待中" : "在途中" }}
    </td>
    <td>{{ (isWaiting ? "" : "") + " " + timeToShow }}</td>
    <td v-if="stationEstimate">{{ stationEstimate }}</td>
  </tr>
</template>
<script>
function parseSecond(second) {
  let s = Math.abs(second);
  let h = Math.floor(s / 3600);
  s -= h * 3600;
  let m = Math.floor(s / 60);
  s -= m * 60;
  return [h, m, s];
}
function formatNumber(number) {
  return number < 10 ? "0" + number : number;
}
export default {
  props: {
    secondFromDispatch: { type: Number },
    stationEstimate: { type: String },
    startSecond: { type: Number },
  },
  computed: {
    timeToShow: function () {
      let parsedSecond = parseSecond(this.secondFromDispatch);
      let moreThanHalf = parsedSecond[2] >= 30;
      if (parsedSecond[1] > 0)
        return [parsedSecond[0]>0?parsedSecond[0]+"":"",parsedSecond[1], "", moreThanHalf ? "" : ""].join("");
      else {
        return moreThanHalf ? "半分钟" : "不到半分";
      }
    },
    startTime: function () {
      let parsedSecond = parseSecond(this.startSecond);
      return [
        "",
        formatNumber(parsedSecond[0]),
        ":",
        formatNumber(parsedSecond[1]),
      ].join("");
    },
    isWaiting: function () {
      return this.secondFromDispatch <= 0;
    },
  },
};
</script>
<style lang="scss">
</style>
 No newline at end of file
+222 −0
Original line number Diff line number Diff line
<template>
  <div>
    <table v-if="busToShow" class="bus-timer-tb">
      <thead>
        <tr>
          <th colspan="4">
            {{ stations[0][0] }} > {{ stations[stations.length - 1][0] }}
          </th>
        </tr>
        <bus-item
          v-for="(value, key) in busToShow"
          :secondFromDispatch="value[0]"
          :stationEstimate="stationEstimate(value[0])"
          :startSecond="value[1]"
          :key="key"
        ></bus-item>
        <tr>
          <td v-if="Object.keys(busToShow).length==0" colspan="4">
            短时间没有班次了
          </td>
        </tr>
      </thead>
    </table>
    <p class="plus-note">* 站点估计仅供参考</p>
    <div v-if="false">
      {{ formatNumber(hour) }}:{{ formatNumber(minute) }}:{{
        formatNumber(second)
      }}
    </div>
  </div>
</template>
<script>
function getSecondToDayStart(h, m, s) {
  return h * 3600 + m * 60 + s;
}
function parseTimes(times) {
  let parsedTime = [];
  for (let item of times) {
    let timeArray = item.split(":");
    let secondToDayStart = getSecondToDayStart(
      Number(timeArray[0].trim()),
      Number(timeArray[1].trim()),
      0
    );
    parsedTime.push(secondToDayStart);
  }
  return parsedTime.sort((a, b) => a - b);
}
import BusItem from "./BusItem.vue";
export default {
  data() {
    return {
      // Second from the start of the day, which we call "zero"
      secondFromZero: 0,
      second: 0,
      minute: 0,
      hour: 0,
      timeRangeAfterDispatch: 3
    };
  },
  props: {
    /*
        times: should be like ["07:10","08:20"]
        stations: should be like [["station1",0],["station2",20],...,[station final",100]]
      */
    times: {},
    stations: {},
    minuteOnRoad: {
      type: Number,
      default: 20,
    },
    timeRangeBeforeDispatch: { type: Number, default: 60 }
  },
  components: {
    BusItem: BusItem,
  },
  mounted() {
    // Init time
    var data = new Date();
    this.hour = data.getHours();
    this.minute = data.getMinutes();
    this.second = data.getSeconds();
    // Init second to day start
    this.secondFromZero = getSecondToDayStart(
      this.hour,
      this.minute,
      this.second
    );
    // Set Timer
    setInterval(() => {
      this.tick();
    }, 1000);
  },
  methods: {
    // Increase timers
    tick: function () {
      this.secondFromZero += 1;
      this.second += 1;

      if (this.second >= 60) {
        this.minute += 1;
        this.second -= 60;
      }
      if (this.minute >= 60) {
        this.hour += 1;
        this.minute -= 60;
      }
      if (this.hour >= 24) {
        this.hour = 0;
        this.minute -= 60;
      }
    },
    // Add zero in front of a number
    formatNumber: function (number) {
      return number < 10 ? "0" + number : number;
    },
    stationEstimate: function (secondFromDispatch) {
      if (!this.stationNames) return "null";
      if (secondFromDispatch <= 0) return this.stationNames[0];
      let nStations = this.stationNames.length;
      if (secondFromDispatch >= this.minuteOnRoad * 60) return this.stationNames[nStations-1];
      let currentPostion = secondFromDispatch / 60 / this.minuteOnRoad;
      let currentStation = "";
      for (let p in this.stationPositions) {
        if (currentPostion < this.stationPositions[p]) {
          currentStation = this.stationNames[p];
          break;
        }
      }
      return currentStation;
    },
  },
  computed: {
    secondList: function(){
      return parseTimes(this.times)
    },
    busToShow: function () {
      if (!this.secondList) return null;
      let busDispatched = [];
      let busWaiting = [];
      for (let dispatchTime of this.secondList) {
        let diff = this.secondFromZero - dispatchTime;
        if (diff < 0 && diff > -this.timeRangeBeforeDispatch * 60) {
          busWaiting.push([diff, dispatchTime]);
        }
        if (diff > 0 && diff < this.timeRangeAfterDispatch * 60) {
          busDispatched.push([diff, dispatchTime]);
        }
      }
      return busDispatched.concat(busWaiting);
    },
    stationNames: function () {
      let stationNames = [];
      for (let item of this.stations) {
        stationNames.push(item[0]);
      }
      return stationNames;
    },
    stationPositions: function () {
      let stationPositions = [];
      for (let item of this.stations) {
        stationPositions.push(item[1]);
      }
      return stationPositions;
    },
  },
};
</script>
<style lang="scss" scoped>
table {
  /*border-collapse: collapse;*/
  border-spacing: 0;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 14px;
  color: #444;
  font-weight: 500;
  margin-top: 5px;
  width: 95%;
  max-width: 500px;
}
@media (max-width: 320px) {
  table { font-size: 12px; }
  .bus-timer-tb td {
  padding: 0px;
}
}
.bus-running {
  background-color: rgba(175, 255, 94, 0.233);
  color: green;
}
.bus-waiting {
  background-color: rgba(238, 238, 238, 0.411);
}

.plus-note {
  font-size: 10px;
}
.bus-timer-tb th,
.bus-timer-tb td {
  border-left: none;
  border-top: none;
  padding: 10px;
  text-align: left;
}
.bus-timer-tb th {
  background-color: #dce9f9;
  border-top: none;
}
.bus-timer-tb td:first-child,
.bus-timer-tb th:first-child {
  border-left: none;
}
.bus-timer-tb th:first-child {
  border-radius: 6px 6px 0 0;
}
.bus-timer-tb tr:last-child td:first-child {
  border-radius: 0 0 0 6px;
}
.bus-timer-tb tr:last-child td:last-child {
  border-radius: 0 0 6px 0;
}
</style>
+47 −0
Original line number Diff line number Diff line
<template>
  <slot :data="data"></slot>
</template>
<script>
export function fetchJSONData(url) {
  return new Promise(function (resolve, reject) {
    let xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = function () {
      if (this.status == 200 && this.status < 300) {
        let data = JSON.parse(xhr.response);
        resolve(data);
      } else {
        reject({
          status: this.status,
          statusText: xhr.statusText,
        });
      }
    };
    xhr.onerror = function () {
      reject({
        status: this.status,
        statusText: xhr.statusText,
      });
    };
    xhr.send();
  });
}
export default {
  data() {
    return {
      data: null,
    };
  },
  props: {
    path: { type: String },
  },
  watch: {
    path(val) {
      if (val)
        return fetchJSONData(val).then((data) => {
          this.data = data;
        });
    },
  },
};
</script>
 No newline at end of file
+31 −0
Original line number Diff line number Diff line
<template>
    <div class="cards">
        <div v-for="(value,index) in data" :key="index" class="card"> {{ value }} </div>
    </div>
</template>
<script>
export default {
    props:["data"]
}
</script>
<style lang="scss" scoped>
.card {
  background-color: rgba(238, 238, 238, 0.411);
  color: black;
  padding:  0.5rem;
  font-size: 13px;
}
.cards {
  max-width: 500px;
  margin: 0px;
  display: grid;
  grid-gap: 0.3rem;
  grid-template-columns: repeat(3, 1fr);
}
@media (min-width: 300px) {
  .cards { grid-template-columns: repeat(4, 1fr); }
}
@media (min-width: 400px) {
  .cards { grid-template-columns: repeat(6, 1fr); }
}
</style>
 No newline at end of file
Loading