u-datetime-picker.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. "use strict";
  2. const common_vendor = require("../../../../common/vendor.js");
  3. function times(n, iteratee) {
  4. let index = -1;
  5. const result = Array(n < 0 ? 0 : n);
  6. while (++index < n) {
  7. result[index] = iteratee(index);
  8. }
  9. return result;
  10. }
  11. const _sfc_main = {
  12. name: "datetime-picker",
  13. mixins: [common_vendor.mpMixin, common_vendor.mixin, common_vendor.props$14],
  14. data() {
  15. return {
  16. // 原来的日期选择器不方便,这里增加一个hasInput选项支持类似element的自带输入框的功能。
  17. inputValue: "",
  18. // 表单显示值
  19. showByClickInput: false,
  20. // 是否在hasInput模式下显示日期选择弹唱
  21. columns: [],
  22. innerDefaultIndex: [],
  23. innerFormatter: (type, value) => value
  24. };
  25. },
  26. watch: {
  27. show(newValue, oldValue) {
  28. if (newValue) {
  29. this.updateColumnValue(this.innerValue);
  30. }
  31. },
  32. modelValue(newValue) {
  33. this.init();
  34. },
  35. propsChange() {
  36. this.init();
  37. }
  38. },
  39. computed: {
  40. // 如果以下这些变量发生了变化,意味着需要重新初始化各列的值
  41. propsChange() {
  42. return [this.mode, this.maxDate, this.minDate, this.minHour, this.maxHour, this.minMinute, this.maxMinute, this.filter];
  43. }
  44. },
  45. mounted() {
  46. this.init();
  47. },
  48. emits: ["close", "cancel", "confirm", "change", "update:modelValue"],
  49. methods: {
  50. getInputValue(newValue) {
  51. if (newValue == "" || !newValue || newValue == void 0) {
  52. this.inputValue = "";
  53. return;
  54. }
  55. if (this.mode == "time") {
  56. this.inputValue = newValue;
  57. } else {
  58. if (this.format) {
  59. this.inputValue = common_vendor.dayjs(newValue).format(this.format);
  60. } else {
  61. let format = "";
  62. switch (this.mode) {
  63. case "date":
  64. format = "YYYY-MM-DD";
  65. break;
  66. case "year-month":
  67. format = "YYYY-MM";
  68. break;
  69. case "datetime":
  70. format = "YYYY-MM-DD HH:mm";
  71. break;
  72. case "time":
  73. format = "HH:mm";
  74. break;
  75. }
  76. this.inputValue = common_vendor.dayjs(newValue).format(format);
  77. }
  78. }
  79. },
  80. init() {
  81. this.innerValue = this.correctValue(this.modelValue);
  82. this.updateColumnValue(this.innerValue);
  83. this.getInputValue(this.innerValue);
  84. },
  85. // 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用
  86. setFormatter(e) {
  87. this.innerFormatter = e;
  88. },
  89. // 关闭选择器
  90. close() {
  91. if (this.closeOnClickOverlay) {
  92. this.$emit("close");
  93. }
  94. },
  95. // 点击工具栏的取消按钮
  96. cancel() {
  97. if (this.hasInput) {
  98. this.showByClickInput = false;
  99. }
  100. this.$emit("cancel");
  101. },
  102. // 点击工具栏的确定按钮
  103. confirm() {
  104. this.$emit("confirm", {
  105. value: this.innerValue,
  106. mode: this.mode
  107. });
  108. this.$emit("update:modelValue", this.innerValue);
  109. if (this.hasInput) {
  110. this.getInputValue(this.innerValue);
  111. this.showByClickInput = false;
  112. }
  113. },
  114. //用正则截取输出值,当出现多组数字时,抛出错误
  115. intercept(e, type) {
  116. let judge = e.match(/\d+/g);
  117. if (judge.length > 1) {
  118. common_vendor.error("请勿在过滤或格式化函数时添加数字");
  119. return 0;
  120. } else if (type && judge[0].length == 4) {
  121. return judge[0];
  122. } else if (judge[0].length > 2) {
  123. common_vendor.error("请勿在过滤或格式化函数时添加数字");
  124. return 0;
  125. } else {
  126. return judge[0];
  127. }
  128. },
  129. // 列发生变化时触发
  130. change(e) {
  131. const { indexs, values } = e;
  132. let selectValue = "";
  133. if (this.mode === "time") {
  134. selectValue = `${this.intercept(values[0][indexs[0]])}:${this.intercept(values[1][indexs[1]])}`;
  135. } else {
  136. const year = parseInt(this.intercept(values[0][indexs[0]], "year"));
  137. const month = parseInt(this.intercept(values[1][indexs[1]]));
  138. let date = parseInt(values[2] ? this.intercept(values[2][indexs[2]]) : 1);
  139. let hour = 0, minute = 0;
  140. const maxDate = common_vendor.dayjs(`${year}-${month}`).daysInMonth();
  141. if (this.mode === "year-month") {
  142. date = 1;
  143. }
  144. date = Math.min(maxDate, date);
  145. if (this.mode === "datetime") {
  146. hour = parseInt(this.intercept(values[3][indexs[3]]));
  147. minute = parseInt(this.intercept(values[4][indexs[4]]));
  148. }
  149. selectValue = Number(new Date(year, month - 1, date, hour, minute));
  150. }
  151. selectValue = this.correctValue(selectValue);
  152. this.innerValue = selectValue;
  153. this.updateColumnValue(selectValue);
  154. this.$emit("change", {
  155. value: selectValue,
  156. mode: this.mode
  157. });
  158. },
  159. // 更新各列的值,进行补0、格式化等操作
  160. updateColumnValue(value) {
  161. this.innerValue = value;
  162. this.updateColumns();
  163. setTimeout(() => {
  164. this.updateIndexs(value);
  165. }, 0);
  166. },
  167. // 更新索引
  168. updateIndexs(value) {
  169. let values = [];
  170. const formatter = this.formatter || this.innerFormatter;
  171. if (this.mode === "time") {
  172. const timeArr = value.split(":");
  173. values = [formatter("hour", timeArr[0]), formatter("minute", timeArr[1])];
  174. } else {
  175. values = [
  176. formatter("year", `${common_vendor.dayjs(value).year()}`),
  177. // 月份补0
  178. formatter("month", common_vendor.padZero(common_vendor.dayjs(value).month() + 1))
  179. ];
  180. if (this.mode === "date") {
  181. values.push(formatter("day", common_vendor.padZero(common_vendor.dayjs(value).date())));
  182. }
  183. if (this.mode === "datetime") {
  184. values.push(formatter("day", common_vendor.padZero(common_vendor.dayjs(value).date())), formatter("hour", common_vendor.padZero(common_vendor.dayjs(value).hour())), formatter("minute", common_vendor.padZero(common_vendor.dayjs(value).minute())));
  185. }
  186. }
  187. const indexs = this.columns.map((column, index) => {
  188. return Math.max(0, column.findIndex((item) => item === values[index]));
  189. });
  190. this.innerDefaultIndex = indexs;
  191. },
  192. // 更新各列的值
  193. updateColumns() {
  194. const formatter = this.formatter || this.innerFormatter;
  195. const results = this.getOriginColumns().map((column) => column.values.map((value) => formatter(column.type, value)));
  196. this.columns = results;
  197. },
  198. getOriginColumns() {
  199. const results = this.getRanges().map(({ type, range }) => {
  200. let values = times(range[1] - range[0] + 1, (index) => {
  201. let value = range[0] + index;
  202. value = type === "year" ? `${value}` : common_vendor.padZero(value);
  203. return value;
  204. });
  205. if (this.filter) {
  206. values = this.filter(type, values);
  207. if (!values || values && values.length == 0) {
  208. common_vendor.index.showToast({
  209. title: "日期filter结果不能为空",
  210. icon: "error",
  211. mask: true
  212. });
  213. }
  214. }
  215. return { type, values };
  216. });
  217. return results;
  218. },
  219. // 通过最大值和最小值生成数组
  220. generateArray(start, end) {
  221. return Array.from(new Array(end + 1).keys()).slice(start);
  222. },
  223. // 得出合法的时间
  224. correctValue(value) {
  225. const isDateMode = this.mode !== "time";
  226. if (isDateMode && !common_vendor.test.date(value)) {
  227. value = this.minDate;
  228. } else if (!isDateMode && !value) {
  229. value = `${common_vendor.padZero(this.minHour)}:${common_vendor.padZero(this.minMinute)}`;
  230. }
  231. if (!isDateMode) {
  232. if (String(value).indexOf(":") === -1)
  233. return common_vendor.error("时间错误,请传递如12:24的格式");
  234. let [hour, minute] = value.split(":");
  235. hour = common_vendor.padZero(common_vendor.range(this.minHour, this.maxHour, Number(hour)));
  236. minute = common_vendor.padZero(common_vendor.range(this.minMinute, this.maxMinute, Number(minute)));
  237. return `${hour}:${minute}`;
  238. } else {
  239. value = common_vendor.dayjs(value).isBefore(common_vendor.dayjs(this.minDate)) ? this.minDate : value;
  240. value = common_vendor.dayjs(value).isAfter(common_vendor.dayjs(this.maxDate)) ? this.maxDate : value;
  241. return value;
  242. }
  243. },
  244. // 获取每列的最大和最小值
  245. getRanges() {
  246. if (this.mode === "time") {
  247. return [
  248. {
  249. type: "hour",
  250. range: [this.minHour, this.maxHour]
  251. },
  252. {
  253. type: "minute",
  254. range: [this.minMinute, this.maxMinute]
  255. }
  256. ];
  257. }
  258. const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary("max", this.innerValue);
  259. const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary("min", this.innerValue);
  260. const result = [
  261. {
  262. type: "year",
  263. range: [minYear, maxYear]
  264. },
  265. {
  266. type: "month",
  267. range: [minMonth, maxMonth]
  268. },
  269. {
  270. type: "day",
  271. range: [minDate, maxDate]
  272. },
  273. {
  274. type: "hour",
  275. range: [minHour, maxHour]
  276. },
  277. {
  278. type: "minute",
  279. range: [minMinute, maxMinute]
  280. }
  281. ];
  282. if (this.mode === "date")
  283. result.splice(3, 2);
  284. if (this.mode === "year-month")
  285. result.splice(2, 3);
  286. return result;
  287. },
  288. // 根据minDate、maxDate、minHour、maxHour等边界值,判断各列的开始和结束边界值
  289. getBoundary(type, innerValue) {
  290. const value = new Date(innerValue);
  291. const boundary = new Date(this[`${type}Date`]);
  292. const year = common_vendor.dayjs(boundary).year();
  293. let month = 1;
  294. let date = 1;
  295. let hour = 0;
  296. let minute = 0;
  297. if (type === "max") {
  298. month = 12;
  299. date = common_vendor.dayjs(value).daysInMonth();
  300. hour = 23;
  301. minute = 59;
  302. }
  303. if (common_vendor.dayjs(value).year() === year) {
  304. month = common_vendor.dayjs(boundary).month() + 1;
  305. if (common_vendor.dayjs(value).month() + 1 === month) {
  306. date = common_vendor.dayjs(boundary).date();
  307. if (common_vendor.dayjs(value).date() === date) {
  308. hour = common_vendor.dayjs(boundary).hour();
  309. if (common_vendor.dayjs(value).hour() === hour) {
  310. minute = common_vendor.dayjs(boundary).minute();
  311. }
  312. }
  313. }
  314. }
  315. return {
  316. [`${type}Year`]: year,
  317. [`${type}Month`]: month,
  318. [`${type}Date`]: date,
  319. [`${type}Hour`]: hour,
  320. [`${type}Minute`]: minute
  321. };
  322. }
  323. }
  324. };
  325. if (!Array) {
  326. const _easycom_u_input2 = common_vendor.resolveComponent("u-input");
  327. const _easycom_u_picker2 = common_vendor.resolveComponent("u-picker");
  328. (_easycom_u_input2 + _easycom_u_picker2)();
  329. }
  330. const _easycom_u_input = () => "../u-input/u-input.js";
  331. const _easycom_u_picker = () => "../u-picker/u-picker.js";
  332. if (!Math) {
  333. (_easycom_u_input + _easycom_u_picker)();
  334. }
  335. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  336. return common_vendor.e({
  337. a: _ctx.hasInput
  338. }, _ctx.hasInput ? {
  339. b: common_vendor.o(($event) => $data.showByClickInput = !$data.showByClickInput),
  340. c: common_vendor.o(($event) => $data.inputValue = $event),
  341. d: common_vendor.p({
  342. placeholder: _ctx.placeholder,
  343. border: "surround",
  344. modelValue: $data.inputValue
  345. })
  346. } : {}, {
  347. e: common_vendor.sr("picker", "e39cc2d0-1"),
  348. f: common_vendor.o($options.close),
  349. g: common_vendor.o($options.cancel),
  350. h: common_vendor.o($options.confirm),
  351. i: common_vendor.o($options.change),
  352. j: common_vendor.p({
  353. show: _ctx.show || _ctx.hasInput && $data.showByClickInput,
  354. popupMode: _ctx.popupMode,
  355. closeOnClickOverlay: _ctx.closeOnClickOverlay,
  356. columns: $data.columns,
  357. title: _ctx.title,
  358. itemHeight: _ctx.itemHeight,
  359. showToolbar: _ctx.showToolbar,
  360. visibleItemCount: _ctx.visibleItemCount,
  361. defaultIndex: $data.innerDefaultIndex,
  362. cancelText: _ctx.cancelText,
  363. confirmText: _ctx.confirmText,
  364. cancelColor: _ctx.cancelColor,
  365. confirmColor: _ctx.confirmColor
  366. })
  367. });
  368. }
  369. const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-e39cc2d0"], ["__file", "D:/project/学吧/learn_applet/node_modules/uview-plus/components/u-datetime-picker/u-datetime-picker.vue"]]);
  370. wx.createComponent(Component);