buuug7-simple-datetime-picker.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <template>
  2. <view class="buuug7-simple-datetime-picker" v-if="done">
  3. <view
  4. class="mask"
  5. :class="{ show: open }"
  6. @touchmove.stop.prevent
  7. catchtouchmove="true"
  8. >
  9. </view>
  10. <view class="wrap" :class="{ show: open }">
  11. <view class="picker-header" @touchmove.stop.prevent catchtouchmove="true">
  12. <view class="btn-picker cancel" @click="open = false">取消</view>
  13. <view class="btn-picker submit" @click="_onSubmit">确定</view>
  14. </view>
  15. <view class="picker-body">
  16. <picker-view :value="value" @change="_onChange">
  17. <picker-view-column v-if="timeHide[0]">
  18. <view class="column-item" v-for="item in years" :key="item">
  19. {{ item + timeLabel[0] }}
  20. </view>
  21. </picker-view-column>
  22. <picker-view-column v-if="timeHide[1]">
  23. <view class="column-item" v-for="item in months" :key="item">
  24. {{ formatNum(item) + timeLabel[1] }}
  25. </view>
  26. </picker-view-column>
  27. <picker-view-column v-if="timeHide[2]">
  28. <view class="column-item" v-for="item in days" :key="item">
  29. {{ formatNum(item) + timeLabel[2] }}
  30. </view>
  31. </picker-view-column>
  32. <picker-view-column v-if="timeHide[3]">
  33. <view class="column-item" v-for="item in hours" :key="item">
  34. {{ formatNum(item) + timeLabel[3] }}
  35. </view>
  36. </picker-view-column>
  37. <picker-view-column v-if="timeHide[4]">
  38. <view class="column-item" v-for="item in minutes" :key="item">
  39. {{ formatNum(item) + timeLabel[4] }}
  40. </view>
  41. </picker-view-column>
  42. <picker-view-column v-if="timeHide[5]">
  43. <view class="column-item" v-for="item in seconds" :key="item">
  44. {{ formatNum(item) + timeLabel[5] }}
  45. </view>
  46. </picker-view-column>
  47. </picker-view>
  48. </view>
  49. </view>
  50. </view>
  51. </template>
  52. <script>
  53. export default {
  54. name: "buuug7-simple-datetime-picker",
  55. props: {
  56. startYear: {
  57. type: Number,
  58. default: 2000,
  59. },
  60. endYear: {
  61. type: Number,
  62. default: 2099,
  63. },
  64. timeLabel: {
  65. type: Array,
  66. default: () => ["年", "月", "日", "时", "分", "秒"],
  67. },
  68. timeHide: {
  69. type: Array,
  70. default: () => [true, true, true, true, true, false],
  71. },
  72. timeInit: {
  73. type: Number,
  74. default: new Date().valueOf(),
  75. },
  76. },
  77. data() {
  78. return {
  79. open: false,
  80. years: [],
  81. months: [],
  82. days: [],
  83. hours: [],
  84. minutes: [],
  85. seconds: [],
  86. year: "",
  87. month: "",
  88. day: "",
  89. hour: "",
  90. minute: "",
  91. second: "",
  92. value: [0, 0, 0, 0, 0, 0],
  93. done: false,
  94. };
  95. },
  96. computed: {
  97. currentDatetime() {
  98. return new Date(this.timeInit);
  99. },
  100. },
  101. mounted() {
  102. this.init();
  103. },
  104. watch: {
  105. month() {
  106. this.initDays();
  107. },
  108. },
  109. methods: {
  110. init() {
  111. this.initYears();
  112. this.initMonths();
  113. this.initDays();
  114. this.initHours();
  115. this.initMinutes();
  116. this.initSeconds();
  117. this.setSelectValue();
  118. this.done = true;
  119. },
  120. initYears() {
  121. const years = [];
  122. for (let year = this.startYear; year <= this.endYear; year++) {
  123. years.push(year);
  124. if (this.currentDatetime.getFullYear() === year) {
  125. this.$set(this.value, 0, year - this.startYear);
  126. }
  127. }
  128. this.years = years;
  129. },
  130. initMonths() {
  131. const months = [];
  132. for (let month = 1; month <= 12; month++) {
  133. months.push(month);
  134. if (this.currentDatetime.getMonth() + 1 === month) {
  135. this.$set(this.value, 1, month - 1);
  136. }
  137. }
  138. this.months = months;
  139. },
  140. initDays() {
  141. const value = this.value;
  142. const selectedYear = this.years[value[0]];
  143. const selectedMonth = this.months[value[1]];
  144. const days = [];
  145. const totalDays = new Date(selectedYear, selectedMonth, 0).getDate();
  146. for (let day = 1; day <= totalDays; day++) {
  147. days.push(day);
  148. if (this.currentDatetime.getDate() === day) {
  149. this.$set(value, 2, day - 1);
  150. }
  151. }
  152. this.days = days;
  153. },
  154. initHours() {
  155. const hours = [];
  156. for (let hour = 0; hour <= 23; hour++) {
  157. hours.push(hour);
  158. if (this.currentDatetime.getHours() === hour) {
  159. this.$set(this.value, 3, hour);
  160. }
  161. }
  162. this.hours = hours;
  163. },
  164. initMinutes() {
  165. const minutes = [];
  166. for (let minute = 0; minute < 60; minute++) {
  167. minutes.push(minute);
  168. if (this.currentDatetime.getMinutes() === minute) {
  169. this.$set(this.value, 4, minute);
  170. }
  171. }
  172. this.minutes = minutes;
  173. },
  174. initSeconds() {
  175. const seconds = [];
  176. for (let second = 0; second < 60; second++) {
  177. seconds.push(second);
  178. if (this.currentDatetime.getSeconds() === second) {
  179. this.$set(this.value, 5, second);
  180. }
  181. }
  182. this.seconds = seconds;
  183. },
  184. show() {
  185. this.open = true;
  186. },
  187. hide() {
  188. this.open = false;
  189. },
  190. _onChange(e) {
  191. this.value = e.detail.value;
  192. this.setSelectValue();
  193. },
  194. setSelectValue() {
  195. const v = this.value;
  196. this.year = this.years[v[0]];
  197. this.month = this.months[v[1]];
  198. this.day = this.days[v[2]];
  199. this.hour = this.hours[v[3]];
  200. this.minute = this.minutes[v[4]];
  201. this.second = this.seconds[v[5]];
  202. },
  203. _onSubmit() {
  204. const {
  205. year,
  206. month,
  207. day,
  208. hour,
  209. minute,
  210. second,
  211. formatNum,
  212. timeHide,
  213. timeLabel,
  214. } = this;
  215. const result = {
  216. year: timeHide[0] ? formatNum(year) : "",
  217. month: timeHide[1] ? formatNum(month) : "",
  218. day: timeHide[2] ? formatNum(day) : "",
  219. hour: timeHide[3] ? formatNum(hour) : "",
  220. minute: timeHide[4] ? formatNum(minute) : "",
  221. second: timeHide[5] ? formatNum(second) : "",
  222. };
  223. this.$emit("submit", result);
  224. this.hide();
  225. },
  226. formatNum(num) {
  227. return num < 10 ? "0" + num : num + "";
  228. },
  229. },
  230. };
  231. </script>
  232. <style lang="scss">
  233. $transition: all 0.3s ease;
  234. $primary: #488ee9;
  235. .buuug7-simple-datetime-picker {
  236. position: relative;
  237. z-index: 999;
  238. picker-view {
  239. height: 100%;
  240. }
  241. .mask {
  242. position: fixed;
  243. z-index: 1000;
  244. top: 0;
  245. right: 0;
  246. bottom: 0;
  247. left: 0;
  248. background-color: rgba(0, 0, 0, 0.4);
  249. visibility: hidden;
  250. opacity: 0;
  251. transition: $transition;
  252. &.show {
  253. visibility: visible;
  254. opacity: 1;
  255. }
  256. }
  257. .wrap {
  258. z-index: 1001;
  259. position: fixed;
  260. bottom: 0;
  261. left: 0;
  262. width: 100%;
  263. transition: $transition;
  264. transform: translateY(100%);
  265. &.show {
  266. transform: translateY(0);
  267. }
  268. }
  269. .picker-header {
  270. display: flex;
  271. flex-direction: row;
  272. justify-content: space-between;
  273. align-items: center;
  274. padding: 8px 8px;
  275. background-color: darken(#fff, 2%);
  276. background-color: #fff;
  277. }
  278. .picker-body {
  279. width: 100%;
  280. height: 420rpx;
  281. overflow: hidden;
  282. background-color: #fff;
  283. }
  284. .column-item {
  285. text-overflow: ellipsis;
  286. white-space: nowrap;
  287. display: flex;
  288. justify-content: center;
  289. align-items: center;
  290. }
  291. .btn-picker {
  292. position: relative;
  293. display: inline-block;
  294. padding-left: 10px;
  295. padding-right: 10px;
  296. box-sizing: border-box;
  297. text-align: center;
  298. text-decoration: none;
  299. line-height: 2;
  300. -webkit-tap-highlight-color: transparent;
  301. overflow: hidden;
  302. background-color: #eee;
  303. font-size: 14px;
  304. border-radius: 3px;
  305. color: #000;
  306. cursor: pointer;
  307. }
  308. .btn-picker.submit {
  309. background-color: $primary;
  310. color: #fff;
  311. }
  312. }
  313. </style>