program.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. <template>
  2. <div class="program">
  3. <van-cell-group class="van-cell-group--inset">
  4. <van-cell :title="vipGroup.name" class="titleContent" title-class="titleStyle" label-class="labelStyle">
  5. <template #label>
  6. <p>{{ vipGroup.description }}</p>
  7. <!-- <p>排课时间范围:{{ vipGroup.coursesStartTime }} 至 {{ vipGroup.coursesEndTime }}</p> -->
  8. </template>
  9. </van-cell>
  10. </van-cell-group>
  11. <h2 class="van-block__title">{{ typeStatus ? '付费' : '赠送' }}课程排课</h2>
  12. <van-cell-group>
  13. <van-field
  14. :value="typeStatus ? courseType[vipGroup.courseType] : courseType[vipGroup.giveCourseType]"
  15. label="课程类型"
  16. :readonly="true"
  17. input-align="right"
  18. size="large"
  19. placeholder="请选择"
  20. />
  21. <van-field
  22. :value="typeStatus ? vipGroup.vipGroupCategoryNames : vipGroup.giveCategoryName"
  23. label="课程形式"
  24. v-if="courseTypeIsVip"
  25. :readonly="true"
  26. input-align="right"
  27. size="large"
  28. placeholder="请选择"
  29. />
  30. <van-field
  31. v-model="formName.subjectListName"
  32. @click="onGetSheetList('subjectList')"
  33. label="排课声部"
  34. :readonly="true"
  35. input-align="right"
  36. is-link
  37. size="large"
  38. placeholder="请选择"
  39. />
  40. <van-field
  41. v-model="formName.educationalTeacherName"
  42. @click="onGetSheetList('teacherList')"
  43. label="乐团主管"
  44. :readonly="true"
  45. input-align="right"
  46. is-link
  47. size="large"
  48. placeholder="请选择"
  49. />
  50. </van-cell-group>
  51. <template v-if="studentList.length > 0">
  52. <h2 class="van-block__title">上课学员</h2>
  53. <van-cell-group>
  54. <van-cell title-style="flex: 1 auto; color: #1A1A1A;" size="large" v-for="(item, index) in studentList" :key="index">
  55. <template #title>
  56. {{ item.username }} - {{ item.phone }}
  57. </template>
  58. <template #default>
  59. <span @click="onDelete('student', item)"><van-icon name="delete-o" size=".14rem" /> <span style="font-size: .12rem;">删除</span></span>
  60. </template>
  61. </van-cell>
  62. </van-cell-group>
  63. </template>
  64. <div class="addButton" @click="studentStatus = true">
  65. <van-icon name="plus" /> 添加学员
  66. </div>
  67. <h2 class="van-block__title">课时组成</h2>
  68. <van-cell-group>
  69. <van-field
  70. v-if="statusList.hasOnline && teachMode == -1"
  71. v-model="form.onlineClassesNums"
  72. @keyup="onClassKeyUp"
  73. label="线上课次数"
  74. input-align="right"
  75. size="large"
  76. placeholder="请输入次数"
  77. type="number"
  78. />
  79. <van-field
  80. v-if="statusList.hasOffline && teachMode == -1"
  81. v-model="form.offlineClassesNums"
  82. @keyup="onClassKeyUp('offLine')"
  83. label="线下课次数"
  84. input-align="right"
  85. size="large"
  86. placeholder="请输入次数"
  87. type="number"
  88. />
  89. <van-field
  90. v-if="tempOfflineNum > 0"
  91. v-model="formName.teacherSchoolName"
  92. @click="onGetSheetList('teacherSchool')"
  93. label="线下课地址"
  94. :readonly="true"
  95. input-align="right"
  96. is-link
  97. size="large"
  98. placeholder="请选择"
  99. />
  100. <van-field
  101. :value="(form.studentNum || 0) + '人'"
  102. label="班级人数"
  103. :readonly="true"
  104. input-align="right"
  105. size="large"
  106. />
  107. <van-field
  108. :value="(form.singleClassMinutes || 0) + '分钟'"
  109. label="单课时时长"
  110. :readonly="true"
  111. input-align="right"
  112. size="large"
  113. />
  114. </van-cell-group>
  115. <h2 class="van-block__title">课时安排</h2>
  116. <van-cell-group>
  117. <van-cell
  118. title="最早排课时间"
  119. :readonly="true"
  120. v-if="vipGroup.coursesStartTime"
  121. input-align="right"
  122. size="large"
  123. value-class="showText"
  124. :value="vipGroup.coursesStartTime"
  125. >
  126. </van-cell>
  127. <van-cell
  128. title="最晚排课时间"
  129. :readonly="true"
  130. v-if="vipGroup.coursesEndTime"
  131. input-align="right"
  132. size="large"
  133. value-class="showText"
  134. :value="vipGroup.coursesEndTime"
  135. >
  136. </van-cell>
  137. <!-- 为了处理,付费网管课程 -->
  138. <!-- {{ !courseTypeIsVip && isLimitNum && typeStatus ? false : true }} -->
  139. <van-field
  140. v-model="form.totalClassTime"
  141. label="课时总数"
  142. :readonly="!courseTypeIsVip && !isLimitNum && typeStatus ? false : true"
  143. input-align="right"
  144. size="large"
  145. placeholder="请输入排课课时数"
  146. >
  147. <template #extra v-if="form.totalClassTime">
  148. <span style="color: #808080; font-size: 16px;">课时</span>
  149. </template>
  150. </van-field>
  151. <van-field
  152. v-model="form.courseStart"
  153. label="排课开始时间"
  154. :readonly="true"
  155. input-align="right"
  156. is-link
  157. size="large"
  158. placeholder="请选择"
  159. @click="dataForm.status = true"
  160. />
  161. </van-cell-group>
  162. <van-cell-group :border="false" style="margin-top: .1rem">
  163. <van-cell
  164. title-class="title-time"
  165. v-for="(item, index) in scheduleList"
  166. :key="index"
  167. >
  168. <template slot="title">
  169. <span class="online">{{ item.type }}</span>
  170. <span class="week">{{ item.weekStr }}</span>
  171. <span class="timer">{{ item.startTime + "~" + item.endTime }}</span>
  172. </template>
  173. <template slot="default">
  174. <span @click="onDelete('class', item)"><van-icon name="delete-o" size=".14rem" /> <span style="font-size: .12rem;">删除</span></span>
  175. </template>
  176. </van-cell>
  177. </van-cell-group>
  178. <div class="addButton" @click="teachingStatus = true">
  179. <van-icon name="plus" /> 添加课时安排
  180. </div>
  181. <van-cell-group>
  182. <van-field
  183. label="排课列表"
  184. v-if="scheduleList.length > 0"
  185. disabled
  186. input-align="right"
  187. @click="onShowTimeTable"
  188. is-link
  189. size="large"
  190. />
  191. </van-cell-group>
  192. <div class="button-group">
  193. <van-button type="primary" @click="onSubmit" round size="large">确认</van-button>
  194. </div>
  195. <!-- 选择上课学员 -->
  196. <van-popup
  197. v-model="studentStatus"
  198. :lock-scroll="true"
  199. position="bottom"
  200. :style="{ height: '80%' }"
  201. class="studentChose"
  202. >
  203. <student-list
  204. @close="studentStatus = false"
  205. :studentList="studentList"
  206. :activityId="activityId"
  207. :studentNum="form.studentNum"
  208. :courseTypeIsVip="courseTypeIsVip"
  209. :typeStatus="typeStatus"
  210. @submit="onSelectStudent" />
  211. </van-popup>
  212. <!-- 排课开始时间 -->
  213. <van-popup v-model="dataForm.status" position="bottom">
  214. <van-datetime-picker
  215. v-model="dataForm.currentDate"
  216. type="date"
  217. :min-date="dataForm.minDate"
  218. :max-date="dataForm.maxDate"
  219. :formatter="formatter"
  220. @cancel="dataForm.status = false"
  221. @confirm="onCurrentConfirm"
  222. />
  223. </van-popup>
  224. <!-- 课时安排 -->
  225. <van-popup v-model="teachingStatus" position="bottom">
  226. <course-modal :scheduleList="scheduleList" :singleClassMinutes="form.singleClassMinutes" @close="teachingStatus = false" />
  227. </van-popup>
  228. <van-popup v-model="sheetForm.sheetStatus" position="bottom">
  229. <van-picker
  230. :loading="sheetForm.loading"
  231. :default-index="sheetForm.index"
  232. :columns="sheetForm.columns"
  233. show-toolbar
  234. @cancel="sheetForm.sheetStatus = false"
  235. @confirm="onSheetConfirm"
  236. />
  237. </van-popup>
  238. <!-- 课表展示 -->
  239. <van-popup v-model="statusList.classTime" position="bottom" >
  240. <van-row>
  241. <van-col span="12">上课类型</van-col>
  242. <van-col span="12">上课时间</van-col>
  243. </van-row>
  244. <div class="tableContainer">
  245. <van-row v-for="(item, index) in timeTable" :key="index">
  246. <van-col span="12">
  247. {{ item.teachMode == "ONLINE" ? "线上" : "线下" }}
  248. </van-col>
  249. <van-col span="12">
  250. {{ item.classDate }} {{ item.startClassTimeStr }}
  251. </van-col>
  252. </van-row>
  253. </div>
  254. </van-popup>
  255. </div>
  256. </template>
  257. <script>
  258. import dayjs from 'dayjs'
  259. import studentList from './modal/studentList'
  260. import courseModal from './modal/course'
  261. import { courseType } from '../../constant'
  262. import { getActivityWaitCourseStudentNum, createVipGroup, createPracticeGroup } from './api'
  263. import { findSubSubjects, findEducationUsers, findVipSchoolByTeacher2 } from "@/api/teacher";
  264. export default {
  265. components: { studentList, courseModal },
  266. data() {
  267. const query = this.$route.query
  268. return {
  269. courseType,
  270. type: query.type,
  271. activityId: query.activityId,
  272. vipDetail: {},
  273. vipGroup: {},
  274. studentStatus: false,
  275. studentList: [],
  276. checkboxSelectIds: [],
  277. teachMode: null, // -1:所有;0:线上;1:线下"
  278. sheetForm: {
  279. // 上拉弹窗
  280. currentType: null, // 当前选择的类型
  281. sheetStatus: false,
  282. loading: true, // 加载数据
  283. index: 0, // 选中的索引值
  284. columns: [],
  285. },
  286. timeTable: [], // 生成的课表
  287. loadData: {
  288. // 下拉加载数据
  289. subjectList: [], // 声部列表
  290. teacherList: [],
  291. teacherSchool: [], // 线下课地址
  292. },
  293. tempOfflineNum: 0, // 临时存放线下课次数
  294. form: {
  295. vipGroupCategoryId: null,
  296. subjectIdList: null,
  297. educationalTeacherId: null,
  298. singleClassMinutes: null,
  299. onlineClassesNums: null,
  300. offlineClassesNums: null,
  301. totalClassTime: null, // 总课时数
  302. studentNum: null, // 每班人数
  303. courseStart: null, // 排课开始时间
  304. teacherSchoolId: null,
  305. vipGroupActivityId: query.activityId,
  306. },
  307. formName: {
  308. vipGroupCategoryId: null,
  309. subjectListName: null,
  310. subjectListIndex: 0, // 声部名称
  311. educationalTeacherName: null, // 乐团主管
  312. educationalTeacherIndex: 0,
  313. teacherSchoolName: null,
  314. teacherSchoolIndex: 0, // 线下课地址
  315. },
  316. statusList: {
  317. hasOnline: false, // 是否显示线上
  318. hasOffline: false, // 是否显示线下
  319. classTime: false, // 查看排课列表
  320. },
  321. scheduleList: [],
  322. // 排课弹窗
  323. teachingStatus: false, // 课时安排状态
  324. dataForm: {
  325. // 时间下拉框
  326. status: false,
  327. minDate: new Date(),
  328. maxDate: new Date(2035, 10, 1),
  329. currentDate: new Date(),
  330. },
  331. }
  332. },
  333. computed: {
  334. typeStatus() { // 是否是付费课程
  335. return this.type == 'pay' ? true : false
  336. },
  337. courseTypeIsVip() { // 目前只有两种课程,VIP 网管课,则可以这样判断
  338. const type = this.typeStatus ? this.vipGroup.courseType : this.vipGroup.giveCourseType
  339. return type == 'VIP' ? true : false
  340. },
  341. isLimitNum() { // 是否限制排课
  342. return this.vipGroup.minCourseNum > 0 ? true : false
  343. }
  344. },
  345. mounted() {
  346. this.__init()
  347. },
  348. methods: {
  349. async __init() {
  350. try {
  351. let res = await getActivityWaitCourseStudentNum({ activityId: this.activityId })
  352. this.vipDetail = res.data
  353. let vipGroup = res.data.vipGroupActivity
  354. vipGroup.coursesStartTime = vipGroup.coursesStartTime ? dayjs(vipGroup.coursesStartTime).format('YYYY-MM-DD') : null
  355. vipGroup.coursesEndTime = vipGroup.coursesEndTime ? dayjs(vipGroup.coursesEndTime).format('YYYY-MM-DD') : null
  356. this.vipGroup = vipGroup
  357. let form = this.form
  358. // 课程形式
  359. form.vipGroupCategoryId = this.typeStatus ? vipGroup.vipGroupCategoryIdList : vipGroup.giveCategoryId
  360. // 单课时长
  361. form.singleClassMinutes = this.typeStatus ? vipGroup.singleCourseTime : vipGroup.giveSingleCourseTime
  362. if(this.courseTypeIsVip) {
  363. // 每班人数
  364. form.studentNum = this.typeStatus ? vipGroup.vipGroupCategoryNum : vipGroup.giveCategoryNum
  365. this.statusList.hasOnline = this.typeStatus ? this.formatStatus('online', vipGroup.teachMode) : this.formatStatus('online', vipGroup.giveTeachMode)
  366. this.statusList.hasOffline = this.typeStatus ? this.formatStatus('offline', vipGroup.teachMode) : this.formatStatus('online', vipGroup.giveTeachMode)
  367. } else {
  368. form.totalClassTime = null
  369. form.studentNum = 1
  370. this.statusList.hasOnLine = false
  371. this.statusList.hasOffLine = false
  372. }
  373. if(this.isLimitNum || !this.typeStatus) { // 是否限制了排课
  374. // 排课次数,活动排课没有范围一说,最大次数和最小次数必须一致
  375. form.totalClassTime = this.typeStatus ? vipGroup.minCourseNum : vipGroup.giveCourseNum
  376. }
  377. // 如果
  378. if(this.teachMode == 0) {
  379. form.onlineClassesNums = form.totalClassTime || 0
  380. form.offlineClassesNums = 0
  381. } else if(this.teachMode == 1) {
  382. form.onlineClassesNums = 0
  383. form.offlineClassesNums = form.totalClassTime || 0
  384. this.tempOfflineNum = form.totalClassTime || 0
  385. }
  386. } catch {
  387. //
  388. }
  389. },
  390. onGetSheetList(name) {
  391. // 获取科目列表
  392. let sheetForm = this.sheetForm;
  393. sheetForm.columns = [];
  394. sheetForm.sheetStatus = true;
  395. sheetForm.loading = true;
  396. sheetForm.currentType = name;
  397. sheetForm.index = 0;
  398. let arr = this.loadData[name];
  399. if (arr.length > 0) {
  400. sheetForm.columns = arr;
  401. sheetForm.index = this.formName[name + "Index"];
  402. sheetForm.loading = false;
  403. } else {
  404. this.onLoadingData(name);
  405. }
  406. },
  407. onLoadingData() {
  408. // 加载数据
  409. let sheetForm = this.sheetForm;
  410. if (sheetForm.currentType == "subjectList") {
  411. // 声部列表
  412. findSubSubjects().then((res) => {
  413. let result = res.data;
  414. if (result.code == 200 && result.data.length > 0) {
  415. let tempArr = [];
  416. result.data.forEach((item) => {
  417. item.value = item.id;
  418. item.text = item.name;
  419. tempArr.push(item);
  420. });
  421. this.loadData.subjectList = tempArr;
  422. sheetForm.columns = tempArr;
  423. sheetForm.loading = false;
  424. } else {
  425. this.$toast("暂无科目列表");
  426. sheetForm.loading = false;
  427. }
  428. });
  429. } else if (sheetForm.currentType == "teacherSchool") {
  430. // 教师教学点
  431. findVipSchoolByTeacher2().then((res) => {
  432. let result = res.data;
  433. if (result.code == 200 && result.data.length > 0) {
  434. let tempArr = [];
  435. result.data.forEach((item) => {
  436. item.value = item.id;
  437. item.text = item.name;
  438. tempArr.push(item);
  439. });
  440. this.loadData.teacherSchool = tempArr;
  441. sheetForm.columns = tempArr;
  442. sheetForm.loading = false;
  443. } else {
  444. this.$toast("暂无教学点");
  445. sheetForm.loading = false;
  446. }
  447. });
  448. } else if (sheetForm.currentType == "teacherList") {
  449. // 乐团主管
  450. findEducationUsers().then((res) => {
  451. let result = res.data;
  452. if (result.code == 200 && result.data.length > 0) {
  453. let tempArr = [];
  454. result.data.forEach((item) => {
  455. item.value = item.userId;
  456. item.text = item.userName;
  457. tempArr.push(item);
  458. });
  459. this.loadData.teacherList = tempArr;
  460. sheetForm.columns = tempArr;
  461. sheetForm.loading = false;
  462. } else {
  463. this.$toast("暂无乐团主管");
  464. sheetForm.loading = false;
  465. }
  466. });
  467. }
  468. },
  469. onSheetConfirm(value, index) {
  470. // 上拉弹窗
  471. let sheetForm = this.sheetForm,
  472. form = this.form,
  473. formName = this.formName
  474. if (sheetForm.currentType == "subjectList") {
  475. // 科目名称赋值
  476. form.subjectIdList = value.value;
  477. formName.subjectListName = value.text;
  478. formName.subjectListIndex = index;
  479. } else if (sheetForm.currentType == "teacherSchool") {
  480. // 线下课地址
  481. form.teacherSchoolId = value.value;
  482. formName.teacherSchoolName = value.text;
  483. formName.teacherSchoolIndex = index;
  484. } else if (sheetForm.currentType == "teacherList") {
  485. // 乐团主管
  486. form.educationalTeacherId = value.value;
  487. formName.educationalTeacherName = value.text;
  488. formName.educationalTeacherIndex = index;
  489. }
  490. sheetForm.sheetStatus = false;
  491. },
  492. async onSubmit() {
  493. // 次数限制是否可以继续创建
  494. let form = this.form;
  495. let statusList = this.statusList;
  496. if (!form.subjectIdList) {
  497. this.$toast("请选择排课声部");
  498. return false;
  499. }
  500. if (!form.educationalTeacherId) {
  501. this.$toast("请选择乐团主管");
  502. return;
  503. }
  504. if (this.checkboxSelectIds.length <= 0) {
  505. this.$toast("请选择上课学员");
  506. return;
  507. }
  508. let onlineClassesStatus = !form.onlineClassesNums && form.onlineClassesNums <= 0 ? true : false;
  509. let offlineClassesStatus = !form.offlineClassesNums && form.offlineClassesNums <= 0 ? true : false;
  510. if (statusList.hasOnline && onlineClassesStatus) {
  511. this.$toast("请输入线上课次数");
  512. return false;
  513. }
  514. if (statusList.hasOffline) {
  515. if (offlineClassesStatus) {
  516. this.$toast("请输入线下课次数");
  517. return false;
  518. }
  519. // 判断是否有线下
  520. if (form.offlineClassesNums > 0 && !form.teacherSchoolId) {
  521. this.$toast("请选择线下课地址");
  522. return false;
  523. }
  524. }
  525. if (this.scheduleList.length <= 0) {
  526. this.$toast("课时安排不能为空");
  527. return false;
  528. }
  529. if (!this.checkCourseList()) {
  530. return;
  531. }
  532. // 排课
  533. this.setTimeTable();
  534. form.studentIdList = this.checkboxSelectIds.join(",");
  535. form.firstStudentId = this.studentList.length > 0 ? this.studentList[0].userId : null;
  536. form.onlineClassesNum = Number(form.onlineClassesNums);
  537. form.offlineClassesNum = Number(form.offlineClassesNums);
  538. let params = {
  539. courseSchedules: this.timeTable
  540. }
  541. if(this.courseTypeIsVip) {
  542. params.vipGroupApplyBaseInfo = form
  543. params.giveFlag = !this.typeStatus
  544. await this.onPayVip(params)
  545. } else {
  546. params.practiceGroupApplyBaseInfoDto = form
  547. params.practiceGroupApplyBaseInfoDto.studentId = form.studentIdList
  548. params.practiceGroupApplyBaseInfoDto.allCourseNum = form.totalClassTime
  549. params.practiceGroupApplyBaseInfoDto.subjectId = form.subjectIdList
  550. params.giveFlag = !this.typeStatus
  551. await this.onPayPractice(params)
  552. }
  553. },
  554. async onPayVip(params) {
  555. try {
  556. await createVipGroup(params)
  557. this.$toast("排课成功");
  558. setTimeout(() => {
  559. this.$router.back()
  560. }, 1000);
  561. } catch {
  562. //
  563. }
  564. },
  565. async onPayPractice(params) {
  566. try {
  567. await createPracticeGroup(params)
  568. this.$toast("排课成功");
  569. setTimeout(() => {
  570. this.$router.back()
  571. }, 1000);
  572. } catch {
  573. //
  574. }
  575. },
  576. onSelectStudent(items) {
  577. // 选中的数据
  578. const tempItems = items || []
  579. this.studentList = tempItems
  580. // if(tempItems.length <= 0) { // 判断是否有选择学员
  581. this.checkboxSelectIds = []
  582. // }
  583. tempItems.forEach(item => {
  584. this.checkboxSelectIds.push(item.userId)
  585. })
  586. this.studentStatus = false
  587. },
  588. onDelete(type, item) {
  589. if(type == 'student') {
  590. // 删除上课学员
  591. this.$dialog.confirm({
  592. title: '提示',
  593. message: '是否删除该学员?',
  594. confirmButtonText: '确定',
  595. confirmButtonColor: '#269a93',
  596. cancelButtonText: '取消'
  597. }).then(() => {
  598. let index = this.studentList.indexOf(item);
  599. if (index !== -1) {
  600. this.studentList.splice(index, 1);
  601. }
  602. })
  603. } else if(type == 'class') {
  604. // 删除上课学员
  605. this.$dialog.confirm({
  606. title: '提示',
  607. message: '是否删除该课时安排?',
  608. confirmButtonText: '确定',
  609. confirmButtonColor: '#269a93',
  610. cancelButtonText: '取消'
  611. }).then(() => {
  612. let index = this.scheduleList.indexOf(item);
  613. if (index !== -1) {
  614. this.scheduleList.splice(index, 1);
  615. }
  616. })
  617. }
  618. },
  619. onCurrentConfirm(value) {
  620. // 排课开始时间
  621. this.form.courseStart = dayjs(value).format('YYYY-MM-DD')
  622. this.dataForm.status = false;
  623. },
  624. onClassKeyUp(type) {
  625. // 线上课&线下课修改时
  626. if(this.teachMode != -1) return
  627. let form = this.form
  628. let onlineNum = form.onlineClassesNums
  629. let offLineNum = form.offlineClassesNums
  630. // 重置次数,不能
  631. if(parseInt(onlineNum || 0) + parseInt(offLineNum || 0) >= form.totalClassTime) {
  632. if(type == 'offLine') {
  633. let diffNum = form.totalClassTime - parseInt(onlineNum || 0)
  634. offLineNum = diffNum < 0 ? 0 : diffNum
  635. } else {
  636. let diffNum = form.totalClassTime - parseInt(offLineNum || 0)
  637. onlineNum = diffNum < 0 ? 0 : diffNum
  638. }
  639. }
  640. this.form.onlineClassesNums = onlineNum
  641. this.form.offlineClassesNums = offLineNum
  642. this.tempOfflineNum = offLineNum || 0
  643. },
  644. onShowTimeTable() {
  645. // 显示排课列表
  646. if (!this.checkCourseList()) {
  647. return;
  648. }
  649. this.statusList.classTime = true;
  650. this.setTimeTable();
  651. },
  652. setTimeTable() {
  653. if (!this.checkCourseList(false)) {
  654. return;
  655. }
  656. // 重置排课列表
  657. this.timeTable = [];
  658. let form = this.form,
  659. scheduleList = this.scheduleList;
  660. // 拿到线上课数与线下课数 以及
  661. let online = parseInt(
  662. form.onlineClassesNums ? form.onlineClassesNums : 0
  663. );
  664. let offline = parseInt(
  665. form.offlineClassesNums ? form.offlineClassesNums : 0
  666. );
  667. // 网管课默认只有线上课次
  668. if(!this.courseTypeIsVip) {
  669. online = parseInt(form.totalClassTime || 0)
  670. }
  671. // 判断是否有课程安排
  672. if (scheduleList.length <= 0) {
  673. return;
  674. }
  675. let totalCount = Number(online) + Number(offline);
  676. let tempCourseStart = form.courseStart.replace(/-/gi, "/");
  677. let dateOperation = new Date(tempCourseStart);
  678. let forMark = 0;
  679. while (totalCount && totalCount > 0) {
  680. for (let i = 0; i < scheduleList.length; i++) {
  681. if (online == 0 && offline == 0) break;
  682. let num = scheduleList[i].weekIndex - dateOperation.getDay();
  683. // 如果是同一天一个周期会出现排课都排到一天
  684. if (forMark > 0 && num == 0 && i == 0) {
  685. num = num + 7;
  686. }
  687. if (num < 0) {
  688. // 如果为负数则为下周
  689. num = num + 7;
  690. }
  691. let dataStr = this.getThinkDate(dateOperation, num);
  692. // 判断是否大于当前时间
  693. let nowGetTime = new Date().getTime();
  694. let courseTime = new Date(dataStr.replace(/-/gi, "/") +" " + scheduleList[i].startTime + ":00").getTime();
  695. if (nowGetTime < courseTime) {
  696. let tempArr = {
  697. classDate: dataStr,
  698. startClassTimeStr: scheduleList[i].startTime,
  699. endClassTimeStr: scheduleList[i].endTime,
  700. };
  701. // console.log(scheduleList[i].type, online, offline)
  702. if (scheduleList[i].type == "线上" && online > 0) {
  703. tempArr.teachMode = "ONLINE";
  704. this.timeTable.push(tempArr);
  705. online--;
  706. totalCount--;
  707. } else if (scheduleList[i].type == "线下" && offline > 0) {
  708. tempArr.teachMode = "OFFLINE";
  709. this.timeTable.push(tempArr);
  710. offline--;
  711. totalCount--;
  712. }
  713. }
  714. }
  715. // 加一周
  716. if (scheduleList.length == 1) {
  717. dateOperation.setDate(dateOperation.getDate() + 7);
  718. } else if (
  719. scheduleList.every((item) => item.weekStr === scheduleList[0].weekStr)
  720. ) {
  721. // 标记循环次数(标记判断课程安排是不是同一天)
  722. forMark++;
  723. }
  724. }
  725. this.timeTable.sort((a, b) => {
  726. let aStr = dayjs(dayjs(a.classDate).format("YYYY-MM-DD") + " " + a.startClassTimeStr + ":00").valueOf();
  727. let bStr = dayjs(dayjs(b.classDate).format("YYYY-MM-DD") + " " + b.startClassTimeStr + ":00").valueOf();
  728. return aStr - bStr;
  729. });
  730. },
  731. getThinkDate(date, num) {
  732. let Stamp = date;
  733. Stamp.setDate(date.getDate() + num); // 获取当前月数的第几天
  734. return dayjs(Stamp).format('YYYY-MM-DD')
  735. },
  736. checkCourseList(isShowToast = true) {
  737. let form = this.form;
  738. let scheduleList = this.scheduleList || [];
  739. let hasOnLine = false; // 是否有线上课时安排
  740. let hasOffLine = false;
  741. scheduleList.forEach((item) => {
  742. if (item.type == "线上") {
  743. hasOnLine = true;
  744. }
  745. if (item.type == "线下") {
  746. hasOffLine = true;
  747. }
  748. });
  749. let statusList = this.statusList;
  750. let onlineClassesStatus = !form.onlineClassesNums && form.onlineClassesNums <= 0 ? true : false;
  751. let offlineClassesStatus = !form.offlineClassesNums && form.offlineClassesNums <= 0 ? true : false;
  752. if (statusList.hasOnline) {
  753. if (onlineClassesStatus) {
  754. if (isShowToast) {
  755. this.$toast("请输入线上课次数");
  756. }
  757. return false;
  758. }
  759. if (!onlineClassesStatus && !hasOnLine && form.onlineClassesNums > 0) {
  760. if (isShowToast) {
  761. this.$toast("课时安排缺少线上课类型");
  762. }
  763. return false;
  764. }
  765. }
  766. if (statusList.hasOffline) {
  767. if (offlineClassesStatus) {
  768. if (isShowToast) {
  769. this.$toast("请输入线下课次数");
  770. }
  771. return false;
  772. }
  773. if (
  774. !offlineClassesStatus &&
  775. !hasOffLine &&
  776. form.offlineClassesNums > 0
  777. ) {
  778. if (isShowToast) {
  779. this.$toast("课时安排缺少线下课类型");
  780. }
  781. return false;
  782. }
  783. }
  784. return true;
  785. },
  786. formatStatus(type, teachMode) {
  787. // -1:所有;0:线上;1:线下
  788. this.teachMode = teachMode
  789. if(type == 'online' && teachMode == 0) {
  790. return true
  791. } else if(type == 'offline' && teachMode == 1) {
  792. return true
  793. } else if(teachMode == -1) {
  794. return true
  795. } else {
  796. return false
  797. }
  798. },
  799. formatter(type, value) {
  800. if (type === "year") {
  801. return `${value}年`;
  802. } else if (type === "month") {
  803. return `${value}月`;
  804. } else if (type === "day") {
  805. return `${value}日`;
  806. }
  807. return value;
  808. },
  809. }
  810. }
  811. </script>
  812. <style lang="less" scoped>
  813. @import url("../../assets/commonLess/variable.less");
  814. .program {
  815. background-color: #F5F5F5;
  816. min-height: 100vh;
  817. overflow: hidden;
  818. }
  819. .van-cell-group--inset {
  820. margin: .12rem .12rem 0;
  821. overflow: hidden;
  822. border-radius: 8px;
  823. .titleContent {
  824. padding: .14rem .16rem;
  825. }
  826. .titleStyle {
  827. font-size: .2rem;
  828. color: #333333;
  829. font-size: 500;
  830. }
  831. .labelStyle {
  832. padding-top: .08rem;
  833. color: #666666;
  834. font-size: .13rem;
  835. line-height: .2rem;
  836. }
  837. }
  838. .van-row {
  839. line-height: 0.4rem;
  840. border-top: 1px solid #edeef0;
  841. text-align: center;
  842. font-size: 0.14rem;
  843. &:first-child {
  844. border-top: 0;
  845. background: #edeef0;
  846. color: #444;
  847. font-size: 0.15rem;
  848. }
  849. }
  850. .tableContainer {
  851. max-height: 2.44rem;
  852. overflow: auto;
  853. .van-row {
  854. color: #444;
  855. &:first-child {
  856. border-top: 0;
  857. background: #fff;
  858. font-size: 0.14rem;
  859. }
  860. }
  861. }
  862. .van-block__title {
  863. padding: .12rem .14rem .06rem;
  864. color: #808080;
  865. font-size: .14rem;
  866. line-height: .2rem;
  867. }
  868. .button-group {
  869. margin: 0.3rem 0.26rem 0.2rem;
  870. .van-button--primary {
  871. background: @mColor;
  872. border-color: @mColor;
  873. font-size: 0.18rem;
  874. }
  875. }
  876. .title-time {
  877. display: flex;
  878. align-items: center;
  879. flex: 1 auto;
  880. color: #1A1A1A;
  881. font-size: .16rem;
  882. .week {
  883. padding-left: 0.4rem;
  884. padding-right: 0.15rem;
  885. }
  886. }
  887. /deep/.studentChose {
  888. border-radius: .1rem .1rem 0px 0px;
  889. overflow: auto;
  890. background: #F5F5F5;
  891. }
  892. /deep/.van-field__label {
  893. color: #1A1A1A;
  894. }
  895. /deep/.van-field__control, .showText {
  896. font-size: 16px;
  897. color: #808080;
  898. }
  899. .addButton {
  900. margin: .1rem .28rem;
  901. border: 1px dashed #CFCFCF;
  902. line-height: .42rem;
  903. text-align: center;
  904. background: #FBFBFB;
  905. color: #666666;
  906. font-size: .14rem;
  907. border-radius: .05rem;
  908. }
  909. </style>