1
0

tm-calendar.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. <template>
  2. <view class="tm-calendar" :class="[inline?'d-inline-block':'d-block']">
  3. <view @click.stop.prevent="openPoup"><slot></slot></view>
  4. <tm-poup @change="toogle" clss-style="tm-calendar-wk" :black="black_tmeme" ref="pop" height="1040" v-model="show">
  5. <view class="tm-calendar-wk">
  6. <view class="shadow-10">
  7. <view class="tm-calendar-title pa-32 pb-16">
  8. <view class="text-size-g text-align-center text-grey">{{title}}</view>
  9. <view class="tm-calendar-close rounded flex-center" :class="black_tmeme?'grey-darken-3':'grey-lighten-3'">
  10. <tm-icons @click="$refs.pop.close()" name="icon-times" size="24" :color="black_tmeme?'white':'grey'"></tm-icons>
  11. </view>
  12. </view>
  13. <view class="pa-32 flex-center" style="width: 96%;margin: auto;">
  14. <view>
  15. <tm-icons dense @click="preYear" name="icon-angle-double-left" color="grey-lighten-1"></tm-icons>
  16. <text class="px-24"></text>
  17. <tm-icons dense @click="preMonth" name="icon-angle-left" color="grey-lighten-1"></tm-icons>
  18. <!-- <text class="px-8 "></text> -->
  19. </view>
  20. <view class="text-size-n text-weight-b px-40">{{titleValue}}</view>
  21. <view>
  22. <!-- <text class="px-8"></text> -->
  23. <tm-icons dense @click="nextMonth" name="icon-angle-right" color="grey-lighten-1"></tm-icons>
  24. <text class="px-24"></text>
  25. <tm-icons dense @click="nextYear" name="icon-angle-double-right" color="grey-lighten-1"></tm-icons>
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. <view class="tm-calendar-body">
  31. <view class="tm-calendar-bg flex-center">
  32. <text class="text tm-calendar-bg-center-text" :class="[black_tmeme?' opacity-5 ':'']">{{centerValue}}</text>
  33. </view>
  34. <view class="tm-calendar-content ">
  35. <view style="height: 32upx;"></view>
  36. <tm-row>
  37. <!-- #ifdef MP-->
  38. <tm-col color="" align="middle" width="14.28%" v-for="(item,index) in ['一','二','三','四','五','六','日']"
  39. :key="index"><text class="text-size-s py-16">{{item}}</text>
  40. </tm-col>
  41. <!-- #endif -->
  42. <!-- #ifdef H5 || APP-VUE || APP-PLUS -->
  43. <tm-col color="" align="middle" width="14.28%" v-for="(item,index) in ['一','二','三','四','五','六','日']"
  44. :key="index+'_acv'"><text class="text-size-s py-16">{{item}}</text>
  45. </tm-col>
  46. <!-- #endif -->
  47. <tm-col
  48. @click="day_danxuanclick(item,index)"
  49. color=""
  50. :custom-class="isSelectedDateClass(item)"
  51. justify="center" width="14.28%"
  52. v-for="(item,index) in nowData"
  53. :key="index"
  54. >
  55. <view class="tm-calendar-col flex-center flex-col "
  56. :style="[mode=='rang'?{width:'100%',height:'90rpx'}:{width:'90rpx',height:'90rpx',overflow: 'hidden','border-radius': '50% !important'}]"
  57. :class="[
  58. item.start?'round-l-24':'',
  59. item.end?'round-r-24':'',
  60. item.beginEnd?(item.checked===true||item.start||item.end?color_tmeme+(black_tmeme?' bk ':''):(item.guocheng?color_tmeme+' text opacity-7 '+(black_tmeme?'bk':''):'')):'',
  61. black_tmeme&&!item.beginEnd?' opacity-2 ':'']">
  62. <text class="text-size-n "
  63. :class="[
  64. !item.nowMonth&&!item.guocheng&&!item.checked&&!item.start&&!item.end?(black_tmeme?'text-grey-darken-3':'text-grey-lighten-1'):'',
  65. item.checked||item.start||item.end?'text-white':'',
  66. item.guocheng?' text text-'+color_tmeme:'',
  67. !item.beginEnd?'text-grey-lighten-3':''
  68. ]"
  69. >{{item.day}}</text>
  70. <view class="text-size-xs text_bl"
  71. >
  72. <block v-if="item.start">
  73. </block>
  74. <block v-if="item.end">
  75. -止
  76. </block>
  77. <block v-if="!item.start&&!item.end">
  78. {{item.text?item.text:(showNongli?item.nongli.day:'')}}
  79. </block>
  80. </view>
  81. </view>
  82. </tm-col>
  83. </tm-row>
  84. </view>
  85. <view class="" style="height: 40rpx;"></view>
  86. <view class="text-align-center px-32 text-grey ">{{selectedVal}}</view>
  87. <view class="pa-32">
  88. <tm-button :black="black_tmeme" @click="confirm" block itemeClass="round-24" :theme="btnColor?btnColor:color_tmeme" fontSize="32">{{btnText}}</tm-button>
  89. </view>
  90. </view>
  91. </tm-poup>
  92. </view>
  93. </template>
  94. <script>
  95. /**
  96. * 日历
  97. * @description 日历组件,提供节气、农历公历显示,时间范围选择等功能。
  98. * @property {String} mode = [day|rang] 默认:day单选日期,rang范围选择日期。
  99. * @property {String} title = [] 弹层层标题
  100. * @property {String} btn-text = [] 底部按钮确认的文字
  101. * @property {Boolean} inline = [] 默认true,是否内联或者块状block,内联有助于单行内想快速显示操作多个日历。非内联,适合独占一行。
  102. * @property {String} btn-color = [primary|green|orange|red|blue|bg-gradient-blue-lighten] 默认:bg-gradient-blue-lighten底部按钮确认的背景颜色仅支持主题色名称
  103. * @property {String} color = [primary|green|orange|red|blue] 主题默认:primary,提供是请写主题色名称
  104. * @property {String} default-value = [] 默认时间默认:当前时间,格式:'2021-7-21'
  105. * @property {String} bing-end = [] 时间格式:'2021-7-21',范围结束时间当mode=rang时有效
  106. * @property {String} bing-start = [] 时间格式:'2021-7-21',范围结束时间当mode=rang时有效
  107. * @property {Boolean|String} disabled = [true|false] 是否禁用,只读,默认false
  108. * @property {Function} confirm 按钮点击确认时会发送当前选中的数据。如果数据为空,则不触发。
  109. * @property {Function} rang-start 日历为rang时间范围模式时,当设定开始时间触发,并返回开始时间和结束时间(空)的数据。
  110. * @property {Function} rang-end 日历为rang时间范围模式时,当设定结束时间触发,并返回开始时间和结束时间的数据。
  111. * @property {String} time-start = [] 日历时间可选范围开始日期格式'2021-7-21'
  112. * @property {String} time-end = [] 日历时间可选范围结束日期格式'2021-7-21'
  113. * @property {Array<object>} txt = [] 设置日期下标文本;格式[{date:'2021-7-21',text:"测试"}]
  114. * @property {Array<object>} selected-date-class = [] 设置指定日期的样式,格式[{date:'2021-7-21',class:"类名"}]
  115. * @property {Boolean|String} black = [true|false] 是否开启暗黑模式
  116. * @property {Boolean} show-nongli = [true|false] 是否显示农历
  117. * @property {Array} formart = [] 默认['年','月','日'],时间的分割符。
  118. * @example <tm-calendar :txt="bbc" ref='calendar' mode="rang" time-start="2021-7-1" time-end="2021-7-31" @confirm="next" v-model="tts" ></tm-calendar>
  119. */
  120. import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
  121. import tmCol from "@/tm-vuetify/components/tm-col/tm-col.vue"
  122. import tmRow from "@/tm-vuetify/components/tm-row/tm-row.vue"
  123. import tmButton from "@/tm-vuetify/components/tm-button/tm-button.vue"
  124. import tmPoup from "@/tm-vuetify/components/tm-poup/tm-poup.vue"
  125. import * as dayjs from "@/tm-vuetify/tool/function/dayjs/dayjs.min.js"
  126. const calendar = require("@/tm-vuetify/tool/function/dayjs/calendar.js")
  127. dayjs.extend(calendar)
  128. const DayJs = dayjs.default
  129. export default {
  130. components:{tmIcons,tmCol,tmRow,tmButton,tmPoup},
  131. name: "tm-calendar",
  132. props:{
  133. black:{
  134. type:Boolean|String,
  135. default:null
  136. },
  137. disabled:{
  138. type:Boolean|String,
  139. default:false
  140. },
  141. // 默认时间。
  142. defaultValue:{
  143. type:String,
  144. default:''
  145. },
  146. mode:{
  147. type:String,
  148. default:'day'
  149. },
  150. bingStart:{
  151. type:String,
  152. default:null
  153. },
  154. timeStart:{
  155. type:String,
  156. default:null
  157. },
  158. timeEnd:{
  159. type:String,
  160. default:null
  161. },
  162. bingEnd:{
  163. type:String,
  164. default:null
  165. },
  166. // 顶部标题。
  167. title:{
  168. type:String,
  169. default:'选择时间'
  170. },
  171. // 底部按钮文件
  172. btnText:{
  173. type:String,
  174. default:'确认'
  175. },
  176. // 底部按钮背景主题色名称
  177. btnColor:{
  178. type:String,
  179. default:''
  180. },
  181. // 主题色。
  182. color:{
  183. type:String,
  184. default:'primary'
  185. },
  186. value:{
  187. type:Boolean,
  188. default:false
  189. },
  190. txt:{
  191. type:Array,
  192. default:()=>{ return []}
  193. },
  194. // 指定日期的样式类格式同txt
  195. selectedDateClass:{
  196. type:Array,
  197. default:()=>{ return []}
  198. },
  199. // 是否显示家历
  200. showNongli:{
  201. type:Boolean,
  202. default:false
  203. },
  204. // 跟随主题色的改变而改变。
  205. fllowTheme:{
  206. type:Boolean|String,
  207. default:true
  208. },
  209. formart:{
  210. type:Array,
  211. default:()=>{
  212. return ['年','月','日'];
  213. }
  214. },
  215. inline:{
  216. type:Boolean|String,
  217. default:true
  218. }
  219. },
  220. model:{
  221. prop:'value',
  222. event:'input'
  223. },
  224. watch:{
  225. bingStart:function(){
  226. clearTimeout(this.tmid)
  227. let t = this;
  228. this.tmid = setTimeout(function(){
  229. t.watchRangeTime();
  230. },500)
  231. },
  232. bingEnd:function(){
  233. clearTimeout(this.tmid)
  234. let t = this;
  235. this.tmid = setTimeout(function(){
  236. t.watchRangeTime();
  237. },500)
  238. },
  239. value:function(val){
  240. this.show = val;
  241. },
  242. txt:function(val){
  243. if(this.cal){
  244. this.cal.setTimeArrayText(this.txt);
  245. }
  246. },
  247. defaultValue:function(val,oldVal){
  248. if(!this.cal) return;
  249. // 自动更新默认的显示时间。
  250. if(this.mode=='day'){
  251. let d = DayJs().format("YYYY/MM/DD HH:mm:ss");
  252. if(this.defaultValue){
  253. d = this.defaultValue;
  254. }
  255. if(!oldVal||oldVal==''){
  256. this.cal = new this.$tm.calendar({value:d,start:this.timeStart,end:this.timeEnd})
  257. this.nowData = this.cal.getData();
  258. }
  259. this.cal.setValue(d)
  260. let index = this.findItemToindexByDate(this.cal.now_day_month)
  261. if(index>-1){
  262. this.nowData = this.cal.getData();
  263. let item = this.nowData[index];
  264. item.checked = true;
  265. this.selectedDay = item;
  266. this.fanxuanDate();
  267. }
  268. }
  269. }
  270. },
  271. data() {
  272. return {
  273. show: false,
  274. nowData:[],//当前月份数据。
  275. cal:null,//日历对象数据。
  276. selectedDay:null,
  277. start:null,
  278. end:null,
  279. fanwei:[],
  280. tmid:56986,
  281. };
  282. },
  283. destroyed() {
  284. clearTimeout(this.tmid)
  285. },
  286. computed:{
  287. black_tmeme: function() {
  288. if (this.black !== null) return this.black;
  289. return this.$tm.vx.state().tmVuetify.black;
  290. },
  291. color_tmeme:function(){
  292. if(this.$tm.vx.state().tmVuetify.color!==null&&this.$tm.vx.state().tmVuetify.color && this.fllowTheme){
  293. return this.$tm.vx.state().tmVuetify.color;
  294. }
  295. return this.color;
  296. },
  297. titleValue:function(){
  298. if(! this.cal) return ''
  299. return this.cal.value.getFullYear()+(this.formart[0]??'年')+(this.cal.value.getMonth()+1)+(this.formart[1]??'月');
  300. },
  301. centerValue:function(){
  302. if(! this.cal) return ''
  303. return this.cal.value.getMonth()+1;
  304. },
  305. selectedVal:function(){
  306. if(this.mode=='day'&&this.selectedDay){
  307. return this.selectedDay.year+(this.formart[0]??'年')+this.selectedDay.month+(this.formart[1]??'月')+this.selectedDay.day+(this.formart[2]??'');
  308. }
  309. if(this.mode=='rang'&&this.start&&!this.end){
  310. let p = this.start.year+(this.formart[0]??'年')+this.start.month+(this.formart[1]??'月')+this.start.day+(this.formart[2]??'');
  311. let et = '' ;
  312. return p + " ~ " + et;
  313. }
  314. if(this.mode=='rang'&&this.start&&this.end){
  315. let p = this.start.year+(this.formart[0]??'年')+this.start.month+(this.formart[1]??'月')+this.start.day+(this.formart[2]??'日');
  316. let p2 = this.end.year+(this.formart[0]??'年')+this.end.month+(this.formart[1]??'月')+this.end.day+(this.formart[2]??'日');
  317. return p + " ~ " +p2;
  318. }
  319. }
  320. },
  321. mounted() {
  322. this.watchRangeTime();
  323. this.show = this.value;
  324. },
  325. methods: {
  326. watchRangeTime(){
  327. let d = DayJs().format("YYYY/MM/DD HH:mm:ss")
  328. if(this.defaultValue){
  329. d = DayJs(this.defaultValue).format("YYYY/MM/DD HH:mm:ss");
  330. }
  331. this.cal = new this.$tm.calendar({value:d,start:this.timeStart,end:this.timeEnd})
  332. if(this.txt){
  333. this.cal.setTimeArrayText(this.txt);
  334. }
  335. this.nowData = this.cal.getData();
  336. if(this.mode=='day'){
  337. let index = this.findItemToindexByDate(this.cal.now_day_month)
  338. if(index>-1){
  339. let item = this.nowData[index];
  340. item.checked = true;
  341. this.selectedDay = item;
  342. this.fanxuanDate();
  343. }
  344. // 反选选区。
  345. }else if(this.mode=='rang'){
  346. if(this.bingStart&&this.bingEnd){
  347. this.fanxuanxuanwuBydate(
  348. DayJs(this.bingStart),
  349. DayJs(this.bingEnd),
  350. )
  351. }
  352. }
  353. },
  354. openPoup(){
  355. if(this.disabled==true) return;
  356. this.show=!this.show
  357. },
  358. isGuochengBg(item){
  359. if(!item.beginEnd) return '';
  360. if(item.checked===true||item.start||item.end) return this.color_tmeme;
  361. if(item.guocheng) return this.color_tmeme + ' text' ;
  362. if(item.guocheng) return '';
  363. },
  364. isSelectedDateClass(date){
  365. let rangeL = 'round-l-24 round-tr-0 round-br-0'
  366. let rangeR = 'round-r-24 round-tl-0 round-bl-0'
  367. let index = this.selectedDateClass.findIndex((item)=>{
  368. let val = date.year+'-'+date.month+'-'+date.day;
  369. return val == item.date;
  370. })
  371. let pc = '';
  372. if(date.start&&!date.end){
  373. pc = ` ${rangeL} `;
  374. }else if(date.end&&!date.start){
  375. pc = ` ${rangeR} `;
  376. }else if(date.start&&date.end){
  377. pc = ` `
  378. }
  379. if(index >-1){
  380. return this.selectedDateClass[index].class + pc
  381. }
  382. return pc;
  383. },
  384. close(){
  385. this.$refs.pop.close();
  386. },
  387. toogle(e){
  388. this.$emit('input',e);
  389. this.$emit('update:value',e);
  390. if(e){
  391. this.watchRangeTime();
  392. }
  393. },
  394. // 获取当前月份的数据。
  395. getNowMonthData(){
  396. return this.cal.getData();
  397. },
  398. // 设置时间文本数据。
  399. setNowMonthData(e){
  400. if(!Array.isArray(e)) return;
  401. this.cal.setTimeArrayText(e);
  402. this.nowData = this.cal.getData();
  403. let index = this.findItemToindexByDate(this.cal.now_day_month)
  404. if(index>-1){
  405. let item = this.nowData[index];
  406. item.checked = true;
  407. this.selectedDay = item;
  408. }
  409. this.fanxuanDate()
  410. },
  411. confirm(){
  412. if(this.mode=='day'){
  413. if(this.selectedDay){
  414. this.$emit('confirm',this.selectedDay);
  415. this.$emit('update:defaultValue',this.selectedDay.year+'-'+this.selectedDay.month+'-'+this.selectedDay.day)
  416. }
  417. }else if(this.mode=='rang'){
  418. if(this.start&&this.end){
  419. let bts = this.start.year+'-'+this.start.month+'-'+this.start.day;
  420. this.$emit('update:bingStart',bts)
  421. this.$emit('update:defaultValue',bts)
  422. let ets = this.end.year+'-'+this.end.month+'-'+this.end.day;
  423. this.$emit('update:bingEnd',ets)
  424. this.$emit('confirm',[this.start,this.end]);
  425. // this.fanwei
  426. }
  427. }
  428. this.close();
  429. },
  430. preMonth(){
  431. if(!this.cal) return;
  432. this.nowData = this.cal.prevMonth().getData();
  433. this.$nextTick(function(){
  434. this.fanxuanDate();
  435. })
  436. },
  437. nextMonth(){
  438. if(!this.cal) return;
  439. this.nowData = this.cal.nextMonth().getData();
  440. this.$nextTick(function(){
  441. this.fanxuanDate();
  442. })
  443. },
  444. preYear(){
  445. if(!this.cal) return;
  446. this.nowData = this.cal.prevYear().getData();
  447. this.$nextTick(function(){
  448. this.fanxuanDate();
  449. })
  450. },
  451. nextYear(){
  452. if(!this.cal) return;
  453. this.nowData = this.cal.nexYear().getData();
  454. this.$nextTick(function(){
  455. this.fanxuanDate();
  456. })
  457. },
  458. fanxuanDate(){
  459. if(this.mode=='day'){
  460. if(this.selectedDay){
  461. let index = this.findItemToindex(this.selectedDay);
  462. if(index>-1){
  463. this.nowData.splice(index,1,this.selectedDay);
  464. }
  465. }
  466. }else if(this.mode=='rang'){
  467. if(this.start&&!this.end){
  468. let index = this.findItemToindex(this.start);
  469. if(index>-1){
  470. this.nowData.splice(index,1,this.start);
  471. }
  472. return;
  473. }
  474. if(this.start&&this.end){
  475. let index = this.findItemToindex(this.start);
  476. if(index>-1){
  477. this.nowData.splice(index,1,this.start);
  478. }
  479. index = this.findItemToindex(this.end);
  480. if(index>-1){
  481. this.nowData.splice(index,1,this.end);
  482. }
  483. for(let i=0;i<this.fanwei.length;i++){
  484. let idx = this.fanwei[i];
  485. index = this.findItemToindex(idx);
  486. if(index>-1){
  487. this.nowData.splice(index,1,idx);
  488. }
  489. }
  490. return;
  491. }
  492. }
  493. },
  494. isSelected:function(item){
  495. let index = this.selectedDay.indexOf(idx=>{
  496. return idx.year===item.year&&idx.month===item.month&&idx.day===item.day;
  497. })
  498. if(index===-1) return false;
  499. return true;
  500. },
  501. // 查找选中的
  502. findChecked(){
  503. let xz = [];
  504. this.nowData.forEach((item,index)=>{
  505. if(item.checked===true){
  506. xz.push({
  507. item:item,
  508. index:index
  509. })
  510. }
  511. })
  512. return xz;
  513. },
  514. // 查找index
  515. findItemToindex(item){
  516. let index=-1;
  517. for(let i=0;i<this.nowData.length;i++){
  518. let idx = this.nowData[i];
  519. if(idx.year==item.year&&idx.month==item.month&&idx.day==item.day){
  520. index=i;
  521. break;
  522. }
  523. }
  524. return index;
  525. },
  526. // 根据时间选取查找。
  527. findItemToindexByDate(date){
  528. let index=-1;
  529. for(let i=0;i<this.nowData.length;i++){
  530. let idx = this.nowData[i];
  531. if(idx.year==date.getFullYear()&&idx.month==(date.getMonth()+1)&&idx.day==date.getDate()){
  532. index=i;
  533. break;
  534. }
  535. }
  536. return index;
  537. },
  538. // 清除当前日历中选中的部分。
  539. clearCheckedNowDay(){
  540. let xz = [];
  541. this.nowData.forEach((item,index)=>{
  542. item.checked = false;
  543. xz.push(item);
  544. })
  545. this.nowData = xz;
  546. },
  547. // 清除选区的内容。
  548. clearRangeNowDay(){
  549. let xz = [];
  550. let dqdata = this.cal.value;
  551. for(let i=0;i<this.nowData.length;i++){
  552. let item = this.nowData[i];
  553. let index = i;
  554. item.start = false;
  555. item.end = false;
  556. item.guocheng = false;
  557. item.checked = false;
  558. if(item.year==dqdata.getFullYear()&&item.month==dqdata.getMonth()+1){
  559. item.nowMonth =true;
  560. }else{
  561. item.nowMonth =false;
  562. }
  563. xz.push(item);
  564. }
  565. this.nowData = xz;
  566. },
  567. // 通过外围 时间默认的选中
  568. fanxuanxuanwuBydate(start,end){
  569. if(!start||!end) return;
  570. // .format("YYYY/MM/DD HH:mm:ss")
  571. this.$nextTick(function(){
  572. if(start.valueOf()>end.valueOf()) return;
  573. // 获取开始月份的数据。
  574. let sobj = new this.$tm.calendar({value:start.format("YYYY/MM/DD HH:mm:ss")});
  575. // 获取结束月份的数据。
  576. let eobj = new this.$tm.calendar({value:end.format("YYYY/MM/DD HH:mm:ss")});
  577. function findItemToindex_only(obj,type){
  578. let item=null;
  579. for(let i=0;i<obj.length;i++){
  580. let idx = obj[i];
  581. if(idx.nowDay==true){
  582. item = idx;
  583. break;
  584. }
  585. }
  586. if(type == 'start'&&item){
  587. item.start=true;
  588. item.end=false;
  589. item.checked=false;
  590. item.guocheng=false;
  591. }else if(type == 'end'&&item){
  592. item.start=false;
  593. item.end=true;
  594. item.checked=false;
  595. item.guocheng=false;
  596. }
  597. return item;
  598. }
  599. let sodata = sobj.getData();
  600. let eodata = eobj.getData();
  601. let start_obj = null;
  602. let end_obj = null;
  603. start_obj = findItemToindex_only(sodata,'start')
  604. let s_index = this.findItemToindex(start_obj)
  605. if(s_index>-1){
  606. this.nowData.splice(s_index,1,start_obj)
  607. }
  608. end_obj = findItemToindex_only(eodata,'end')
  609. let e_index = this.findItemToindex(end_obj)
  610. if(e_index>-1){
  611. this.nowData.splice(e_index,1,end_obj)
  612. }
  613. this.start = start_obj
  614. this.end = end_obj
  615. // 如果结束和开始相等。
  616. if(start.valueOf()==end.valueOf()){
  617. this.start = {...this.start,start:true,end:true}
  618. this.end = {...this.end,start:true,end:true}
  619. }
  620. // 计算包含的时间 区域。
  621. let start_time = new Date(this.start.year+"/"+this.start.month+"/"+this.start.day).getTime()
  622. let start_bdm = new Date(this.start.year,this.start.month-1).getTime()
  623. let end_time = new Date(this.end.year+"/"+this.end.month+"/"+this.end.day).getTime()
  624. let end_bdm = new Date(this.end.year,this.end.month-1).getTime()
  625. this.fanwei=[];
  626. let m=[];
  627. let testc = new this.$tm.calendar({value:this.start.year+"/"+this.start.month+"/"+this.start.day})
  628. testc.setTimeArrayText(this.txt);
  629. function findItemToindex_only_nob(item,obj){
  630. let istrue = false;
  631. for(let i=0;i<obj.length;i++){
  632. let idx = obj[i];
  633. if(item.year==idx.year&&item.month==idx.month&&item.day==idx.day){
  634. istrue = true;
  635. break;
  636. }
  637. }
  638. return istrue;
  639. }
  640. for(let j=0;j<1000;j++){
  641. let pds = new Date(testc.value.getFullYear(),testc.value.getMonth()).getTime();
  642. let testod = testc.getData();
  643. if(pds<=end_bdm&&pds>=start_bdm){
  644. for(let k=0;k<testod.length;k++){
  645. if(!findItemToindex_only_nob(testod[k],m)){
  646. m.push(testod[k]);
  647. }
  648. }
  649. testc.nextMonth()
  650. }else{
  651. break;
  652. }
  653. }
  654. for(let i=0;i<m.length;i++){
  655. let dod = {...m[i]};
  656. let npds = new Date(dod.year+"/"+(dod.month)+"/"+dod.day);
  657. let dq = npds.getTime()
  658. if(dq > start_time && dq < end_time){
  659. dod.start=false;
  660. dod.end=false;
  661. dod.checked=false;
  662. dod.guocheng=true;
  663. let isindex =this.findItemToindex(dod);
  664. if(isindex>-1){
  665. this.nowData.splice(isindex,1,dod);
  666. }
  667. this.fanwei.push(dod)
  668. }
  669. }
  670. // 开始反选。
  671. this.fanxuanDate();
  672. })
  673. },
  674. day_danxuanclick(e,index) {
  675. // 是否禁用。
  676. if(this.disabled||this.disabled=='true'){
  677. this.$tm.toast("已被禁用")
  678. return;
  679. }
  680. if(!e.beginEnd){
  681. this.$tm.toast("不可选!")
  682. return;
  683. };
  684. if(this.mode=='day'){
  685. this.clearCheckedNowDay();
  686. let p = {...e};
  687. p.checked = true;
  688. this.selectedDay = p;
  689. this.nowData.splice(index,1,p);
  690. }else{
  691. let p = {...e};
  692. if(!this.start&&!this.end){
  693. this.clearRangeNowDay();
  694. p.start = true;
  695. p.end = false;
  696. p.guocheng = false;
  697. this.start = p
  698. this.nowData.splice(index,1,p);
  699. //发布选中开始的事件。
  700. this.$emit("rang-start",{start:p,end:null})
  701. return;
  702. }
  703. if(this.start&&this.end){
  704. this.clearRangeNowDay();
  705. p.start = true;
  706. p.end = false;
  707. p.guocheng = false;
  708. this.start = p
  709. this.nowData.splice(index,1,p);
  710. this.end=null;
  711. //发布选中开始的事件。
  712. this.$emit("rang-start",{start:p,end:null})
  713. return;
  714. }
  715. if(this.start&&!this.end){
  716. this.$nextTick(function(){
  717. let selected = new Date(e.year+"/"+e.month+"/"+e.day).getTime();
  718. let selectedStart = new Date(this.start.year+"/"+this.start.month+"/"+this.start.day).getTime()
  719. if(selected <= selectedStart)
  720. {
  721. // this.clearRangeNowDay();
  722. let enjh = uni.$tm.deepClone(this.start);
  723. enjh.start = selected<selectedStart?false:true;
  724. enjh.end = true;
  725. enjh.guocheng = false;
  726. this.end = enjh
  727. let index_check =-1;
  728. for(let ix =0 ; ix <this.nowData.length;ix++){
  729. let item_check = this.nowData[ix]
  730. if( item_check.month==enjh.month&&item_check.year==enjh.year&&item_check.day==enjh.day){
  731. index_check=ix;
  732. break;
  733. }
  734. }
  735. if(index_check>-1){
  736. this.nowData.splice(index_check,1,this.end);
  737. }
  738. p.start = true;
  739. p.end = selected<selectedStart?false:true;
  740. p.guocheng = false;
  741. this.start = p
  742. }else if(selected > selectedStart)
  743. {
  744. p.start = false;
  745. p.end = true;
  746. p.guocheng = false;
  747. this.end = p
  748. }
  749. this.nowData.splice(index,1,p);
  750. //发布选中开始的事件。
  751. this.$emit("rang-start",{start:p,end:this.end})
  752. //发布选中开始的事件。
  753. this.$emit("rang-end",{start:this.start,end:this.end})
  754. // 计算包含的时间 区域。
  755. let start_time = new Date(this.start.year+"/"+this.start.month+"/"+this.start.day).getTime()
  756. let start_bdm = new Date(this.start.year,this.start.month-1).getTime()
  757. let end_time = new Date(this.end.year+"/"+this.end.month+"/"+this.end.day).getTime()
  758. let end_bdm = new Date(this.end.year,this.end.month-1).getTime()
  759. this.fanwei=[];
  760. let m=[];
  761. let testc = new this.$tm.calendar({value:this.start.year+"-"+this.start.month+"-"+this.start.day})
  762. testc.setTimeArrayText(this.txt);
  763. function findItemToindex_only(item,obj){
  764. let istrue = false;
  765. for(let i=0;i<obj.length;i++){
  766. let idx = obj[i];
  767. if(item.year==idx.year&&item.month==idx.month&&item.day==idx.day){
  768. istrue = true;
  769. break;
  770. }
  771. }
  772. return istrue;
  773. }
  774. for(let j=0;j<1000;j++){
  775. let npsDate = new Date(testc.value.getFullYear(),testc.value.getMonth());
  776. let pds = npsDate.getTime();
  777. let testod = testc.getData();
  778. if(pds<=end_bdm&&pds>=start_bdm){
  779. for(let k=0;k<testod.length;k++){
  780. if(!findItemToindex_only(testod[k],m)){
  781. m.push(testod[k]);
  782. }
  783. }
  784. testc.nextMonth()
  785. }else{
  786. break;
  787. }
  788. }
  789. for(let i=0;i<m.length;i++){
  790. let dod = {...m[i]};
  791. let npds = new Date(dod.year+"/"+(dod.month)+"/"+dod.day);
  792. let dq = npds.getTime()
  793. if(dq > start_time && dq < end_time){
  794. dod.start=false;
  795. dod.end=false;
  796. dod.checked=false;
  797. dod.guocheng=true;
  798. let isindex =this.findItemToindex(dod);
  799. if(isindex>-1){
  800. this.nowData.splice(isindex,1,dod);
  801. }
  802. this.fanwei.push(dod)
  803. }
  804. }
  805. })
  806. }
  807. }
  808. }
  809. },
  810. }
  811. </script>
  812. <style lang="scss" scoped>
  813. .tm-calendar-col{
  814. width: 100%;
  815. // height: 80upx;
  816. min-height: 80upx;
  817. // text-align: center;
  818. // line-height: 80upx;
  819. line-height: inherit;
  820. position: relative;
  821. .text_bl{
  822. // position: absolute;
  823. bottom: 14upx;
  824. }
  825. }
  826. .textOn{
  827. color:#1976d2 !important;
  828. }
  829. .tm-calendar-wk {
  830. width: 100%;
  831. .tm-calendar-title {
  832. position: relative;
  833. .tm-calendar-close {
  834. position: absolute;
  835. top: 32upx;
  836. right: 32upx;
  837. height: 50upx;
  838. width: 50upx;
  839. }
  840. }
  841. }
  842. .tm-calendar-body {
  843. position: relative;
  844. .tm-calendar-bg {
  845. height: 570upx;
  846. .text {
  847. font-size: 400upx !important;
  848. color: rgba(225, 225, 225, 0.4);
  849. &.tm-calendar-bg-center-text span{
  850. font-size: 400upx !important;
  851. }
  852. }
  853. }
  854. .tm-calendar-content {
  855. width: 100%;
  856. position: absolute;
  857. top: 0;
  858. left: 0;
  859. }
  860. }
  861. </style>