TimeRule.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. <template>
  2. <div class="time-rule">
  3. <div class="time-day" ref="day" :style="{ left: timeDayX + 'px'}">
  4. <div :class="['time-minute', minuteActiveClass((n - 1)*minutesPerUnit)]" :style="{width: minutesPerUnit + 'px'}" :title="minuteTitle((n - 1)*minutesPerUnit)"
  5. v-for="n in (1440/minutesPerUnit)" :key="n" @click.prevent="clickMinute((n-1)*minutesPerUnit)"></div>
  6. <div :class="[ n==1 ? 'time-text-first' : 'time-text']" v-for="n in 24" :key="n">{{hourText(n - 1)}}</div>
  7. </div>
  8. <div class="time-cursor" :style="{ left: timeCursorX + 'px'}" ref="cursor">
  9. <div class="time-cursor-text">{{timeCursorText}}</div>
  10. </div>
  11. </div>
  12. </template>
  13. <script>
  14. import moment from 'moment'
  15. export default {
  16. data() {
  17. return {
  18. timeCursorX: 0,
  19. timeDayX: 0,
  20. bMoving: false
  21. }
  22. },
  23. props: {
  24. minutesPerUnit: {
  25. default: 5,
  26. type: Number
  27. },
  28. videos: {
  29. default: () => []
  30. }
  31. },
  32. mounted() {
  33. let cursor = this.$refs.cursor;
  34. let day = this.$refs.day;
  35. let rule = this.$el;
  36. let _this = this;
  37. function moveCursor(e) {
  38. let originPageX = $(cursor).data("originPageX");
  39. let dx = e.pageX - originPageX;
  40. _this.timeCursorX = $(cursor).position().left + dx;
  41. $(cursor).data("originPageX", e.pageX);
  42. }
  43. function touchMoveCursor(e) {
  44. let touch = e.originalEvent.targetTouches[0];
  45. let originPageX = $(cursor).data("originPageX");
  46. let dx = touch.pageX - originPageX;
  47. _this.timeCursorX = $(cursor).position().left + dx;
  48. $(cursor).data("originPageX", touch.pageX);
  49. }
  50. function moveDay(e) {
  51. let originPageX = $(day).data("originPageX");
  52. let dx = e.pageX - originPageX;
  53. _this.timeDayX = $(day).position().left + dx;
  54. $(day).data("originPageX", e.pageX);
  55. }
  56. function touchMoveDay(e) {
  57. let touch = e.originalEvent.targetTouches[0];
  58. let originPageX = $(day).data("originPageX");
  59. let dx = touch.pageX - originPageX;
  60. _this.timeDayX = $(day).position().left + dx;
  61. $(day).data("originPageX", touch.pageX);
  62. }
  63. $(cursor).on("mousedown", function (e) {
  64. $(cursor).data("originPageX", e.pageX);
  65. _this.bMoving = true;
  66. $(document).on("mousemove", moveCursor).one("mouseup", function (e) {
  67. $(document).off("mousemove", moveCursor);
  68. $(cursor).removeData("originPageX");
  69. _this.triggerTimeChange();
  70. _this.bMoving = false;
  71. })
  72. }).on("touchstart", function (e) {
  73. let touch = e.originalEvent.targetTouches[0];
  74. $(cursor).data("originPageX", touch.pageX);
  75. _this.bMoving = true;
  76. $(document).on("touchmove", touchMoveCursor).one("touchend", function (e) {
  77. $(document).off("touchmove", touchMoveCursor);
  78. $(cursor).removeData("originPageX");
  79. _this.triggerTimeChange();
  80. _this.bMoving = false;
  81. })
  82. })
  83. $(day).on("mousedown", function (e) {
  84. if($(e.target).hasClass("time-minute")){
  85. return false;
  86. }
  87. $(day).data("originPageX", e.pageX);
  88. _this.bMoving = true;
  89. $(document).on("mousemove", moveDay).one("mouseup", function (e) {
  90. $(document).off("mousemove", moveDay);
  91. $(day).removeData("originPageX");
  92. _this.triggerTimeChange();
  93. _this.bMoving = false;
  94. })
  95. }).on("touchstart", function (e) {
  96. if($(e.target).hasClass("time-minute")){
  97. return false;
  98. }
  99. let touch = e.originalEvent.targetTouches[0];
  100. $(day).data("originPageX", touch.pageX);
  101. _this.bMoving = true;
  102. $(document).on("touchmove", touchMoveDay).one("touchend", function (e) {
  103. $(document).off("touchmove", touchMoveDay);
  104. $(day).removeData("originPageX");
  105. _this.triggerTimeChange();
  106. _this.bMoving = false;
  107. })
  108. })
  109. },
  110. watch: {
  111. videos: function (val) {
  112. this.triggerTimeChange();
  113. }
  114. },
  115. methods: {
  116. hourText(n) {
  117. let h = moment().hour(n).minute(0).second(0);
  118. return h.format("HH:mm");
  119. },
  120. minuteActiveClass(n) {
  121. let m = moment().hour(0).minute(n);
  122. let mtext = m.format("HH:mm");
  123. return Object.keys(this.activeMinutes).indexOf(mtext) >= 0 ? "active" : "";
  124. },
  125. minuteTitle(n) {
  126. let m = moment().hour(0).minute(n);
  127. let mtext = m.format("HH:mm");
  128. return Object.keys(this.activeMinutes).indexOf(mtext) >= 0 ? mtext : "";
  129. },
  130. clickMinute(n, bTrigger = true) {
  131. if (this.bMoving) return;
  132. this.timeCursorX = n + this.timeDayX;
  133. if (bTrigger) {
  134. this.triggerTimeChange();
  135. }
  136. },
  137. triggerTimeChange() {
  138. this.$emit("timeChange", this.activeMinutes[this.timeCursorText]);
  139. }
  140. },
  141. computed: {
  142. timeCursorText() {
  143. if (this.timeCursorX >= $(this.$el).innerWidth()) {
  144. this.timeCursorX = $(this.$el).innerWidth() - 1;
  145. }
  146. if (this.timeCursorX < 0) {
  147. this.timeCursorX = 0;
  148. }
  149. if (this.timeDayX < $(this.$el).innerWidth() - $(this.$refs.day).outerWidth()) {
  150. this.timeDayX = $(this.$el).innerWidth() - $(this.$refs.day).outerWidth();
  151. }
  152. if (this.timeDayX > 0) {
  153. this.timeDayX = 0;
  154. }
  155. if (this.timeCursorX - this.timeDayX >= 1440) {
  156. this.timeDayX = $(this.$el).innerWidth() - $(this.$refs.day).outerWidth();
  157. this.timeCursorX = $(this.$el).innerWidth() - 1;
  158. }
  159. var mx = parseInt((this.timeCursorX - this.timeDayX)/this.minutesPerUnit) * this.minutesPerUnit;
  160. var m = moment().hour(0).minute(mx);
  161. return m.format("HH:mm");
  162. },
  163. activeMinutes() {
  164. var minutes = {};
  165. var idx = 0;
  166. for (var video of this.videos) {
  167. var start = moment(video.StartTime, "YYYY-MM-DDTHH:mm:ss");
  168. var end = moment(video.EndTime, "YYYY-MM-DDTHH:mm:ss");
  169. if(!start.isSame(end, "day")) { // 跨天
  170. if(idx == 0) {
  171. start = moment(end).startOf("day");
  172. } else {
  173. end = moment(start).endOf("day");
  174. }
  175. }
  176. var _start = moment(start).startOf("hour");
  177. for(var i=0;;i+=5) {
  178. var c = moment(_start).add(i, "minute");
  179. if(c.isBefore(start, "minute")) {
  180. continue;
  181. }
  182. if(c.isAfter(end, "minute")) {
  183. break;
  184. }
  185. var mtext = c.format("HH:mm");
  186. minutes[mtext] = Object.assign({}, video, {
  187. StartTime: c.format("YYYY-MM-DDTHH:mm:ss")
  188. });
  189. }
  190. idx++;
  191. }
  192. return minutes;
  193. }
  194. }
  195. }
  196. </script>
  197. <style lang="less" scoped>
  198. @import url(~assets/styles/variables.less);
  199. .time-rule {
  200. overflow: hidden;
  201. position: relative;
  202. height: 50px;
  203. margin: 0 auto;
  204. width: 100%;
  205. font-size: 12px;
  206. max-width: 1440px;
  207. background-color: #CCC;
  208. }
  209. .time-day {
  210. position: absolute;
  211. left: 0;
  212. top: 0;
  213. height: 100%;
  214. width: 1440px;
  215. cursor: pointer;
  216. -ms-user-select: none;
  217. user-select: none;
  218. }
  219. .time-minute {
  220. float: left;
  221. height: 8px;
  222. margin: 0;
  223. cursor: default;
  224. }
  225. .time-minute.active {
  226. background-color: @base-active;
  227. cursor: pointer;
  228. }
  229. .time-text {
  230. float: left;
  231. width: 60px;
  232. border-left: 1px solid #999;
  233. border-top: 1px solid #999;
  234. -ms-user-select: none;
  235. user-select: none;
  236. text-align: center;
  237. height: 25px;
  238. line-height: 25px;
  239. }
  240. .time-text-first {
  241. .time-text;
  242. border-left: 0;
  243. }
  244. .time-cursor {
  245. position: absolute;
  246. left: 0;
  247. top: 0;
  248. height: 30px;
  249. width: 2px;
  250. background-color: red;
  251. text-align: center;
  252. }
  253. .time-cursor-text {
  254. position: absolute;
  255. padding: 0 5px;
  256. width: 60px;
  257. left: -30px;
  258. top: 30px;
  259. border: 1px solid red;
  260. height: 15px;
  261. line-height: 15px;
  262. cursor: move;
  263. background-color: white;
  264. -ms-user-select: none;
  265. user-select: none;
  266. }
  267. </style>