移动端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

197 lines
5.0 KiB

  1. <!-- 日期选择表单组件 zhao -->
  2. <template>
  3. <div>
  4. <van-field
  5. :readonly="true"
  6. :clickable="!readonly"
  7. :name="name"
  8. :value="visibleValue"
  9. :label="label"
  10. :placeholder="placeholder"
  11. @click="openPopup"
  12. input-align="right"
  13. right-icon="arrow-down"
  14. :rules="rules"
  15. :required="required"
  16. :label-width="labelWidth || 'auto'"
  17. :input-align="inputAlign || 'left'"
  18. :size="size || ''"
  19. >
  20. <!-- <template #button>
  21. <van-icon name="notes-o" size="20"/>
  22. </template>-->
  23. </van-field>
  24. <van-popup v-model="popupVisible" position="bottom" v-if="type === 'year'">
  25. <van-picker
  26. ref="picker"
  27. :title="label"
  28. show-toolbar
  29. :columns="yearColumns"
  30. :readonly="readonly"
  31. v-model="internalValue"
  32. @confirm="onConfirm"
  33. @cancel="onCancel"
  34. @change="onChanged"
  35. />
  36. </van-popup>
  37. <van-popup v-model="popupVisible" position="bottom" v-else>
  38. <van-datetime-picker
  39. ref="picker"
  40. v-model="internalValue"
  41. :type="type || 'date'"
  42. :readonly="readonly"
  43. :title="label || ''"
  44. :min-date="minDate"
  45. :max-date="maxDate"
  46. @confirm="onConfirm"
  47. @cancel="onCancel"
  48. @change="onChanged"
  49. />
  50. </van-popup>
  51. </div>
  52. </template>
  53. <script>
  54. import { formatDate } from "element-ui/src/utils/date-util.js"
  55. import {strtotime} from "@/utils";
  56. export default {
  57. name: "fieldDatePicker",
  58. props: [
  59. 'name', 'readonly', 'value', 'label', 'placeholder', 'required', 'rules', 'labelWidth', 'inputAlign',
  60. 'type', // 类型, 仅支持 datetime date time year-month month-day datehour, 额外支持year(但formatter必须为yyyy, 可以提供yearRangeLength=<Number>指定年范围)
  61. 'formatter', // value的格式化 String|Function|undefined 字符串为格式字符串, 函数则必须有返回 undefined则不转换
  62. 'clearable', // 点击取消时清空绑定值
  63. 'yearRangeLength', // type === 'year' 时生成的年份数量范围 [YEAR - yearRangeLength, YEAR + yearRangeLength]
  64. 'minDate', 'maxDate',
  65. 'size',
  66. ],
  67. watch: {
  68. value: function (newVal, oldVal) {
  69. this.visibleValue = newVal;
  70. this.internalValue = new Date(newVal);
  71. },
  72. },
  73. created() {
  74. if(this.value)
  75. {
  76. this.visibleValue = this.value;
  77. this.internalValue = new Date(this.value);
  78. }
  79. // 默认当前
  80. /* else {
  81. this.syncValue(new Date);
  82. }*/
  83. },
  84. data() {
  85. return {
  86. popupVisible: false,
  87. internalValue: new Date(this.value || Date.now()),
  88. visibleValue: this.value,
  89. loading: false,
  90. };
  91. },
  92. methods: {
  93. openPopup() {
  94. if(!this.readonly)
  95. {
  96. //console.log(this.internalValue);
  97. this.popupVisible = true;
  98. this.$nextTick(() => {
  99. try
  100. {
  101. if(1)
  102. {
  103. let values = (this.visibleValue || this.getValue(new Date)).split(/\D+/); //TODO: 按非数字符号粗略分割解析初始值, 仅对于类似yyyy-MM-dd
  104. //console.log(values);
  105. let picker = this.$refs.picker.getPicker ? this.$refs.picker.getPicker() : this.$refs.picker;
  106. picker.setValues(values);
  107. }
  108. else {
  109. //TODO: 打开时保存初始值, 取消或点击遮罩未确定的时候恢复该初始值到v-model
  110. }
  111. }
  112. catch (e)
  113. {
  114. console.error(e);
  115. }
  116. })
  117. }
  118. },
  119. closePopup() {
  120. this.popupVisible = false;
  121. },
  122. onConfirm(data) {
  123. this.syncValue(data);
  124. this.$emit('input', this.visibleValue);
  125. this.$emit('confirm', this.visibleValue, this.internalValue);
  126. this.closePopup();
  127. },
  128. onCancel() {
  129. this.closePopup();
  130. this.$emit('cancel');
  131. if(this.clearable)
  132. {
  133. this.visibleValue = '';
  134. this.internalValue = null;
  135. this.$emit('input', this.internalValue);
  136. }
  137. },
  138. onChanged(data) {
  139. this.$emit('change', this.getValue(data), data);
  140. },
  141. getValue(data) {
  142. let type = typeof(this.formatter);
  143. if(type === 'function')
  144. return this.formatter(data);
  145. else if(type === 'string')
  146. return formatDate(data, this.formatter);
  147. else
  148. return data;
  149. },
  150. syncValue(data) {
  151. this.internalValue = data;
  152. this.visibleValue = this.getValue(data);
  153. },
  154. genYearColumns(num) {
  155. let d;
  156. try
  157. {
  158. if(this.value)
  159. {
  160. d = strtotime(this.value, 'yyyy');
  161. }
  162. else
  163. d = new Date;
  164. }
  165. catch(e)
  166. {
  167. d = new Date;
  168. }
  169. let y = d.getFullYear();
  170. let arr = ['' + y];
  171. for(let i = 1; i <= num; i++)
  172. {
  173. arr.push('' + (y + i));
  174. arr.splice(0, 0, '' + (y - i));
  175. }
  176. return arr;
  177. },
  178. strtotime,
  179. },
  180. computed: {
  181. yearColumns() {
  182. if(this.type !== 'year')
  183. return [];
  184. return this.genYearColumns(this.yearRangeLength || 100);
  185. },
  186. }
  187. }
  188. </script>
  189. <style scoped>
  190. </style>