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;
width: 100%;
left: 0;
top: 0;
}
.memberHome .weui-tabbar__icon img{
width: 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;
width: 85%;
}s
.activityIndex .activeItem .title{
font-size: 18px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.activityIndex .time-line{
font-size: 14px;
width: 100%;
height: 20px;
}
.activityIndex .activeItem .view{
float: right;
font-size: 14px;
}
.activityIndex .activeItem .newsImg img{
width: 100%;
min-height: 180px;
}
.activityIndex .sbottom img{
width: 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{
width: 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{
width: 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;
width: 100%;
}
.personalCourses .activeItem .sbottom{
color: white;
position: absolute;
bottom: 10px;
padding:10px;
width: 85%
}
.personalCourses .activeItem .title{
font-size: 18px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.personalCourses .time-line{
font-size: 14px;
width: 100%;
height: 20px;
}
.personalCourses .activeItem .view{
float: right;
font-size: 14px;
}
.personalCourses .activeItem img{
width: 100%
}
.personalCourses .vux-tab .vux-tab-item.vux-tab-disabled {
color: #666;
}
.personalCourses .vux-tab .vux-tab-item.vux-tab-selected{
color:#DD5858;
border-width: 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{
width: 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 {
width: 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="{ width: 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{
width: 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;
width: 100%;
}
.groupCourses .activeItem .sbottom{
color: white;
position: absolute;
bottom: 10px;
padding:10px;
width: 85%
}
.groupCourses .activeItem .title{
font-size: 18px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.groupCourses .time-line{
font-size: 14px;
width: 100%;
height: 20px;
}
.groupCourses .activeItem .view{
float: right;
font-size: 14px;
}
.groupCourses .activeItem img{
width: 100%
}
.groupCourses .vux-tab .vux-tab-item.vux-tab-disabled {
color: #666;
}
.groupCourses .vux-tab .vux-tab-item.vux-tab-selected{
color:#DD5858;
border-width: 3px !important;
border-bottom: 3px solid #DD5858;
}
.groupCourses .bookBtn{
position: absolute;
bottom: 20px;
right: 20px;
}
.groupCourses button.weui-btn_mini{
width: 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{
width: 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;
width: 100%;
border-radius: 10px;
position: absolute;
height: 100%;
top: 0
}
.groupCourses .d-box .d-title{
margin-bottom:15px;
}
.groupCourses .d-box .weui-dialog{
max-width: 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
}
}
作者:jser_dimple
-------------------------------------------
个性签名:一个人在年轻的时候浪费自己的才华与天赋是一件非常可惜的事情
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
万水千山总是情,打赏5毛买辣条行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!
微信
支付宝