courseList.vue 36 KB

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