tm-calendar.vue 27 KB

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