courseList.vue 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. <template>
  2. <div class="cl-container">
  3. <!-- 搜索类型 -->
  4. <save-form
  5. ref="searchForm"
  6. :inline="true"
  7. save-key="teamDetails-courseList"
  8. class="searchForm"
  9. :model="searchForm"
  10. @submit="search"
  11. @reset="onReSet"
  12. >
  13. <el-form-item prop="courseStatus">
  14. <el-select
  15. v-model.trim="searchForm.courseStatus"
  16. clearable
  17. filterable
  18. placeholder="课程类型"
  19. >
  20. <el-option
  21. v-for="(item, index) in courseArray"
  22. :key="index"
  23. :label="item.label"
  24. :value="item.value"
  25. />
  26. </el-select>
  27. </el-form-item>
  28. <el-form-item prop="classStatus">
  29. <el-select
  30. v-model.trim="searchForm.classStatus"
  31. clearable
  32. filterable
  33. placeholder="课程状态"
  34. >
  35. <el-option label="未开始" value="NOT_START" />
  36. <el-option label="进行中" value="UNDERWAY" />
  37. <el-option label="已结束" value="OVER" />
  38. </el-select>
  39. </el-form-item>
  40. <el-form-item prop="class">
  41. <!-- getMusicGroupAllClass -->
  42. <el-select
  43. v-model.trim="searchForm.class"
  44. placeholder="班级名称"
  45. filterable
  46. clearable
  47. >
  48. <el-option
  49. v-for="(item, index) in classList"
  50. :key="index"
  51. :value="item.id"
  52. :label="item.name"
  53. />
  54. </el-select>
  55. </el-form-item>
  56. <el-form-item prop="isSettlement">
  57. <el-select
  58. v-model.trim="searchForm.isSettlement"
  59. placeholder="是否结算"
  60. filterable
  61. clearable
  62. >
  63. <el-option value="0" label="未结算" />
  64. <el-option value="1" label="已结算" />
  65. </el-select>
  66. </el-form-item>
  67. <el-form-item prop="homeworkFlag">
  68. <el-select
  69. v-model.trim="searchForm.homeworkFlag"
  70. placeholder="是否布置作业"
  71. filterable
  72. clearable
  73. >
  74. <el-option :value="false" label="未布置" />
  75. <el-option :value="true" label="已布置" />
  76. </el-select>
  77. </el-form-item>
  78. <el-form-item prop="serviceFlag">
  79. <el-select
  80. v-model.trim="searchForm.serviceFlag"
  81. placeholder="是否服务"
  82. filterable
  83. clearable
  84. >
  85. <el-option :value="true" label="是" />
  86. <el-option :value="false" label="否" />
  87. </el-select>
  88. </el-form-item>
  89. <el-form-item prop="timer">
  90. <el-date-picker
  91. v-model.trim="searchForm.timer"
  92. style="width: 420px"
  93. type="daterange"
  94. value-format="yyyy-MM-dd"
  95. range-separator="至"
  96. start-placeholder="课程开始日期"
  97. end-placeholder="课程结束日期"
  98. :picker-options="{
  99. firstDayOfWeek: 1
  100. }"
  101. />
  102. </el-form-item>
  103. <el-form-item>
  104. <el-button native-type="submit" type="danger">
  105. 搜索
  106. </el-button>
  107. <el-button type="primary" native-type="reset">
  108. 重置
  109. </el-button>
  110. <el-button
  111. v-if="permission('export/exportMusicGroupCourseScheduleDetail')"
  112. type="primary"
  113. @click="exportCourse"
  114. >
  115. 导出
  116. </el-button>
  117. </el-form-item>
  118. </save-form>
  119. <div class="btnWraps" style="margin-bottom:20px;">
  120. <el-button
  121. v-if="permission('courseScheduleConvert/action')"
  122. type="primary"
  123. @click="transCourse"
  124. >
  125. 课程转换
  126. </el-button>
  127. </div>
  128. <div style="font-size: 14px; padding-bottom: 10px">
  129. 总出勤率:<span style="color: #f85043; font-weight: 600">{{
  130. detail.attendanceRate
  131. }}</span>
  132. &nbsp;&nbsp;&nbsp;&nbsp;总达标率:<span
  133. style="color: #f85043; font-weight: 600"
  134. >{{ detail.standardRate }}</span
  135. >
  136. &nbsp;&nbsp;&nbsp;&nbsp; 总作业提交率:<span
  137. style="color: #f85043; font-weight: 600"
  138. >{{ detail.homeworkCommitRate }}</span
  139. >
  140. </div>
  141. <!-- 列表 -->
  142. <div class="tableWrap">
  143. <el-table
  144. :data="tableList"
  145. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  146. @selection-change="handleSelectionChange"
  147. >
  148. <el-table-column
  149. type="selection"
  150. width="55"
  151. :selectable="checkSelectable"
  152. />
  153. <el-table-column
  154. align="center"
  155. prop="courseScheduleId"
  156. label="课程编号"
  157. />
  158. <el-table-column align="center" width="180px" label="时间">
  159. <template slot-scope="scope">
  160. {{ scope.row.classDate }}
  161. {{
  162. scope.row.startClassTime
  163. ? scope.row.startClassTime.substr(0, 5)
  164. : ""
  165. }}-{{
  166. scope.row.endClassTime ? scope.row.endClassTime.substr(0, 5) : ""
  167. }}
  168. </template>
  169. </el-table-column>
  170. <el-table-column
  171. align="center"
  172. prop="courseScheduleName"
  173. label="课程名称"
  174. />
  175. <el-table-column
  176. align="center"
  177. prop="courseScheduleType"
  178. label="课程类型"
  179. >
  180. <template slot-scope="scope">
  181. <div>{{ scope.row.courseScheduleType | coursesType }}</div>
  182. </template>
  183. </el-table-column>
  184. <el-table-column
  185. align="center"
  186. prop="courseScheduleStatus"
  187. label="课程状态"
  188. >
  189. s
  190. <template slot-scope="scope">
  191. <div>{{ scope.row.courseScheduleStatus | coursesStatus }}</div>
  192. </template>
  193. </el-table-column>
  194. <el-table-column align="center" label="老师签到">
  195. <template slot-scope="scope">
  196. <div v-if="scope.row.courseScheduleStatus != 'NOT_START'">
  197. {{ scope.row.signInStatus | attendanceType }}
  198. </div>
  199. <span v-else>--</span>
  200. </template>
  201. </el-table-column>
  202. <el-table-column align="center" label="老师签退">
  203. <template slot-scope="scope">
  204. <div v-if="scope.row.courseScheduleStatus != 'NOT_START'">
  205. {{ scope.row.signOutStatus | attendanceOutType }}
  206. </div>
  207. <span v-else>--</span>
  208. </template>
  209. </el-table-column>
  210. <el-table-column
  211. align="center"
  212. prop="masterTeacherName"
  213. label="指导老师"
  214. />
  215. <!-- <el-table-column
  216. align="center"
  217. prop="teachingUserNames"
  218. label="助教老师"
  219. >
  220. <template slot-scope="scope">
  221. <copy-text>{{ scope.row.teachingUserNames }}</copy-text>
  222. </template>
  223. </el-table-column> -->
  224. <el-table-column align="center" label="结算状态">
  225. <template slot-scope="scope">
  226. {{ scope.row.settlementTime ? "已结算" : "未结算" }}
  227. </template>
  228. </el-table-column>
  229. <el-table-column align="center" prop="remark" label="是否点名">
  230. <template slot-scope="scope">
  231. <div v-if="scope.row.courseScheduleStatus != 'NOT_START'">
  232. {{ scope.row.isCallNames ? "已点名" : "未点名" }}
  233. </div>
  234. <span v-else>--</span>
  235. </template>
  236. </el-table-column>
  237. <el-table-column align="center" prop="attendanceRate" label="出勤率">
  238. <template slot-scope="scope">
  239. <div>
  240. {{
  241. scope.row.courseScheduleStatistics.attendanceRate &&
  242. scope.row.courseScheduleStatus == "OVER"
  243. ? scope.row.courseScheduleStatistics.attendanceRate
  244. : "--"
  245. }}
  246. </div>
  247. </template>
  248. </el-table-column>
  249. <el-table-column align="center" prop="standardRate" label="达标率">
  250. <template slot-scope="scope">
  251. <div>
  252. {{
  253. scope.row.courseScheduleStatistics.standardRate &&
  254. scope.row.courseScheduleStatus == "OVER"
  255. ? scope.row.courseScheduleStatistics.standardRate
  256. : "--"
  257. }}
  258. </div>
  259. </template>
  260. </el-table-column>
  261. <el-table-column align="center" prop="remark" label="是否服务">
  262. <template slot-scope="scope">
  263. <div>
  264. {{ scope.row.courseScheduleStatistics.serviceFlag ? "是" : "否" }}
  265. </div>
  266. </template>
  267. </el-table-column>
  268. <el-table-column align="center" prop="remark" label="是否布置课后作业">
  269. <template slot-scope="scope">
  270. <div>
  271. {{
  272. scope.row.courseScheduleStatistics.homeworkFlag
  273. ? "已布置"
  274. : "未布置"
  275. }}
  276. </div>
  277. </template>
  278. </el-table-column>
  279. <el-table-column align="center" prop="remark" label="作业提交率">
  280. <template slot-scope="scope">
  281. <div>
  282. {{
  283. scope.row.courseScheduleStatistics.homeworkCommitRate &&
  284. scope.row.courseScheduleStatistics.homeworkFlag
  285. ? scope.row.courseScheduleStatistics.homeworkCommitRate
  286. : "--"
  287. }}
  288. </div>
  289. </template>
  290. </el-table-column>
  291. <el-table-column align="center" prop="remark" label="备注" />
  292. <el-table-column
  293. align="center"
  294. width="280px"
  295. label="操作"
  296. fixed="right"
  297. >
  298. <template slot-scope="scope">
  299. <div>
  300. <!-- {child: 'teacherAttendance/updateTeacherAttendance', parent: '/teamDetails/courseList'} -->
  301. <el-button
  302. v-if="
  303. scope.row.courseScheduleStatus == 'OVER' &&
  304. !scope.row.settlementTime &&
  305. permission(
  306. 'teacherAttendance/updateTeacherAttendance?t=568'
  307. )
  308. "
  309. type="text"
  310. @click="onMarkAttendance(scope.row)"
  311. >
  312. 补考勤
  313. </el-button>
  314. <el-button
  315. v-if="
  316. scope.row.courseScheduleStatus == 'OVER' &&
  317. permission(
  318. 'studentAttendance/updateStudentAttendances?t=570'
  319. )
  320. "
  321. type="text"
  322. @click="onCallName(scope.row)"
  323. >
  324. 点名表
  325. </el-button>
  326. <!-- OVER -->
  327. <!-- <el-button
  328. v-if="scope.row.courseScheduleStatus == 'OVER' && permission('courseSchedule/classStartDateAdjust1')"
  329. type="text"
  330. @click="resetClass(scope.row)"
  331. >调整</el-button>-->
  332. <el-button
  333. v-if="
  334. !scope.row.settlementTime &&
  335. permission(
  336. 'courseSchedule/classStartDateAdjust/teamCourseListInfo'
  337. )
  338. "
  339. type="text"
  340. @click="resetClass(scope.row)"
  341. >
  342. 调整
  343. </el-button>
  344. <!-- <el-button v-if="scope.row.courseScheduleStatus == 'NOT_START' && permission('courseSchedule/batchDelete')"
  345. type="text"
  346. @click="removeSingleClass(scope.row)">删除</el-button> -->
  347. <!-- v-if="scope.row.courseScheduleStatus == 'NOT_START' && permission('courseSchedule/batchDelete')" teamDetail/resetTpye-->
  348. <!-- <el-button type="text"
  349. @click="resetType(scope.row)"
  350. v-if="permission('teamDetail/resetTpye')&&scope.row.courseScheduleType!='HIGH_ONLINE'&&scope.row.courseScheduleType!='MUSIC_NETWORK'">类型调整</el-button> -->
  351. <el-button
  352. v-if="
  353. scope.row.courseScheduleStatus == 'OVER' &&
  354. !scope.row.settlementTime &&
  355. permission(
  356. 'courseSchedule/cleanAttendancecourseSchedule/classStartDateAdjust/teamCourseListInfo'
  357. )
  358. "
  359. type="text"
  360. @click="clearAttend(scope.row)"
  361. >
  362. 清除考勤
  363. </el-button>
  364. </div>
  365. </template>
  366. </el-table-column>
  367. </el-table>
  368. <pagination
  369. save-key="teamDetails-courseList"
  370. sync
  371. :total.sync="rules.total"
  372. :page.sync="rules.page"
  373. :limit.sync="rules.limit"
  374. :page-sizes="rules.page_size"
  375. @pagination="getList"
  376. />
  377. </div>
  378. <el-dialog
  379. title="课程调整"
  380. width="400px"
  381. :before-close="handleClose"
  382. :visible.sync="courseVisible"
  383. >
  384. <el-form
  385. v-if="courseVisible"
  386. ref="maskForm"
  387. :model="maskForm"
  388. class="maskForm"
  389. :rules="maskRules"
  390. label-position="right"
  391. label-width="120px"
  392. :inline="true"
  393. >
  394. <el-form-item label="主教老师" prop="teacher">
  395. <remote-search
  396. v-model="maskForm.teacher"
  397. :commit="'setTeachers'"
  398. :width="220"
  399. />
  400. </el-form-item>
  401. <el-form-item
  402. v-if="
  403. maskForm.courseScheduleType != 'MUSIC_NETWORK' &&
  404. maskForm.courseScheduleType != 'HIGH_ONLINE' &&
  405. $helpers.permission('is/teacher/findTeachers')
  406. "
  407. label="助教老师"
  408. prop="assistant"
  409. >
  410. <remote-search
  411. v-model="maskForm.assistant"
  412. :commit="'setTeachers'"
  413. :width="220"
  414. :multiple="true"
  415. />
  416. </el-form-item>
  417. <el-form-item label="上课日期" prop="date">
  418. <el-date-picker
  419. v-model.trim="maskForm.date"
  420. type="date"
  421. :picker-options="beginDate()"
  422. value-format="yyyy-MM-dd"
  423. placeholder="选择日期"
  424. />
  425. </el-form-item>
  426. <el-form-item v-if="courseVisible" label="课程时长" prop="timer">
  427. <el-select v-model="maskForm.timer" @change="changeTime">
  428. <el-option
  429. v-for="(item, index) in typeTimeList"
  430. :key="index"
  431. :disabled="item > baseTimer ? true : false"
  432. :value="parseInt(item)"
  433. :label="item"
  434. />
  435. </el-select>
  436. </el-form-item>
  437. <el-form-item v-if="courseVisible" label="开始时间" prop="startTime">
  438. <el-time-picker
  439. v-model.trim="maskForm.startTime"
  440. placeholder="起始时间"
  441. format="HH:mm"
  442. value-format="HH:mm"
  443. :picker-options="{
  444. selectableRange: `${nowTime} - 23:30:00`
  445. }"
  446. @change="changeStartTime"
  447. />
  448. </el-form-item>
  449. <el-form-item v-if="courseVisible" label="结束时间" prop="endTime">
  450. <el-time-select
  451. v-model.trim="maskForm.endTime"
  452. placeholder="结束时间"
  453. disabled
  454. :picker-options="{
  455. start: '04:30',
  456. step: '00:05',
  457. end: '23:30',
  458. minTime: maskForm.startTime
  459. }"
  460. />
  461. </el-form-item>
  462. <el-form-item
  463. v-if="
  464. maskForm.courseScheduleType != 'HIGH_ONLINE' &&
  465. maskForm.courseScheduleType != 'MUSIC_NETWORK'
  466. "
  467. label="教学地点"
  468. prop="schoolId"
  469. >
  470. <el-select
  471. v-model.trim="maskForm.schoolId"
  472. style="width: 220px !important"
  473. filterable
  474. clearable
  475. >
  476. <el-option
  477. v-for="(item, index) in schoolList"
  478. :key="index"
  479. :value="item.id"
  480. :label="item.name"
  481. />
  482. </el-select>
  483. </el-form-item>
  484. </el-form>
  485. <div slot="footer" class="dialog-footer">
  486. <el-button @click="courseVisible = false">
  487. 取 消
  488. </el-button>
  489. <el-button type="primary" @click="submitResetClass">
  490. 确 定
  491. </el-button>
  492. </div>
  493. </el-dialog>
  494. <el-dialog
  495. title="修改时间"
  496. width="400px"
  497. :before-close="handleCloseTimer"
  498. :visible.sync="timerVisible"
  499. >
  500. <el-form :model="timerMask">
  501. <el-form-item
  502. label="上课日期"
  503. :rules="[{ required: true, message: '请选择日期', trigger: 'blur' }]"
  504. >
  505. <el-date-picker
  506. v-model.trim="timerMask.timer"
  507. type="date"
  508. format="yyyy-MM-dd"
  509. value-format="yyyy-MM-dd"
  510. :picker-options="{
  511. firstDayOfWeek: 1
  512. }"
  513. placeholder="选择日期"
  514. />
  515. </el-form-item>
  516. </el-form>
  517. <div slot="footer" class="dialog-footer">
  518. <el-button @click="timerVisible = false">
  519. 取 消
  520. </el-button>
  521. <el-button type="primary" @click="batchAdjustmentTime">
  522. 确 定
  523. </el-button>
  524. </div>
  525. </el-dialog>
  526. <el-dialog
  527. title="补考勤"
  528. width="400px"
  529. :visible.sync="markAttendance.status"
  530. >
  531. <el-form>
  532. <el-form-item label="签到状态">
  533. {{ markAttendance.dataInfo.signInStatus | attendanceType }}
  534. </el-form-item>
  535. <el-form-item label="签到时间">
  536. {{ markAttendance.dataInfo.signInTime }}
  537. </el-form-item>
  538. <el-form-item label="签退状态">
  539. {{ markAttendance.dataInfo.signOutStatus | attendanceOutType }}
  540. </el-form-item>
  541. <el-form-item label="签退时间">
  542. {{ markAttendance.dataInfo.signOutTime }}
  543. </el-form-item>
  544. </el-form>
  545. <div slot="footer" class="dialog-footer">
  546. <el-button @click="markAttendance.status = false">
  547. 取 消
  548. </el-button>
  549. <el-button
  550. type="primary"
  551. :disabled="
  552. markAttendance.dataInfo.signOutStatus == 1 &&
  553. markAttendance.dataInfo.signInStatus == 1
  554. ? true
  555. : false
  556. "
  557. @click="batchAdjustmentTime"
  558. >
  559. 确定补卡
  560. </el-button>
  561. </div>
  562. </el-dialog>
  563. <el-dialog title="点名表" width="800px" :visible.sync="rollCall.status">
  564. <el-table :data="rollCall.gridData">
  565. <el-table-column align="center" property="userName" label="学员姓名" />
  566. <el-table-column align="center" property="phone" label="手机号" />
  567. <el-table-column
  568. align="center"
  569. property="subjectName"
  570. label="学员声部"
  571. />
  572. <el-table-column align="center" label="到课状态">
  573. <template slot-scope="scope">
  574. {{ scope.row.status | studentCallName }}
  575. </template>
  576. </el-table-column>
  577. <el-table-column
  578. v-if="!rollCall.selectItem.settlementTime"
  579. align="center"
  580. label="操作"
  581. width="240px"
  582. >
  583. <template slot-scope="scope">
  584. <el-button
  585. size="mini"
  586. type="primary"
  587. round
  588. @click="onChangeRollCall('TRUANT', scope.row)"
  589. >
  590. 未到
  591. </el-button>
  592. <el-button
  593. size="mini"
  594. type="warning"
  595. round
  596. @click="onChangeRollCall('LEAVE', scope.row)"
  597. >
  598. 请假
  599. </el-button>
  600. <el-button
  601. size="mini"
  602. type="success"
  603. round
  604. @click="onChangeRollCall('NORMAL', scope.row)"
  605. >
  606. 到课
  607. </el-button>
  608. </template>
  609. </el-table-column>
  610. </el-table>
  611. <pagination
  612. sync
  613. :total.sync="rollCall.total"
  614. :page.sync="rollCall.page"
  615. :limit.sync="rollCall.limit"
  616. :page-sizes="rollCall.page_size"
  617. @pagination="getCallName"
  618. />
  619. </el-dialog>
  620. <transStart
  621. ref="transStart"
  622. :active-course-list="activeCourseList"
  623. @getList="getList"
  624. />
  625. </div>
  626. </template>
  627. <script>
  628. import dayjs from "dayjs";
  629. import pagination from "@/components/Pagination/index";
  630. import { bathDelete } from "@/api/vipSeting";
  631. import {
  632. resetCourse,
  633. getMusicGroupAllClass,
  634. getCourseSchedule,
  635. updateTeacherAttendance,
  636. findAttendanceStudentByCourseWithPage,
  637. updateStudentAttendances,
  638. cleanAttendance,
  639. getOrganCourseDurationSettings
  640. } from "@/api/buildTeam";
  641. import { permission } from "@/utils/directivePage";
  642. import { diffTimerFormMinute, addTimerFormMinute } from "@/utils/date";
  643. import { classTimeList, musicCourseType } from "@/utils/searchArray";
  644. import { getSchool } from "@/api/systemManage";
  645. import cleanDeep from "clean-deep";
  646. import { Export } from "@/utils/downLoadFile";
  647. import { getMusicGroupCourseScheduleStatistics } from "../api";
  648. import transStart from "./courseTransModals/transStart.vue";
  649. let that;
  650. export default {
  651. name: "TcourseList",
  652. components: {
  653. pagination,
  654. transStart
  655. },
  656. filters: {
  657. studentCallName: value => {
  658. let template = {
  659. NORMAL: "到课",
  660. TRUANT: "未到",
  661. LEAVE: "请假",
  662. DROP_OUT: "退学",
  663. LATE: "迟到",
  664. "": "未到"
  665. };
  666. return template[value];
  667. }
  668. },
  669. data() {
  670. return {
  671. baseTimer: 0, // 基础的分钟数
  672. classTimeList,
  673. courseArray: musicCourseType,
  674. typeVisible: false,
  675. timerVisible: false,
  676. courseVisible: false,
  677. searchForm: {
  678. courseStatus: "", // 课程类型
  679. classStatus: "", // 课程状态
  680. timer: [], // 时间
  681. class: "",
  682. isSettlement: "",
  683. homeworkFlag: "",
  684. serviceFlag: ""
  685. },
  686. tableList: [],
  687. searchLsit: [],
  688. rules: {
  689. // 分页规则
  690. limit: 10, // 限制显示条数
  691. page: 1, // 当前页
  692. total: 0, // 总条数
  693. page_size: [10, 20, 40, 50] // 选择限制显示条数
  694. },
  695. maskForm: {
  696. teacher: "",
  697. assistant: "",
  698. date: "",
  699. id: "",
  700. startTime: "",
  701. endTime: "",
  702. type: "",
  703. timer: "",
  704. courseScheduleType: null,
  705. address: "",
  706. teachMode: "",
  707. schoolId: ""
  708. },
  709. typeForm: {
  710. teacher: "",
  711. assistant: "",
  712. date: "",
  713. startTime: "",
  714. endTime: "",
  715. type: null,
  716. id: null
  717. },
  718. maskRules: {
  719. schoolId: [
  720. { required: true, message: "请选教学地点", trigger: "blur" }
  721. ],
  722. teacher: [
  723. { required: true, message: "请选择主教老师名称", trigger: "blur" }
  724. ],
  725. date: [{ required: true, message: "请选择上课时间", trigger: "blur" }]
  726. // startTime: [{ required: true, message: '请选择上课开始时间', trigger: 'blur' },],
  727. // endTime: [{ required: true, message: '请选择上课结束时间', trigger: 'blur' },],
  728. },
  729. typeRules: {
  730. type: [{ required: true, message: "请选择课程类型", trigger: "blur" }]
  731. },
  732. teacherList: [],
  733. classList: [],
  734. activeCourseList: [],
  735. timerMask: {
  736. timer: ""
  737. },
  738. markAttendance: {
  739. // 考勤状态
  740. status: false,
  741. dataInfo: {}
  742. },
  743. rollCall: {
  744. // 点名表
  745. status: false,
  746. gridData: [],
  747. selectItem: {}, // 选中状态
  748. limit: 10, // 限制显示条数
  749. page: 1, // 当前页
  750. total: 0, // 总条数
  751. page_size: [10, 20, 40, 50] // 选择限制显示条数
  752. },
  753. organId: "",
  754. schoolList: [],
  755. courseTimeList: {},
  756. typeTimeList: [],
  757. detail: {
  758. attendanceRate: "0.00%",
  759. homeworkCommitRate: "0.00%",
  760. standardRate: "0.00%"
  761. }
  762. };
  763. },
  764. computed: {
  765. nowTime() {
  766. // console.log(that.maskForm.date)
  767. let str = "06:00:00";
  768. if (that.maskForm.date == dayjs(new Date()).format("YYYY-MM-DD")) {
  769. str = dayjs(new Date()).format("HH:mm:ss");
  770. }
  771. return str;
  772. }
  773. },
  774. watch: {
  775. "maskForm.timer"(val) {
  776. this.maskForm.endTime = addTimerFormMinute(
  777. this.maskForm.date,
  778. this.maskForm.startTime,
  779. val
  780. );
  781. }
  782. },
  783. created() {
  784. that = this;
  785. },
  786. mounted() {
  787. this.init();
  788. getSchool({ organId: this.$route.query.organId }).then(res => {
  789. if (res.code == 200) {
  790. this.schoolList = res.data;
  791. }
  792. });
  793. },
  794. activated() {
  795. this.init();
  796. },
  797. methods: {
  798. async init() {
  799. this.teamid = this.$route.query.id;
  800. this.organId = this.$route.query.organId;
  801. try {
  802. const res = await getOrganCourseDurationSettings({
  803. organId: this.organId
  804. });
  805. this.courseTimeList = res.data;
  806. } catch {}
  807. // MusicStore.dispatch('getBaseInfo', {
  808. // data: { musicGroupId: this.teamid }
  809. // }).then((res) => {
  810. // console.log(res)
  811. // })
  812. this.getList();
  813. // 获取所有老师
  814. // findMusicGroupClassTeacher({ musicGroupId: this.teamid }).then(res => {
  815. // if (res.code == 200) {
  816. // this.teacherList = res.data;
  817. // }
  818. // })
  819. // getTeacher().then(res => {
  820. // if (res.code == 200) {
  821. // this.teacherList = res.data;
  822. // }
  823. // });
  824. // 获取班级列表
  825. getMusicGroupAllClass({ musicGroupId: this.teamid }).then(res => {
  826. if (res.code == 200) {
  827. this.classList = res.data;
  828. }
  829. });
  830. },
  831. onMarkAttendance(item) {
  832. // 补考勤
  833. this.markAttendance = {
  834. status: true,
  835. dataInfo: item
  836. };
  837. },
  838. onCallName(item) {
  839. // 点名表
  840. this.rollCall.page = 1;
  841. this.rollCall.selectItem = item;
  842. this.getCallName();
  843. },
  844. getCallName() {
  845. let rollCall = this.rollCall;
  846. let params = {
  847. page: rollCall.page,
  848. rows: rollCall.limit,
  849. courseScheduleId: rollCall.selectItem.courseScheduleId
  850. };
  851. findAttendanceStudentByCourseWithPage(params).then(res => {
  852. let result = res.data;
  853. rollCall.status = true;
  854. if (res.code == 200) {
  855. rollCall.gridData = result.rows;
  856. rollCall.total = result.total;
  857. }
  858. });
  859. },
  860. onChangeRollCall(type, row) {
  861. let rollCall = this.rollCall;
  862. let params = {
  863. courseScheduleId: rollCall.selectItem.courseScheduleId,
  864. studentAttendances: [
  865. {
  866. userId: row.studentId,
  867. status: type
  868. }
  869. ]
  870. };
  871. updateStudentAttendances(params).then(res => {
  872. if (res.code == 200) {
  873. this.$message.success("修改成功");
  874. row.status = type;
  875. this.getList();
  876. } else {
  877. this.$message.error(res.msg);
  878. }
  879. });
  880. },
  881. permission(str, parent) {
  882. return permission(str, parent);
  883. },
  884. search() {
  885. this.rules.page = 1;
  886. this.getList();
  887. },
  888. async getList() {
  889. let searchForm = this.searchForm;
  890. if (!searchForm.timer) {
  891. searchForm.timer = [];
  892. }
  893. let obj = {
  894. classScheduleStatus: searchForm.classStatus || null,
  895. classScheduleType: searchForm.courseStatus || null,
  896. musicGroupId: this.teamid,
  897. startTime: searchForm.timer[0] || null,
  898. endTime: searchForm.timer[1] || null,
  899. page: this.rules.page,
  900. rows: this.rules.limit,
  901. classGroupId: searchForm.class || null,
  902. isSettlement: searchForm.isSettlement || null,
  903. homeworkFlag: searchForm.homeworkFlag,
  904. serviceFlag: searchForm.serviceFlag
  905. };
  906. getCourseSchedule(obj).then(res => {
  907. if (res.code == 200) {
  908. // const result = res.data.rows || [];
  909. // result.forEach(row => {
  910. // if (row.teachingTeachers && row.teachingTeachers.length > 0) {
  911. // const names = [];
  912. // row.teachingTeachers.forEach(teacher => {
  913. // names.push(teacher.userName);
  914. // });
  915. // row.teachingUserNames = names.join(",");
  916. // } else {
  917. // row.teachingUserNames = "";
  918. // }
  919. // });
  920. this.tableList = res.data.rows;
  921. this.rules.total = res.data.total;
  922. }
  923. });
  924. try {
  925. const res = await getMusicGroupCourseScheduleStatistics({ ...obj });
  926. if (res.data) {
  927. this.detail = { ...res.data };
  928. }
  929. } catch (e) {
  930. console.log(e);
  931. }
  932. },
  933. async exportCourse() {
  934. // 导出
  935. let searchForm = this.searchForm;
  936. if (!searchForm.timer) {
  937. searchForm.timer = [];
  938. }
  939. let obj = {
  940. classScheduleStatus: searchForm.classStatus || null,
  941. classScheduleType: searchForm.courseStatus || null,
  942. musicGroupId: this.teamid,
  943. startTime: searchForm.timer[0] || null,
  944. endTime: searchForm.timer[1] || null,
  945. page: this.rules.page,
  946. rows: this.rules.limit,
  947. classGroupId: searchForm.class || null,
  948. isSettlement: searchForm.isSettlement || null,
  949. homeworkFlag: searchForm.homeworkFlag,
  950. serviceFlag: searchForm.serviceFlag
  951. };
  952. Export(
  953. this,
  954. {
  955. url: "/api-web/export/exportMusicGroupCourseScheduleDetail",
  956. fileName: "乐团课表详情.xls",
  957. method: "get",
  958. params: {
  959. ...obj
  960. }
  961. },
  962. "您确定导出乐团课表详情?"
  963. );
  964. },
  965. resetClass(row) {
  966. this.maskForm.teacher = parseInt(row.masterTeacherId);
  967. this.maskForm.courseScheduleType = row.courseScheduleType;
  968. // this.courseTimeList
  969. for (let key in this.courseTimeList) {
  970. if (key == row.courseScheduleType) {
  971. this.typeTimeList = this.courseTimeList[key].split(",");
  972. }
  973. }
  974. // this.maskForm.type = row.courseScheduleType;
  975. this.maskForm.assistant = [];
  976. for (let i in row.teachingTeachers) {
  977. if (row.teachingTeachers[i].teacherRole == "TEACHING") {
  978. this.maskForm.assistant.push(row.teachingTeachers[i].userId);
  979. }
  980. }
  981. this.maskForm.date = row.classDate;
  982. this.$set(
  983. this.maskForm,
  984. "startTime",
  985. row.startClassTimeStr.substring(0, 5)
  986. );
  987. let time = diffTimerFormMinute(
  988. row.classDate,
  989. row.startClassTimeStr,
  990. row.endClassTimeStr
  991. );
  992. this.baseTimer = time;
  993. this.maskForm.timer = time;
  994. this.maskForm.endTime = addTimerFormMinute(
  995. row.classDate,
  996. row.startClassTimeStr,
  997. time
  998. );
  999. // this.maskForm.endTime = row.endClassTimeStr.substring(0, 5);
  1000. this.maskForm.id = row.courseScheduleId;
  1001. this.maskForm.schoolId = row.schoolId;
  1002. this.courseVisible = true;
  1003. // 修改课时
  1004. // let obj = {
  1005. // actualTeacherId: this.maskForm.teacher,
  1006. // classDate: this.maskForm.date,
  1007. // classGroupId: row.id
  1008. // }
  1009. },
  1010. removeSingleClass(row) {
  1011. this.$confirm("是否删除该课程?", "提示", {
  1012. confirmButtonText: "确定",
  1013. cancelButtonText: "取消",
  1014. type: "warning"
  1015. })
  1016. .then(() => {
  1017. let courseScheduleIds = row.courseScheduleId;
  1018. bathDelete({ courseScheduleIds }).then(res => {
  1019. if (res.code == 200) {
  1020. this.$message.success("删除成功");
  1021. this.getList();
  1022. }
  1023. });
  1024. })
  1025. .catch(() => {});
  1026. },
  1027. removeCourses() {
  1028. // 批量删除
  1029. if (this.activeCourseList.length < 1) {
  1030. this.$message.error("请至少选择一节课");
  1031. return;
  1032. }
  1033. let arr = [];
  1034. arr = this.activeCourseList.map(item => {
  1035. return item.courseScheduleId;
  1036. });
  1037. this.$confirm("是否删除该课程?", "提示", {
  1038. confirmButtonText: "确定",
  1039. cancelButtonText: "取消",
  1040. type: "warning"
  1041. })
  1042. .then(() => {
  1043. let courseScheduleIds = arr.join(",");
  1044. bathDelete({ courseScheduleIds }).then(res => {
  1045. if (res.code == 200) {
  1046. this.$message.success("删除成功");
  1047. this.getList();
  1048. }
  1049. });
  1050. })
  1051. .catch(() => {});
  1052. },
  1053. submitResetClass() {
  1054. let maskForm = this.maskForm;
  1055. let diff = dayjs(maskForm.date + " " + maskForm.startTime).diff(
  1056. new Date(),
  1057. "second"
  1058. );
  1059. if (diff <= 0) {
  1060. this.$message.error("课程开始时间必须大于当前时间");
  1061. return;
  1062. }
  1063. if (!maskForm.startTime || !maskForm.endTime) {
  1064. this.$message.error("请填写开始时间或结束时间");
  1065. return;
  1066. }
  1067. this.$confirm("是否确定?", "提示", {
  1068. confirmButtonText: "确定",
  1069. cancelButtonText: "取消",
  1070. type: "warning"
  1071. })
  1072. .then(() => {
  1073. let teachingTeacherIdList = maskForm.assistant.join(",");
  1074. if (teachingTeacherIdList.length <= 0) {
  1075. let teachingTeacherIdList = null;
  1076. }
  1077. let obj = {
  1078. actualTeacherId: maskForm.teacher,
  1079. startClassTimeStr: maskForm.startTime,
  1080. endClassTimeStr: maskForm.endTime,
  1081. id: maskForm.id,
  1082. teachingTeacherIdList,
  1083. classDate: maskForm.date,
  1084. type: maskForm.type,
  1085. groupType: "MUSIC",
  1086. schoolId: maskForm.schoolId
  1087. };
  1088. resetCourse(cleanDeep(obj)).then(res => {
  1089. if (res.code == 200) {
  1090. this.$message.success("修改成功");
  1091. this.getList();
  1092. this.courseVisible = false;
  1093. }
  1094. if (res.code == 206) {
  1095. this.$confirm(`当前课程课酬预计为0,是否继续`, "提示", {
  1096. confirmButtonText: "确定",
  1097. cancelButtonText: "取消",
  1098. type: "warning"
  1099. }).then(res => {
  1100. obj.allowZeroSalary = true;
  1101. resetCourse(cleanDeep(obj)).then(res => {
  1102. if (res.code == 200) {
  1103. this.$message.success("修改成功");
  1104. this.getList();
  1105. this.courseVisible = false;
  1106. }
  1107. });
  1108. });
  1109. }
  1110. });
  1111. })
  1112. .catch(() => {});
  1113. },
  1114. handleClose() {
  1115. this.courseVisible = false;
  1116. (this.maskForm = {
  1117. teacher: "",
  1118. assistant: "",
  1119. date: "",
  1120. id: "",
  1121. startTime: "",
  1122. endTime: "",
  1123. schoolId: null
  1124. }),
  1125. this.$refs["maskForm"].resetFields();
  1126. },
  1127. handleSelectionChange(val) {
  1128. this.activeCourseList = val;
  1129. },
  1130. checkSelectable(val) {
  1131. return (
  1132. val.courseScheduleStatus == "NOT_START" &&
  1133. (val.courseScheduleType == "TRAINING_SINGLE" ||
  1134. val.courseScheduleType == "SINGLE")
  1135. );
  1136. // return true;
  1137. },
  1138. batchAdjustmentTime() {
  1139. let tempData = this.markAttendance.dataInfo;
  1140. let params = {
  1141. teacherId: tempData.masterTeacherId,
  1142. courseScheduleId: tempData.courseScheduleId,
  1143. signInStatus: 1,
  1144. signOutStatus: 1
  1145. };
  1146. updateTeacherAttendance(params).then(res => {
  1147. if (res.code == 200) {
  1148. this.$message.success("补卡成功");
  1149. this.markAttendance.status = false;
  1150. this.getList();
  1151. } else {
  1152. this.$message.error(res.msg);
  1153. }
  1154. });
  1155. },
  1156. handleCloseTimer() {
  1157. this.timerVisible = false;
  1158. this.timerMask.timer = "";
  1159. },
  1160. resetTimer() {
  1161. if (this.activeCourseList.length < 1) {
  1162. this.$message.error("请至少选择一节课");
  1163. return;
  1164. }
  1165. this.timerVisible = true;
  1166. },
  1167. resetType(row) {
  1168. this.typeForm.type = row.courseScheduleType;
  1169. this.typeForm.id = row.courseScheduleId;
  1170. this.typeForm.teacher = parseInt(row.masterTeacherId);
  1171. // this.maskForm.type = row.courseScheduleType;
  1172. this.typeForm.assistant = [];
  1173. for (let i in row.teachingTeachers) {
  1174. if (row.teachingTeachers[i].teacherRole == "TEACHING") {
  1175. this.typeForm.assistant.push(row.teachingTeachers[i].userId);
  1176. }
  1177. }
  1178. this.typeForm.date = row.classDate;
  1179. this.$set(
  1180. this.typeForm,
  1181. "startTime",
  1182. row.startClassTimeStr.substring(0, 5)
  1183. );
  1184. this.typeForm.endTime = row.endClassTimeStr.substring(0, 5);
  1185. // console.log(row.type)
  1186. this.typeVisible = true;
  1187. },
  1188. submitResetType() {
  1189. this.$refs.typeForm.validate(res => {
  1190. if (res) {
  1191. let teachingTeacherIdList = this.typeForm.assistant.join(",");
  1192. if (teachingTeacherIdList.length <= 0) {
  1193. let teachingTeacherIdList = null;
  1194. }
  1195. let obj = {
  1196. actualTeacherId: this.typeForm.teacher,
  1197. startClassTimeStr: this.typeForm.startTime,
  1198. endClassTimeStr: this.typeForm.endTime,
  1199. id: this.typeForm.id,
  1200. type: this.typeForm.type,
  1201. teachingTeacherIdList,
  1202. classDate: this.typeForm.date
  1203. };
  1204. resetCourse(obj).then(res => {
  1205. if (res.code == 200) {
  1206. this.$message.success("修改成功");
  1207. this.getList();
  1208. this.typeVisible = false;
  1209. }
  1210. });
  1211. }
  1212. });
  1213. },
  1214. // 清除考勤
  1215. clearAttend(row) {
  1216. this.$confirm("是否清除考勤记录?", "提示", {
  1217. confirmButtonText: "确定",
  1218. cancelButtonText: "取消",
  1219. type: "warning"
  1220. })
  1221. .then(() => {
  1222. cleanAttendance({ courseScheduleIds: row.courseScheduleId }).then(
  1223. res => {
  1224. if (res.code == 200) {
  1225. this.$message.success("清除成功");
  1226. this.getList();
  1227. } else {
  1228. this.$message.error(res.msg);
  1229. }
  1230. }
  1231. );
  1232. })
  1233. .catch(() => {});
  1234. },
  1235. changeStartTime(val) {
  1236. this.$nextTick(res => {
  1237. this.maskForm.endTime = addTimerFormMinute(
  1238. this.maskForm.date,
  1239. val,
  1240. this.maskForm.timer
  1241. );
  1242. });
  1243. },
  1244. changeTime(val) {
  1245. this.$nextTick(res => {
  1246. this.maskForm.endTime = addTimerFormMinute(
  1247. this.maskForm.date,
  1248. this.maskForm.startTime,
  1249. val
  1250. );
  1251. });
  1252. },
  1253. onReSet() {
  1254. this.$refs.searchForm.resetFields();
  1255. this.search();
  1256. },
  1257. beginDate() {
  1258. return {
  1259. firstDayOfWeek: 1,
  1260. disabledDate(time) {
  1261. return time.getTime() + 86400000 <= new Date().getTime();
  1262. //开始时间不选时,结束时间最大值小于等于当天
  1263. }
  1264. };
  1265. },
  1266. transCourse() {
  1267. if (this.activeCourseList.length < 1) {
  1268. this.$message.error("请至少选择一节课");
  1269. return;
  1270. }
  1271. let arr = [];
  1272. this.activeCourseList.forEach(item => {
  1273. arr.push(item.courseScheduleType);
  1274. });
  1275. arr = [...new Set(arr)];
  1276. if (arr.length > 1) {
  1277. this.$message.error("请选择同一种课程类型");
  1278. return;
  1279. }
  1280. this.$refs.transStart.openDialog();
  1281. }
  1282. }
  1283. };
  1284. </script>
  1285. <style lang="scss" scoped>
  1286. .cl-container {
  1287. .topFrom {
  1288. margin: 20px 30px 0;
  1289. .classlist {
  1290. display: flex;
  1291. flex-direction: row;
  1292. justify-content: flex-start;
  1293. align-items: center;
  1294. ul {
  1295. li {
  1296. list-style: none;
  1297. }
  1298. }
  1299. }
  1300. }
  1301. // .searchForm {
  1302. // // margin: 0 30px;
  1303. // }
  1304. }
  1305. .btnWraps {
  1306. display: flex;
  1307. flex-direction: row;
  1308. justify-content: flex-start;
  1309. div {
  1310. margin-right: 20px;
  1311. }
  1312. }
  1313. .maskForm {
  1314. ::v-deep .el-input {
  1315. width: 220px;
  1316. }
  1317. }
  1318. </style>