tm-calendarView.vue 24 KB

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