time-picker.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. "use strict";
  2. const common_vendor = require("../../../../common/vendor.js");
  3. const uni_modules_uniDatetimePicker_components_uniDatetimePicker_i18n_index = require("./i18n/index.js");
  4. const { t } = common_vendor.initVueI18n(uni_modules_uniDatetimePicker_components_uniDatetimePicker_i18n_index.messages);
  5. const _sfc_main = {
  6. name: "UniDatetimePicker",
  7. components: {},
  8. data() {
  9. return {
  10. indicatorStyle: `height: 50px;`,
  11. visible: false,
  12. fixNvueBug: {},
  13. dateShow: true,
  14. timeShow: true,
  15. title: "日期和时间",
  16. // 输入框当前时间
  17. time: "",
  18. // 当前的年月日时分秒
  19. year: 1920,
  20. month: 0,
  21. day: 0,
  22. hour: 0,
  23. minute: 0,
  24. second: 0,
  25. // 起始时间
  26. startYear: 1920,
  27. startMonth: 1,
  28. startDay: 1,
  29. startHour: 0,
  30. startMinute: 0,
  31. startSecond: 0,
  32. // 结束时间
  33. endYear: 2120,
  34. endMonth: 12,
  35. endDay: 31,
  36. endHour: 23,
  37. endMinute: 59,
  38. endSecond: 59
  39. };
  40. },
  41. props: {
  42. type: {
  43. type: String,
  44. default: "datetime"
  45. },
  46. value: {
  47. type: [String, Number],
  48. default: ""
  49. },
  50. modelValue: {
  51. type: [String, Number],
  52. default: ""
  53. },
  54. start: {
  55. type: [Number, String],
  56. default: ""
  57. },
  58. end: {
  59. type: [Number, String],
  60. default: ""
  61. },
  62. returnType: {
  63. type: String,
  64. default: "string"
  65. },
  66. disabled: {
  67. type: [Boolean, String],
  68. default: false
  69. },
  70. border: {
  71. type: [Boolean, String],
  72. default: true
  73. },
  74. hideSecond: {
  75. type: [Boolean, String],
  76. default: false
  77. }
  78. },
  79. watch: {
  80. value: {
  81. handler(newVal, oldVal) {
  82. if (newVal) {
  83. this.parseValue(this.fixIosDateFormat(newVal));
  84. this.initTime(false);
  85. } else {
  86. this.time = "";
  87. this.parseValue(Date.now());
  88. }
  89. },
  90. immediate: true
  91. },
  92. type: {
  93. handler(newValue) {
  94. if (newValue === "date") {
  95. this.dateShow = true;
  96. this.timeShow = false;
  97. this.title = "日期";
  98. } else if (newValue === "time") {
  99. this.dateShow = false;
  100. this.timeShow = true;
  101. this.title = "时间";
  102. } else {
  103. this.dateShow = true;
  104. this.timeShow = true;
  105. this.title = "日期和时间";
  106. }
  107. },
  108. immediate: true
  109. },
  110. start: {
  111. handler(newVal) {
  112. this.parseDatetimeRange(this.fixIosDateFormat(newVal), "start");
  113. },
  114. immediate: true
  115. },
  116. end: {
  117. handler(newVal) {
  118. this.parseDatetimeRange(this.fixIosDateFormat(newVal), "end");
  119. },
  120. immediate: true
  121. },
  122. // 月、日、时、分、秒可选范围变化后,检查当前值是否在范围内,不在则当前值重置为可选范围第一项
  123. months(newVal) {
  124. this.checkValue("month", this.month, newVal);
  125. },
  126. days(newVal) {
  127. this.checkValue("day", this.day, newVal);
  128. },
  129. hours(newVal) {
  130. this.checkValue("hour", this.hour, newVal);
  131. },
  132. minutes(newVal) {
  133. this.checkValue("minute", this.minute, newVal);
  134. },
  135. seconds(newVal) {
  136. this.checkValue("second", this.second, newVal);
  137. }
  138. },
  139. computed: {
  140. // 当前年、月、日、时、分、秒选择范围
  141. years() {
  142. return this.getCurrentRange("year");
  143. },
  144. months() {
  145. return this.getCurrentRange("month");
  146. },
  147. days() {
  148. return this.getCurrentRange("day");
  149. },
  150. hours() {
  151. return this.getCurrentRange("hour");
  152. },
  153. minutes() {
  154. return this.getCurrentRange("minute");
  155. },
  156. seconds() {
  157. return this.getCurrentRange("second");
  158. },
  159. // picker 当前值数组
  160. ymd() {
  161. return [this.year - this.minYear, this.month - this.minMonth, this.day - this.minDay];
  162. },
  163. hms() {
  164. return [this.hour - this.minHour, this.minute - this.minMinute, this.second - this.minSecond];
  165. },
  166. // 当前 date 是 start
  167. currentDateIsStart() {
  168. return this.year === this.startYear && this.month === this.startMonth && this.day === this.startDay;
  169. },
  170. // 当前 date 是 end
  171. currentDateIsEnd() {
  172. return this.year === this.endYear && this.month === this.endMonth && this.day === this.endDay;
  173. },
  174. // 当前年、月、日、时、分、秒的最小值和最大值
  175. minYear() {
  176. return this.startYear;
  177. },
  178. maxYear() {
  179. return this.endYear;
  180. },
  181. minMonth() {
  182. if (this.year === this.startYear) {
  183. return this.startMonth;
  184. } else {
  185. return 1;
  186. }
  187. },
  188. maxMonth() {
  189. if (this.year === this.endYear) {
  190. return this.endMonth;
  191. } else {
  192. return 12;
  193. }
  194. },
  195. minDay() {
  196. if (this.year === this.startYear && this.month === this.startMonth) {
  197. return this.startDay;
  198. } else {
  199. return 1;
  200. }
  201. },
  202. maxDay() {
  203. if (this.year === this.endYear && this.month === this.endMonth) {
  204. return this.endDay;
  205. } else {
  206. return this.daysInMonth(this.year, this.month);
  207. }
  208. },
  209. minHour() {
  210. if (this.type === "datetime") {
  211. if (this.currentDateIsStart) {
  212. return this.startHour;
  213. } else {
  214. return 0;
  215. }
  216. }
  217. if (this.type === "time") {
  218. return this.startHour;
  219. }
  220. },
  221. maxHour() {
  222. if (this.type === "datetime") {
  223. if (this.currentDateIsEnd) {
  224. return this.endHour;
  225. } else {
  226. return 23;
  227. }
  228. }
  229. if (this.type === "time") {
  230. return this.endHour;
  231. }
  232. },
  233. minMinute() {
  234. if (this.type === "datetime") {
  235. if (this.currentDateIsStart && this.hour === this.startHour) {
  236. return this.startMinute;
  237. } else {
  238. return 0;
  239. }
  240. }
  241. if (this.type === "time") {
  242. if (this.hour === this.startHour) {
  243. return this.startMinute;
  244. } else {
  245. return 0;
  246. }
  247. }
  248. },
  249. maxMinute() {
  250. if (this.type === "datetime") {
  251. if (this.currentDateIsEnd && this.hour === this.endHour) {
  252. return this.endMinute;
  253. } else {
  254. return 59;
  255. }
  256. }
  257. if (this.type === "time") {
  258. if (this.hour === this.endHour) {
  259. return this.endMinute;
  260. } else {
  261. return 59;
  262. }
  263. }
  264. },
  265. minSecond() {
  266. if (this.type === "datetime") {
  267. if (this.currentDateIsStart && this.hour === this.startHour && this.minute === this.startMinute) {
  268. return this.startSecond;
  269. } else {
  270. return 0;
  271. }
  272. }
  273. if (this.type === "time") {
  274. if (this.hour === this.startHour && this.minute === this.startMinute) {
  275. return this.startSecond;
  276. } else {
  277. return 0;
  278. }
  279. }
  280. },
  281. maxSecond() {
  282. if (this.type === "datetime") {
  283. if (this.currentDateIsEnd && this.hour === this.endHour && this.minute === this.endMinute) {
  284. return this.endSecond;
  285. } else {
  286. return 59;
  287. }
  288. }
  289. if (this.type === "time") {
  290. if (this.hour === this.endHour && this.minute === this.endMinute) {
  291. return this.endSecond;
  292. } else {
  293. return 59;
  294. }
  295. }
  296. },
  297. /**
  298. * for i18n
  299. */
  300. selectTimeText() {
  301. return t("uni-datetime-picker.selectTime");
  302. },
  303. okText() {
  304. return t("uni-datetime-picker.ok");
  305. },
  306. clearText() {
  307. return t("uni-datetime-picker.clear");
  308. },
  309. cancelText() {
  310. return t("uni-datetime-picker.cancel");
  311. }
  312. },
  313. mounted() {
  314. },
  315. methods: {
  316. /**
  317. * @param {Object} item
  318. * 小于 10 在前面加个 0
  319. */
  320. lessThanTen(item) {
  321. return item < 10 ? "0" + item : item;
  322. },
  323. /**
  324. * 解析时分秒字符串,例如:00:00:00
  325. * @param {String} timeString
  326. */
  327. parseTimeType(timeString) {
  328. if (timeString) {
  329. let timeArr = timeString.split(":");
  330. this.hour = Number(timeArr[0]);
  331. this.minute = Number(timeArr[1]);
  332. this.second = Number(timeArr[2]);
  333. }
  334. },
  335. /**
  336. * 解析选择器初始值,类型可以是字符串、时间戳,例如:2000-10-02、'08:30:00'、 1610695109000
  337. * @param {String | Number} datetime
  338. */
  339. initPickerValue(datetime) {
  340. let defaultValue = null;
  341. if (datetime) {
  342. defaultValue = this.compareValueWithStartAndEnd(datetime, this.start, this.end);
  343. } else {
  344. defaultValue = Date.now();
  345. defaultValue = this.compareValueWithStartAndEnd(defaultValue, this.start, this.end);
  346. }
  347. this.parseValue(defaultValue);
  348. },
  349. /**
  350. * 初始值规则:
  351. * - 用户设置初始值 value
  352. * - 设置了起始时间 start、终止时间 end,并 start < value < end,初始值为 value, 否则初始值为 start
  353. * - 只设置了起始时间 start,并 start < value,初始值为 value,否则初始值为 start
  354. * - 只设置了终止时间 end,并 value < end,初始值为 value,否则初始值为 end
  355. * - 无起始终止时间,则初始值为 value
  356. * - 无初始值 value,则初始值为当前本地时间 Date.now()
  357. * @param {Object} value
  358. * @param {Object} dateBase
  359. */
  360. compareValueWithStartAndEnd(value, start, end) {
  361. let winner = null;
  362. value = this.superTimeStamp(value);
  363. start = this.superTimeStamp(start);
  364. end = this.superTimeStamp(end);
  365. if (start && end) {
  366. if (value < start) {
  367. winner = new Date(start);
  368. } else if (value > end) {
  369. winner = new Date(end);
  370. } else {
  371. winner = new Date(value);
  372. }
  373. } else if (start && !end) {
  374. winner = start <= value ? new Date(value) : new Date(start);
  375. } else if (!start && end) {
  376. winner = value <= end ? new Date(value) : new Date(end);
  377. } else {
  378. winner = new Date(value);
  379. }
  380. return winner;
  381. },
  382. /**
  383. * 转换为可比较的时间戳,接受日期、时分秒、时间戳
  384. * @param {Object} value
  385. */
  386. superTimeStamp(value) {
  387. let dateBase = "";
  388. if (this.type === "time" && value && typeof value === "string") {
  389. const now = /* @__PURE__ */ new Date();
  390. const year = now.getFullYear();
  391. const month = now.getMonth() + 1;
  392. const day = now.getDate();
  393. dateBase = year + "/" + month + "/" + day + " ";
  394. }
  395. if (Number(value) && typeof value !== NaN) {
  396. value = parseInt(value);
  397. dateBase = 0;
  398. }
  399. return this.createTimeStamp(dateBase + value);
  400. },
  401. /**
  402. * 解析默认值 value,字符串、时间戳
  403. * @param {Object} defaultTime
  404. */
  405. parseValue(value) {
  406. if (!value) {
  407. return;
  408. }
  409. if (this.type === "time" && typeof value === "string") {
  410. this.parseTimeType(value);
  411. } else {
  412. let defaultDate = null;
  413. defaultDate = new Date(value);
  414. if (this.type !== "time") {
  415. this.year = defaultDate.getFullYear();
  416. this.month = defaultDate.getMonth() + 1;
  417. this.day = defaultDate.getDate();
  418. }
  419. if (this.type !== "date") {
  420. this.hour = defaultDate.getHours();
  421. this.minute = defaultDate.getMinutes();
  422. this.second = defaultDate.getSeconds();
  423. }
  424. }
  425. if (this.hideSecond) {
  426. this.second = 0;
  427. }
  428. },
  429. /**
  430. * 解析可选择时间范围 start、end,年月日字符串、时间戳
  431. * @param {Object} defaultTime
  432. */
  433. parseDatetimeRange(point, pointType) {
  434. if (!point) {
  435. if (pointType === "start") {
  436. this.startYear = 1920;
  437. this.startMonth = 1;
  438. this.startDay = 1;
  439. this.startHour = 0;
  440. this.startMinute = 0;
  441. this.startSecond = 0;
  442. }
  443. if (pointType === "end") {
  444. this.endYear = 2120;
  445. this.endMonth = 12;
  446. this.endDay = 31;
  447. this.endHour = 23;
  448. this.endMinute = 59;
  449. this.endSecond = 59;
  450. }
  451. return;
  452. }
  453. if (this.type === "time") {
  454. const pointArr = point.split(":");
  455. this[pointType + "Hour"] = Number(pointArr[0]);
  456. this[pointType + "Minute"] = Number(pointArr[1]);
  457. this[pointType + "Second"] = Number(pointArr[2]);
  458. } else {
  459. if (!point) {
  460. pointType === "start" ? this.startYear = this.year - 60 : this.endYear = this.year + 60;
  461. return;
  462. }
  463. if (Number(point) && Number(point) !== NaN) {
  464. point = parseInt(point);
  465. }
  466. const hasTime = /[0-9]:[0-9]/;
  467. if (this.type === "datetime" && pointType === "end" && typeof point === "string" && !hasTime.test(
  468. point
  469. )) {
  470. point = point + " 23:59:59";
  471. }
  472. const pointDate = new Date(point);
  473. this[pointType + "Year"] = pointDate.getFullYear();
  474. this[pointType + "Month"] = pointDate.getMonth() + 1;
  475. this[pointType + "Day"] = pointDate.getDate();
  476. if (this.type === "datetime") {
  477. this[pointType + "Hour"] = pointDate.getHours();
  478. this[pointType + "Minute"] = pointDate.getMinutes();
  479. this[pointType + "Second"] = pointDate.getSeconds();
  480. }
  481. }
  482. },
  483. // 获取 年、月、日、时、分、秒 当前可选范围
  484. getCurrentRange(value) {
  485. const range = [];
  486. for (let i = this["min" + this.capitalize(value)]; i <= this["max" + this.capitalize(value)]; i++) {
  487. range.push(i);
  488. }
  489. return range;
  490. },
  491. // 字符串首字母大写
  492. capitalize(str) {
  493. return str.charAt(0).toUpperCase() + str.slice(1);
  494. },
  495. // 检查当前值是否在范围内,不在则当前值重置为可选范围第一项
  496. checkValue(name, value, values) {
  497. if (values.indexOf(value) === -1) {
  498. this[name] = values[0];
  499. }
  500. },
  501. // 每个月的实际天数
  502. daysInMonth(year, month) {
  503. return new Date(year, month, 0).getDate();
  504. },
  505. //兼容 iOS、safari 日期格式
  506. fixIosDateFormat(value) {
  507. if (typeof value === "string") {
  508. value = value.replace(/-/g, "/");
  509. }
  510. return value;
  511. },
  512. /**
  513. * 生成时间戳
  514. * @param {Object} time
  515. */
  516. createTimeStamp(time) {
  517. if (!time)
  518. return;
  519. if (typeof time === "number") {
  520. return time;
  521. } else {
  522. time = time.replace(/-/g, "/");
  523. if (this.type === "date") {
  524. time = time + " 00:00:00";
  525. }
  526. return Date.parse(time);
  527. }
  528. },
  529. /**
  530. * 生成日期或时间的字符串
  531. */
  532. createDomSting() {
  533. const yymmdd = this.year + "-" + this.lessThanTen(this.month) + "-" + this.lessThanTen(this.day);
  534. let hhmmss = this.lessThanTen(this.hour) + ":" + this.lessThanTen(this.minute);
  535. if (!this.hideSecond) {
  536. hhmmss = hhmmss + ":" + this.lessThanTen(this.second);
  537. }
  538. if (this.type === "date") {
  539. return yymmdd;
  540. } else if (this.type === "time") {
  541. return hhmmss;
  542. } else {
  543. return yymmdd + " " + hhmmss;
  544. }
  545. },
  546. /**
  547. * 初始化返回值,并抛出 change 事件
  548. */
  549. initTime(emit = true) {
  550. this.time = this.createDomSting();
  551. if (!emit)
  552. return;
  553. if (this.returnType === "timestamp" && this.type !== "time") {
  554. this.$emit("change", this.createTimeStamp(this.time));
  555. this.$emit("input", this.createTimeStamp(this.time));
  556. this.$emit("update:modelValue", this.createTimeStamp(this.time));
  557. } else {
  558. this.$emit("change", this.time);
  559. this.$emit("input", this.time);
  560. this.$emit("update:modelValue", this.time);
  561. }
  562. },
  563. /**
  564. * 用户选择日期或时间更新 data
  565. * @param {Object} e
  566. */
  567. bindDateChange(e) {
  568. const val = e.detail.value;
  569. this.year = this.years[val[0]];
  570. this.month = this.months[val[1]];
  571. this.day = this.days[val[2]];
  572. },
  573. bindTimeChange(e) {
  574. const val = e.detail.value;
  575. this.hour = this.hours[val[0]];
  576. this.minute = this.minutes[val[1]];
  577. this.second = this.seconds[val[2]];
  578. },
  579. /**
  580. * 初始化弹出层
  581. */
  582. initTimePicker() {
  583. if (this.disabled)
  584. return;
  585. const value = this.fixIosDateFormat(this.value);
  586. this.initPickerValue(value);
  587. this.visible = !this.visible;
  588. },
  589. /**
  590. * 触发或关闭弹框
  591. */
  592. tiggerTimePicker(e) {
  593. this.visible = !this.visible;
  594. },
  595. /**
  596. * 用户点击“清空”按钮,清空当前值
  597. */
  598. clearTime() {
  599. this.time = "";
  600. this.$emit("change", this.time);
  601. this.$emit("input", this.time);
  602. this.$emit("update:modelValue", this.time);
  603. this.tiggerTimePicker();
  604. },
  605. /**
  606. * 用户点击“确定”按钮
  607. */
  608. setTime() {
  609. this.initTime();
  610. this.tiggerTimePicker();
  611. }
  612. }
  613. };
  614. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  615. return common_vendor.e({
  616. a: common_vendor.t($data.time),
  617. b: !$data.time
  618. }, !$data.time ? {
  619. c: common_vendor.t($options.selectTimeText)
  620. } : {}, {
  621. d: $props.disabled ? 1 : "",
  622. e: $props.border ? 1 : "",
  623. f: common_vendor.o((...args) => $options.initTimePicker && $options.initTimePicker(...args)),
  624. g: $data.visible
  625. }, $data.visible ? {
  626. h: common_vendor.o((...args) => $options.tiggerTimePicker && $options.tiggerTimePicker(...args))
  627. } : {}, {
  628. i: $data.visible
  629. }, $data.visible ? common_vendor.e({
  630. j: common_vendor.t($options.selectTimeText),
  631. k: $data.dateShow
  632. }, $data.dateShow ? {
  633. l: common_vendor.f($options.years, (item, index, i0) => {
  634. return {
  635. a: common_vendor.t($options.lessThanTen(item)),
  636. b: index
  637. };
  638. }),
  639. m: common_vendor.f($options.months, (item, index, i0) => {
  640. return {
  641. a: common_vendor.t($options.lessThanTen(item)),
  642. b: index
  643. };
  644. }),
  645. n: common_vendor.f($options.days, (item, index, i0) => {
  646. return {
  647. a: common_vendor.t($options.lessThanTen(item)),
  648. b: index
  649. };
  650. }),
  651. o: $data.indicatorStyle,
  652. p: $options.ymd,
  653. q: common_vendor.o((...args) => $options.bindDateChange && $options.bindDateChange(...args))
  654. } : {}, {
  655. r: $data.timeShow
  656. }, $data.timeShow ? common_vendor.e({
  657. s: common_vendor.f($options.hours, (item, index, i0) => {
  658. return {
  659. a: common_vendor.t($options.lessThanTen(item)),
  660. b: index
  661. };
  662. }),
  663. t: common_vendor.f($options.minutes, (item, index, i0) => {
  664. return {
  665. a: common_vendor.t($options.lessThanTen(item)),
  666. b: index
  667. };
  668. }),
  669. v: !$props.hideSecond
  670. }, !$props.hideSecond ? {
  671. w: common_vendor.f($options.seconds, (item, index, i0) => {
  672. return {
  673. a: common_vendor.t($options.lessThanTen(item)),
  674. b: index
  675. };
  676. })
  677. } : {}, {
  678. x: common_vendor.n($props.hideSecond ? "time-hide-second" : ""),
  679. y: $data.indicatorStyle,
  680. z: $options.hms,
  681. A: common_vendor.o((...args) => $options.bindTimeChange && $options.bindTimeChange(...args)),
  682. B: common_vendor.n($props.hideSecond ? "sign-center" : "sign-left"),
  683. C: !$props.hideSecond
  684. }, !$props.hideSecond ? {} : {}) : {}, {
  685. D: common_vendor.t($options.clearText),
  686. E: common_vendor.o((...args) => $options.clearTime && $options.clearTime(...args)),
  687. F: common_vendor.t($options.cancelText),
  688. G: common_vendor.o((...args) => $options.tiggerTimePicker && $options.tiggerTimePicker(...args)),
  689. H: common_vendor.t($options.okText),
  690. I: common_vendor.o((...args) => $options.setTime && $options.setTime(...args)),
  691. J: common_vendor.n($data.dateShow && $data.timeShow ? "" : "fix-nvue-height"),
  692. K: common_vendor.s($data.fixNvueBug)
  693. }) : {});
  694. }
  695. const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "/Users/RuHu.Xu/Desktop/mall-newfeifan-zx-app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue"]]);
  696. wx.createComponent(Component);