teamCourseList.vue 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. <template>
  2. <div class="m-container">
  3. <h2>
  4. <div class="squrt"></div>
  5. 课表列表
  6. <filter-search
  7. ref="filterSearch"
  8. @reload="reloadSearch"
  9. @setTimeForSearch="setTimeForSearch"
  10. :keys="['searchType']"
  11. :moreKeys="['start', 'end', 'organId']"
  12. />
  13. </h2>
  14. <div class="m-core">
  15. <!-- 搜索类型 -->
  16. <save-form
  17. :inline="true"
  18. class="searchForm"
  19. @submit="search"
  20. @reset="reset"
  21. ref="searchForm"
  22. :model.sync="searchForm"
  23. >
  24. <el-form-item>
  25. <el-input
  26. type="number"
  27. v-model.trim="searchForm.courseIdSearch"
  28. clearable
  29. placeholder="课程编号"
  30. />
  31. </el-form-item>
  32. <el-form-item>
  33. <el-input
  34. v-model.trim="searchForm.search"
  35. clearable
  36. placeholder="课程组编号/课程名称"
  37. />
  38. </el-form-item>
  39. <el-form-item>
  40. <el-select
  41. v-model.trim="searchForm.schoolId"
  42. clearable
  43. filterable
  44. placeholder="请选择教学点"
  45. >
  46. <el-option
  47. v-for="(item, index) in selects.schools"
  48. :key="index"
  49. :value="item.id"
  50. :label="item.name"
  51. ></el-option>
  52. </el-select>
  53. </el-form-item>
  54. <el-form-item>
  55. <remote-search
  56. :commit="'setTeachers'"
  57. v-model="searchForm.teacherIdList"
  58. />
  59. <!-- <el-select
  60. v-model.trim="searchForm.teacherIdList"
  61. clearable
  62. filterable
  63. placeholder="请选择老师"
  64. >
  65. <el-option
  66. v-for="(item, index) in selects.teachers"
  67. :key="index"
  68. :value="item.id"
  69. :label="item.realName"
  70. ></el-option>
  71. </el-select> -->
  72. </el-form-item>
  73. <el-form-item>
  74. <el-select
  75. class="multiple"
  76. v-model.trim="searchForm.organIdList"
  77. filterable
  78. clearable
  79. placeholder="请选择分部"
  80. >
  81. <el-option
  82. v-for="(item, index) in selects.branchs"
  83. :key="index"
  84. :label="item.name"
  85. :value="item.id"
  86. ></el-option>
  87. </el-select>
  88. </el-form-item>
  89. <el-form-item>
  90. <el-select
  91. v-model.trim="searchForm.groupType"
  92. clearable
  93. filterable
  94. placeholder="课程组类型"
  95. >
  96. <el-option
  97. v-for="item in courseListType"
  98. :key="item.value"
  99. :value="item.value"
  100. :label="item.label"
  101. ></el-option>
  102. </el-select>
  103. </el-form-item>
  104. <el-form-item>
  105. <el-select
  106. v-model.trim="searchForm.courseType"
  107. clearable
  108. filterable
  109. placeholder="课程类型"
  110. >
  111. <el-option
  112. v-for="(item, index) in courseType"
  113. :key="index"
  114. :value="item.value"
  115. :label="item.label"
  116. ></el-option>
  117. </el-select>
  118. </el-form-item>
  119. <el-form-item>
  120. <el-select
  121. v-model.trim="searchForm.teachMode"
  122. clearable
  123. filterable
  124. placeholder="教学模式"
  125. >
  126. <el-option label="线上课" value="ONLINE"></el-option>
  127. <el-option label="线下课" value="OFFLINE"></el-option>
  128. </el-select>
  129. </el-form-item>
  130. <el-form-item>
  131. <el-select
  132. v-model.trim="searchForm.courseStatus"
  133. clearable
  134. filterable
  135. placeholder="课程状态"
  136. >
  137. <el-option label="未开始" value="NOT_START"></el-option>
  138. <el-option label="进行中" value="UNDERWAY"></el-option>
  139. <el-option label="已结束" value="OVER"></el-option>
  140. </el-select>
  141. </el-form-item>
  142. <el-form-item>
  143. <el-select
  144. v-model.trim="searchForm.mergeCourseType"
  145. clearable
  146. filterable
  147. placeholder="合并课程类型"
  148. >
  149. <el-option
  150. v-for="(item, index) in mergeCourseTypeOptions"
  151. :key="index"
  152. :value="item.value"
  153. :label="item.label"
  154. ></el-option>
  155. </el-select>
  156. </el-form-item>
  157. <el-form-item>
  158. <el-select
  159. v-model.trim="searchForm.teachType"
  160. clearable
  161. filterable
  162. placeholder="老师类型"
  163. >
  164. <el-option
  165. v-for="item in workTypeOptions"
  166. :key="item.label"
  167. :label="item.label"
  168. :value="item.value"
  169. ></el-option>
  170. </el-select>
  171. </el-form-item>
  172. <el-form-item>
  173. <el-select
  174. v-model.trim="searchForm.isCallNames"
  175. clearable
  176. filterable
  177. placeholder="是否点名"
  178. >
  179. <el-option label="是" value="1"></el-option>
  180. <el-option label="否" value="0"></el-option>
  181. </el-select>
  182. </el-form-item>
  183. <el-form-item>
  184. <el-date-picker
  185. v-model.trim="searchForm.timer"
  186. type="daterange"
  187. value-format="yyyy-MM-dd"
  188. range-separator="至"
  189. start-placeholder="上课开始日期"
  190. end-placeholder="上课结束日期"
  191. :picker-options="{
  192. firstDayOfWeek: 1,
  193. }"
  194. ></el-date-picker>
  195. </el-form-item>
  196. <el-form-item>
  197. <el-date-picker
  198. v-model.trim="searchForm.creatTimer"
  199. type="daterange"
  200. value-format="yyyy-MM-dd"
  201. range-separator="至"
  202. start-placeholder="创建开始日期"
  203. end-placeholder="创建结束日期"
  204. :picker-options="{
  205. firstDayOfWeek: 1,
  206. }"
  207. ></el-date-picker>
  208. </el-form-item>
  209. <el-row type="flex" justify="space-around">
  210. <el-col>
  211. <el-button native-type="submit" type="primary">搜索</el-button>
  212. <el-button native-type="reset" type="danger">重置</el-button>
  213. <el-button
  214. v-permission="'export/superFindCourseSchedules'"
  215. @click="onCourseExport"
  216. type="primary"
  217. >导出课表</el-button
  218. >
  219. </el-col>
  220. </el-row>
  221. </save-form>
  222. <!-- 列表 -->
  223. <div class="tableWrap" style="margin-top: 20px">
  224. <el-table
  225. :data="tableList"
  226. ref="tableList"
  227. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  228. @selection-change="handleSelectionChange"
  229. @select="onTableSelect"
  230. row-key="id"
  231. >
  232. >
  233. <el-table-column
  234. v-permission="'courseSchedule/batchDelete?page=teamCourseList'"
  235. type="selection"
  236. width="55"
  237. ></el-table-column>
  238. <el-table-column
  239. align="center"
  240. prop="organName"
  241. label="分部名称"
  242. ></el-table-column>
  243. <el-table-column
  244. align="center"
  245. width="150px"
  246. prop="musicGroupId"
  247. label="乐团/课程组编号"
  248. >
  249. <template slot-scope="scope">
  250. <el-button type="text" @click="gotoCourse(scope.row)">
  251. <copy-text>{{ scope.row.musicGroupId }}</copy-text>
  252. </el-button>
  253. </template>
  254. </el-table-column>
  255. <el-table-column
  256. align="center"
  257. prop="id"
  258. width="100px"
  259. label="课程编号"
  260. >
  261. <template slot-scope="scope">
  262. <copy-text>{{ scope.row.id }}</copy-text>
  263. </template>
  264. </el-table-column>
  265. <el-table-column align="center" width="200px" label="上课时间">
  266. <template slot-scope="scope"
  267. >{{
  268. scope.row.startClassTime
  269. ? scope.row.startClassTime.substr(0, 16)
  270. : ""
  271. }}-{{
  272. scope.row.endClassTime
  273. ? scope.row.endClassTime.substr(11, 5)
  274. : ""
  275. }}</template
  276. >
  277. </el-table-column>
  278. <el-table-column
  279. align="center"
  280. prop="subjectName"
  281. label="声部"
  282. ></el-table-column>
  283. <el-table-column prop="name" width="150px" label="课程名称">
  284. <template slot-scope="scope">
  285. <copy-text>{{ scope.row.name }}</copy-text>
  286. </template>
  287. </el-table-column>
  288. <el-table-column align="center" width="150px" label="课程类型">
  289. <template slot-scope="scope">
  290. <div>{{ scope.row.type | coursesType }}</div>
  291. </template>
  292. </el-table-column>
  293. <el-table-column align="center" label="教学模式">
  294. <template slot-scope="scope">
  295. <div>{{ scope.row.teachMode | teachMode }}</div>
  296. </template>
  297. </el-table-column>
  298. <el-table-column
  299. align="center"
  300. prop="teacherName"
  301. width="110"
  302. label="主教老师"
  303. ></el-table-column>
  304. <el-table-column align="center" prop="schoolName" label="教学点">
  305. <template slot-scope="scope">
  306. <div>
  307. {{ scope.row.schoolName ? scope.row.schoolName : "网络教室" }}
  308. </div>
  309. </template>
  310. </el-table-column>
  311. <el-table-column
  312. align="center"
  313. prop="courseScheduleStatus"
  314. label="课程状态"
  315. >
  316. <template slot-scope="scope">
  317. <div>{{ scope.row.status | coursesStatus }}</div>
  318. </template>
  319. </el-table-column>
  320. <el-table-column align="center" label="考勤申诉">
  321. <template slot-scope="scope">
  322. <div>{{ scope.row.isComplaints == 1 ? "是" : "否" }}</div>
  323. </template>
  324. </el-table-column>
  325. <el-table-column align="center" prop="isLock" label="是否冻结">
  326. <template slot-scope="scope">{{
  327. scope.row.isLock ? "是" : "否"
  328. }}</template>
  329. </el-table-column>
  330. <el-table-column
  331. align="center"
  332. prop="newCourseId"
  333. label="合并类型"
  334. width="130px"
  335. >
  336. <template slot-scope="scope">
  337. <div>
  338. <span
  339. v-if="
  340. scope.row.newCourseId > 0 &&
  341. scope.row.newCourseId == scope.row.id
  342. "
  343. >合并课
  344. </span>
  345. <el-button
  346. type="text"
  347. @click="common(scope.row)"
  348. v-if="
  349. scope.row.newCourseId > 0 &&
  350. scope.row.newCourseId != scope.row.id
  351. "
  352. >
  353. 被合并课
  354. </el-button>
  355. </div>
  356. </template>
  357. </el-table-column>
  358. <el-table-column
  359. align="center"
  360. prop="isCallNames"
  361. label="是否点名"
  362. fixed="right"
  363. >
  364. <template slot-scope="scope">{{
  365. scope.row.isCallNames ? "是" : "否"
  366. }}</template>
  367. </el-table-column>
  368. <el-table-column
  369. align="center"
  370. label="详情"
  371. fixed="right"
  372. width="220px"
  373. >
  374. <template slot-scope="scope">
  375. <div>
  376. <!-- <el-button
  377. type="text"
  378. @click="removeCourse(scope.row)"
  379. v-permission="
  380. 'courseSchedule/batchDelete?page=teamCourseList'
  381. "
  382. >删除</el-button
  383. > -->
  384. <auth auths="/teamCourseListDetail">
  385. <!-- v-if="permission('teamCourseList/details')" -->
  386. <el-button type="text" @click="lookDetail(scope.row)"
  387. >详情</el-button
  388. >
  389. </auth>
  390. <el-button
  391. type="text"
  392. v-if="
  393. permission('courseSchedule/classStartDateAdjust?hight') &&
  394. (!scope.row.isLock || scope.row.newCourseId > 0)
  395. "
  396. @click="resetClass(scope.row)"
  397. >调整</el-button
  398. >
  399. <!-- <el-button
  400. type="text"
  401. @click="addCompound(scope.row)"
  402. v-if="
  403. scope.row.groupType == 'MUSIC' &&
  404. scope.row.type != 'MUSIC_NETWORK' &&
  405. scope.row.type != 'HIGH_ONLINE' &&
  406. scope.row.status == 'NOT_START' &&
  407. !isAddCom(scope.row) &&
  408. permission('courseSchedule/courseMerge') &&
  409. scope.row.newCourseId <= 0 &&
  410. !scope.row.beMerged &&
  411. !scope.row.isLock // 李焕辜临轩要求冻结课程不能合并
  412. "
  413. >添加合课</el-button
  414. >
  415. <el-button
  416. type="text"
  417. v-if="
  418. isAddCom(scope.row) &&
  419. permission('courseSchedule/courseMerge')
  420. "
  421. @click="cancleCompound(scope.row)"
  422. >取消合课</el-button
  423. > -->
  424. <el-button
  425. type="text"
  426. v-if="
  427. scope.row.newCourseId == scope.row.id &&
  428. permission('courseSchedule/mergeCourseSplit') &&
  429. scope.row.status != 'OVER'
  430. "
  431. @click="resetCompound(scope.row)"
  432. >取消合并</el-button
  433. >
  434. <el-button
  435. type="text"
  436. v-if="
  437. scope.row.status == 'OVER' &&
  438. !scope.row.isSettlement &&
  439. permission('courseSchedule/cleanAttendance')
  440. "
  441. @click="clearAttend(scope.row)"
  442. >清除考勤</el-button
  443. >
  444. </div>
  445. </template>
  446. </el-table-column>
  447. </el-table>
  448. <pagination
  449. :total.sync="rules.total"
  450. :page.sync="rules.page"
  451. :limit.sync="rules.limit"
  452. :page-sizes="rules.page_size"
  453. @pagination="getList"
  454. sync
  455. />
  456. </div>
  457. </div>
  458. <el-dialog title="课表详情" :visible.sync="classVisible" width="1000px">
  459. <el-form :model="maskForm" :inline="true">
  460. <el-form-item label="老师姓名">
  461. <!-- <el-input v-model.trim="maskForm.teacherName"
  462. disabled></el-input>-->
  463. <div class="inputStyle">{{ maskForm.teacherName }}</div>
  464. </el-form-item>
  465. <el-form-item label="课程模式">
  466. <!-- <el-input :value="maskForm.teachMode | teachMode"
  467. disabled></el-input>-->
  468. <div class="inputStyle">{{ maskForm.teachMode | teachMode }}</div>
  469. <!-- <span>{{maskForm.teachMode }}</span> -->
  470. </el-form-item>
  471. <el-form-item label="课程类型">
  472. <!-- <el-input :value="maskForm.type |classType"
  473. disabled></el-input>-->
  474. <div class="inputStyle">{{ maskForm.type | coursesType }}</div>
  475. </el-form-item>
  476. <!-- courseScheduleStatus -->
  477. <el-form-item label="课程状态">
  478. <!-- <el-input :value="maskForm.type |classType"
  479. disabled></el-input>-->
  480. <div class="inputStyle">{{ maskForm.status | coursesStatus }}</div>
  481. </el-form-item>
  482. <!-- <el-form-item label="签到时间">
  483. <div class="inputStyle">{{maskForm.signInTime | dateForMinFormat}}</div>
  484. </el-form-item>
  485. <el-form-item label="签退时间">
  486. <div class="inputStyle">{{maskForm.signOutTime | dateForMinFormat}}</div>
  487. </el-form-item> -->
  488. <el-form-item label="是否点名">
  489. <!-- <el-input :value="maskForm.isCallNames | isCall"
  490. disabled></el-input>-->
  491. <div class="inputStyle">{{ maskForm.isCallNames | isCall }}</div>
  492. </el-form-item>
  493. <!-- <el-form-item label="签到状态">
  494. <div class="inputStyle"
  495. :class="maskForm.isSignIn==1?'':'red'">{{ maskForm.isSignIn | attendanceType}}</div>
  496. </el-form-item>
  497. <el-form-item label="签退状态">
  498. <div class="inputStyle"
  499. :class="maskForm.isSignIn==1?'':'red'">{{ maskForm.isSignOut | attendanceOutType}}</div>
  500. </el-form-item> -->
  501. <el-form-item label="上课时间">
  502. {{
  503. maskForm.startClassTime
  504. ? maskForm.startClassTime.substr(0, 16)
  505. : ""
  506. }}-{{
  507. maskForm.endClassTime ? maskForm.endClassTime.substr(11, 5) : ""
  508. }}
  509. </el-form-item>
  510. <el-form-item label="上课时长">
  511. <div
  512. class="inputStyle"
  513. :class="maskForm.attendClassTime <= 120 ? '' : 'red'"
  514. >
  515. {{
  516. maskForm.attendClassTime >= 0 ? maskForm.attendClassTime : 0
  517. }}分钟
  518. <el-tooltip placement="top" popper-class="mTooltip">
  519. <div slot="content">学员和老师同时在教室里的时长。</div>
  520. <!-- <img :src="imageIcon" class="micon el-tooltip" style="width:8px height:8px" alt /> -->
  521. <i
  522. class="el-icon-question micon el-tooltip"
  523. style="font-size: 18px; color: #f56c6c"
  524. v-permission="'export/teacherSalary'"
  525. ></i>
  526. </el-tooltip>
  527. </div>
  528. </el-form-item>
  529. <el-form-item label="学员考勤" v-if="maskForm.status != 'NOT_START'">
  530. <div
  531. class="inputStyle"
  532. :class="maskForm.errorAttendanceNum != 0 ? 'red' : null"
  533. >
  534. {{ maskForm.errorAttendanceNum != 0 ? "异常" : "正常" }}
  535. </div>
  536. </el-form-item>
  537. <el-form-item label="老师考勤" v-if="maskForm.status != 'NOT_START'">
  538. <div
  539. class="inputStyle"
  540. :class="
  541. maskForm.signInStatusEnum == 1 && maskForm.signOutStatusEnum == 1
  542. ? null
  543. : 'red'
  544. "
  545. >
  546. {{
  547. maskForm.signInStatusEnum == 1 && maskForm.signOutStatusEnum == 1
  548. ? "正常"
  549. : "异常"
  550. }}
  551. </div>
  552. </el-form-item>
  553. <el-form-item v-if="maskForm.school" label="教学点">
  554. {{ maskForm.school.name }}
  555. <el-tooltip content="查看教学点" :open-delay="0.5">
  556. <i
  557. @click="openLocation(maskForm.school)"
  558. class="el-icon-map-location"
  559. style="cursor: pointer"
  560. ></i>
  561. </el-tooltip>
  562. </el-form-item>
  563. </el-form>
  564. <!-- v-if="maskForm.status != 'NOT_START'" -->
  565. <el-tabs v-model.trim="activeName" type="card" @tab-click="handleClick">
  566. <el-tab-pane
  567. label="学员列表"
  568. name="first"
  569. v-if="permission('/teamCourseListDetailStudnetList')"
  570. >
  571. <div v-if="activeName == 'first'">
  572. <!-- studentRollCall -->
  573. <studentRollCall
  574. :courseScheduleId="maskForm.id"
  575. :isMainGo="isMainGo"
  576. ></studentRollCall>
  577. </div>
  578. </el-tab-pane>
  579. <!-- <el-tab-pane label="GPS定位"
  580. v-if="maskForm.teachMode == 'OFFLINE'"
  581. name="second">
  582. <div v-if="activeName == 'second'">
  583. <gpsLoction :courseScheduleId="maskForm.id"></gpsLoction>
  584. </div>
  585. </el-tab-pane> -->
  586. <el-tab-pane
  587. label="老师列表"
  588. name="second"
  589. v-if="permission('/teamCourseListDetailTeacherList')"
  590. >
  591. <div v-if="activeName == 'second'">
  592. <teacherList
  593. :courseScheduleId="maskForm.id"
  594. :teachMode="maskForm.teachMode"
  595. :courseStatus="maskForm.status"
  596. ></teacherList>
  597. </div>
  598. </el-tab-pane>
  599. <!-- v-if="maskForm.teachMode != 'OFFLINE'" -->
  600. <el-tab-pane
  601. label="作业"
  602. name="third"
  603. v-if="permission('/teamCourseListDetailWorkList')"
  604. >
  605. <div v-if="activeName == 'third'">
  606. <studentWork :courseScheduleId="maskForm.id"></studentWork>
  607. </div>
  608. </el-tab-pane>
  609. <!-- v-if="maskForm.type == 'VIP' || maskForm.type == 'PRACTICE'" -->
  610. <el-tab-pane
  611. label="评论"
  612. name="four"
  613. v-if="permission('/teamCourseListDetailCommentList')"
  614. >
  615. <div v-if="activeName == 'four'">
  616. <courseEvaluate :courseScheduleId="maskForm.id"></courseEvaluate>
  617. </div>
  618. </el-tab-pane>
  619. <el-tab-pane
  620. label="调整记录"
  621. v-if="permission('/teamCourseListDetailAdjust')"
  622. name="five"
  623. >
  624. <div v-if="activeName == 'five'">
  625. <infoMsg :courseScheduleId="maskForm.id"></infoMsg>
  626. </div>
  627. </el-tab-pane>
  628. <!-- infoMsg -->
  629. </el-tabs>
  630. </el-dialog>
  631. <el-dialog :visible.sync="show" width="400px" title="课程调整">
  632. <resetClass
  633. :show="show"
  634. v-if="show"
  635. @closeReset="closeReset"
  636. @getList="getList"
  637. :id="id"
  638. />
  639. </el-dialog>
  640. <el-dialog title="查看教学点" :visible.sync="locationVisible">
  641. <school-location
  642. v-if="maskForm.school"
  643. :longitudeLatitude="maskForm.school.longitudeLatitude"
  644. :address="maskForm.school.address"
  645. />
  646. </el-dialog>
  647. <addCompound
  648. ref="addCompound"
  649. :compoundList="deleteList"
  650. v-if="permission('courseSchedule/courseMerge')"
  651. v-show="deleteList.length > 0"
  652. @clearCom="clearCom"
  653. @getList="getList"
  654. @removeCourse="removeCourse"
  655. @cancleCompound="cancleCompound"
  656. />
  657. </div>
  658. </template>
  659. <script>
  660. import pagination from "@/components/Pagination/index";
  661. import {
  662. superFindCourseSchedules,
  663. cleanAttendance,
  664. cancelCourseMerge,
  665. } from "@/api/buildTeam";
  666. import { bathDelete } from "@/api/vipSeting";
  667. import { workType, mergeCourseType } from "@/constant";
  668. import { objectToOptions, getTimes } from "@/utils";
  669. import { getTeacherPersonalAttendanceDetail } from "@/api/teacherManager";
  670. import { getSchool } from "@/api/systemManage";
  671. import { courseType, courseListType } from "@/utils/searchArray";
  672. import studentRollCall from "./componentCourse/studentRollCall";
  673. import gpsLoction from "./componentCourse/gpsLocation";
  674. import studentWork from "./componentCourse/studentWork";
  675. import courseEvaluate from "./componentCourse/courseEvaluate";
  676. import { permission } from "@/utils/directivePage";
  677. import axios from "axios";
  678. import { getToken } from "@/utils/auth";
  679. import load from "@/utils/loading";
  680. import SchoolLocation from "./components/modals/school-location";
  681. import resetClass from "./componentCourse/resetClass";
  682. import teacherList from "./componentCourse/teacherList";
  683. import addCompound from "./componentCourse/addCompound";
  684. import infoMsg from "./componentCourse/infoMsg";
  685. let nowTime = new Date();
  686. nowTime =
  687. nowTime.getFullYear() +
  688. "-" +
  689. (nowTime.getMonth() + 1) +
  690. "-" +
  691. nowTime.getDate();
  692. const initSearch = {
  693. teachMode: null, // 教学模式
  694. organIdList: null,
  695. courseStatus: null,
  696. courseType: null,
  697. timer: [nowTime, nowTime], // 时间
  698. class: null,
  699. teachType: null,
  700. mergeCourseType: null,
  701. isCallNames: null, // 是否点名
  702. search: null, // 乐团名称 编号 vip课名称
  703. teacherIdList: null, // 老师编号
  704. schoolId: null, // 教学点编号
  705. creatTimer: [],
  706. courseIdSearch: null,
  707. };
  708. export default {
  709. data() {
  710. return {
  711. classVisible: false,
  712. timerVisible: false,
  713. courseVisible: false,
  714. locationVisible: false,
  715. courseType: courseType,
  716. mergeCourseType,
  717. courseListType: courseListType,
  718. searchForm: { ...initSearch },
  719. tableList: [],
  720. searchLsit: [],
  721. organList: [],
  722. rules: {
  723. // 分页规则
  724. limit: 10, // 限制显示条数
  725. page: 1, // 当前页
  726. total: 0, // 总条数
  727. page_size: [10, 20, 40, 50], // 选择限制显示条数
  728. },
  729. teacherList: [],
  730. schoolList: [],
  731. maskForm: {},
  732. activeName: "first",
  733. id: null,
  734. show: false,
  735. compoundList: [],
  736. deleteList: [],
  737. isMainGo: false,
  738. isDetele: false,
  739. };
  740. },
  741. components: {
  742. pagination,
  743. studentRollCall,
  744. gpsLoction,
  745. studentWork,
  746. courseEvaluate,
  747. resetClass,
  748. teacherList,
  749. addCompound,
  750. infoMsg,
  751. SchoolLocation,
  752. },
  753. created() {
  754. this.searchForm.timer = [nowTime, nowTime];
  755. },
  756. computed: {
  757. workTypeOptions() {
  758. return objectToOptions(workType);
  759. },
  760. mergeCourseTypeOptions() {
  761. return objectToOptions(mergeCourseType);
  762. },
  763. },
  764. mounted() {
  765. const { query } = this.$route;
  766. if (query.start || query.end) {
  767. this.searchForm.timer = [query.start, query.end];
  768. } else {
  769. let flag = false;
  770. for (let item in this.searchForm) {
  771. if (typeof this.searchForm[item] == "object") {
  772. // 对象或者数组
  773. if (this.searchForm[item]?.length > 0) {
  774. flag = true;
  775. }
  776. } else {
  777. if (this.searchForm[item]) {
  778. flag = true;
  779. }
  780. }
  781. }
  782. if (!flag) {
  783. this.searchForm.timer = [nowTime, nowTime];
  784. }
  785. }
  786. // 课程时间段异常,不需要时间搜索
  787. if (query.searchType == "COURSE_TIME_ERROR") {
  788. this.searchForm.timer = [];
  789. }
  790. if (query.organId) {
  791. this.searchForm.organIdList = Number(query.organId);
  792. }
  793. this.$store.dispatch("setBranchs");
  794. this.$store.dispatch("setTeachers");
  795. this.$store.dispatch("setSchools");
  796. this.init();
  797. },
  798. methods: {
  799. init() {
  800. this.getList();
  801. },
  802. setTimeForSearch() {
  803. const { query } = this.$route;
  804. if (query.start || query.end) {
  805. this.searchForm.timer = [query.start, query.end];
  806. } else {
  807. this.searchForm.timer = []
  808. }
  809. },
  810. permission(str, parent) {
  811. return permission(str, parent);
  812. },
  813. reloadSearch(notSetTime) {
  814. if (!notSetTime) {
  815. this.searchForm.timer = [nowTime, nowTime];
  816. }
  817. this.rules.page = 1;
  818. this.getList();
  819. },
  820. async removeCourse(row) {
  821. if (this.deleteList.length < 1 && !row) {
  822. this.$message.error("请自少选择一节课");
  823. return;
  824. }
  825. let flag = false;
  826. let arr = this.deleteList.map((course) => {
  827. if (course.isSettlement || course.status == "UNDERWAY") {
  828. flag = true;
  829. }
  830. return course.id;
  831. });
  832. if (flag) {
  833. this.$message.error("已结算或进行中的课程无法删除");
  834. return;
  835. }
  836. let courseScheduleIds = arr.join(",") || row.id;
  837. this.$confirm("是否确认删除此数据?", "提示", {
  838. type: "warning",
  839. })
  840. .then(() => {
  841. bathDelete({ courseScheduleIds: courseScheduleIds })
  842. .then((res) => {
  843. if (res.code == 200) {
  844. this.$message.success("删除成功");
  845. this.getList();
  846. this.clearCom();
  847. }
  848. })
  849. .catch((e) => {
  850. this.$refs.addCompound.isLook = true;
  851. });
  852. })
  853. .catch((e) => {
  854. this.$refs.addCompound.isLook = true;
  855. });
  856. },
  857. reset() {
  858. this.searchForm = { ...initSearch };
  859. this.search();
  860. },
  861. search() {
  862. this.rules.page = 1;
  863. this.$refs.searchForm.save(this.searchForm);
  864. this.getList();
  865. },
  866. common(row) {
  867. this.searchForm = {
  868. ...initSearch,
  869. timer: [],
  870. courseIdSearch: row.newCourseId,
  871. };
  872. this.search();
  873. },
  874. getSearchForm() {
  875. let searchForm = this.searchForm;
  876. if (!searchForm.timer || searchForm.timer.length <= 0) {
  877. searchForm.timer = [];
  878. // this.$message.error("请选择时间段");
  879. // return;
  880. }
  881. if (!searchForm.creatTimer || searchForm.creatTimer.length <= 0) {
  882. searchForm.creatTimer = [];
  883. }
  884. let count = 0;
  885. for (let item in searchForm) {
  886. if (searchForm[item] && !Array.isArray(searchForm[item])) {
  887. count++;
  888. } else if (
  889. Array.isArray(searchForm[item]) &&
  890. searchForm[item].length > 0
  891. ) {
  892. count++;
  893. }
  894. }
  895. // 课程时间段异常,不需要时间搜索,则课表列表搜索可以不要条件搜索
  896. // if (count <= 0) {
  897. // this.$message.error("请至少选择一个搜索条件");
  898. // return false;
  899. // }
  900. const { creatTimer, timer, ...rest } = searchForm;
  901. return {
  902. ...rest,
  903. page: this.rules.page,
  904. rows: this.rules.limit,
  905. searchType: this.$route.query.searchType,
  906. ...getTimes(creatTimer, ["createStartDate", "createEndDate"]),
  907. ...getTimes(timer, ["startTime", "endTime"]),
  908. };
  909. },
  910. openLocation(school) {
  911. this.locationVisible = true;
  912. },
  913. onCourseExport() {
  914. // 课表导出
  915. if (!this.getSearchForm()) {
  916. return;
  917. }
  918. let url = "/api-web/export/superFindCourseSchedules";
  919. const options = {
  920. method: "get",
  921. headers: {
  922. Authorization: getToken(),
  923. },
  924. params: this.getSearchForm(),
  925. url,
  926. responseType: "blob",
  927. };
  928. this.$confirm("您确定导出报表", "提示", {
  929. confirmButtonText: "确定",
  930. cancelButtonText: "取消",
  931. type: "warning",
  932. })
  933. .then(() => {
  934. load.startLoading();
  935. axios(options)
  936. .then((res) => {
  937. let blob = new Blob([res.data], {
  938. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
  939. type: "application/vnd.ms-excel;charset=utf-8",
  940. //word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  941. });
  942. let text = new Response(blob).text();
  943. text.then((res) => {
  944. // 判断是否报错
  945. if (res.indexOf("code") != -1) {
  946. let json = JSON.parse(res);
  947. this.$message.error(json.msg);
  948. } else {
  949. let objectUrl = URL.createObjectURL(blob);
  950. let link = document.createElement("a");
  951. let fname = "课表列表" + new Date().getTime() + ".xls"; //下载文件的名字
  952. link.href = objectUrl;
  953. link.setAttribute("download", fname);
  954. document.body.appendChild(link);
  955. link.click();
  956. }
  957. });
  958. load.endLoading();
  959. })
  960. .catch((error) => {
  961. this.$message.error("导出数据失败,请联系管理员");
  962. load.endLoading();
  963. });
  964. })
  965. .catch(() => {});
  966. },
  967. getList() {
  968. if (!this.getSearchForm()) {
  969. return;
  970. }
  971. superFindCourseSchedules(this.getSearchForm()).then((res) => {
  972. if (res.code == 200) {
  973. this.tableList = res.data.rows;
  974. this.rules.total = res.data.total;
  975. let idList = this.deleteList.map((course) => {
  976. return course.id;
  977. });
  978. this.isDetele = true;
  979. this.$nextTick(() => {
  980. this.tableList.forEach((course) => {
  981. if (idList.indexOf(course.id) != -1) {
  982. this.$refs.tableList.toggleRowSelection(course, true);
  983. }
  984. });
  985. this.isDetele = false;
  986. });
  987. // let arr = this.$helpers.lodash.differenceWith( this.tableList, this.deleteList,'id')
  988. }
  989. });
  990. },
  991. lookDetail(row) {
  992. // this.maskForm = row;
  993. // 发请求 获取详情 row.id
  994. this.maskForm = row;
  995. this.activeName = "first";
  996. this.classVisible = true;
  997. getTeacherPersonalAttendanceDetail({ courseScheduleId: row.id }).then(
  998. (res) => {
  999. if (res.code == 200) {
  1000. this.maskForm = { ...this.maskForm, ...res.data };
  1001. this.maskForm.id = row.id;
  1002. this.activeName = "first";
  1003. this.classVisible = true;
  1004. this.isMainGo = this.$refs.filterSearch?.show;
  1005. console.log(this.isMainGo);
  1006. }
  1007. }
  1008. );
  1009. },
  1010. handleClick(tab, event) {
  1011. // console.log(tab, event);
  1012. },
  1013. resetClass(row) {
  1014. console.log(row);
  1015. this.id = row.id;
  1016. this.show = true;
  1017. },
  1018. closeReset() {
  1019. this.show = false;
  1020. },
  1021. clearAttend(row) {
  1022. this.$confirm("是否清除考勤记录?", "提示", {
  1023. confirmButtonText: "确定",
  1024. cancelButtonText: "取消",
  1025. type: "warning",
  1026. })
  1027. .then(() => {
  1028. cleanAttendance({ courseScheduleIds: row.id }).then((res) => {
  1029. if (res.code == 200) {
  1030. this.$message.success("清除成功");
  1031. this.getList();
  1032. } else {
  1033. this.$message.error(res.msg);
  1034. }
  1035. });
  1036. })
  1037. .catch(() => {});
  1038. },
  1039. // addCompound(row) {
  1040. // this.compoundList.push(row);
  1041. // this.compoundList = [...new Set(this.compoundList)];
  1042. // },
  1043. // isAddCom(row) {
  1044. // let flag = false;
  1045. // this.compoundList.forEach((com) => {
  1046. // if (com.id == row.id) {
  1047. // flag = true;
  1048. // }
  1049. // });
  1050. // return flag;
  1051. // },
  1052. cancleCompound(row) {
  1053. let indexNum = null;
  1054. this.deleteList.forEach((com, index) => {
  1055. if (com.id == row.id) {
  1056. indexNum = index;
  1057. }
  1058. });
  1059. if (indexNum + "") {
  1060. this.deleteList.splice(indexNum, 1);
  1061. }
  1062. this.tableList.forEach((course, index) => {
  1063. if (course.id == row.id) {
  1064. this.$refs.tableList.toggleRowSelection(course, false);
  1065. }
  1066. });
  1067. if (this.deleteList.length <= 0) {
  1068. this.clearCom();
  1069. }
  1070. },
  1071. clearCom() {
  1072. // this.deleteList = [];
  1073. this.$set(this, "deleteList", []);
  1074. this.$refs.tableList.clearSelection();
  1075. this.$refs.addCompound.isLook = false;
  1076. },
  1077. resetCompound(row) {
  1078. this.$confirm("您确定取消合并该课程?", "提示", {
  1079. confirmButtonText: "确定",
  1080. cancelButtonText: "取消",
  1081. type: "warning",
  1082. })
  1083. .then(() => {
  1084. cancelCourseMerge({ mainCourseId: row.id }).then((res) => {
  1085. if (res.code == 200) {
  1086. this.$message.success("提交成功");
  1087. this.getList();
  1088. }
  1089. });
  1090. })
  1091. .catch(() => {});
  1092. },
  1093. handleSelectionChange(arr) {
  1094. // this.deleteList = arr;
  1095. if (arr.length > 0) {
  1096. // 有可能加 有可能减
  1097. this.deleteList = this.deleteList.concat(arr);
  1098. // 去重
  1099. this.deleteList = this.$helpers.lodash.uniqBy(this.deleteList, "id");
  1100. }
  1101. // else if(){}
  1102. else {
  1103. if (this.isDetele) return;
  1104. // 有2种 1是新页
  1105. // 2是点击反选
  1106. let idList = this.deleteList.map((course) => {
  1107. return course.id;
  1108. });
  1109. this.$nextTick(() => {
  1110. let tableIdList = [];
  1111. this.tableList.forEach((course) => {
  1112. tableIdList.push(course.id);
  1113. if (idList.indexOf(course.id) != -1) {
  1114. this.$refs.tableList.toggleRowSelection(course, false);
  1115. // 删除这个元素
  1116. }
  1117. });
  1118. this.deleteList = this.$helpers.lodash.remove(
  1119. this.deleteList,
  1120. function (item) {
  1121. return tableIdList.indexOf(item.id) == -1;
  1122. }
  1123. );
  1124. if (this.deleteList.length <= 0) {
  1125. this.clearCom();
  1126. }
  1127. });
  1128. }
  1129. },
  1130. gotoCourse(row) {
  1131. if (row.groupType == "MUSIC") {
  1132. this.$router.push({
  1133. path: "/teamList",
  1134. query: { search: row.musicGroupId },
  1135. });
  1136. } else if (row.groupType == "VIP") {
  1137. this.$router.push({
  1138. path: "/vipManager/vipList",
  1139. query: { search: row.musicGroupId },
  1140. });
  1141. } else if (row.groupType == "PRACTICE") {
  1142. this.$router.push({
  1143. path: "/accompanyManager/accompany",
  1144. query: { search: row.musicGroupId },
  1145. });
  1146. }
  1147. },
  1148. onTableSelect(rows, row) {
  1149. let idList = this.deleteList.map((course) => {
  1150. return course.id;
  1151. });
  1152. if (idList.indexOf(row.id) != -1) {
  1153. this.deleteList.splice(idList.indexOf(row.id), 1);
  1154. if (this.deleteList.length <= 0) {
  1155. this.clearCom();
  1156. }
  1157. }
  1158. },
  1159. },
  1160. filters: {
  1161. isCall(val) {
  1162. if (val == 0) {
  1163. return "未点名";
  1164. } else if (val == 1) {
  1165. return "已点名";
  1166. }
  1167. },
  1168. },
  1169. watch: {
  1170. classVisible(val) {
  1171. if (!val) {
  1172. this.activeName = null;
  1173. }
  1174. },
  1175. },
  1176. };
  1177. </script>
  1178. <style lang="scss" scoped>
  1179. .visible {
  1180. visibility: hidden;
  1181. }
  1182. .cl-container {
  1183. .topFrom {
  1184. margin: 20px 30px 0;
  1185. .classlist {
  1186. display: flex;
  1187. flex-direction: row;
  1188. justify-content: flex-start;
  1189. align-items: center;
  1190. ul {
  1191. li {
  1192. list-style: none;
  1193. }
  1194. }
  1195. }
  1196. }
  1197. .searchForm {
  1198. margin: 0 30px;
  1199. }
  1200. }
  1201. .btnWraps {
  1202. display: flex;
  1203. flex-direction: row;
  1204. justify-content: flex-start;
  1205. div {
  1206. margin-right: 20px;
  1207. }
  1208. }
  1209. .inputStyle {
  1210. width: 180px;
  1211. }
  1212. .red {
  1213. color: red;
  1214. }
  1215. .exportBtn {
  1216. background: #13817a;
  1217. }
  1218. .newBand {
  1219. margin-top: 30px;
  1220. }
  1221. </style>