chenmushan-week-calendar.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. <template>
  2. <view class="cal">
  3. <view class="cal-top">
  4. <!-- <view class="prev" @click="changeWeek('prev')" v-if="prevActive">上一周</view> -->
  5. <text class="date" ref="t1">{{ nowSelectDateString }}</text>
  6. <view class="cal_top_right" v-if="liveData">
  7. <image :src="handleWeatherIcon(liveData.weather)" alt="" class="cal_images" />
  8. <view class="weather_wrap">
  9. <text class="top">
  10. {{liveData.city}}
  11. </text>
  12. <text class="bottom">
  13. {{liveData.weather}}/{{liveData.temperature}}℃
  14. </text>
  15. </view>
  16. </view>
  17. <view class="cal_top_right" v-else>
  18. <image src="/static/home/weather/icon-yingtian.png" alt="" class="cal_images" />
  19. <view class="weather_wrap">
  20. <text class="top">
  21. 广州市
  22. </text>
  23. <text class="bottom">
  24. 晴天/22℃
  25. </text>
  26. </view>
  27. </view>
  28. <!-- <view class="next" @click="changeWeek('next')" v-if="prevActive">下一周</view> -->
  29. </view>
  30. <view class="cal-content">
  31. <view class="cal-ul cal-weeks">
  32. <view v-for="(item, i) of baseData.weekTitles" :key="i" :id="baseData.selectedDate.week == item ? 'calWeeksSelected' : ''" class='cal-li'>
  33. <text class="weekText">{{item}}</text>
  34. </view>
  35. </view>
  36. <view class="activeWeek" :style="{left : this.activeLeft}" v-if="showActiveWeek">
  37. <text class="activeWeekText">{{baseData.selectedDate.week}}</text>
  38. </view>
  39. <swiper :current="current" ref="calSwiper" class="cal-swiper" :duration="200" circular
  40. @animationfinish="swiperFisnish" disable-touch>
  41. <swiper-item v-for="(days, i) of weeks" :key="i">
  42. <view class="cal-ul cal-days">
  43. <view class="cal-li" v-for="(item, j) of days" :key="j" @click="changeSelected(item)">
  44. <view class="cal-day-li">
  45. <!-- :style="{ color: item.ym == baseData.selectedDate.ym ? '#333' : '#999' }" -->
  46. <text
  47. :class="[item.timeSpan == baseData.selectedDate.timeSpan ? 'cal-day-li-selected' : '','day_text']">{{ item.d }}</text>
  48. </view>
  49. </view>
  50. </view>
  51. </swiper-item>
  52. </swiper>
  53. </view>
  54. </view>
  55. </template>
  56. <script>
  57. /**
  58. * weekCalendar 周日历选择组件
  59. * @description 日历选择某一天的组件
  60. * @bug 因是使用swiper组件开发快速滑动多屏 无法触发 @animationfinish 导致展示异常
  61. * @property {Number} defaultDate 默认时间时间戳
  62. * @event {Function} changeDate 当前选中日期发生改变
  63. * @example <chenmushan-week-calendar @changeDate="changeDate"></chenmushan-week-calendar>
  64. */
  65. import Amap from '@/js_sdk/Lyn4ever-gaodeRoutePlanning/lyn4ever-gaode.js';
  66. export default {
  67. props: {
  68. defaultDate: {
  69. type: Number,
  70. default: 0
  71. },
  72. prevActive: {
  73. type: Boolean,
  74. default: true
  75. },
  76. nextActive: {
  77. type: Boolean,
  78. default: true
  79. }
  80. },
  81. data() {
  82. return {
  83. showActiveWeek : false,
  84. weeks: [],
  85. propDate: null,
  86. current: 0,
  87. baseData: {
  88. weekTitles: ['日', '一', '二', '三', '四', '五', '六'],
  89. current: 0,
  90. selectedDate: {
  91. d: null, // 在当前月份中的天
  92. ym: '', // 年月拼接
  93. timeSpan: 0, // 时间戳
  94. week: ''
  95. }
  96. },
  97. activeLeft : 0,
  98. liveData : null, // 当前天气
  99. };
  100. },
  101. mounted() {
  102. this.propDate = this.defaultDate == 0 ? new Date() : new Date(this.defaultDate);
  103. this.initData();
  104. this.handleActiveWeek();
  105. },
  106. methods: {
  107. handleWeatherIcon(weather){
  108. let src = "";
  109. switch (weather) {
  110. case "多云":
  111. src = "/static/home/weather/icon-duoyun.png";
  112. break;
  113. case "雷雨":
  114. src = "/static/home/weather/icon-leiyu.png";
  115. break;
  116. case "阴天":
  117. src = "/static/home/weather/icon-yingtian.png";
  118. break;
  119. case "晴":
  120. src = "/static/home/weather/icon-qingtian.png";
  121. break;
  122. case "阵雨":
  123. src = "/static/home/weather/icon-zhenyu.png";
  124. break;
  125. default:
  126. src = "/static/home/weather/icon-yingtian.png";
  127. break;
  128. }
  129. return src;
  130. },
  131. getWeather(){
  132. Amap.getWeather(data=>{
  133. const { liveData } = data;
  134. this.liveData = liveData;
  135. })
  136. },
  137. initData() {
  138. let lastSat = new Date(this.propDate);
  139. this.$set(this.baseData, 'selectedDate', {
  140. d: lastSat.getDate(),
  141. ym: `${lastSat.getFullYear()}${lastSat.getMonth() + 1}`,
  142. timeSpan: +lastSat,
  143. m: new Date(lastSat),
  144. week: this.baseData.weekTitles[new Date(lastSat).getDay()]
  145. });
  146. // 寻找到距离当前日期最近的周六
  147. while (lastSat.getDay() != 6) lastSat.setDate(lastSat.getDate() + 1);
  148. this.$set(this.weeks, 0, this.getWeekDaysByLastSat(lastSat));
  149. // this.$set(this.weeks, 1, this.getWeekDaysByWeeks(this.weeks[0], true));
  150. // this.$set(this.weeks, 2, this.getWeekDaysByWeeks(this.weeks[0], false));
  151. this.current = 0;
  152. },
  153. swiperFisnish(e) {
  154. let current = e.detail.current;
  155. this.changeWeeks(current > this.baseData.current, current);
  156. this.$set(this.baseData, 'upCurrIndex', current);
  157. },
  158. changeWeeks(direction, current) {
  159. let nextIndex = current + 1 > 2 ? 0 : current + 1;
  160. let prevIndex = current - 1 < 0 ? 2 : current - 1;
  161. this.$set(this.weeks, nextIndex, this.getWeekDaysByWeeks(this.weeks[current], true));
  162. this.$set(this.weeks, prevIndex, this.getWeekDaysByWeeks(this.weeks[current], false));
  163. },
  164. // 修改周时间
  165. changeWeek(type) {
  166. let current = this.current;
  167. let nextIndex = current + 1 > 2 ? 0 : current + 1;
  168. let prevIndex = current - 1 < 0 ? 2 : current - 1;
  169. if (type == 'prev') {
  170. this.current = prevIndex;
  171. } else {
  172. this.current = nextIndex;
  173. }
  174. },
  175. // 通过周六数据获取一周的数据
  176. getWeekDaysByLastSat(lastSat) {
  177. lastSat = new Date(lastSat);
  178. let reuslt = [];
  179. for (var i = 0; i < 7; i++) {
  180. reuslt.push({
  181. d: lastSat.getDate(),
  182. ym: `${lastSat.getFullYear()}${lastSat.getMonth() + 1}`,
  183. timeSpan: +lastSat,
  184. m: new Date(lastSat)
  185. });
  186. lastSat.setDate(lastSat.getDate() - 1);
  187. }
  188. return reuslt.reverse();
  189. },
  190. // 通过一周的数据获取本周的上周或下周
  191. getWeekDaysByWeeks(weeks, direction) {
  192. // 下周
  193. if (direction) {
  194. let nextLastSat = new Date(weeks[weeks.length - 1].timeSpan);
  195. nextLastSat.setDate(nextLastSat.getDate() + 7);
  196. return this.getWeekDaysByLastSat(nextLastSat);
  197. }
  198. // 上周
  199. else {
  200. let prevLstSat = new Date(weeks[0].timeSpan);
  201. prevLstSat.setDate(prevLstSat.getDate() - 1);
  202. return this.getWeekDaysByLastSat(prevLstSat);
  203. }
  204. },
  205. // 修改当前选中
  206. changeSelected(item) {
  207. if (this.baseData.selectedDate.timeSpan != item.timeSpan) {
  208. this.$set(this.baseData, 'selectedDate', {
  209. ...item,
  210. m: new Date(item.timeSpan),
  211. week: this.baseData.weekTitles[new Date(item.timeSpan).getDay()]
  212. });
  213. this.$emit('changeDate', this.baseData.selectedDate);
  214. }
  215. },
  216. handleActiveWeek(){
  217. this.showActiveWeek = false;
  218. this.$nextTick(()=>{
  219. let el = uni.createSelectorQuery().in(this).select('#calWeeksSelected');
  220. el.boundingClientRect(data=>{
  221. this.activeLeft = data.left + 'px';
  222. }).exec();
  223. });
  224. this.showActiveWeek = true;
  225. }
  226. },
  227. computed: {
  228. nowSelectDateString() {
  229. let m = this.baseData.selectedDate.m;
  230. return m ? `${m.getFullYear()}-${m.getMonth() + 1}-${m.getDate()}` : '';
  231. }
  232. },
  233. watch: {
  234. defaultDate: {
  235. handler(newVal, oldVal) {
  236. this.propDate = this.defaultDate == 0 ? new Date() : new Date(this.defaultDate);
  237. this.initData();
  238. },
  239. immediate: true
  240. },
  241. // 监听对象中某一个属性
  242. 'baseData.selectedDate.week'(week) {
  243.  this.handleActiveWeek();
  244. }
  245. },
  246. created(){
  247. this.getWeather();
  248. },
  249. };
  250. </script>
  251. <style lang="scss" scoped>
  252. .cal {
  253. width: 750rpx;
  254. // margin: 0 auto;
  255. overflow: hidden;
  256. margin: 20rpx 0;
  257. }
  258. .cal-content {
  259. padding: 30rpx 0;
  260. // margin-left: -30rpx;
  261. width: 750rpx;
  262. position: relative;
  263. }
  264. // .calWeeksSelected{
  265. // position: relative;
  266. // .weekText{
  267. // z-index: 11;
  268. // }
  269. .activeWeek {
  270. position: absolute;
  271. top: 20rpx;
  272. right: 0;
  273. width: 107.14285714285714rpx;
  274. padding-top: 10rpx;
  275. height: 140rpx;
  276. border-radius: 6rpx;
  277. background: #fff;
  278. box-shadow: 0px 4px 20px 0px rgba(13, 29, 54, 0.10);
  279. border-radius: 20rpx;
  280. .activeWeekText{
  281. font-size: 34rpx;
  282. text-align: center;
  283. color: #B3B3C6;
  284. }
  285. }
  286. // }
  287. .cal-top {
  288. position: relative;
  289. display: flex;
  290. flex-direction: row;
  291. justify-content: space-between;
  292. height: 120rpx;
  293. display: flex;
  294. align-items: center;
  295. justify-content: space-between;
  296. padding: 0rpx 30rpx;
  297. .date {
  298. font-size: 34rpx;
  299. color: #666666;
  300. font-weight: bold;
  301. // pointer-events: none;
  302. }
  303. .cal_top_right {
  304. display: flex;
  305. flex-direction: row;
  306. align-items: center;
  307. justify-content: space-between;
  308. .cal_images {
  309. width: 68rpx;
  310. height: 68rpx;
  311. }
  312. .weather_wrap {
  313. .bottom,
  314. .top {
  315. color: #666666;
  316. font-size: 28rpx;
  317. }
  318. margin-left: 30rpx;
  319. }
  320. }
  321. }
  322. .cal-swiper {
  323. margin-top: 20rpx;
  324. height: 100rpx;
  325. }
  326. .cal-ul {
  327. position: relative;
  328. display: flex;
  329. flex-direction: row;
  330. justify-content: space-between;
  331. .cal-li {
  332. flex: 1;
  333. text-align: center;
  334. }
  335. }
  336. .cal-weeks {
  337. .weekText {
  338. font-size: 34rpx;
  339. text-align: center;
  340. color: #B3B3C6;
  341. }
  342. }
  343. .cal-days {
  344. .cal-li {
  345. display: flex;
  346. flex-direction: row;
  347. justify-content: center;
  348. }
  349. }
  350. .cal-day-li {
  351. display: flex;
  352. justify-content: center;
  353. align-items: center;
  354. width: 63rpx;
  355. height: 63rpx;
  356. .day_text {
  357. font-size: 34rpx;
  358. color: #333;
  359. }
  360. }
  361. .cal-day-li-selected {
  362. // background-color: #3ea3ff;
  363. // border-radius: 50%;
  364. color: #3ea3ff !important;
  365. font-weight: bold;
  366. }
  367. </style>