tn-picker.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. <template>
  2. <view v-if="value" class="tn-picker-class tn-picker">
  3. <tn-popup
  4. v-model="value"
  5. mode="bottom"
  6. :popup="false"
  7. length="auto"
  8. :safeAreaInsetBottom="safeAreaInsetBottom"
  9. :maskCloseable="maskCloseable"
  10. :zIndex="elZIndex"
  11. @close="close"
  12. >
  13. <view class="tn-picker__content" :style="{ zIndex: elZIndex }">
  14. <!-- 顶部 -->
  15. <view class="tn-picker__content__header tn-border-solid-bottom" @touchmove.stop.prevent>
  16. <!-- 取消按钮 -->
  17. <view
  18. class="tn-picker__content__header__btn tn-picker__content__header--cancel"
  19. :style="{ color: cancelColor }"
  20. hover-class="tn-hover-class"
  21. :hover-stay-time="150"
  22. @tap="getResult('cancel')"
  23. >{{cancelText}}</view>
  24. <!-- 标题 -->
  25. <view class="tn-picker__content__header__title">{{ title }}</view>
  26. <!-- 确认按钮 -->
  27. <view
  28. class="tn-picker__content__header__btn tn-picker__content__header--confirm"
  29. :style="{ color: moving ? cancelColor : confirmColor}"
  30. hover-class="tn-hover-class"
  31. :hover-stay-time="150"
  32. @touchmove.stop
  33. @tap.stop="getResult('confirm')"
  34. >{{confirmText}}</view>
  35. </view>
  36. <!-- 主体 -->
  37. <view class="tn-picker__content__body">
  38. <!-- 地区选择 -->
  39. <picker-view
  40. v-if="mode === 'region'"
  41. class="tn-picker__content__body__view"
  42. :value="valueArr"
  43. @change="change"
  44. @pickstart="pickStart"
  45. @pickend="pickEnd"
  46. >
  47. <picker-view-column v-if="!reset && params.province">
  48. <view class="tn-picker__content__body__item" v-for="(item, index) in provinces" :key="index">
  49. <view class="tn-text-ellipsis">{{ item.label }}</view>
  50. </view>
  51. </picker-view-column>
  52. <picker-view-column v-if="!reset && params.city">
  53. <view class="tn-picker__content__body__item" v-for="(item, index) in citys" :key="index">
  54. <view class="tn-text-ellipsis">{{ item.label }}</view>
  55. </view>
  56. </picker-view-column>
  57. <picker-view-column v-if="!reset && params.area">
  58. <view class="tn-picker__content__body__item" v-for="(item, index) in areas" :key="index">
  59. <view class="tn-text-ellipsis">{{ item.label }}</view>
  60. </view>
  61. </picker-view-column>
  62. </picker-view>
  63. <!-- 时间选择 -->
  64. <picker-view
  65. v-else-if="mode === 'time'"
  66. class="tn-picker__content__body__view"
  67. :value="valueArr"
  68. @change="change"
  69. @pickstart="pickStart"
  70. @pickend="pickEnd"
  71. >
  72. <picker-view-column v-if="!reset && params.year">
  73. <view class="tn-picker__content__body__item" v-for="(item, index) in years" :key="index">
  74. {{ item }}
  75. <text v-if="showTimeTag" class="tn-picker__content__body__item__text">年</text>
  76. </view>
  77. </picker-view-column>
  78. <picker-view-column v-if="!reset && params.month">
  79. <view class="tn-picker__content__body__item" v-for="(item, index) in months" :key="index">
  80. {{ formatNumber(item) }}
  81. <text v-if="showTimeTag" class="tn-picker__content__body__item--text">月</text>
  82. </view>
  83. </picker-view-column>
  84. <picker-view-column v-if="!reset && params.day">
  85. <view class="tn-picker__content__body__item" v-for="(item, index) in days" :key="index">
  86. {{ formatNumber(item) }}
  87. <text v-if="showTimeTag" class="tn-picker__content__body__item--text">日</text>
  88. </view>
  89. </picker-view-column>
  90. <picker-view-column v-if="!reset && params.hour">
  91. <view class="tn-picker__content__body__item" v-for="(item, index) in hours" :key="index">
  92. {{ formatNumber(item) }}
  93. <text v-if="showTimeTag" class="tn-picker__content__body__item--text">时</text>
  94. </view>
  95. </picker-view-column>
  96. <picker-view-column v-if="!reset && params.minute">
  97. <view class="tn-picker__content__body__item" v-for="(item, index) in minutes" :key="index">
  98. {{ formatNumber(item) }}
  99. <text v-if="showTimeTag" class="tn-picker__content__body__item--text">分</text>
  100. </view>
  101. </picker-view-column>
  102. <picker-view-column v-if="!reset && params.second">
  103. <view class="tn-picker__content__body__item" v-for="(item, index) in seconds" :key="index">
  104. {{ formatNumber(item) }}
  105. <text v-if="showTimeTag" class="tn-picker__content__body__item--text">秒</text>
  106. </view>
  107. </picker-view-column>
  108. </picker-view>
  109. <!-- 单列选择 -->
  110. <picker-view
  111. v-else-if="mode === 'selector'"
  112. class="tn-picker__content__body__view"
  113. :value="valueArr"
  114. @change="change"
  115. @pickstart="pickStart"
  116. @pickend="pickEnd"
  117. >
  118. <picker-view-column v-if="!reset">
  119. <view class="tn-picker__content__body__item" v-for="(item, index) in range" :key="index">
  120. <view class="tn-text-ellipsis">{{ getItemValue(item, 'selector') }}</view>
  121. </view>
  122. </picker-view-column>
  123. </picker-view>
  124. <!-- 多列选择 -->
  125. <picker-view
  126. v-else-if="mode === 'multiSelector'"
  127. class="tn-picker__content__body__view"
  128. :value="valueArr"
  129. @change="change"
  130. @pickstart="pickStart"
  131. @pickend="pickEnd"
  132. >
  133. <picker-view-column v-if="!reset" v-for="(item, index) in range" :key="index">
  134. <view class="tn-picker__content__body__item" v-for="(sub_item, sub_index) in item" :key="sub_index">
  135. <view class="tn-text-ellipsis">{{ getItemValue(sub_item, 'multiSelector') }}</view>
  136. </view>
  137. </picker-view-column>
  138. </picker-view>
  139. </view>
  140. </view>
  141. </tn-popup>
  142. </view>
  143. </template>
  144. <script>
  145. import provinces from '../../libs/utils/province.js'
  146. import citys from '../../libs/utils/city.js'
  147. import areas from '../../libs/utils/area.js'
  148. export default {
  149. name: 'tn-picker',
  150. props: {
  151. value: {
  152. type: Boolean,
  153. default: false,
  154. },
  155. // 顶部标题
  156. title: {
  157. type: String,
  158. default: ''
  159. },
  160. // picker中显示的参数
  161. params: {
  162. type: Object,
  163. default() {
  164. return {
  165. year: true,
  166. month: true,
  167. day: true,
  168. hour: false,
  169. minute: false,
  170. second: false,
  171. province: true,
  172. city: true,
  173. area: true,
  174. timestamp: true
  175. }
  176. }
  177. },
  178. // 模式选择,region-地区类型,time-时间类型,selector-单列模式,multiSelector-多列模式
  179. mode: {
  180. type: String,
  181. default: 'time'
  182. },
  183. // 当mode=selector或者mode=multiSelector时,提供的数组
  184. range: {
  185. type: Array,
  186. default() {
  187. return []
  188. }
  189. },
  190. // 当mode=selector或者mode=multiSelector时,提供的默认项下标
  191. defaultSelector: {
  192. type: Array,
  193. default() {
  194. return [0]
  195. }
  196. },
  197. // 当range是一个Array<Object>时,通过rangeKey来指定Object中key的值作为显示的内容
  198. rangeKey: {
  199. type: String,
  200. default: ''
  201. },
  202. // 时间模式 ,是否显示时间后的单位
  203. showTimeTag: {
  204. type: Boolean,
  205. default: true
  206. },
  207. // 开始年份
  208. startYear: {
  209. type: [String, Number],
  210. default: 1950
  211. },
  212. // 结束年份
  213. endYear: {
  214. type: [String, Number],
  215. default: 2050
  216. },
  217. // 默认显示的时间
  218. // 2021-09-01 || 2021-09-01 13:00:23 || 2021/09/01
  219. defaultTime: {
  220. type: String,
  221. default: ''
  222. },
  223. // 默认显示的地区
  224. // 可传类似["广东省", "广州市", "天河区"]
  225. defaultRegin: {
  226. type: Array,
  227. default() {
  228. return []
  229. }
  230. },
  231. // 默认显示的地区编码
  232. // 可传类似["11", "1101", "110101"]
  233. // 如果defaultRegin和areaCode同时存在,优先使用areaCode的值
  234. areaCode: {
  235. type: Array,
  236. default() {
  237. return []
  238. }
  239. },
  240. // 取消按钮的文字
  241. cancelText: {
  242. type: String,
  243. default: '取消'
  244. },
  245. // 取消按钮的颜色
  246. cancelColor: {
  247. type: String,
  248. default: ''
  249. },
  250. // 确认按钮的文字
  251. confirmText: {
  252. type: String,
  253. default: '确认'
  254. },
  255. // 确认按钮的演示
  256. confirmColor: {
  257. type: String,
  258. default: ''
  259. },
  260. safeAreaInsetBottom: {
  261. type: Boolean,
  262. default: false
  263. },
  264. // 是否允许通过点击遮罩关闭
  265. maskCloseable: {
  266. type: Boolean,
  267. default: true
  268. },
  269. zIndex: {
  270. type: Number,
  271. default: 0
  272. }
  273. },
  274. computed: {
  275. // 监听参数变化
  276. propsChange() {
  277. return [this.mode, this.defaultTime, this.startYear, this.endYear, this.defaultRegin, this.areaCode]
  278. },
  279. // 监听地区发生变化
  280. regionChange() {
  281. return [this.province, this.city]
  282. },
  283. // 监听年月发生变化
  284. yearAndMonth() {
  285. return [this.year, this.month]
  286. },
  287. elZIndex() {
  288. return this.zIndex ? this.zIndex : this.$t.zIndex.popup
  289. }
  290. },
  291. data() {
  292. return {
  293. years: [],
  294. months: [],
  295. days: [],
  296. hours: [],
  297. minutes: [],
  298. seconds: [],
  299. year: 0,
  300. month: 0,
  301. day: 0,
  302. hour: 0,
  303. minute: 0,
  304. second: 0,
  305. reset: false,
  306. startDate: '',
  307. endDate: '',
  308. valueArr: [],
  309. provinces: provinces,
  310. citys: citys[0],
  311. areas: areas[0][0],
  312. province: 0,
  313. city: 0,
  314. area: 0,
  315. // 列是否还在滑动中,微信小程序如果在滑动中就点确定,结果可能不准确
  316. moving: false
  317. }
  318. },
  319. watch: {
  320. propsChange() {
  321. this.reset = true
  322. setTimeout(() => this.init(), 10)
  323. },
  324. regionChange() {
  325. // 如果地区发生变化,为了让picker联动起来,必须重置this.citys和this.areas
  326. this.citys = citys[this.province]
  327. this.areas = areas[this.province][this.city]
  328. },
  329. yearAndMonth() {
  330. // 月份的变化,实时变更日的天数,因为不同月份,天数不一样
  331. // 一个月可能有30,31天,甚至闰年2月的29天,平年2月28天
  332. if (this.params.year) this.setDays()
  333. },
  334. value(val) {
  335. // 微信和QQ小程序由于一些奇怪的原因(故同时对所有平台均初始化一遍),需要重新初始化才能显示正确的值
  336. if (val) {
  337. this.reset = true
  338. setTimeout(() => this.init(), 10)
  339. }
  340. }
  341. },
  342. mounted() {
  343. this.init()
  344. },
  345. methods: {
  346. // 记录开始滑动
  347. pickStart() {
  348. // #ifdef MP-WEIXIN
  349. this.moving = true
  350. // #endif
  351. },
  352. // 记录滚动结束
  353. pickEnd() {
  354. // #ifdef MP-WEIXIN
  355. this.moving = false
  356. // #endif
  357. },
  358. // 根据传递的列表的数据获取显示的数据
  359. getItemValue(item, mode) {
  360. // 单列模式或者多列模式中的getItemValue同时被执行,故在这里再加一层判断
  361. if (this.mode === mode) {
  362. return typeof item === 'object' ? item[this.rangeKey] : item
  363. }
  364. },
  365. // 往数字前面补0
  366. formatNumber(num) {
  367. return this.$t.number.formatNumberAddZero(num)
  368. },
  369. // 生成递进的数组
  370. generateArray(start, end) {
  371. // 转为数值格式,否则用户给end-year等传递字符串值时,下面的end+1会导致字符串拼接,而不是相加
  372. start = Number(start)
  373. end = Number(end)
  374. end = end > start ? end : start
  375. // 生成数组并获取其中索引然后提取出来(获取开始和结束之间的数据)
  376. return [...Array(end+1).keys()].slice(start)
  377. },
  378. getIndex(arr, val) {
  379. let index = arr.indexOf(val)
  380. // 如果index为-1着找不到元素
  381. // ~(-1)=(-1)-1=0
  382. return ~index ? index : 0
  383. },
  384. // 日期时间处理
  385. initTimeValue() {
  386. // 格式化时间,在IE浏览器(uni不存在此情况),无法识别日期间的"-"间隔符号
  387. let fdate = this.defaultTime.replace(/\-/g, '/')
  388. fdate = fdate && fdate.indexOf('/') == -1 ? `2021/01/01 ${fdate}` : fdate
  389. let time = null
  390. if (fdate) time = new Date(fdate)
  391. else time = new Date()
  392. // 获取年月日时分秒
  393. this.year = time.getFullYear()
  394. this.month = time.getMonth() + 1
  395. this.day = time.getDate()
  396. this.hour = time.getHours()
  397. this.minute = time.getMinutes()
  398. this.second = time.getSeconds()
  399. },
  400. // 初始化数据
  401. init() {
  402. this.valueArr = []
  403. this.reset = false
  404. if (this.mode === 'time') {
  405. this.initTimeValue()
  406. if (this.params.year) {
  407. this.valueArr.push(0)
  408. this.setYears()
  409. }
  410. if (this.params.month) {
  411. this.valueArr.push(0)
  412. this.setMonths()
  413. }
  414. if (this.params.day) {
  415. this.valueArr.push(0)
  416. this.setDays()
  417. }
  418. if (this.params.hour) {
  419. this.valueArr.push(0)
  420. this.setHours()
  421. }
  422. if (this.params.minute) {
  423. this.valueArr.push(0)
  424. this.setMinutes()
  425. }
  426. if (this.params.second) {
  427. this.valueArr.push(0)
  428. this.setSeconds()
  429. }
  430. } else if (this.mode === 'region') {
  431. if (this.params.province) {
  432. this.valueArr.push(0)
  433. this.setProvinces()
  434. }
  435. if (this.params.city) {
  436. this.valueArr.push(0)
  437. this.setCitys()
  438. }
  439. if (this.params.area) {
  440. this.valueArr.push(0)
  441. this.setAreas()
  442. }
  443. } else if (this.mode === 'selector') {
  444. this.valueArr = this.defaultSelector
  445. } else if (this.mode === 'multiSelector') {
  446. this.valueArr = this.defaultSelector
  447. this.multiSelectorValue = this.defaultSelector
  448. }
  449. this.$forceUpdate()
  450. },
  451. // 设置picker某一列的值
  452. setYears() {
  453. this.years = this.generateArray(this.startYear, this.endYear)
  454. // 设置this.valueArr某一项的值,是为了让picker预选中某一个值
  455. this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this.year))
  456. },
  457. setMonths() {
  458. this.months = this.generateArray(1, 12)
  459. this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this.month))
  460. },
  461. setDays() {
  462. let totalDays = new Date(this.year, this.month, 0).getDate()
  463. this.days = this.generateArray(1, totalDays)
  464. let index = 0
  465. // 避免多次触发导致值数组计算错误
  466. if (this.params.year && this.params.month) index = 2
  467. else if (this.params.month) index = 1
  468. else if (this.params.year) index = 1
  469. else index = 0
  470. // 当月份变化时,会导致日期的天数也会变化,如果原来选的天数大于变化后的天数,则重置为变化后的最大值
  471. // 比如原来选中3月31日,调整为2月后,日期变为最大29,这时如果day值继续为31显然不合理,于是将其置为29(picker-column从1开始)
  472. if (this.day > this.days.length) this.day = this.days.length
  473. this.valueArr.splice(index, 1, this.getIndex(this.days, this.day))
  474. },
  475. setHours() {
  476. this.hours = this.generateArray(0, 23)
  477. this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this.hour))
  478. },
  479. setMinutes() {
  480. this.minutes = this.generateArray(0, 59)
  481. this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this.minute))
  482. },
  483. setSeconds() {
  484. this.seconds = this.generateArray(0, 59)
  485. this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second))
  486. },
  487. setProvinces() {
  488. if (!this.params.province) return
  489. let tmp = ''
  490. let useCode = false
  491. // 如果同时配置了defaultRegion和areaCode,优先使用areaCode参数
  492. if (this.areaCode.length) {
  493. tmp = this.areaCode[0]
  494. useCode = true
  495. } else if (this.defaultRegin.length) {
  496. tmp = this.defaultRegin[0]
  497. } else {
  498. tmp = 0
  499. }
  500. // 遍历省份数组
  501. provinces.map((v, k) => {
  502. if (useCode ? v.value == tmp : v.label == tmp) {
  503. this.province = k
  504. return
  505. }
  506. })
  507. this.provinces = provinces
  508. this.valueArr.splice(0, 1, this.province)
  509. },
  510. setCitys() {
  511. if (!this.params.city) return
  512. let tmp = ''
  513. let useCode = false
  514. // 如果同时配置了defaultRegion和areaCode,优先使用areaCode参数
  515. if (this.areaCode.length) {
  516. tmp = this.areaCode[1]
  517. useCode = true
  518. } else if (this.defaultRegin.length) {
  519. tmp = this.defaultRegin[1]
  520. } else {
  521. tmp = 0
  522. }
  523. // 遍历省份数组
  524. citys[this.province].map((v, k) => {
  525. if (useCode ? v.value == tmp : v.label == tmp) {
  526. this.city = k
  527. return
  528. }
  529. })
  530. this.citys = citys[this.province]
  531. this.valueArr.splice(1, 1, this.city)
  532. },
  533. setAreas() {
  534. if (!this.params.area) return
  535. let tmp = ''
  536. let useCode = false
  537. // 如果同时配置了defaultRegion和areaCode,优先使用areaCode参数
  538. if (this.areaCode.length) {
  539. tmp = this.areaCode[2]
  540. useCode = true
  541. } else if (this.defaultRegin.length) {
  542. tmp = this.defaultRegin[2]
  543. } else {
  544. tmp = 0
  545. }
  546. // 遍历省份数组
  547. areas[this.province][this.city].map((v, k) => {
  548. if (useCode ? v.value == tmp : v.label == tmp) {
  549. this.area = k
  550. return
  551. }
  552. })
  553. this.areas = areas[this.province][this.city]
  554. this.valueArr.splice(2, 1, this.area)
  555. },
  556. close() {
  557. this.$emit('input', false)
  558. },
  559. // 监听用户修改了picker列选项
  560. change(event) {
  561. this.valueArr = event.detail.value
  562. let i = 0
  563. if (this.mode === 'time') {
  564. // 使用i++是因为不知道数组的长度
  565. if (this.params.year) this.year = this.years[this.valueArr[i++]]
  566. if (this.params.month) this.month = this.months[this.valueArr[i++]]
  567. if (this.params.day) this.day = this.days[this.valueArr[i++]]
  568. if (this.params.hour) this.hour = this.hours[this.valueArr[i++]]
  569. if (this.params.minute) this.minute = this.minutes[this.valueArr[i++]]
  570. if (this.params.second) this.second = this.seconds[this.valueArr[i++]]
  571. } else if (this.mode === 'region') {
  572. // 标记省市是否发生了变化
  573. let provinceChange = false,
  574. cityChange = false
  575. if (this.params.province) {
  576. let value = this.valueArr[i++]
  577. if (this.province != value) {
  578. // 如果省份发生了变化,则重置市区的索引为0
  579. this.city = 0
  580. this.area = 0
  581. provinceChange = true
  582. }
  583. this.province = value
  584. }
  585. if (this.params.city && !provinceChange) {
  586. let value = this.valueArr[i++]
  587. if (this.city != value) {
  588. // 如果市发生了变化,则重置区的索引为0
  589. this.area = 0
  590. cityChange = true
  591. }
  592. this.city = value
  593. }
  594. if (this.params.area && !provinceChange && !cityChange) this.area = this.valueArr[i++]
  595. // 如果有省市进行了改变,重新设置列表的值
  596. if (provinceChange || cityChange) {
  597. this.valueArr = [this.province, this.city, this.area]
  598. }
  599. } else if (this.mode === 'multiSelector') {
  600. let index = null
  601. // 对比前后两个数组,寻找变更的是哪一列,如果某一个元素不同,即可判定该列发生了变化
  602. this.defaultSelector.map((v, idx) => {
  603. if (v != event.detail.value[idx]) index = idx
  604. })
  605. // 为了让用户对多列变化时,动态设置其他列
  606. if (index != null) {
  607. this.$emit('columnchange', {
  608. column: index,
  609. index: event.detail.value[index]
  610. })
  611. }
  612. }
  613. },
  614. // 用户点击确定按钮
  615. getResult(event = null) {
  616. // #ifdef MP-WEIXIN
  617. if (this.moving) return
  618. // #endif
  619. let result = {}
  620. // 只返回用户需要的数据
  621. if (this.mode === 'time') {
  622. if (this.params.year) result.year = this.formatNumber(this.year || 0)
  623. if (this.params.month) result.month = this.formatNumber(this.month || 0)
  624. if (this.params.day) result.day = this.formatNumber(this.day || 0)
  625. if (this.params.hour) result.hour = this.formatNumber(this.hour || 0)
  626. if (this.params.minute) result.minute = this.formatNumber(this.minute || 0)
  627. if (this.params.second) result.second = this.formatNumber(this.second || 0)
  628. if (this.params.timestamp) result.timestamp = this.getTimestamp()
  629. } else if (this.mode === 'region') {
  630. if (this.params.province) result.province = provinces[this.province]
  631. if (this.params.city) result.city = citys[this.province][this.city]
  632. if (this.params.area) result.area = areas[this.province][this.city][this.area]
  633. } else if (this.mode === 'multiSelector') {
  634. result = this.valueArr
  635. } else if (this.mode === 'selector') {
  636. result = this.valueArr
  637. }
  638. if (event) this.$emit(event, result)
  639. this.close()
  640. },
  641. // 获取时间戳
  642. getTimestamp() {
  643. // yyyy-mm-dd为安卓写法,不支持iOS,需要使用"/"分隔,才能二者兼容
  644. let time = this.year + '/' + this.month + '/' + this.day + ' ' + this.hour + ':' + this.minute + ':' + this.second;
  645. return new Date(time).getTime() / 1000;
  646. }
  647. }
  648. }
  649. </script>
  650. <style lang="scss" scoped>
  651. .tn-picker {
  652. &__content {
  653. position: relative;
  654. &__header {
  655. position: relative;
  656. display: flex;
  657. flex-direction: row;
  658. width: 100%;
  659. height: 90rpx;
  660. padding: 0 40rpx;
  661. align-items: center;
  662. justify-content: space-between;
  663. box-sizing: border-box;
  664. font-size: 30rpx;
  665. background-color: #FFFFFF;
  666. &__btn {
  667. padding: 16rpx;
  668. box-sizing: border-box;
  669. text-align: center;
  670. text-decoration: none;
  671. }
  672. &__title {
  673. color: $tn-font-color;
  674. }
  675. &--cancel {
  676. color: $tn-font-sub-color;
  677. }
  678. &--confirm {
  679. color: $tn-main-color;
  680. }
  681. }
  682. &__body {
  683. width: 100%;
  684. height: 500rpx;
  685. overflow: hidden;
  686. background-color: #FFFFFF;
  687. &__view {
  688. height: 100%;
  689. box-sizing: border-box;
  690. }
  691. &__item {
  692. display: flex;
  693. flex-direction: row;
  694. align-items: center;
  695. justify-content: center;
  696. font-size: 32rpx;
  697. color: $tn-font-color;
  698. padding: 0 8rpx;
  699. &--text {
  700. font-size: 24rpx;
  701. padding-left: 8rpx;
  702. }
  703. }
  704. }
  705. }
  706. }
  707. </style>