uni-datetime-picker.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. <template>
  2. <view class="uni-datetime-picker">
  3. <view @click="initTimePicker">
  4. <slot>
  5. <view class="uni-datetime-picker-timebox-pointer"
  6. :class="{'uni-datetime-picker-disabled': disabled, 'uni-datetime-picker-timebox': border}">
  7. <text class="uni-datetime-picker-text">{{time}}</text>
  8. <view v-if="!time" class="uni-datetime-picker-time">
  9. <text class="uni-datetime-picker-text">选择{{title}}</text>
  10. </view>
  11. </view>
  12. </slot>
  13. </view>
  14. <view v-if="visible" id="mask" class="uni-datetime-picker-mask" @click="tiggerTimePicker"></view>
  15. <view v-if="visible" class="uni-datetime-picker-popup" :class="[dateShow && timeShow ? '' : 'fix-nvue-height']" :style="fixNvueBug">
  16. <view class="uni-title">
  17. <text class="uni-datetime-picker-text">设置{{title}}</text>
  18. </view>
  19. <view v-if="dateShow" class="uni-datetime-picker__container-box">
  20. <picker-view class="uni-datetime-picker-view" :indicator-style="indicatorStyle" :value="ymd"
  21. @change="bindDateChange">
  22. <picker-view-column>
  23. <view class="uni-datetime-picker-item" v-for="(item,index) in years" :key="index">
  24. <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
  25. </view>
  26. </picker-view-column>
  27. <picker-view-column>
  28. <view class="uni-datetime-picker-item" v-for="(item,index) in months" :key="index">
  29. <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
  30. </view>
  31. </picker-view-column>
  32. <picker-view-column>
  33. <view class="uni-datetime-picker-item" v-for="(item,index) in days" :key="index">
  34. <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
  35. </view>
  36. </picker-view-column>
  37. </picker-view>
  38. <!-- 兼容 nvue 不支持伪类 -->
  39. <text class="uni-datetime-picker-sign sign-left">-</text>
  40. <text class="uni-datetime-picker-sign sign-right">-</text>
  41. </view>
  42. <view v-if="timeShow" class="uni-datetime-picker__container-box">
  43. <picker-view class="uni-datetime-picker-view" :class="[hideSecond ? 'time-hide-second' : '']"
  44. :indicator-style="indicatorStyle" :value="hms" @change="bindTimeChange">
  45. <picker-view-column>
  46. <view class="uni-datetime-picker-item" v-for="(item,index) in hours" :key="index">
  47. <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
  48. </view>
  49. </picker-view-column>
  50. <picker-view-column>
  51. <view class="uni-datetime-picker-item" v-for="(item,index) in minutes" :key="index">
  52. <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
  53. </view>
  54. </picker-view-column>
  55. <picker-view-column v-if="!hideSecond">
  56. <view class="uni-datetime-picker-item" v-for="(item,index) in seconds" :key="index">
  57. <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
  58. </view>
  59. </picker-view-column>
  60. </picker-view>
  61. <!-- 兼容 nvue 不支持伪类 -->
  62. <text class="uni-datetime-picker-sign" :class="[hideSecond ? 'sign-center' : 'sign-left']">:</text>
  63. <text v-if="!hideSecond" class="uni-datetime-picker-sign sign-right">:</text>
  64. </view>
  65. <view class="uni-datetime-picker-btn">
  66. <view @click="clearTime">
  67. <text class="uni-datetime-picker-btn-text">清空</text>
  68. </view>
  69. <view class="uni-datetime-picker-btn-group">
  70. <view class="uni-datetime-picker-cancel" @click="tiggerTimePicker">
  71. <text class="uni-datetime-picker-btn-text">取消</text>
  72. </view>
  73. <view @click="setTime">
  74. <text class="uni-datetime-picker-btn-text">确定</text>
  75. </view>
  76. </view>
  77. </view>
  78. </view>
  79. <!-- #ifdef H5 -->
  80. <keypress v-if="visible" @esc="tiggerTimePicker" @enter="setTime" />
  81. <!-- #endif -->
  82. </view>
  83. </template>
  84. <script>
  85. // #ifdef H5
  86. import keypress from './keypress'
  87. // #endif
  88. /**
  89. * DatetimePicker 时间选择器
  90. * @description 可以同时选择日期和时间的选择器
  91. * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
  92. * @property {String} type = [datetime | date | time] 显示模式
  93. * @property {Boolean} multiple = [true|false] 是否多选
  94. * @property {String|Number} value 默认值
  95. * @property {String|Number} start 起始日期或时间
  96. * @property {String|Number} end 起始日期或时间
  97. * @property {String} return-type = [timestamp | string]
  98. * @event {Function} change 选中发生变化触发
  99. */
  100. export default {
  101. name: 'UniDatetimePicker',
  102. components: {
  103. // #ifdef H5
  104. keypress
  105. // #endif
  106. },
  107. data() {
  108. return {
  109. indicatorStyle: `height: 50px;`,
  110. visible: false,
  111. fixNvueBug: {},
  112. dateShow: true,
  113. timeShow: true,
  114. title: '日期和时间',
  115. // 输入框当前时间
  116. time: '',
  117. // 当前的年月日时分秒
  118. year: 1900,
  119. month: 0,
  120. day: 0,
  121. hour: 0,
  122. minute: 0,
  123. second: 0,
  124. // 起始时间
  125. startYear: 1920,
  126. startMonth: 1,
  127. startDay: 1,
  128. startHour: 0,
  129. startMinute: 0,
  130. startSecond: 0,
  131. // 结束时间
  132. endYear: 2120,
  133. endMonth: 12,
  134. endDay: 31,
  135. endHour: 23,
  136. endMinute: 59,
  137. endSecond: 59,
  138. }
  139. },
  140. props: {
  141. type: {
  142. type: String,
  143. default: 'datetime'
  144. },
  145. value: {
  146. type: [String, Number],
  147. default: ''
  148. },
  149. start: {
  150. type: [Number, String],
  151. default: ''
  152. },
  153. end: {
  154. type: [Number, String],
  155. default: ''
  156. },
  157. returnType: {
  158. type: String,
  159. default: 'string'
  160. },
  161. disabled: {
  162. type: [Boolean, String],
  163. default: false
  164. },
  165. border: {
  166. type: [Boolean, String],
  167. default: true
  168. },
  169. hideSecond: {
  170. type: [Boolean, String],
  171. default: false
  172. }
  173. },
  174. watch: {
  175. value: {
  176. handler(newVal, oldVal) {
  177. if (newVal) {
  178. this.parseValue(this.fixIosDateFormat(newVal)) //兼容 iOS、safari 日期格式
  179. this.initTime(false)
  180. } else {
  181. this.parseValue(Date.now())
  182. }
  183. },
  184. immediate: true
  185. },
  186. type: {
  187. handler(newValue) {
  188. if (newValue === 'date') {
  189. this.dateShow = true
  190. this.timeShow = false
  191. this.title = '日期'
  192. } else if (newValue === 'time') {
  193. this.dateShow = false
  194. this.timeShow = true
  195. this.title = '时间'
  196. } else {
  197. this.dateShow = true
  198. this.timeShow = true
  199. this.title = '日期和时间'
  200. }
  201. },
  202. immediate: true
  203. },
  204. start: {
  205. handler(newVal) {
  206. this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'start') //兼容 iOS、safari 日期格式
  207. },
  208. immediate: true
  209. },
  210. end: {
  211. handler(newVal) {
  212. this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'end') //兼容 iOS、safari 日期格式
  213. },
  214. immediate: true
  215. },
  216. // 月、日、时、分、秒可选范围变化后,检查当前值是否在范围内,不在则当前值重置为可选范围第一项
  217. months(newVal) {
  218. this.checkValue('month', this.month, newVal)
  219. },
  220. days(newVal) {
  221. this.checkValue('day', this.day, newVal)
  222. },
  223. hours(newVal) {
  224. this.checkValue('hour', this.hour, newVal)
  225. },
  226. minutes(newVal) {
  227. this.checkValue('minute', this.minute, newVal)
  228. },
  229. seconds(newVal) {
  230. this.checkValue('second', this.second, newVal)
  231. }
  232. },
  233. created() {
  234. this.form = this.getForm('uniForms')
  235. this.formItem = this.getForm('uniFormsItem')
  236. if (this.formItem) {
  237. if (this.formItem.name) {
  238. this.rename = this.formItem.name
  239. this.form.inputChildrens.push(this)
  240. }
  241. }
  242. },
  243. computed: {
  244. // 当前年、月、日、时、分、秒选择范围
  245. years() {
  246. return this.getCurrentRange('year')
  247. },
  248. months() {
  249. return this.getCurrentRange('month')
  250. },
  251. days() {
  252. return this.getCurrentRange('day')
  253. },
  254. hours() {
  255. return this.getCurrentRange('hour')
  256. },
  257. minutes() {
  258. return this.getCurrentRange('minute')
  259. },
  260. seconds() {
  261. return this.getCurrentRange('second')
  262. },
  263. // picker 当前值数组
  264. ymd() {
  265. return [this.year - this.minYear, this.month - this.minMonth, this.day - this.minDay]
  266. },
  267. hms() {
  268. return [this.hour - this.minHour, this.minute - this.minMinute, this.second - this.minSecond]
  269. },
  270. // 当前 date 是 start
  271. currentDateIsStart() {
  272. return this.year === this.startYear && this.month === this.startMonth && this.day === this.startDay
  273. },
  274. // 当前 date 是 end
  275. currentDateIsEnd() {
  276. return this.year === this.endYear && this.month === this.endMonth && this.day === this.endDay
  277. },
  278. // 当前年、月、日、时、分、秒的最小值和最大值
  279. minYear() {
  280. return this.startYear
  281. },
  282. maxYear() {
  283. return this.endYear
  284. },
  285. minMonth() {
  286. if (this.year === this.startYear) {
  287. return this.startMonth
  288. } else {
  289. return 1
  290. }
  291. },
  292. maxMonth() {
  293. if (this.year === this.endYear) {
  294. return this.endMonth
  295. } else {
  296. return 12
  297. }
  298. },
  299. minDay() {
  300. if (this.year === this.startYear && this.month === this.startMonth) {
  301. return this.startDay
  302. } else {
  303. return 1
  304. }
  305. },
  306. maxDay() {
  307. if (this.year === this.endYear && this.month === this.endMonth) {
  308. return this.endDay
  309. } else {
  310. return this.daysInMonth(this.year, this.month)
  311. }
  312. },
  313. minHour() {
  314. if (this.type === 'datetime') {
  315. if (this.currentDateIsStart) {
  316. return this.startHour
  317. } else {
  318. return 0
  319. }
  320. }
  321. if (this.type === 'time') {
  322. return this.startHour
  323. }
  324. },
  325. maxHour() {
  326. if (this.type === 'datetime') {
  327. if (this.currentDateIsEnd) {
  328. return this.endHour
  329. } else {
  330. return 23
  331. }
  332. }
  333. if (this.type === 'time') {
  334. return this.endHour
  335. }
  336. },
  337. minMinute() {
  338. if (this.type === 'datetime') {
  339. if (this.currentDateIsStart && this.hour === this.startHour) {
  340. return this.startMinute
  341. } else {
  342. return 0
  343. }
  344. }
  345. if (this.type === 'time') {
  346. if (this.hour === this.startHour) {
  347. return this.startMinute
  348. } else {
  349. return 0
  350. }
  351. }
  352. },
  353. maxMinute() {
  354. if (this.type === 'datetime') {
  355. if (this.currentDateIsEnd && this.hour === this.endHour) {
  356. return this.endMinute
  357. } else {
  358. return 59
  359. }
  360. }
  361. if (this.type === 'time') {
  362. if (this.hour === this.endHour) {
  363. return this.endMinute
  364. } else {
  365. return 59
  366. }
  367. }
  368. },
  369. minSecond() {
  370. if (this.type === 'datetime') {
  371. if (this.currentDateIsStart && this.hour === this.startHour && this.minute === this.startMinute) {
  372. return this.startSecond
  373. } else {
  374. return 0
  375. }
  376. }
  377. if (this.type === 'time') {
  378. if (this.hour === this.startHour && this.minute === this.startMinute) {
  379. return this.startSecond
  380. } else {
  381. return 0
  382. }
  383. }
  384. },
  385. maxSecond() {
  386. if (this.type === 'datetime') {
  387. if (this.currentDateIsEnd && this.hour === this.endHour && this.minute === this.endMinute) {
  388. return this.endSecond
  389. } else {
  390. return 59
  391. }
  392. }
  393. if (this.type === 'time') {
  394. if (this.hour === this.endHour && this.minute === this.endMinute) {
  395. return this.endSecond
  396. } else {
  397. return 59
  398. }
  399. }
  400. }
  401. },
  402. mounted() {
  403. // #ifdef APP-NVUE
  404. const res = uni.getSystemInfoSync();
  405. this.fixNvueBug = {
  406. top: res.windowHeight / 2,
  407. left: res.windowWidth / 2
  408. }
  409. // #endif
  410. },
  411. methods: {
  412. /**
  413. * @param {Object} item
  414. * 小于 10 在前面加个 0
  415. */
  416. lessThanTen(item) {
  417. return item < 10 ? '0' + item : item
  418. },
  419. /**
  420. * 获取父元素实例
  421. */
  422. getForm(name = 'uniForms') {
  423. let parent = this.$parent;
  424. let parentName = parent.$options.name;
  425. while (parentName !== name) {
  426. parent = parent.$parent;
  427. if (!parent) return false
  428. parentName = parent.$options.name;
  429. }
  430. return parent;
  431. },
  432. /**
  433. * 解析时分秒字符串,例如:00:00:00
  434. * @param {String} timeString
  435. */
  436. parseTimeType(timeString) {
  437. if (timeString) {
  438. let timeArr = timeString.split(':')
  439. this.hour = Number(timeArr[0])
  440. this.minute = Number(timeArr[1])
  441. this.second = Number(timeArr[2])
  442. }
  443. },
  444. /**
  445. * 解析选择器初始值,类型可以是字符串、时间戳,例如:2000-10-02、'08:30:00'、 1610695109000
  446. * @param {String | Number} datetime
  447. */
  448. initPickerValue(datetime) {
  449. let defaultValue = null
  450. if (datetime) {
  451. defaultValue = this.compareValueWithStartAndEnd(datetime, this.start, this.end)
  452. } else {
  453. defaultValue = Date.now()
  454. defaultValue = this.compareValueWithStartAndEnd(defaultValue, this.start, this.end)
  455. }
  456. this.parseValue(defaultValue)
  457. },
  458. /**
  459. * 初始值规则:
  460. * - 用户设置初始值 value
  461. * - 设置了起始时间 start、终止时间 end,并 start < value < end,初始值为 value, 否则初始值为 start
  462. * - 只设置了起始时间 start,并 start < value,初始值为 value,否则初始值为 start
  463. * - 只设置了终止时间 end,并 value < end,初始值为 value,否则初始值为 end
  464. * - 无起始终止时间,则初始值为 value
  465. * - 无初始值 value,则初始值为当前本地时间 Date.now()
  466. * @param {Object} value
  467. * @param {Object} dateBase
  468. */
  469. compareValueWithStartAndEnd(value, start, end) {
  470. let winner = null
  471. value = this.superTimeStamp(value)
  472. start = this.superTimeStamp(start)
  473. end = this.superTimeStamp(end)
  474. if (start && end) {
  475. if (value < start) {
  476. winner = new Date(start)
  477. } else if (value > end) {
  478. winner = new Date(end)
  479. } else {
  480. winner = new Date(value)
  481. }
  482. } else if (start && !end) {
  483. winner = start <= value ? new Date(value) : new Date(start)
  484. } else if (!start && end) {
  485. winner = value <= end ? new Date(value) : new Date(end)
  486. } else {
  487. winner = new Date(value)
  488. }
  489. return winner
  490. },
  491. /**
  492. * 转换为可比较的时间戳,接受日期、时分秒、时间戳
  493. * @param {Object} value
  494. */
  495. superTimeStamp(value) {
  496. let dateBase = ''
  497. if (this.type === 'time' && value && typeof value === 'string') {
  498. const now = new Date()
  499. const year = now.getFullYear()
  500. const month = now.getMonth() + 1
  501. const day = now.getDate()
  502. dateBase = year + '/' + month + '/' + day + ' '
  503. }
  504. if (Number(value) && typeof value !== NaN) {
  505. value = parseInt(value)
  506. dateBase = 0
  507. }
  508. return this.createTimeStamp(dateBase + value)
  509. },
  510. /**
  511. * 解析默认值 value,字符串、时间戳
  512. * @param {Object} defaultTime
  513. */
  514. parseValue(value) {
  515. if (!value) return
  516. if (this.type === 'time' && typeof value === "string") {
  517. this.parseTimeType(value)
  518. } else {
  519. let defaultDate = null
  520. defaultDate = new Date(value)
  521. if (this.type !== 'time') {
  522. this.year = defaultDate.getFullYear()
  523. this.month = defaultDate.getMonth() + 1
  524. this.day = defaultDate.getDate()
  525. }
  526. if (this.type !== 'date') {
  527. this.hour = defaultDate.getHours()
  528. this.minute = defaultDate.getMinutes()
  529. this.second = defaultDate.getSeconds()
  530. }
  531. }
  532. if (this.hideSecond) {
  533. this.second = 0
  534. }
  535. },
  536. /**
  537. * 解析可选择时间范围 start、end,年月日字符串、时间戳
  538. * @param {Object} defaultTime
  539. */
  540. parseDatetimeRange(point, pointType) {
  541. if (point && this.type === 'time') {
  542. const pointArr = point.split(':')
  543. this[pointType + 'Hour'] = Number(pointArr[0])
  544. this[pointType + 'Minute'] = Number(pointArr[1])
  545. this[pointType + 'Second'] = Number(pointArr[2])
  546. } else {
  547. if (!point) {
  548. pointType === 'start' ? this.startYear = this.year - 60 : this.endYear = this.year + 60
  549. return
  550. }
  551. if (Number(point) && Number(point) !== NaN) {
  552. point = parseInt(point)
  553. }
  554. // datetime 的 end 没有时分秒, 则不限制
  555. const hasTime = /[0-9]:[0-9]/
  556. if (this.type === 'datetime' && pointType === 'end' && typeof point === 'string' && !hasTime.test(
  557. point)) {
  558. point = point + ' 23:59:59'
  559. }
  560. const pointDate = new Date(point)
  561. this[pointType + 'Year'] = pointDate.getFullYear()
  562. this[pointType + 'Month'] = pointDate.getMonth() + 1
  563. this[pointType + 'Day'] = pointDate.getDate()
  564. if (this.type === 'datetime') {
  565. this[pointType + 'Hour'] = pointDate.getHours()
  566. this[pointType + 'Minute'] = pointDate.getMinutes()
  567. this[pointType + 'Second'] = pointDate.getSeconds()
  568. }
  569. }
  570. },
  571. // 获取 年、月、日、时、分、秒 当前可选范围
  572. getCurrentRange(value) {
  573. const range = []
  574. for (let i = this['min' + this.capitalize(value)]; i <= this['max' + this.capitalize(value)]; i++) {
  575. range.push(i)
  576. }
  577. return range
  578. },
  579. // 字符串首字母大写
  580. capitalize(str) {
  581. return str.charAt(0).toUpperCase() + str.slice(1)
  582. },
  583. // 检查当前值是否在范围内,不在则当前值重置为可选范围第一项
  584. checkValue(name, value, values) {
  585. if (values.indexOf(value) === -1) {
  586. this[name] = values[0]
  587. }
  588. },
  589. // 每个月的实际天数
  590. daysInMonth(year, month) { // Use 1 for January, 2 for February, etc.
  591. return new Date(year, month, 0).getDate();
  592. },
  593. //兼容 iOS、safari 日期格式
  594. fixIosDateFormat(value) {
  595. if (typeof value === 'string') {
  596. value = value.replace(/-/g, '/')
  597. }
  598. return value
  599. },
  600. /**
  601. * 生成时间戳
  602. * @param {Object} time
  603. */
  604. createTimeStamp(time) {
  605. if (!time) return
  606. if (typeof time === "number") {
  607. return time
  608. } else {
  609. time = time.replace(/-/g, '/')
  610. if (this.type === 'date') {
  611. time = time + ' ' + '00:00:00'
  612. }
  613. return Date.parse(time)
  614. }
  615. },
  616. /**
  617. * 生成日期或时间的字符串
  618. */
  619. createDomSting() {
  620. const yymmdd = this.year +
  621. '-' +
  622. this.lessThanTen(this.month) +
  623. '-' +
  624. this.lessThanTen(this.day)
  625. let hhmmss = this.lessThanTen(this.hour) +
  626. ':' +
  627. this.lessThanTen(this.minute)
  628. if(!this.hideSecond) {
  629. hhmmss = hhmmss + ':' + this.lessThanTen(this.second)
  630. }
  631. if (this.type === 'date') {
  632. return yymmdd
  633. } else if (this.type === 'time') {
  634. return hhmmss
  635. } else {
  636. return yymmdd + ' ' + hhmmss
  637. }
  638. },
  639. /**
  640. * 初始化返回值,并抛出 change 事件
  641. */
  642. initTime(emit = true) {
  643. this.time = this.createDomSting()
  644. if (!emit) return
  645. if (this.returnType === 'timestamp' && this.type !== 'time') {
  646. this.formItem && this.formItem.setValue(this.createTimeStamp(this.time))
  647. this.$emit('change', this.createTimeStamp(this.time))
  648. this.$emit('input', this.createTimeStamp(this.time))
  649. } else {
  650. this.formItem && this.formItem.setValue(this.time)
  651. this.$emit('change', this.time)
  652. this.$emit('input', this.time)
  653. }
  654. },
  655. /**
  656. * 用户选择日期或时间更新 data
  657. * @param {Object} e
  658. */
  659. bindDateChange(e) {
  660. const val = e.detail.value
  661. this.year = this.years[val[0]]
  662. this.month = this.months[val[1]]
  663. this.day = this.days[val[2]]
  664. },
  665. bindTimeChange(e) {
  666. const val = e.detail.value
  667. this.hour = this.hours[val[0]]
  668. this.minute = this.minutes[val[1]]
  669. this.second = this.seconds[val[2]]
  670. },
  671. /**
  672. * 初始化弹出层
  673. */
  674. initTimePicker() {
  675. if (this.disabled) return
  676. const value = this.fixIosDateFormat(this.value)
  677. this.initPickerValue(value)
  678. this.visible = !this.visible
  679. },
  680. /**
  681. * 触发或关闭弹框
  682. */
  683. tiggerTimePicker(e) {
  684. this.visible = !this.visible
  685. },
  686. /**
  687. * 用户点击“清空”按钮,清空当前值
  688. */
  689. clearTime() {
  690. this.time = ''
  691. this.formItem && this.formItem.setValue(this.time)
  692. this.$emit('change', this.time)
  693. this.$emit('input', this.time)
  694. this.tiggerTimePicker()
  695. },
  696. /**
  697. * 用户点击“确定”按钮
  698. */
  699. setTime() {
  700. this.initTime()
  701. this.tiggerTimePicker()
  702. }
  703. }
  704. }
  705. </script>
  706. <style>
  707. .uni-datetime-picker {
  708. /* #ifndef APP-NVUE */
  709. width: 100%;
  710. /* #endif */
  711. }
  712. .uni-datetime-picker-view {
  713. height: 130px;
  714. width: 270px;
  715. /* #ifndef APP-NVUE */
  716. cursor: pointer;
  717. /* #endif */
  718. }
  719. .uni-datetime-picker-item {
  720. height: 50px;
  721. line-height: 50px;
  722. text-align: center;
  723. font-size: 14px;
  724. }
  725. .uni-datetime-picker-btn {
  726. margin-top: 60px;
  727. /* #ifndef APP-NVUE */
  728. display: flex;
  729. cursor: pointer;
  730. /* #endif */
  731. flex-direction: row;
  732. justify-content: space-between;
  733. }
  734. .uni-datetime-picker-btn-text {
  735. font-size: 14px;
  736. color: #007AFF;
  737. }
  738. .uni-datetime-picker-btn-group {
  739. /* #ifndef APP-NVUE */
  740. display: flex;
  741. /* #endif */
  742. flex-direction: row;
  743. }
  744. .uni-datetime-picker-cancel {
  745. margin-right: 30px;
  746. }
  747. .uni-datetime-picker-mask {
  748. position: fixed;
  749. bottom: 0px;
  750. top: 0px;
  751. left: 0px;
  752. right: 0px;
  753. background-color: rgba(0, 0, 0, 0.4);
  754. transition-duration: 0.3s;
  755. z-index: 998;
  756. }
  757. .uni-datetime-picker-popup {
  758. border-radius: 8px;
  759. padding: 30px;
  760. width: 270px;
  761. /* #ifdef APP-NVUE */
  762. height: 500px;
  763. /* #endif */
  764. /* #ifdef APP-NVUE */
  765. width: 330px;
  766. /* #endif */
  767. background-color: #fff;
  768. position: fixed;
  769. top: 50%;
  770. left: 50%;
  771. transform: translate(-50%, -50%);
  772. transition-duration: 0.3s;
  773. z-index: 999;
  774. }
  775. .fix-nvue-height {
  776. /* #ifdef APP-NVUE */
  777. height: 330px;
  778. /* #endif */
  779. }
  780. .uni-datetime-picker-time {
  781. color: grey;
  782. }
  783. .uni-datetime-picker-column {
  784. height: 50px;
  785. }
  786. .uni-datetime-picker-timebox {
  787. border: 1px solid #E5E5E5;
  788. border-radius: 5px;
  789. padding: 7px 10px;
  790. /* #ifndef APP-NVUE */
  791. box-sizing: border-box;
  792. cursor: pointer;
  793. /* #endif */
  794. }
  795. .uni-datetime-picker-timebox-pointer {
  796. /* #ifndef APP-NVUE */
  797. cursor: pointer;
  798. /* #endif */
  799. }
  800. .uni-datetime-picker-disabled {
  801. opacity: 0.4;
  802. /* #ifdef H5 */
  803. cursor: not-allowed !important;
  804. /* #endif */
  805. }
  806. .uni-datetime-picker-text {
  807. font-size: 14px;
  808. }
  809. .uni-datetime-picker-sign {
  810. position: absolute;
  811. top: 53px;
  812. /* 减掉 10px 的元素高度,兼容nvue */
  813. color: #999;
  814. /* #ifdef APP-NVUE */
  815. font-size: 16px;
  816. /* #endif */
  817. }
  818. .sign-left {
  819. left: 86px;
  820. }
  821. .sign-right {
  822. right: 86px;
  823. }
  824. .sign-center {
  825. left: 135px;
  826. }
  827. .uni-datetime-picker__container-box {
  828. position: relative;
  829. display: flex;
  830. align-items: center;
  831. justify-content: center;
  832. margin-top: 40px;
  833. }
  834. .time-hide-second {
  835. width: 180px;
  836. }
  837. </style>