vue2-vux-fitness-project

非常感谢那些无私开源的程序员,希望我也能够有能力像你们那样,开源很多很有意思的东西~~

//index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
    <title>fitness-app</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
//App.vue
<template>
  <div class="app" style="height:100%;">
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'app'
}
</script>

<style lang="less">
@import '~vux/src/styles/reset.less';

body {
  background-color: #fbf9fe;
}
</style>
//main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import FastClick from 'fastclick'
import VueRouter from 'vue-router'
import App from './App'

import router from'./router/memberRouter.js'      //---------自定义的路由文件
import Base from './assets/js/baseFun.js'         //---------自定义的公共函数和公共请求方法
import stores from './store/store'                //---------自定义的全局变量
import './assets/css/base.css'                    //---------引入的全局公共css

FastClick.attach(document.body)
Vue.config.productionTip = false

//注册全局函数和全局常量
Vue.prototype.baseFun=Base.baseFun;  //-----注册到vue的全局,方便各个组件和页面js调用公共函数
Vue.prototype.baseAjax=Base.baseAjax;//-----将封装的ajax请求函数注册到vue的全局 

Vue.use(VueRouter)

var globalVm=new Vue({
	router,            //-----router文件
    el: '#app',
    store:stores,          //-----全局变量
    template: '<App/>',
    components: { App }
})
//memberRouter.js路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import memberHome from '@/components/memberHome'
import activityIndex from '@/components/member/activities/activityIndex'
import activityDetail from '@/components/member/activities/activityDetail'
import groupCourses from '@/components/member/groupCourses/groupCourses'
import personalCourses from '@/components/member/personalCourses/personalCourses'
import personalCourseDetail from '@/components/member/personalCourses/personalCourseDetail'
import mine from '@/components/member/mine/mine'

Vue.use(VueRouter)

const router = new VueRouter({
    mode: 'hash',
    base: __dirname,
    //路由映射map
    routes: [
        { path: '/', redirect: '/memberHome/activityIndex' },
        { path: '*', redirect: '/memberHome/activityIndex' },
	    {
	      path: '/memberHome',
	      name: 'memberHome',
	      component: memberHome,
	      children:[
	      	   {
			      path: '/memberHome/activityIndex',
			      name: 'activityIndex',
			      component: activityIndex
			    },
			     {
			      path: '/memberHome/activityDetail/:activityId',
			      name: 'activityDetail',
			      component: activityDetail
			    },
			    {
			      path: '/memberHome/groupCourses',
			      name: 'groupCourses',
			      component: groupCourses
			    },
			    {
			      path: '/memberHome/mine',
			      name: 'mine',
			      component: mine
			    },
			    {
			      path: '/memberHome/personalCourses',
			      name: 'personalCourses',
			      component: personalCourses
			    },
			     {
			      path: '/memberHome/personalCourseDetail/:courseId/:date',
			      name: 'personalCourseDetail',
			      component: personalCourseDetail
			    }

	      ]
	    },
	     
    ]
});

export default router;

固定头部和下部

//memberHome.vue
<template>
  <div class="memberHome" style="height: 100%">
   <view-box ref="viewbox" body-padding-top="46px">
     <div class="vux-demo-header-box" slot="header">
      <!-- 插槽过来的变动的头部 -->
        <x-header :left-options="{backText: ''}" v-show="headShow">{{pageTitle}}</x-header>
     </div>
     <div v-transfer-dom class="loading-box">
        <loading :show="loading" position="absolute"></loading>
    </div>
    <!-- 中间部分固定 -->
        <router-view></router-view>
        <!-- 下部是固定部分 -->
     <tabbar v-show="footerShow">
      <tabbar-item selected link="/memberHome/newsIndex">
        <img slot="icon" src="../assets/images/icons/news_icon.png">
        <span slot="label">最新活动</span>
      </tabbar-item>
      <tabbar-item link="/memberHome/groupCourses">
        <img slot="icon" src="../assets/images/icons/group_icon.png">
        <span slot="label">团体课</span>
      </tabbar-item>
      <tabbar-item  link="/memberHome/personalCourses">
        <img slot="icon" src="../assets/images/icons/private_icon.png">
        <span slot="label">私教课</span>
      </tabbar-item>
      <tabbar-item link="/memberHome/mine">
        <img  slot="icon" src="../assets/images/icons/mine_icon.png">
        <span slot="label">我的</span>
      </tabbar-item>
    </tabbar>
    </view-box>
  </div>
</template>

<script>
  import { Tabbar,Icon,TabbarItem ,XHeader,Loading,ViewBox} from 'vux'
  import { TransferDomDirective as TransferDom } from 'vux'

  import {mapGetters} from 'vuex'
 
  export default {
    computed:mapGetters([
      'headShow',
      'loading',
      'footerShow',
      'pageTitle'
    ]),
    data(){
      let data={

      }
      return data
    },
    mounted() {
      
    },
    directives: {
        TransferDom
      },
    components: {
      Tabbar,
      TabbarItem,
      XHeader,
      Loading,
      ViewBox,
      Icon
    }
  }
</script>
<style>

.memberHome .vux-demo-header-box {
  z-index: 100;
  position: absolute;
   100%;
  left: 0;
  top: 0;
}

.memberHome .weui-tabbar__icon img{
       auto;
      height: 90%;
}

 .memberHome .weui-tabbar__item.weui-bar__item_on .weui-tabbar__label{
    color: #DD5858
}

</style>

store中是存储状态的

//store.js
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'
import actions from './actions'

Vue.use(Vuex);
export default new Vuex.Store({
	modules:{
		mutations
	},
	actions
});


//data.js相当于state

