学员端小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
11 KiB

11 months ago
10 months ago
11 months ago
10 months ago
10 months ago
11 months ago
10 months ago
11 months ago
10 months ago
10 months ago
11 months ago
10 months ago
11 months ago
10 months ago
10 months ago
11 months ago
10 months ago
11 months ago
10 months ago
11 months ago
11 months ago
11 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
11 months ago
  1. <template>
  2. <view class="step1">
  3. <view class="card">
  4. <view class="dateBox">
  5. <view class="month-row">
  6. <view class="month" @click="show=true">{{ currentMonth }}</view>
  7. <view class="arrow">
  8. <u-icon name="arrow-down" :size="12" :color="'#1989FA'"></u-icon>
  9. </view>
  10. </view>
  11. <view class="date_row">
  12. <view class="icon left" @click="changeDateIndex(-1)">
  13. <u-icon name="arrow-left" :size="12" :color="'#fff'"></u-icon>
  14. </view>
  15. <view class="dateArr" >
  16. <view class="dateWidth" v-for="(item,index) in dateArr[currentDay]" :key="index" @click="chooseDate(item)" >
  17. <u-transition :show="true" mode="fade">
  18. <view class="transition">
  19. <view class="date" :class="{active: chooseDay==item.date}">
  20. <!-- <view class="dian"></view> -->
  21. <view class="week">{{ item.week }}</view>
  22. <view class="num">{{ item.num }}</view>
  23. </view>
  24. </view>
  25. </u-transition>
  26. </view>
  27. </view>
  28. <view class="icon right" @click="changeDateIndex(1)">
  29. <u-icon name="arrow-right" :size="12" :color="'#fff'"></u-icon>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. <view class="card" >
  35. <view class="timeCon" v-if="timerArr.length||timerArr2.length">
  36. <view class="h2" v-if="timerArr.length">上午</view>
  37. <view class="time_box">
  38. <view class="time_item" v-for="(item,index) in timerArr" :key="index" @click="chooseCourse(item)" :class="{active: (FormData.courseArr.findIndex(val=>val.id==item.id))!=-1, disable: item.status!=0}" >
  39. <!-- <view class="flex" v-if="item.status==0">
  40. <view class="lab">{{ item.appointmentAlreadyCount ||0 }} <text>/</text> {{ item.appointmentSumCount}} </view>
  41. <view class="iconArrowBg" v-if="item.appointmentAlreadyCount">
  42. <u-icon name="arrow-right" :size="10" :color="'#fff'"></u-icon>
  43. </view>
  44. </view> -->
  45. <view class="lab" >{{ statusTxt[item.status] }}</view>
  46. <view class="time">{{ item.classTime }}</view>
  47. </view>
  48. </view>
  49. <view class="h2" v-if="timerArr2.length">下午</view>
  50. <view class="time_box">
  51. <view class="time_item" v-for="(item,index) in timerArr2" :key="index" @click="chooseCourse(item)" :class="{active: (FormData.courseArr.findIndex(val=>val.id==item.id))!=-1, disable: item.status!=0}">
  52. <!-- <view class="flex" v-if="item.status==0">
  53. <view class="lab">{{ item.appointmentAlreadyCount ||0 }} <text>/</text> {{ item.appointmentSumCount}} </view>
  54. <view class="iconArrowBg" v-if="item.appointmentAlreadyCount">
  55. <u-icon name="arrow-right" :size="10" :color="'#fff'"></u-icon>
  56. </view>
  57. </view> -->
  58. <view class="lab" >{{ statusTxt[item.status] }}</view>
  59. <view class="time">{{ item.classTime }}</view>
  60. </view>
  61. </view>
  62. </view>
  63. <view class="card" v-if="!timerArr2.length&&!timerArr.length" style="padding: 0 0 60rpx 0;">
  64. <nodata>暂无预约排课</nodata>
  65. </view>
  66. </view>
  67. <u-datetime-picker
  68. :show="show"
  69. v-model="chooseMonth"
  70. :minDate="minDate"
  71. :maxDate="maxDate"
  72. mode="year-month"
  73. @confirm="changeMonth"
  74. @cancel="show=false"
  75. ></u-datetime-picker>
  76. </view>
  77. </template>
  78. <script>
  79. import { getDates, getMonthsBetweenDates } from '@/config/utils.js'
  80. import { scheduleClass } from '@/config/api.js'
  81. export default {
  82. props: ['step', 'FormData'],
  83. data() {
  84. return {
  85. maxDate: 0,
  86. minDate: 0,
  87. monthArr: [],
  88. show: false,
  89. dateArr: [],
  90. currentDay: 0,//当前显示的日期组索引
  91. chooseDay: '',
  92. chooseMonth: '',
  93. timerArr: [],
  94. statusTxt: ['可预约', '未开放', '已过期', '已约满', '已约过'], //状态0、未过期 1、无排课,2、已过期,3已约满
  95. timerArr2: [],
  96. chooseTimerId: '',
  97. endDate: null,
  98. startDate: null,
  99. courseIds: '',
  100. radioVal: '',
  101. }
  102. },
  103. mounted() {
  104. this.initDate()
  105. },
  106. computed: {
  107. currentMonth() {
  108. let tiemr = new Date(this.chooseDay) * 1
  109. return this.$u.date(tiemr, 'yyyy.mm')
  110. }
  111. },
  112. watch: {
  113. courseIds: {
  114. handler(val) {
  115. let allTimer = [...this.timerArr,...this.timerArr2]
  116. let total = allTimer.reduce((pre, item)=>{
  117. if(item.status==1) {
  118. pre.push(item.classTime)
  119. }
  120. return pre
  121. },[])
  122. if(total.length==this.courseIds.length) {
  123. this.radioVal = 0
  124. }
  125. }
  126. }
  127. },
  128. methods: {
  129. // 获得排课
  130. async scheduleClassFn() {
  131. uni.showLoading({
  132. title: '正在加载...'
  133. })
  134. this.FormData.courseArr = []
  135. let obj = { "coachId": this.FormData.coachId, "trainType": this.FormData.trainType, "subject": this.FormData.subject, "classDate": this.chooseDay, "studentId": this.FormData.studentId}
  136. const {data: res} = await scheduleClass(obj)
  137. uni.hideLoading()
  138. this.timerArr2 = res.afternoonScheduleClass.sort((a,b)=>{
  139. return parseInt(a.classTime.slice(0,2)) - parseInt(b.classTime.slice(0,2))
  140. })
  141. this.timerArr = res.morningScheduleClass.sort((a,b)=>{
  142. return parseInt(a.classTime.slice(0,2)) - parseInt(b.classTime.slice(0,2))
  143. })
  144. // 如果是今天的日期检查有没有过期
  145. if(this.chooseDay==this.dateArr[0][0].date) {
  146. let arr = [...this.timerArr,...this.timerArr2]
  147. arr.forEach(item=>{
  148. let timer = new Date() * 1
  149. let date = this.chooseDay+' '+(item.classTime.split('-')[0])
  150. date = date.replace(/-/g,'/');
  151. let timer2 = new Date(date).getTime();
  152. if(timer>timer2) {
  153. item.status = 2
  154. }
  155. })
  156. }
  157. console.log(this.timerArr)
  158. },
  159. // 初始化日期
  160. async initDate() {
  161. this.startDate = this.$u.timeFormat(new Date()*1, 'yyyy-mm-dd');
  162. // 定义一个表示一个月的毫秒数
  163. this.minDate = new Date()*1
  164. const oneMonthMilliseconds = 30 * 24 * 60 * 60 * 1000;
  165. this.maxDate = this.endDate = this.minDate + oneMonthMilliseconds
  166. this.dateArr = getDates(this.startDate, this.endDate);
  167. this.chooseDay = this.dateArr[0][0].date
  168. console.log(this.dateArr)
  169. this.scheduleClassFn()
  170. },
  171. // 点击月份
  172. changeMonth(val) {
  173. let startDate = this.$u.date(val.value, 'yyyy-mm-dd')
  174. for(let i=0; i<this.dateArr.length; i++) {
  175. for(let j=0; j<this.dateArr[i].length; j++) {
  176. let date = this.dateArr[i][j].date
  177. if(startDate==date) {
  178. this.currentDay = i
  179. this.chooseDay = date
  180. }
  181. }
  182. }
  183. this.show = false
  184. },
  185. // 选择日期
  186. chooseDate(item) {
  187. this.chooseDay = item.date
  188. this.scheduleClassFn()
  189. // console.log('*****')
  190. // console.log(this.chooseDay)
  191. },
  192. changeDateIndex(num) {
  193. if(this.currentDay==0&&num==-1) return this.$u.toast('已是可选最小日期')
  194. if(this.currentDay==this.dateArr.length-1&&num==1) return this.$u.toast('已是可选最大日期')
  195. this.currentDay = this.currentDay + num
  196. this.chooseDay = this.dateArr[this.currentDay][0].date
  197. this.scheduleClassFn()
  198. },
  199. chooseCourse(item) {
  200. if(item.status!=0) return
  201. let index = this.FormData.courseArr.findIndex(val=>val.id==item.id)
  202. if( index==-1) {
  203. // 最大可预约次数
  204. let arr = [...this.timerArr,...this.timerArr2]
  205. let status4 = arr.reduce((p,v)=>{
  206. if(v.status==4) p++
  207. return p
  208. },0)
  209. if((status4+this.FormData.courseArr.length)>=4 ){
  210. this.$u.toast('一天最多能约四节课')
  211. }else {
  212. this.FormData.courseArr.push(item)
  213. // console.log(this.FormData.courseArr)
  214. this.$emit('updatedForm', this.FormData)
  215. }
  216. }else {
  217. this.FormData.courseArr.splice(index,1)
  218. this.$emit('updatedForm', this.FormData)
  219. }
  220. },
  221. }
  222. }
  223. </script>
  224. <style lang="scss" scoped>
  225. .card {
  226. width: 100%;
  227. margin-bottom: 24rpx;
  228. overflow: hidden;
  229. .dateBox {
  230. padding: 36rpx 0 40rpx 0;
  231. .month-row {
  232. display: flex;
  233. justify-content: center;
  234. align-items: center;
  235. margin-bottom: 36rpx;
  236. .month {
  237. font-size: 32rpx;
  238. color: $themC;
  239. }
  240. .arrow {
  241. margin-left: 6rpx;
  242. }
  243. }
  244. .date_row {
  245. width: 100%;
  246. height: 100rpx;
  247. position: relative;
  248. .icon {
  249. width: 40rpx;
  250. height: 40rpx;
  251. background: rgba(51,51,51,0.18);
  252. backdrop-filter: blur(4rpx);
  253. position: absolute;
  254. top: 50%;
  255. transform: translateY(-50%);
  256. display: flex;
  257. align-items: center;
  258. justify-content: center;
  259. border-radius: 50%;
  260. &.left {
  261. left: 16rpx;
  262. }
  263. &.right {
  264. right: 16rpx;
  265. }
  266. }
  267. .dateArr {
  268. display: flex;
  269. padding: 0 70rpx;
  270. // justify-content: space-between;
  271. &.oneDate {
  272. justify-content: center;
  273. }
  274. .dateWidth {
  275. width: 20%;
  276. display: flex;
  277. justify-content: center;
  278. }
  279. .date {
  280. width: 74rpx;
  281. height: 100rpx;
  282. border-radius: 16rpx;
  283. display: flex;
  284. flex-direction: column;
  285. align-items: center;
  286. justify-content: center;
  287. font-size: 28rpx;
  288. color: #333;
  289. .dian {
  290. width: 12rpx;
  291. height: 12rpx;
  292. background: #D8D8D8;
  293. border-radius: 50%;
  294. &.active {
  295. background: #1989FA;
  296. }
  297. }
  298. &.active {
  299. background: rgba(25,137,250,0.1);
  300. border: 2rpx solid #1989FA;
  301. color: $themC;
  302. }
  303. .week {
  304. }
  305. .num {
  306. margin-top: 4rpx;
  307. }
  308. }
  309. }
  310. }
  311. }
  312. }
  313. .card {
  314. .timeCon {
  315. padding: 0 24rpx 40rpx 24rpx;
  316. }
  317. .h2 {
  318. line-height: 90rpx;
  319. font-weight: 500;
  320. color: #333;
  321. }
  322. .time_box {
  323. display: flex;
  324. flex-wrap: wrap;
  325. justify-content: space-between;
  326. &::after{
  327. display:block;
  328. content:"";
  329. width: 32%;
  330. height:0px;
  331. }
  332. .time_item {
  333. width: 30%;
  334. height: 120rpx;
  335. background: #F8F8F8;
  336. border-radius: 12rpx;
  337. display: flex;
  338. flex-direction: column;
  339. justify-content: center;
  340. align-items: center;
  341. border-radius: 12rpx;
  342. margin-bottom: 20rpx;
  343. color: #333;
  344. &.active {
  345. background: rgba(25,137,250,0.1);
  346. border: 2rpx solid #1989FA;
  347. color: $themC;
  348. }
  349. &.disable {
  350. opacity: 0.4;
  351. }
  352. .lab {
  353. font-size: 28rpx;
  354. font-weight: 500;
  355. }
  356. .time {
  357. font-size: 24rpx;
  358. margin-top: 4rpx;
  359. }
  360. }
  361. }
  362. }
  363. .btn {
  364. width: 47%;
  365. height: 72rpx;
  366. background: #1989FA;
  367. border-radius: 8rpx;
  368. font-size: 28rpx;
  369. color: #fff;
  370. text-align: center;
  371. line-height: 72rpx;
  372. margin: 108rpx auto 50rpx auto;
  373. }
  374. .iconArrowBg {
  375. background: #D8D8D8;
  376. width: 26rpx;
  377. height: 26rpx;
  378. border-radius: 50%;
  379. display: flex;
  380. justify-content: center;
  381. align-items: center;
  382. margin-left: 4px;
  383. }
  384. .step2 {
  385. display: flex;
  386. justify-content: space-between;
  387. align-items: center;
  388. padding-bottom: 40px;
  389. .btnBg {
  390. width: 310rpx;
  391. }
  392. }
  393. </style>