courseList.vue 39 KB

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