errorCourse.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. <template>
  2. <div>
  3. <div class="m-core">
  4. <!-- 搜索类型 -->
  5. <save-form
  6. :inline="true"
  7. class="searchForm"
  8. @submit="search"
  9. @reset="reset"
  10. ref="searchForm"
  11. :model.sync="searchForm"
  12. >
  13. <el-form-item>
  14. <el-input
  15. type="number"
  16. v-model.trim="searchForm.courseIdSearch"
  17. clearable
  18. placeholder="课程编号"
  19. />
  20. </el-form-item>
  21. <el-form-item>
  22. <remote-search
  23. :commit="'setTeachers'"
  24. v-model="searchForm.teacherIdList"
  25. />
  26. </el-form-item>
  27. <el-form-item>
  28. <el-select
  29. v-model.trim="searchForm.courseType"
  30. clearable
  31. filterable
  32. placeholder="课程类型"
  33. >
  34. <el-option
  35. v-for="(item, index) in courseType"
  36. :key="index"
  37. :value="item.value"
  38. :label="item.label"
  39. ></el-option>
  40. </el-select>
  41. </el-form-item>
  42. <el-form-item>
  43. <el-select
  44. v-model.trim="searchForm.courseStatus"
  45. clearable
  46. filterable
  47. placeholder="课程状态"
  48. >
  49. <el-option label="未开始" value="NOT_START"></el-option>
  50. <el-option label="进行中" value="UNDERWAY"></el-option>
  51. <el-option label="已结束" value="OVER"></el-option>
  52. </el-select>
  53. </el-form-item>
  54. <el-form-item>
  55. <el-date-picker
  56. v-model.trim="searchForm.timer"
  57. type="daterange"
  58. value-format="yyyy-MM-dd"
  59. range-separator="至"
  60. start-placeholder="上课开始日期"
  61. end-placeholder="上课结束日期"
  62. :picker-options="{
  63. firstDayOfWeek: 1,
  64. }"
  65. ></el-date-picker>
  66. </el-form-item>
  67. <el-form-item>
  68. <el-button
  69. :type="isSearch ? 'primary' : 'info'"
  70. icon="el-icon-circle-plus-outline"
  71. @click="showMove = true"
  72. >更多选项</el-button
  73. >
  74. </el-form-item>
  75. <el-form-item>
  76. <el-button native-type="submit" type="primary">搜索</el-button>
  77. <el-button native-type="reset" type="danger">重置</el-button>
  78. </el-form-item>
  79. </save-form>
  80. <!-- 列表 -->
  81. <div class="tableWrap">
  82. <el-table
  83. :data="tableList"
  84. ref="tableList"
  85. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  86. row-key="id"
  87. >
  88. >
  89. <el-table-column
  90. align="center"
  91. prop="organName"
  92. label="分部名称"
  93. ></el-table-column>
  94. <el-table-column
  95. align="center"
  96. width="170px"
  97. prop="musicGroupId"
  98. label="乐团/课程组编号"
  99. >
  100. <template slot-scope="scope">
  101. <el-button type="text" @click="gotoCourse(scope.row)">
  102. <copy-text>{{ scope.row.musicGroupId }}</copy-text>
  103. </el-button>
  104. </template>
  105. </el-table-column>
  106. <el-table-column
  107. align="center"
  108. prop="id"
  109. width="100px"
  110. label="课程编号"
  111. >
  112. <template slot-scope="scope">
  113. <copy-text>{{ scope.row.id }}</copy-text>
  114. </template>
  115. </el-table-column>
  116. <el-table-column align="center" width="200px" label="上课时间">
  117. <template slot-scope="scope"
  118. >{{
  119. scope.row.startClassTime
  120. ? scope.row.startClassTime.substr(0, 16)
  121. : ""
  122. }}-{{
  123. scope.row.endClassTime
  124. ? scope.row.endClassTime.substr(11, 5)
  125. : ""
  126. }}</template
  127. >
  128. </el-table-column>
  129. <el-table-column
  130. align="center"
  131. prop="subjectName"
  132. label="声部"
  133. ></el-table-column>
  134. <el-table-column prop="name" width="150px" label="课程名称">
  135. <template slot-scope="scope">
  136. <copy-text>{{ scope.row.name }}</copy-text>
  137. </template>
  138. </el-table-column>
  139. <el-table-column align="center" width="150px" label="课程类型">
  140. <template slot-scope="scope">
  141. <div>{{ scope.row.type | coursesType }}</div>
  142. </template>
  143. </el-table-column>
  144. <el-table-column align="center" label="教学模式">
  145. <template slot-scope="scope">
  146. <div>{{ scope.row.teachMode | teachMode }}</div>
  147. </template>
  148. </el-table-column>
  149. <el-table-column
  150. align="center"
  151. prop="teacherName"
  152. width="110"
  153. label="主教老师"
  154. ></el-table-column>
  155. <el-table-column align="center" prop="schoolName" label="教学点">
  156. <template slot-scope="scope">
  157. <div>
  158. {{ scope.row.schoolName ? scope.row.schoolName : "网络教室" }}
  159. </div>
  160. </template>
  161. </el-table-column>
  162. <el-table-column
  163. align="center"
  164. prop="courseScheduleStatus"
  165. label="课程状态"
  166. >
  167. <template slot-scope="scope">
  168. <div>{{ scope.row.status | coursesStatus }}</div>
  169. </template>
  170. </el-table-column>
  171. <el-table-column align="center" label="考勤申诉">
  172. <template slot-scope="scope">
  173. <div>{{ scope.row.isComplaints == 1 ? "是" : "否" }}</div>
  174. </template>
  175. </el-table-column>
  176. <el-table-column align="center" prop="isLock" label="是否冻结">
  177. <template slot-scope="scope">{{
  178. scope.row.isLock ? "是" : "否"
  179. }}</template>
  180. </el-table-column>
  181. <el-table-column align="center" label="产生时间">
  182. <template slot-scope="scope">
  183. <div>
  184. {{ scope.row.generateTime }}
  185. </div>
  186. </template>
  187. </el-table-column>
  188. <el-table-column align="center" label="处理时间">
  189. <template slot-scope="scope">
  190. <div>
  191. {{ scope.row.dealTime }}
  192. </div>
  193. </template>
  194. </el-table-column>
  195. <el-table-column
  196. align="center"
  197. prop="isCallNames"
  198. label="是否点名"
  199. fixed="right"
  200. >
  201. <template slot-scope="scope">{{
  202. scope.row.isCallNames ? "是" : "否"
  203. }}</template>
  204. </el-table-column>
  205. <el-table-column
  206. align="center"
  207. label="详情"
  208. fixed="right"
  209. width="220px"
  210. >
  211. <template slot-scope="scope">
  212. <div>
  213. <auth auths="/teamCourseListDetail">
  214. <el-button type="text" @click="lookDetail(scope.row)"
  215. >查看</el-button
  216. >
  217. </auth>
  218. </div>
  219. </template>
  220. </el-table-column>
  221. </el-table>
  222. <pagination
  223. :total.sync="rules.total"
  224. :page.sync="rules.page"
  225. :limit.sync="rules.limit"
  226. :page-sizes="rules.page_size"
  227. @pagination="getList"
  228. sync
  229. />
  230. </div>
  231. </div>
  232. <el-dialog
  233. title="更多选项"
  234. :visible.sync="showMove"
  235. v-if="showMove"
  236. width="700px"
  237. >
  238. <el-form
  239. :inline="true"
  240. class="searchForm"
  241. @submit="search"
  242. @reset="reset"
  243. ref="searchForm2"
  244. :model.sync="searchForm"
  245. label-width="120px"
  246. >
  247. <el-form-item label="课程组编号/名称" prop="search">
  248. <el-input
  249. style="width: 180px"
  250. v-model.trim="searchForm.search"
  251. clearable
  252. placeholder="课程组编号/课程名称"
  253. />
  254. </el-form-item>
  255. <el-form-item label="教学点" prop="schoolId">
  256. <el-select
  257. style="width: 180px"
  258. v-model.trim="searchForm.schoolId"
  259. clearable
  260. filterable
  261. placeholder="请选择教学点"
  262. >
  263. <el-option
  264. v-for="(item, index) in selects.schools"
  265. :key="index"
  266. :value="item.id"
  267. :label="item.name"
  268. ></el-option>
  269. </el-select>
  270. </el-form-item>
  271. <el-form-item label="分部" prop="organIdList">
  272. <el-select
  273. style="width: 180px"
  274. class="multiple"
  275. v-model.trim="searchForm.organIdList"
  276. filterable
  277. clearable
  278. placeholder="请选择分部"
  279. >
  280. <el-option
  281. v-for="(item, index) in selects.branchs"
  282. :key="index"
  283. :label="item.name"
  284. :value="item.id"
  285. ></el-option>
  286. </el-select>
  287. </el-form-item>
  288. <el-form-item label="课程组类型" prop="groupType">
  289. <el-select
  290. style="width: 180px"
  291. v-model.trim="searchForm.groupType"
  292. clearable
  293. filterable
  294. placeholder="课程组类型"
  295. >
  296. <el-option
  297. v-for="item in courseListType"
  298. :key="item.value"
  299. :value="item.value"
  300. :label="item.label"
  301. ></el-option>
  302. </el-select>
  303. </el-form-item>
  304. <el-form-item label="教学模式" prop="teachMode">
  305. <el-select
  306. style="width: 180px"
  307. v-model.trim="searchForm.teachMode"
  308. clearable
  309. filterable
  310. placeholder="教学模式"
  311. >
  312. <el-option label="线上课" value="ONLINE"></el-option>
  313. <el-option label="线下课" value="OFFLINE"></el-option>
  314. </el-select>
  315. </el-form-item>
  316. <el-form-item label="合并课类型" prop="mergeCourseType">
  317. <el-select
  318. style="width: 180px"
  319. v-model.trim="searchForm.mergeCourseType"
  320. clearable
  321. filterable
  322. placeholder="合并课程类型"
  323. >
  324. <el-option
  325. v-for="(item, index) in mergeCourseTypeOptions"
  326. :key="index"
  327. :value="item.value"
  328. :label="item.label"
  329. ></el-option>
  330. </el-select>
  331. </el-form-item>
  332. <el-form-item label="老师类型" prop="teachType">
  333. <el-select
  334. style="width: 180px"
  335. v-model.trim="searchForm.teachType"
  336. clearable
  337. filterable
  338. placeholder="老师类型"
  339. >
  340. <el-option
  341. v-for="item in workTypeOptions"
  342. :key="item.label"
  343. :label="item.label"
  344. :value="item.value"
  345. ></el-option>
  346. </el-select>
  347. </el-form-item>
  348. <el-form-item label="是否点名" prop="isCallNames">
  349. <el-select
  350. style="width: 180px"
  351. v-model.trim="searchForm.isCallNames"
  352. clearable
  353. filterable
  354. placeholder="是否点名"
  355. >
  356. <el-option label="是" value="1"></el-option>
  357. <el-option label="否" value="0"></el-option>
  358. </el-select>
  359. </el-form-item>
  360. <el-form-item label="创建日期" prop="creatTimer">
  361. <el-date-picker
  362. v-model.trim="searchForm.creatTimer"
  363. type="daterange"
  364. value-format="yyyy-MM-dd"
  365. range-separator="-"
  366. start-placeholder="创建开始日期"
  367. end-placeholder="创建结束日期"
  368. :picker-options="{
  369. firstDayOfWeek: 1,
  370. }"
  371. ></el-date-picker>
  372. </el-form-item>
  373. </el-form>
  374. <span slot="footer" class="dialog-footer">
  375. <el-button @click="cancleMore">取 消</el-button>
  376. <el-button type="primary" @click="okMore">确 定</el-button>
  377. </span>
  378. </el-dialog>
  379. <!-- showMove -->
  380. </div>
  381. </template>
  382. <script>
  383. import pagination from "@/components/Pagination/index";
  384. import {
  385. superFindCourseSchedules,
  386. cleanAttendance,
  387. cancelCourseMerge,
  388. } from "@/api/buildTeam";
  389. import { bathDelete } from "@/api/vipSeting";
  390. import { workType, mergeCourseType } from "@/constant";
  391. import { objectToOptions, getTimes } from "@/utils";
  392. import { getTeacherPersonalAttendanceDetail } from "@/api/teacherManager";
  393. import { courseType, courseListType } from "@/utils/searchArray";
  394. import { permission } from "@/utils/directivePage";
  395. import { getHistoryErrCourse } from "../api";
  396. let nowTime = new Date();
  397. nowTime =
  398. nowTime.getFullYear() +
  399. "-" +
  400. (nowTime.getMonth() + 1) +
  401. "-" +
  402. nowTime.getDate();
  403. const initSearch = {
  404. teachMode: null, // 教学模式
  405. organIdList: null,
  406. courseStatus: null,
  407. courseType: null,
  408. timer: [], // 时间
  409. class: null,
  410. teachType: null,
  411. mergeCourseType: null,
  412. isCallNames: null, // 是否点名
  413. search: null, // 乐团名称 编号 vip课名称
  414. teacherIdList: null, // 老师编号
  415. schoolId: null, // 教学点编号
  416. creatTimer: [],
  417. courseIdSearch: null,
  418. };
  419. export default {
  420. props:['searchType'],
  421. data() {
  422. return {
  423. classVisible: false,
  424. timerVisible: false,
  425. courseVisible: false,
  426. locationVisible: false,
  427. courseType: courseType,
  428. mergeCourseType,
  429. courseListType: courseListType,
  430. searchForm: { ...initSearch },
  431. tableList: [],
  432. searchLsit: [],
  433. organList: [],
  434. rules: {
  435. // 分页规则
  436. limit: 10, // 限制显示条数
  437. page: 1, // 当前页
  438. total: 0, // 总条数
  439. page_size: [10, 20, 40, 50], // 选择限制显示条数
  440. },
  441. teacherList: [],
  442. schoolList: [],
  443. maskForm: {},
  444. activeName: "first",
  445. id: null,
  446. show: false,
  447. compoundList: [],
  448. deleteList: [],
  449. isMainGo: false,
  450. isDetele: false,
  451. showMove: false,
  452. };
  453. },
  454. components: {
  455. pagination,
  456. },
  457. created() {
  458. // this.searchForm.timer = [nowTime, nowTime];
  459. },
  460. computed: {
  461. workTypeOptions() {
  462. return objectToOptions(workType);
  463. },
  464. mergeCourseTypeOptions() {
  465. return objectToOptions(mergeCourseType);
  466. },
  467. isSearch() {
  468. return (
  469. this.searchForm.search ||
  470. this.searchForm.schoolId ||
  471. this.searchForm.organIdList ||
  472. this.searchForm.groupType ||
  473. this.searchForm.teachMode ||
  474. this.searchForm.mergeCourseType ||
  475. this.searchForm.teachType ||
  476. this.searchForm.isCallNames ||
  477. this.searchForm.creatTimer?.length > 0
  478. );
  479. },
  480. },
  481. mounted() {
  482. const { query } = this.$route;
  483. if (query.start || query.end) {
  484. this.searchForm.timer = [query.start, query.end];
  485. } else {
  486. let flag = false;
  487. for (let item in this.searchForm) {
  488. if (typeof this.searchForm[item] == "object") {
  489. // 对象或者数组
  490. if (this.searchForm[item]?.length > 0) {
  491. flag = true;
  492. }
  493. } else {
  494. if (this.searchForm[item]) {
  495. flag = true;
  496. }
  497. }
  498. }
  499. if (!flag) {
  500. this.searchForm.timer = [];
  501. }
  502. }
  503. // 课程时间段异常,不需要时间搜索
  504. if (query.searchType == "COURSE_TIME_ERROR") {
  505. this.searchForm.timer = [];
  506. }
  507. if (query.organId) {
  508. this.searchForm.organIdList = Number(query.organId);
  509. }
  510. this.$store.dispatch("setBranchs");
  511. this.$store.dispatch("setTeachers");
  512. this.$store.dispatch("setSchools");
  513. this.init();
  514. },
  515. methods: {
  516. init() {
  517. this.getList();
  518. },
  519. setTimeForSearch() {
  520. const { query } = this.$route;
  521. if (query.start || query.end) {
  522. this.searchForm.timer = [query.start, query.end];
  523. } else {
  524. this.searchForm.timer = [];
  525. }
  526. },
  527. permission(str, parent) {
  528. return permission(str, parent);
  529. },
  530. reloadSearch(notSetTime) {
  531. if (!notSetTime) {
  532. this.searchForm.timer = [nowTime, nowTime];
  533. }
  534. this.rules.page = 1;
  535. this.getList();
  536. },
  537. reset() {
  538. this.searchForm = { ...initSearch };
  539. this.search();
  540. },
  541. search() {
  542. this.rules.page = 1;
  543. this.$refs.searchForm.save(this.searchForm);
  544. this.getList();
  545. },
  546. common(row) {
  547. this.searchForm = {
  548. ...initSearch,
  549. timer: [],
  550. courseIdSearch: row.newCourseId,
  551. };
  552. this.search();
  553. },
  554. getSearchForm() {
  555. let searchForm = this.searchForm;
  556. if (!searchForm.timer || searchForm.timer.length <= 0) {
  557. searchForm.timer = [];
  558. // this.$message.error("请选择时间段");
  559. // return;
  560. }
  561. if (!searchForm.creatTimer || searchForm.creatTimer.length <= 0) {
  562. searchForm.creatTimer = [];
  563. }
  564. let count = 0;
  565. for (let item in searchForm) {
  566. if (searchForm[item] && !Array.isArray(searchForm[item])) {
  567. count++;
  568. } else if (
  569. Array.isArray(searchForm[item]) &&
  570. searchForm[item].length > 0
  571. ) {
  572. count++;
  573. }
  574. }
  575. // 课程时间段异常,不需要时间搜索,则课表列表搜索可以不要条件搜索
  576. // if (count <= 0) {
  577. // this.$message.error("请至少选择一个搜索条件");
  578. // return false;
  579. // }
  580. const { creatTimer, timer, ...rest } = searchForm;
  581. return {
  582. ...rest,
  583. page: this.rules.page,
  584. rows: this.rules.limit,
  585. searchType: this.searchType,
  586. ...getTimes(creatTimer, ["createStartDate", "createEndDate"]),
  587. ...getTimes(timer, ["startTime", "endTime"]),
  588. };
  589. },
  590. async getList() {
  591. if (!this.getSearchForm()) {
  592. return;
  593. }
  594. try {
  595. const res = await getHistoryErrCourse(this.getSearchForm());
  596. this.tableList = res.data.rows;
  597. this.rules.total = res.data.total;
  598. } catch (e) {
  599. console.log(e);
  600. }
  601. // superFindCourseSchedules(this.getSearchForm()).then((res) => {
  602. // if (res.code == 200) {
  603. // this.tableList = res.data.rows;
  604. // this.rules.total = res.data.total;
  605. // let idList = this.deleteList.map((course) => {
  606. // return course.id;
  607. // });
  608. // this.isDetele = true;
  609. // this.$nextTick(() => {
  610. // this.tableList.forEach((course) => {
  611. // if (idList.indexOf(course.id) != -1) {
  612. // this.$refs.tableList.toggleRowSelection(course, true);
  613. // }
  614. // });
  615. // this.isDetele = false;
  616. // });
  617. // // let arr = this.$helpers.lodash.differenceWith( this.tableList, this.deleteList,'id')
  618. // }
  619. // });
  620. },
  621. lookDetail(row) {
  622. this.$router.push({path:'/teamCourseList'})
  623. // this.maskForm = row;
  624. // 发请求 获取详情 row.id
  625. // this.maskForm = row;
  626. // this.activeName = "first";
  627. // this.classVisible = true;
  628. // getTeacherPersonalAttendanceDetail({ courseScheduleId: row.id }).then(
  629. // (res) => {
  630. // if (res.code == 200) {
  631. // this.maskForm = { ...this.maskForm, ...res.data };
  632. // this.maskForm.id = row.id;
  633. // this.activeName = "first";
  634. // this.classVisible = true;
  635. // this.isMainGo = this.$refs.filterSearch?.show;
  636. // }
  637. // }
  638. // );
  639. },
  640. resetClass(row) {
  641. this.id = row.id;
  642. this.show = true;
  643. },
  644. closeReset() {
  645. this.show = false;
  646. },
  647. gotoCourse(row) {
  648. if (row.groupType == "MUSIC") {
  649. this.$router.push({
  650. path: "/teamList",
  651. query: { search: row.musicGroupId },
  652. });
  653. } else if (row.groupType == "VIP") {
  654. this.$router.push({
  655. path: "/vipManager/vipList",
  656. query: { search: row.musicGroupId },
  657. });
  658. } else if (row.groupType == "PRACTICE") {
  659. this.$router.push({
  660. path: "/accompanyManager/accompany",
  661. query: { search: row.musicGroupId },
  662. });
  663. }
  664. },
  665. },
  666. filters: {
  667. isCall(val) {
  668. if (val == 0) {
  669. return "未点名";
  670. } else if (val == 1) {
  671. return "已点名";
  672. }
  673. },
  674. },
  675. watch: {
  676. classVisible(val) {
  677. if (!val) {
  678. this.activeName = null;
  679. }
  680. },
  681. },
  682. };
  683. </script>
  684. <style lang="scss" scoped>
  685. .visible {
  686. visibility: hidden;
  687. }
  688. .cl-container {
  689. .topFrom {
  690. margin: 20px 30px 0;
  691. .classlist {
  692. display: flex;
  693. flex-direction: row;
  694. justify-content: flex-start;
  695. align-items: center;
  696. ul {
  697. li {
  698. list-style: none;
  699. }
  700. }
  701. }
  702. }
  703. .searchForm {
  704. margin: 0 30px;
  705. }
  706. }
  707. .btnWraps {
  708. display: flex;
  709. flex-direction: row;
  710. justify-content: flex-start;
  711. div {
  712. margin-right: 20px;
  713. }
  714. }
  715. .inputStyle {
  716. width: 180px;
  717. }
  718. .red {
  719. color: red;
  720. }
  721. .green {
  722. color: #14928a;
  723. }
  724. .exportBtn {
  725. background: #13817a;
  726. }
  727. .newBand {
  728. margin-top: 30px;
  729. }
  730. </style>