//是否显示头部
export const UPDATE_HEAD='UPDATE_HEAD';

//是否显示loading
export const UPDATE_LOADING='UPDATE_LOADING';

//是否显示footer
export const UPDATE_FOOTER='UPDATE_FOOTER';

//页面标题
export const UPDATE_PAGE_TITLE='UPDATE_PAGE_TITLE';
//action.js
//import 数据 from ''	这里面可以获取数据
import * as data from './data'

export default{

	UPDATE_HEAD:({commit})=>{
		commit(data.UPDATE_HEAD);
	},
	UPDATE_LOADING:({commit})=>{
		commit(data.UPDATE_LOADING);
	},
	UPDATE_FOOTER:({commit})=>{
		commit(data.UPDATE_FOOTER)
	},
	UPDATE_PAGE_TITLE:({commit})=>{
		commit(data.UPDATE_PAGE_TITLE)
	}
}

//mutations.js
import {
	UPDATE_HEAD,
	UPDATE_LOADING,
	UPDATE_FOOTER,
	UPDATE_PAGE_TITLE
} from './data'

const state={
	headShow:true,
	loading:false,
	footerShow:true,
	pageTitle:'首页'
};


const mutations={
	/*head*/
	[UPDATE_HEAD](state,type){
		state.headShow=type;
	},
	/*loading*/
	[UPDATE_LOADING](state,type){
		state.loading=type;
	},
	/*footer*/
	[UPDATE_FOOTER](state,type){
		state.footerShow=type;
	},
	/*title*/
	[UPDATE_PAGE_TITLE](state,type){
		state.pageTitle=type;
	}
};

const getters={
	headShow(state){
		return state.headShow;
	},
	loading(state){
		return state.loading;
	},
	footerShow(state){
		return state.footerShow;
	},
	pageTitle(state){
		return state.pageTitle;
	}
};

export default{
	state,
	mutations,
	getters
}

//activityIndex.vue
<template>
  <div class="activityIndex page">
    <div class="activeItem" v-for="item in itemList">
      <router-link :to="'/memberHome/activityDetail/'+item.id">
          <div class="newsImg">
             <img src="../../../assets/images/news-img.png"/>
          </div>
          <div class='sbottom'>
            <p class="title">{{item.title}}</p>
            <p class="time-line"><span  class='time'>{{item.startDate}} - {{item.endDate}}</span> 
            <span class="view"><span class="view_icon"><img src="../../../assets/images/icons/view.png"></span>{{item.viewer || 0}}人</span></p>
          </div>
        </router-link>
    </div>

  </div>
</template>
<script>
  import { Tabbar, TabbarItem ,XHeader,XButton,XImg} from 'vux'
  export default {
    mounted() {
      this.loadLatest();
      //插入头部
      this.$store.commit('UPDATE_PAGE_TITLE', '最新活动')
    },
    data(){
      return {
        itemList:''
      }
    },
    methods:{
      loadLatest(){
        //从后端取数据
          let self=this;
          this.baseAjax({
            url:'../../../static/basicData/latestActivity.json',
            showLoading:true,
            success:function(data){
                console.log(data)
                self.itemList=data.returnObject
            }
          })
      }
    },
    components: {
      Tabbar,
      TabbarItem,
      XHeader,
      XButton,
      XImg
    }
  }

</script>
<style>
  
.activityIndex .activeItem{
  margin:10px 10px 0 10px;
  position: relative;
  height: 180px;
  overflow: hidden;
  border-radius: 5px
}

.activityIndex .activeItem .sbottom{
    color: white;
    position: absolute;
    bottom: 10px;
    padding: 10px;
     85%;
}s


.activityIndex .activeItem .title{
  font-size: 18px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.activityIndex .time-line{
  font-size: 14px;
   100%;
  height: 20px;
}

.activityIndex .activeItem .view{
  float: right;
  font-size: 14px;
}

 .activityIndex .activeItem .newsImg img{
     100%;
    min-height: 180px;
 }

 .activityIndex  .sbottom img{
        16px;
    height: 12px;
    padding-right: 5px;
 }
</style>


//activityDetail.vue
<template>
	<div class="activityDetail">
		<div class="newsImg">
             <img src="../../../assets/images/news-img.png"/>
		</div>
		<div class="detail-box">
			<div class="text-top">
				<p class="title">{{mainData.title}}</p>
				<div class="sDate">
					<flexbox>
				      <flexbox-item>发布时间:{{mainData.publishDate}}</flexbox-item>
				      <flexbox-item>浏览量:{{mainData.viewer}}</flexbox-item>
					</flexbox>
				</div>
			</div>
			<div class="detail-text">
				<p v-html="mainData.content">
					{{mainData.content}}
				</p>
			</div>
		</div>
		
	</div>
</template>
<script>
	import {Flexbox, FlexboxItem,XImg} from 'vux'

	export default{
		 mounted() {
	      this.loadDetail();
	      this.$store.commit('UPDATE_PAGE_TITLE', '活动详情');

	    },
	    data(){
	      return {
	        mainData:''
	      }
	    },
	    methods:{
	    	loadDetail(){
	    		 let self=this;
	    		 let id=this.$route.params.activityId;
		          this.baseAjax({
		            url:'../../../static/basicData/activityDetail.json',
		            showLoading:true,
		            success:function(data){
		                console.log('data.returnObject',data.returnObject)
		                self.mainData=data.returnObject		 
		            }
		          })
	    	}	
	    },

	    components:{
	    	Flexbox, FlexboxItem,XImg
	    }
	}
</script>
<style>

 .activityDetail .newsImg{
 	height:180px;
 	overflow: hidden;
 }

.activityDetail .title{
	font-size: 16px;
	line-height: 22px;
}

.activityDetail .detail-text{
	color: #666;
	padding:10px 15px;
}

.activityDetail .detail-text p{
	text-indent: 28px;
	font-size: 14px;
	line-height: 22px;
	color: #666
}

 .activityDetail .newsImg img{
     100%;
    min-height: 180px;
 }

  .activityDetail  .sDate{
		margin-top: 10px;
		font-size: 12px;
		color: #666
 }

  .activityDetail  .text-top{
		border-bottom: 1px solid #eee;
		padding: 10px 15px 15px 15px; 
 }

	
</style>

//mine.vue
<template>
  <div clas="mine">
  	<h1>我的课程</h1>
  </div>
</template>

//personalCourses.js
//封装的日期组件
import { Tab, TabItem,XImg,dateFormat,XButton,Flexbox, FlexboxItem,InlineCalendar,Popup} from 'vux';

  let cnM=['一','二','三','四','五','六','七','八','九','十','十一','十二'];

  // 获取一周的日期
  // 获取当前星期的星期一的日期,返回的是一个Date对象。
  function getMonDate(dd){    //config为日期 例如:2016-04-19
      let d=new Date(dd);
      let day=d.getDay();
      let date=d.getDate();
      if(day==1)
      return d;
      if(day==0)
      d.setDate(date-6);
      else
      d.setDate(date-day+1);
      return d;
  }

  //获取一周的日期;
  function getWeekDate(self,confg){
      let d=getMonDate(confg);
      let wkd=new Date(confg).getDay();
      self.selectIndex=wkd==0?6:wkd-1
      for(var i=0;i<7;i++){
          self.dateList[i].date = d.getDate();
          self.dateList[i].configDate=dateFormat(new Date(d), 'YYYY-MM-DD');
          d.setDate(d.getDate()+1);
     }
  }

  export default {
    mounted() {
      this.$store.commit('UPDATE_PAGE_TITLE', '私教课')
      getWeekDate(this,this.myd);  //加载一周数据
      this.loadCourses();    //加载课程列表
    },
    data(){
      let self=this;
      let data={
          calendarDate:"",
          dateList :[
            {week:'周一',date:'',configDate:'',limit:false},
            {week:'周二',date:'',configDate:'',limit:false},
            {week:'周三',date:'',configDate:'',limit:false},
            {week:'周四',date:'',configDate:'',limit:false},
            {week:'周五',date:'',configDate:'',limit:false},
            {week:'周六',date:'',configDate:'',limit:false},
            {week:'周日',date:'',configDate:'',limit:false}
          ],
          myd:dateFormat(new Date(), 'YYYY-MM-DD'),
          pickMonth:cnM[new Date().getMonth()],
          pickDate:new Date().getDate(),
          selectIndex:null,
          courseList:'',
          showCalendar:false,
          weeksList:['日','一','二','三','四','五','六'],
          coursesQueryData:{
              date:dateFormat(new Date(), 'YYYY-MM-DD'),
           }


       }

      return data
    },
    methods:{

      // 获取团体课列表
      loadCourses(){
          let self=this;
          //与后端交互请求后端数据
          this.baseAjax({
            url:'../../../static/basicData/personalCourse.json',
            params:{
              date:self.coursesQueryData.date
            },
            showLoading:true,
            success:function(data){
              console.log(data)
                self.courseList=data.returnObject;
            }
          })
      },
      //选择日期
      calendarChange(date){
          if(date==this.coursesQueryData.date) return;
          getWeekDate(this,date);
          this.coursesQueryData.date=date;
          this.showCalendar=false;
          this.loadCourses();
      },

      //日期点击事件
      dateHandler(idx){
        this.selectIndex=idx;
        this.coursesQueryData.date=this.dateList[idx].configDate;
        this.loadCourses();
      },

      //打开日期控件
      openCalendar(){
        this.showCalendar=true;
      }
    },
    components: {
      Tab,TabItem,XImg,XButton,Flexbox, FlexboxItem,InlineCalendar,Popup
    }
  }
//src/components/member/personalCourses/personalCourses.vue
<template>
  <div class="personalCourses">
    <div class="topDate">
       <tab :animate=false :line-width="1">
          <tab-item disabled>
              <div class='left-calendar' @click="openCalendar()" >
                <p class="pickDate">{{pickDate}}</p>
                <p class="pickMonth">{{pickMonth}}月</p>
              </div>
          </tab-item>
          <tab-item @on-item-click="dateHandler(index)" v-for="(date,index) in dateList" :key="index" v-bind:class="{'vux-tab-selected': index==selectIndex ,'vux-tab-notSelected': index!=selectIndex}">
                <p>{{date.week}}</p>
                <p>{{date.date}}</p>
          </tab-item>
       </tab>
    </div>
    <div class="classItems">
    	<div class="item-box" v-for="(item,index) in courseList" :key="index">
    		 <flexbox>
                   <flexbox-item :span="3">
                   		<div class="item-icon">
                   			<img src="../../../assets/images/timg.png"/>
                   		</div>
                   </flexbox-item>
                   <flexbox-item>
                   		<div class="top-name">
                   			<flexbox>
          								<flexbox-item>
          									<div>{{item.name}}</div>
          									<p class="item-desc">{{item.description}}</p>
          								</flexbox-item>
          								<flexbox-item :span="4">
                            <router-link :to="'/memberHome/personalCourseDetail/'+item.id+'/'+coursesQueryData.date" v-show="item.status==1" >
                               <x-button mini type="warn"  action-type='button' >预约</x-button>
                            </router-link>
                            <x-button mini type="default" v-show="item.status==2"  action-type='button' >已预约</x-button>
          								</flexbox-item>
          	            </flexbox>
                             		</div>
                             		<div class="bottom-cer">
          		                   	<span>{{item.certification}}</span>
          		                </div>
                          </flexbox-item>
          </flexbox>
    	</div>
    </div>

    <div>
      <popup v-model="showCalendar">
        <inline-calendar
          @on-change="calendarChange"
          class="my-inline-calendar"
          v-model="calendarDate"
          :weeks-list="weeksList"
          >
        </inline-calendar>
      </popup>
    </div>

  </div>
</template>
<script>
  import personalCourses  from  "./js/personalCourses.js"
  export default personalCourses
</script>

<style>
  .personalCourses .vux-tab .vux-tab-item{
    line-height: 20px;
  }
  
  .personalCourses .pickDate
  {
    color:#DD5858;
    font-size: 16px;
  }

  .personalCourses .classItems{
     margin-top: 60px;
  }

  .personalCourses .left-calendar{
    margin-left:5px;
    border-radius: 5px;
    background: #eee;
  }

  .personalCourses .vux-tab{
    height: 46px
  }

  .personalCourses .activeItem img{
     100%
 }

 .personalCourses .activeItem{
  margin:10px 10px 0 10px;
  position: relative;
  height: 180px;
  overflow: hidden;
  border-radius: 5px
}

.personalCourses .topDate{
   position: absolute;
   top: 52px;
   z-index: 10;
    100%;
}

.personalCourses .activeItem .sbottom{
  color: white;
  position: absolute;
  bottom: 10px;
  padding:10px;
   85%
}


.personalCourses .activeItem .title{
  font-size: 18px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.personalCourses .time-line{
  font-size: 14px;
   100%;
  height: 20px;
}

.personalCourses .activeItem .view{
  float: right;
  font-size: 14px;
}

 .personalCourses .activeItem img{
     100%
 }

 .personalCourses .vux-tab .vux-tab-item.vux-tab-disabled {
    color: #666;
}

.personalCourses .vux-tab .vux-tab-item.vux-tab-selected{
  color:#DD5858;
  border- 3px !important;
  border-bottom: 3px solid #DD5858;
}

 .personalCourses .vux-tab .vux-tab-item.vux-tab-notSelected{
      border-bottom:1px solid #eee;
      color: #666
   }

   .personalCourses .inline-calendar td.current > span.vux-calendar-each-date {
    background-color: #DD5858;
  }

   .personalCourses .inline-calendar td.is-today{
    color:#DD5858;
  }

  .personalCourses  .item-box .item-icon{
		height: 60px;
		text-align: center;
		overflow: hidden;
  }

   .personalCourses  .item-box .item-icon img{
		height: 100%;
		border-radius: 50%
   }

   .personalCourses  .item-box {
   		border-bottom:1px solid #eee;
   		background: #fff;
   }

   .personalCourses  .top-name{
   	   border-bottom:1px solid #eee;
   	   padding: 10px 0;
   	   margin-right: 10px;
   }

   .personalCourses  .item-desc{
   	    font-size:12px;
   	    line-height: 20px;
   	    color: #666
   }

   .personalCourses .bottom-cer{
   		padding:10px 0;
   		font-size:12px;
   	    color: #666
   }
   .personalCourses .bottom-cer span{
   	    padding: 5px;
	    border-radius: 5px;
	    background: #eee;
	    margin: 5px;
   }

   .personalCourses button.weui-btn_mini{
     65px;
    padding: 0;
}


</style>

//personalCourseDetail.vue
<template>
  <div class="personalCourseDetail">
		<div class="top-box">
			<flexbox>
               <flexbox-item :span="3">
               		<div class="item-icon">
               			<img src="../../../assets/images/timg.png"/>
               		</div>
               </flexbox-item>
               <flexbox-item>
               		<div class="top-name">
						<div class="s-name"><span>{{mainData.name}}</span><span class="name-label">私教</span></div>
						<p class="item-desc">{{mainData.description}}</p>
               		</div>
               		<div class="bottom-cer">
               			<x-icon type="ios-clock-outline" size="20" class="icon-clock"></x-icon>
               			<p><span>{{currentDate}}</span><span>({{currentDay}})</span></p>
	                </div>
                </flexbox-item>
	          </flexbox>
		</div>
		<div>
			<p class="remark">上课时间(时长:1小时)</p>
		</div>
		<div class="time-box">
			<div v-for="(item,index) in timeList" class="time-item" :key="index">
				<div class="group-head" @click="item.showList=!item.showList">
	                <flexbox>
	                   <flexbox-item :span="2">
	                  		 <div  v-show="index==0" class="s-icon"><x-icon type="ios-partlysunny-outline" size="30"></x-icon></div>
	                  		 <div  v-show="index==1" class="s-icon"><x-icon type="ios-sunny-outline" size="30"></x-icon></div>
	                  		 <div  v-show="index==2" class="s-icon"><x-icon type="ios-moon-outline" size="30"></x-icon></div>
	                   </flexbox-item>
	                   <flexbox-item ><div>{{item.name}}</div></flexbox-item>
	                   <flexbox-item :span="2"><div class="arrow-icon"><x-icon type="ios-arrow-down" size="20"></x-icon></div></flexbox-item>
	                </flexbox>
         </div>
          <div class="list-box" v-show="item.showList">
                <div class="checker-box">
                  <checker
                      v-model="checkTime"
                      type="checkbox"
                      default-item-class="checkTime-item"
                      selected-item-class="checkTime-item-selected"
                      disabled-item-class="checkTime-item-disabled"
                      >
                        <checker-item 
                          v-for="(sitem,sindex) in item.list" 
                          :key="sindex" 
                          :value="sitem.time" 
                          :disabled="!sitem.isEnable"
                          @on-item-click="checkMyTime(index,sitem.time,sitem.isEnable)">{{sitem.time}}
                        </checker-item>
                  </checker>
                </div>
          </div>
			</div>
      <div class="labels">
          <div class="is-allow">可选</div>
          <div class="no-allow">不可选</div>
          <div class="is-select">已选择</div>
      </div>
      <div class="bottom-btn" v-show="showReserveBtn">
          <x-button type="warn" @click.native="makeReserve">确定预约</x-button>
      </div>
		</div>
    <toast v-model="showSuccess" type="text" class="showSuccess" :time="2000">预约成功</toast>
    <toast v-model="showError" type="text" class="showError" :time="2000">预约失败</toast>
    <toast v-model="showMsg" type="text" class="showMsg" :time="2000">请选择1h相邻的时间段</toast>
  </div>
</template>
<script>
  import personalCourseDetail  from  "./js/personalCourseDetail.js"
  export default personalCourseDetail
</script>

<style>

	.personalCourseDetail .top-box{
		background: #fff
	}

	.personalCourseDetail .item-icon{
		height: 60px;
		text-align: center;
		overflow: hidden;
  }

   .personalCourseDetail .item-icon img{
		height: 100%;
		border-radius: 50%
   }

   .personalCourseDetail  .item-box {
   		border-bottom:1px solid #eee;
   		background: #fff;
   }

   .personalCourseDetail  .top-name{
   	   border-bottom:1px solid #eee;
   	   padding: 10px 0 5px 0;
   	   margin-right: 10px;
   }

   .personalCourseDetail  .item-desc{
   	    font-size:12px;
   	    line-height: 20px;
   	    color: #666;
        clear:both;
   }

   .personalCourseDetail .bottom-cer{
   		padding:10px 0;
   		font-size:12px;
   	    color: #666;
   	    position :relative;
   }

    .personalCourseDetail .bottom-cer p{
    	padding-left: 15px;
    	line-height: 20px;
    }
	
	.personalCourseDetail .bottom-cer p span{
		padding-left: 10px
	}

   .personalCourseDetail .icon-clock{
   		position:absolute;
   		fill: #666;
   }

   .personalCourseDetail .s-icon{
 	   padding-left: 20px
   }

	 .personalCourseDetail .group-head{
		 font-size: 14px;
		 padding-top: 5px;
     border-bottom: 1px solid #eee
	  }

   .personalCourseDetail .remark{
   	 height: 40px;
   	 font-size: 14px;
   	 line-height: 40px;
     color: #666;
   	 padding-left: 20px
   }

    .personalCourseDetail .time-box{
   	 background: #fff;
     padding-bottom:10px
     ;
   }

   .personalCourseDetail .checker-box{
      margin:15px;
   }

    .personalCourseDetail  .time-item{
		   border-bottom: 1px solid #eee
   }
    .personalCourseDetail  .arrow-icon{
   	  text-align: right;
   	  padding-right: 15px;

   }

   .personalCourseDetail .checkTime-item {
	   20%;
	  height: 32px;
	  line-height: 32px;
	  text-align: center;
    border: 1px solid #ccc;
	  background-color: #fff;
    color: #000;
    box-sizing: border-box;
	}
	.personalCourseDetail .checkTime-item-selected {
	  background: #333333 url(../../../assets/images/bgIcon/select-icon.png) no-repeat right bottom;
    background-size:12px 10px;
	  color: #fff;
    border: 1px solid #333333;
    border-right:1px solid #ccc;

	}
  .personalCourseDetail .checkTime-item-disabled{
      background: #DEDCDC;
  }

  .personalCourseDetail .bottom-btn{
      padding:20px;
  }

  .personalCourseDetail .labels{
      margin:5px 30px;
      height: 30px;
      line-height: 30px
  }

    .personalCourseDetail .labels >div{
        float:left;
        margin-right: 20px;
        font-size: 12px;
        padding-left: 20px;

    }

    .personalCourseDetail .labels .is-allow{
        background: url(../../../assets/images/bgIcon/is-allow.png) no-repeat left center ;
        background-size:12px;
    }

    .personalCourseDetail .labels .no-allow{
        background: url(../../../assets/images/bgIcon/no-allow.png) no-repeat left center ;
        background-size:12px;
    }

    .personalCourseDetail .labels .is-select{
      background: url(../../../assets/images/bgIcon/is-select.png) no-repeat left center ;
      background-size:12px;
    }

    .personalCourseDetail .s-name span{
        height:30px;
        line-height: 30px;
        display:block;
        float: left;
    }

  .personalCourseDetail .s-name .name-label{
      background: #6B106A;
      color: #fff;
      font-size: 12px;
      height:20px;
      line-height: 20px;
      margin: 5px 10px;
      padding:0 10px;
    }

    .personalCourseDetail  .showSuccess .weui-toast__content{
         background: url(../../../assets/images/bgIcon/success.png) no-repeat left center ;
      background-size:20px;
    }

    .personalCourseDetail  .showSuccess .weui-toast{
      padding-left: 10px;
    }


</style>
//personalCourseDetail.js

import { XImg,XButton,Flexbox, FlexboxItem,XDialog,Checker, CheckerItem,Toast} from 'vux';

export default {
	mounted(){
		this.loadDetail();
		this.$store.commit('UPDATE_PAGE_TITLE', '课程预约');
	},
	computed:{
		currentDay(){
			let date=this.$route.params.date;
			let day=new Date(date).getDay();
			let cnM=['日','一','二','三','四','五','六'];
			return "周"+cnM[day]
		}
	},
	data(){
		let self=this;
		let data={
			mainData:{},
			showSuccess:false,
			showError:false,
			showMsg:false,
			currentDate:self.$route.params.date,
			checkTime:[],
			activeType:0,
			timeListArr:[[],[],[]],
			showReserveBtn:true,
			timeList:[
				{name:"上午",
				list:[],
				showList:false
				},
				{name:"下午",
				list:[],
				showList:false
				},
				{name:"晚上",
				list:[],
				showList:false
				}
			]
		}
		return data;
	},
	methods:{
		// 获取详细信息
		loadDetail(){
			let self=this;
	    	let courseId=this.$route.params.courseId;
	    	let date=this.$route.params.date;
		          this.baseAjax({
		            url:'../../../static/basicData/personalDetail.json',
		            showLoading:true,
		            params:{
		            	courseId:courseId,
		            	date:date
		            },
		            success:function(data){
		                self.mainData=data.returnObject[0];
		                //从后端请求的~~不同人的数据不同
		                self.computeTimeLost(self.mainData.scheduleTime)

		        }
		    })
		},
		// 计算时间列表
		computeTimeLost(list){
			let self=this;
			let len=list.length;
			for(let i=0;i<len;i++){
				let type=list[i].type-1;
				list[i].check=false;
				self.timeList[type].list.push(list[i]);
				self.timeListArr[type].push(list[i].time);

			}
			console.log(self.timeList)
		},
		//选中时间
		checkMyTime(idx,val,isEnable){
			if(!isEnable) return;
			if(this.activeType!=idx){
				this.checkTime=[val];
				this.activeType=idx
			}
			console.log(this.checkTime)
		},
		//预定私教课
		makeReserve(){
			if(!this.validateTime()) return;
			let self=this;
	    	let courseId=this.$route.params.courseId;
	    	let date=this.$route.params.date;
		          this.baseAjax({
		            url:'../../../static/basicData/makeReserve.json',
		            type:'get',
		            showLoading:true,
		            params:{
		            	courseId:courseId,
		            	memberId:"666",
		            	reservedTime:self.checkTime.join(","),
		            	trainerId:"999"
		            },
		            success:function(data){
		               console.log(data)
		               if(data.isSuccess){
		               		self.showSuccess=true;
		               		self.showReserveBtn=false;
		               }else{
		               		self.showError=true;
		               }
		        }
		    })
		},
		//预定私教课
		validateTime(){
			if(!this.checkTime || this.checkTime.length!=2){
				this.showMsg=true;
				return false
			}
			let type=this.activeType;
			let tlist=this.timeListArr[type];
			let t1=tlist.indexOf(this.checkTime[0]);
			let t2=tlist.indexOf(this.checkTime[1]);
			if(Math.abs(t1-t2) !=1){
				this.showMsg=true;
				return false
			}
			return true;

		}

	},
	components:{
		XImg,XButton,Flexbox, FlexboxItem,XDialog,Checker, CheckerItem,Toast
	}
}

//groupCourses.vue
<template>
  <div class="groupCourses">
    <div class="topDate">
       <tab :animate=false :line-width="1">
          <tab-item disabled>
              <div class='left-calendar' @click="openCalendar()" >
                <p class="pickDate">{{pickDate}}</p>
                <p class="pickMonth">{{pickMonth}}月</p>
              </div>
          </tab-item>
          <tab-item @on-item-click="dateHandler(index)" v-for="(date,index) in dateList" :key="index" v-bind:class="{'vux-tab-selected': index==selectIndex ,'vux-tab-notSelected': index!=selectIndex}">
                <p>{{date.week}}</p>
                <p>{{date.date}}</p>
          </tab-item>
       </tab>
       <div class="selectGroup">
          <div class="purpose">
              <div class="purpose-name group-head" @click="showPurpose=!showPurpose">
                <flexbox>
                   <flexbox-item :span="2"><div class="purpose-icon"><img src="../../../assets/images/icons/purpose_icon.png"></div></flexbox-item>
                   <flexbox-item ><div>目的-{{coursesQueryData.purposeName}}</div></flexbox-item>
                   <flexbox-item :span="2"><div class="arrow-icon"><x-icon type="ios-arrow-down" size="20"></x-icon></div></flexbox-item>
                </flexbox>
              </div>
              <div class="purpose-items group-items" v-show="showPurpose">
                   <p v-for="item in purposeList" @click="queryByPurpose(item)">{{item.name}}</p>
              </div>
          </div>
          <div class="categoryName">
              <div class="category-name group-head" @click="showCategory=!showCategory">
                <flexbox>
                   <flexbox-item :span="2"><div class="purpose-icon"><img src="../../../assets/images/icons/category_icon.png"></div></flexbox-item>
                   <flexbox-item ><div>分类-{{coursesQueryData.categoryName}}</div></flexbox-item>
                   <flexbox-item :span="2"><div class="arrow-icon"><x-icon type="ios-arrow-down" size="20"></x-icon></div></flexbox-item>
                </flexbox>
              </div>
              <div class="category-items group-items" v-show="showCategory">
                  <p v-for="item in categoryList" @click="queryByCategory(item)">{{item.name}}</p>
              </div>
          </div>
       </div>
    </div>
    <div class="classItems">
      <div class="activeItem" v-for="(item,index) in courseList" :key="index">
          <img src="../../../assets/images/news-img.png"/>
          <div class='sbottom'>
            <p class="title">{{item.title}}</p>
            <p class="time-line"><span  class='time'>{{item.startTime}} - {{item.endTime}}</span> 
            <span class="view">{{item.viewer}}</span></p>
          </div>
          <div class="qtyProgress">
            <div class='qbar' v-bind:style="{  item.barWidth,background:item.bgColor}">
            </div>
            <div class="qty"><span>{{item.reservation}}</span> / <span>{{item.personMax}}</span></div>
          </div>
          <div class="bookBtn">
              <x-button  mini type="warn"  action-type='button'  @click.native="makeReserve(item.id,index)">预约</x-button>
              <!-- <x-button  mini  action-type='button' type="default">已预约</x-button> -->
          </div>
      </div>
    </div>
    <div>
      <popup v-model="showCalendar">
        <inline-calendar
          @on-change="calendarChange"
          class="my-inline-calendar"
          v-model="calendarDate"
          :weeks-list="weeksList"
          >
        </inline-calendar>
      </popup>
    </div>
    <div>
        <x-dialog v-model="showSuccess" class="d-box" @click="showSuccess=false">
             <div @click="showSuccess=false">
               <div class="d-icon">
                  <img src="../../../assets/images/dialog-success.png">
               </div>
               <p class="d-title">预约成功,记得准时签到噢!</p>
             </div>
        </x-dialog>
        <x-dialog v-model="showSorry" class="d-box" >
            <div @click="showSorry=false">
              <div class="d-icon">
                    <img src="../../../assets/images/dialog-sorry.png">
                 </div>
                 <p class="d-title">人数已满,下次记得早点预约噢!</p>
            </div>
        </x-dialog>
    </div>

  </div>
</template>
<script>
  import groupCourses  from  "./js/groupCourses.js"
  export default groupCourses
</script>

<style>
  .groupCourses .vux-tab .vux-tab-item{
    line-height: 20px;
  }
  
  .groupCourses .pickDate
  {
    color:#DD5858;
    font-size: 16px;
  }

  .groupCourses .classItems{
     margin-top: 145px;
  }

  .groupCourses .left-calendar{
    margin-left:5px;
    border-radius: 5px;
    background: #eee;
  }

  .groupCourses .vux-tab{
    height: 46px
  }

  .groupCourses .activeItem img{
     100%
 }

 .groupCourses .activeItem{
  margin:10px 10px 0 10px;
  position: relative;
  height: 180px;
  overflow: hidden;
  border-radius: 5px
}

.groupCourses .topDate{
   position: absolute;
   top: 52px;
   z-index: 10;
    100%;
}

.groupCourses .activeItem .sbottom{
  color: white;
  position: absolute;
  bottom: 10px;
  padding:10px;
   85%
}


.groupCourses .activeItem .title{
  font-size: 18px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.groupCourses .time-line{
  font-size: 14px;
   100%;
  height: 20px;
}

.groupCourses .activeItem .view{
  float: right;
  font-size: 14px;
}

 .groupCourses .activeItem img{
     100%
 }

 .groupCourses .vux-tab .vux-tab-item.vux-tab-disabled {
    color: #666;
}

.groupCourses .vux-tab .vux-tab-item.vux-tab-selected{
  color:#DD5858;
  border- 3px !important;
  border-bottom: 3px solid #DD5858;
}
.groupCourses .bookBtn{
    position: absolute;
    bottom: 20px;
    right: 20px;
}
.groupCourses button.weui-btn_mini{
     65px;
    padding: 0;
}

.groupCourses .selectGroup{
  background: #fff
}

.groupCourses .group-head{
    padding: 10px 0 5px 0;
    font-size: 14px;
    border-bottom: 1px solid #eee
}

.groupCourses .purpose-icon, .groupCourses .category-icon{
  text-align: right;
  padding-right: 10px
}
.groupCourses .purpose-icon img{
    height:20px;
 }

 .groupCourses .arrow-icon{
  text-align: right;
  padding-right: 15px;
 }

  .groupCourses .group-items{
    padding:0 30px;
    border-bottom: 1px solid #eee
 }
 .groupCourses .group-items p{
      overflow: hidden;
      text-align: center;
      font-size: 14px;
      height: 30px;
      line-height:30px;
      color: #666;

   }

 .groupCourses .vux-tab .vux-tab-item.vux-tab-notSelected{
      border-bottom:1px solid #eee;
      color: #666
   }

   .groupCourses .inline-calendar td.current > span.vux-calendar-each-date {
    background-color: #DD5858;
  }

   .groupCourses .inline-calendar td.is-today{
    color:#DD5858;
  }

  .groupCourses .qtyProgress{
     70px;
    position: absolute;
    top: 10px;
    left: 10px;
    border-radius: 10px;
    height: 20px;
    line-height: 20px;
    font-size: 12px;
    text-align: center;
    background: #666;
    color: #fff
  }

  .groupCourses .qbar{
    border-radius: 10px;
    position: absolute;
    height: 100%;
    top: 0
  }

  .groupCourses .qty{
    text-align: center;
     100%;
    border-radius: 10px;
    position: absolute;
    height: 100%;
    top: 0
  }

  .groupCourses .d-box .d-title{
      margin-bottom:15px;
  }

  .groupCourses .d-box  .weui-dialog{
     max- 240px;
  }

   .groupCourses .d-icon{
      text-align: center;
      padding:10px;
   }

  .groupCourses .d-icon img{
      height: 70px;
      margin:15px auto;
  }

</style>
//groupCourses.js
import { Tab, TabItem,XImg,dateFormat,XButton,Flexbox, FlexboxItem,InlineCalendar,Popup,XDialog} from 'vux';

  let cnM=['一','二','三','四','五','六','七','八','九','十','十一','十二'];

  // 获取一周的日期
  // 获取当前星期的星期一的日期,返回的是一个Date对象。
  function getMonDate(dd){    //config为日期 例如:2016-04-19
      let d=new Date(dd);
      let day=d.getDay();
      let date=d.getDate();
      if(day==1)
      return d;
      if(day==0)
      d.setDate(date-6);
      else
      d.setDate(date-day+1);
      return d;
  }

  //获取一周的日期;
  function getWeekDate(self,confg){
      let d=getMonDate(confg);
      let wkd=new Date(confg).getDay();
      self.selectIndex=wkd==0?6:wkd-1
      for(var i=0;i<7;i++){
          self.dateList[i].date = d.getDate();
          self.dateList[i].configDate=dateFormat(new Date(d), 'YYYY-MM-DD');
          d.setDate(d.getDate()+1);
     }
  }

  export default {
    mounted() {
      this.$store.commit('UPDATE_PAGE_TITLE', '团体课')
      getWeekDate(this,this.myd);  //加载一周数据
      this.loadCourses();    //加载课程列表
    },
    data(){
      let self=this;
      let data={
        showSuccess:false,
        showSorry:false,
        calendarDate:"",
          dateList :[
            {week:'周一',date:'',configDate:'',limit:false},
            {week:'周二',date:'',configDate:'',limit:false},
            {week:'周三',date:'',configDate:'',limit:false},
            {week:'周四',date:'',configDate:'',limit:false},
            {week:'周五',date:'',configDate:'',limit:false},
            {week:'周六',date:'',configDate:'',limit:false},
            {week:'周日',date:'',configDate:'',limit:false}
          ],

           myd:dateFormat(new Date(), 'YYYY-MM-DD'),
           pickMonth:cnM[new Date().getMonth()],
           pickDate:new Date().getDate(),
           selectIndex:null,
           courseList:'',
           showCategory:false,
           showPurpose:false,
           showCalendar:false,
           categoryList:[
             {name:'全部',id:'1009'},
             {name:'减肥',id:'1009'},
             {name:'增肌',id:'1009'}
           ],
          purposeList:[
             {name:'全部',id:'1009'},
             {name:'健身操',id:'1009'},
             {name:'瑜伽',id:'1009'},
             {name:'动感单车',id:'1009'}
          ],
          weeksList:['日','一','二','三','四','五','六'],
          coursesQueryData:{
              categoryId:"ioio",
              date:dateFormat(new Date(), 'YYYY-MM-DD'),
              purposeId:'yuyuy',
              categoryName:"全部",
              purposeName:"全部"
           }


       }

      return data
    },
    methods:{

      // 获取团体课列表
      loadCourses(){
          let self=this;
          //与后端交互获取数据
          this.baseAjax({
            url:'../../../static/basicData/groupCourse.json',
            params:{
              categoryId:self.coursesQueryData.categoryId,
              date:self.coursesQueryData.date,
              purposeId:self.coursesQueryData.purposeId,
            },
            showLoading:true,
            success:function(data){
              console.log(data)
                self.courseList=data.returnObject;
                self.computListBar()
            }
          })
      },
      //选择日期
      calendarChange(date){
          if(date==this.coursesQueryData.date) return;
          getWeekDate(this,date);
          this.coursesQueryData.date=date;
          this.showCalendar=false;
          this.loadCourses();
      },

      //头部参课人数
      computListBar(){
          var self=this;
          var len=self.courseList.length;
          for(var i=0;i<len;i++){
              var widthNo=(self.courseList[i].reservation/self.courseList[i].personMax).toFixed(2);
              self.courseList[i].barWidth=widthNo*100+"%";
                if(widthNo<=0.5) {
                  self.courseList[i].bgColor="#4FCC51"
                }else if(widthNo>0.5 && widthNo!=1) {
                  self.courseList[i].bgColor="#E16F34";
                }else if(widthNo==1){
                  self.courseList[i].bgColor="#DD5858";
                }
            }
      },

      //日期点击事件
      dateHandler(idx){
        this.selectIndex=idx;
        this.coursesQueryData.date=this.dateList[idx].configDate;
        this.loadCourses();
      },

      //打开日期控件
      openCalendar(){
        this.showCalendar=true;
      },
      //预定团体课程
      makeReserve(id,idx){
        let self=this;
        if(self.courseList[idx].reservation==self.courseList[idx].personMax){
          self.showSorry=true;
          return;
        }
          this.baseAjax({
            url:'../../../static/basicData/makeReserve.json',
            get:"post",
            params:{
              courseId:id,
              memberId:"111"
            },
            showLoading:true,
            success:function(data){
              if(data.isSuccess){
                  self.courseList[idx].reservation=self.courseList[idx].reservation+1;
                  self.showSuccess=true;
                  self.computListBar();
              }
            }
          })
      },
      //目的筛选课程
      queryByPurpose(item){
        this.showCategory=false;
        this.showPurpose=false;
        this.coursesQueryData.purposeId=item.id;
        this.coursesQueryData.purposeName=item.name;
        this.loadCourses();
      },
      //类别筛选课程
      queryByCategory(item){
        this.showCategory=false;
        this.showPurpose=false;
        this.coursesQueryData.categoryId=item.id;
        this.coursesQueryData.categoryName=item.name;
        this.loadCourses();
      }
    },
    components: {
      Tab,TabItem,XImg,XButton,Flexbox, FlexboxItem,InlineCalendar,Popup,XDialog
    }
  }

表白这位小姐姐,爱你呀谢谢你无私分享的精神鸭

原文地址:https://www.cnblogs.com/smart-girl/p/10819272.html