serverIndexList.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. <!-- -->
  2. <template>
  3. <div class="m-container">
  4. <h2>
  5. <div class="squrt"></div>服务指标
  6. </h2>
  7. <div class="m-core">
  8. <el-form :inline="true"
  9. :model="searchForm">
  10. <el-form-item>
  11. <el-input v-model.trim="searchForm.search"
  12. @keyup.enter.native="search"
  13. placeholder="学生姓名"></el-input>
  14. </el-form-item>
  15. <el-form-item>
  16. <el-select placeholder="指导老师"
  17. v-model="searchForm.teacherId"
  18. clearable
  19. filterable>
  20. <el-option v-for="(item,index) in teacherList"
  21. :label="item.realName"
  22. :value="item.id"
  23. :key="index"></el-option>
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item prop="organId">
  27. <el-select class="multiple"
  28. v-model.trim="searchForm.organIdList"
  29. filterable
  30. clearable
  31. placeholder="请选择分部">
  32. <el-option v-for="(item,index) in organList"
  33. :key="index"
  34. :label="item.name"
  35. :value="item.id"></el-option>
  36. </el-select>
  37. </el-form-item>
  38. <!-- <el-form-item>
  39. <el-select placeholder="当前有VIP课" v-model="searchForm.existVipCourse" clearable>
  40. <el-option label="是" value="1"></el-option>
  41. <el-option label="否" value="0"></el-option>
  42. </el-select>
  43. </el-form-item> -->
  44. <el-form-item>
  45. <el-select placeholder="实际安排"
  46. v-model="searchForm.actualExercisesNumIsAchieve"
  47. clearable>
  48. <el-option label="符合预期"
  49. value="1"></el-option>
  50. <el-option label="不符合预期"
  51. value="0"></el-option>
  52. </el-select>
  53. </el-form-item>
  54. <el-form-item>
  55. <el-select placeholder="提交次数"
  56. v-model="searchForm.exercisesReplyNumIsAchieve"
  57. clearable>
  58. <el-option label="符合预期"
  59. value="1"></el-option>
  60. <el-option label="不符合预期"
  61. value="0"></el-option>
  62. </el-select>
  63. </el-form-item>
  64. <el-form-item>
  65. <el-select placeholder="评价次数"
  66. v-model="searchForm.exercisesMessageNumIsAchieve"
  67. clearable>
  68. <el-option label="符合预期"
  69. value="1"></el-option>
  70. <el-option label="不符合预期"
  71. value="0"></el-option>
  72. </el-select>
  73. </el-form-item>
  74. <el-form-item>
  75. <el-select placeholder="及时评价"
  76. v-model="searchForm.exercisesMessageTimelyNumIsAchieve"
  77. clearable>
  78. <el-option label="符合预期"
  79. value="1"></el-option>
  80. <el-option label="不符合预期"
  81. value="0"></el-option>
  82. </el-select>
  83. </el-form-item>
  84. <el-form-item>
  85. <el-select placeholder="是否有VIP课"
  86. v-model="searchForm.existVipCourse"
  87. clearable>
  88. <el-option label="是"
  89. value="1"></el-option>
  90. <el-option label="否"
  91. value="0"></el-option>
  92. </el-select>
  93. </el-form-item>
  94. <el-form-item>
  95. <el-select placeholder="是否有付费网管课"
  96. v-model="searchForm.existPracticeCourse"
  97. clearable>
  98. <el-option label="是"
  99. value="1"></el-option>
  100. <el-option label="否"
  101. value="0"></el-option>
  102. </el-select>
  103. </el-form-item>
  104. <br>
  105. <el-form-item label="周次选择">
  106. <el-date-picker v-model.trim="searchForm.timer"
  107. style="width:400px;"
  108. type="daterange"
  109. :picker-options="{
  110. firstDayOfWeek: 1
  111. }"
  112. value-format="yyyy-MM-dd"
  113. range-separator="至"
  114. start-placeholder="周次开始日期"
  115. end-placeholder="周次结束日期"
  116. @change="getWeekTime"></el-date-picker>
  117. </el-form-item>
  118. <el-form-item label="作业提交时间">
  119. <el-date-picker v-model.trim="searchForm.workTimer"
  120. style="width:400px;"
  121. type="daterange"
  122. :picker-options="{
  123. firstDayOfWeek: 1
  124. }"
  125. value-format="yyyy-MM-dd"
  126. range-separator="至"
  127. start-placeholder="提交开始日期"
  128. end-placeholder="提交结束日期"></el-date-picker>
  129. </el-form-item>
  130. <el-form-item>
  131. <el-button type="danger"
  132. @click="search">搜索</el-button>
  133. <el-button @click="onReSet"
  134. type="primary">重置</el-button>
  135. <el-button @click="onExport"
  136. type="primary"
  137. v-permission="'export/exercisesSituations'"
  138. style=" background: #14928a; border:1px solid #14928a;">导出</el-button>
  139. </el-form-item>
  140. </el-form>
  141. <div class="tableWrap">
  142. <el-table style="width: 100%"
  143. :header-cell-style="{background:'#EDEEF0',color:'#444'}"
  144. :data="tableList">
  145. <el-table-column align="center"
  146. prop="studentId"
  147. label="学员编号"></el-table-column>
  148. <el-table-column align="center"
  149. prop="studentName"
  150. label="学生姓名"></el-table-column>
  151. <el-table-column align="center"
  152. prop="organName"
  153. label="所属分部"></el-table-column>
  154. <el-table-column align="center"
  155. prop="groupNames"
  156. label="乐团名称"></el-table-column>
  157. <el-table-column align="center"
  158. prop="teacherName"
  159. label="指导老师"></el-table-column>
  160. <el-table-column align="center"
  161. prop="educationalTeacherName"
  162. label="乐团主管"></el-table-column>
  163. <el-table-column align="center"
  164. prop="courseIds"
  165. width="100"
  166. label="服务课程">
  167. <template slot-scope="scope">
  168. <copy-text>{{scope.row.courseIds || '课外训练'}}</copy-text>
  169. </template>
  170. </el-table-column>
  171. <!-- <el-table-column align="center" label="当前有VIP课" width="100" >
  172. <template slot-scope="scope">
  173. <div>{{scope.row.existVipCourse?'是':'否'}}</div>
  174. </template>
  175. </el-table-column> -->
  176. <el-table-column align="center"
  177. label="预期安排">
  178. <template slot-scope="scope">
  179. <div>{{scope.row.expectExercisesNum+'次'}}</div>
  180. </template>
  181. </el-table-column>
  182. <el-table-column align="center"
  183. width="120"
  184. prop>
  185. <template slot="header"
  186. slot-scope="scope">
  187. <p style="position: relative; "> 实际安排 <el-tooltip placement="top"
  188. popper-class="mTooltip">
  189. <div slot="content">
  190. 以周为单位,实际发生一次课外训练或网管课作业布置,记一次,一周只统计一次
  191. </div>
  192. <!-- <img :src="imageIcon"
  193. class="micon el-tooltip"
  194. style="width:8px height:8px"
  195. alt /> -->
  196. <i class="el-icon-question"
  197. style="font-size: 18px; color: #F56C6C"></i>
  198. </el-tooltip>
  199. </p>
  200. </template>
  201. <template slot-scope="scope">
  202. <div>{{scope.row.actualExercisesNum+'次'}}</div>
  203. </template>
  204. </el-table-column>
  205. <el-table-column align="center"
  206. prop
  207. label="提交次数">
  208. <template slot-scope="scope">
  209. <div>{{scope.row.exercisesReplyNum+'次'}}</div>
  210. </template>
  211. </el-table-column>
  212. <el-table-column align="center"
  213. prop
  214. label="评价次数">
  215. <template slot-scope="scope">
  216. <div>{{scope.row.exercisesMessageNum+'次'}}</div>
  217. </template>
  218. </el-table-column>
  219. <el-table-column align="center"
  220. prop
  221. label="及时评价次数">
  222. <template slot-scope="scope">
  223. <div>{{scope.row.exercisesMessageTimelyNum+'次'}}</div>
  224. </template>
  225. </el-table-column>
  226. <el-table-column align="center"
  227. label="VIP课">
  228. <template slot-scope="scope">
  229. <div>{{scope.row.existVipCourse + '节'}}</div>
  230. </template>
  231. </el-table-column>
  232. <el-table-column align="center"
  233. label="付费网管课">
  234. <template slot-scope="scope">
  235. <div>{{scope.row.existPracticeCourse+ '节'}}</div>
  236. </template>
  237. </el-table-column>
  238. <el-table-column align="center"
  239. label="作业提交时间">
  240. <template slot-scope="scope">
  241. <div>{{scope.row.lastSubmitTime}}</div>
  242. </template>
  243. </el-table-column>
  244. <el-table-column align="center"
  245. width="120"
  246. label="服务周期">
  247. <template slot-scope="scope">
  248. <div>{{dayjs(scope.row.monday).format('YYYY-MM-DD')}}</div>
  249. <div>{{dayjs(scope.row.sunday).format('YYYY-MM-DD')}}</div>
  250. </template>
  251. </el-table-column>
  252. <el-table-column align="center"
  253. label="操作">
  254. <!-- -->
  255. <template slot-scope="scope">
  256. <div v-if="scope.row.actualExercisesNum >0">
  257. <el-button type="text"
  258. @click="lookDetail(scope.row)">查看</el-button>
  259. </div>
  260. </template>
  261. </el-table-column>
  262. </el-table>
  263. <pagination :total="rules.total"
  264. :page.sync="rules.page"
  265. :limit.sync="rules.limit"
  266. :page-sizes="rules.page_size"
  267. @pagination="getList" />
  268. </div>
  269. </div>
  270. </div>
  271. </template>
  272. <script>
  273. import axios from "axios";
  274. import { getToken } from "@/utils/auth";
  275. import pagination from "@/components/Pagination/index";
  276. import load from "@/utils/loading";
  277. import dayjs from 'dayjs'
  278. import { getEmployeeOrgan, getTeacher } from "@/api/buildTeam";
  279. import { findStudentExtracurricularExercisesSituations } from "@/api/afterSchool";
  280. // findStudentExtracurricularExercisesSituations
  281. let nowTime = new Date();
  282. nowTime =
  283. nowTime.getFullYear() +
  284. "-" +
  285. (nowTime.getMonth() + 1) +
  286. "-" +
  287. nowTime.getDate();
  288. export default {
  289. components: { pagination },
  290. data () {
  291. return {
  292. tableList: [],
  293. searchForm: {
  294. timer: [],
  295. search: null,
  296. organIdList: null,
  297. actualExercisesNumIsAchieve: null, // 训练次数
  298. exercisesMessageNumIsAchieve: null, //评价
  299. exercisesMessageTimelyNumIsAchieve: null, //及时评价
  300. exercisesReplyNumIsAchieve: null, // 提交次数
  301. teacherId: null,
  302. existVipCourse: null,
  303. existPracticeCourse: null,
  304. workTimer: []
  305. },
  306. organList: [],
  307. teacherList: [],
  308. rules: {
  309. // 分页规则
  310. limit: 10, // 限制显示条数
  311. page: 1, // 当前页
  312. total: 0, // 总条数
  313. page_size: [10, 20, 40, 50] // 选择限制显示条数
  314. },
  315. // imageIcon: require("@/assets/images/base/warning.png"),
  316. };
  317. },
  318. //生命周期 - 创建完成(可以访问当前this实例)
  319. created () {
  320. // 设置默认为当前周
  321. },
  322. //生命周期 - 挂载完成(可以访问DOM元素)
  323. mounted () {
  324. this.searchForm.timer = [];
  325. this.searchForm.timer.push(this.getNowDateAndMonday(nowTime));
  326. this.searchForm.timer.push(this.getNowDateAndSunday(nowTime));
  327. getTeacher().then(res => {
  328. if (res.code == 200) {
  329. this.teacherList = res.data;
  330. }
  331. });
  332. getEmployeeOrgan().then(res => {
  333. if (res.code == 200) {
  334. this.organList = res.data;
  335. }
  336. });
  337. // 获取分部 老师
  338. this.init();
  339. },
  340. activated () {
  341. this.init();
  342. },
  343. methods: {
  344. dayjs,
  345. init () {
  346. if (this.$route.query.teacherId) {
  347. this.searchForm.teacherId = this.$route.query.teacherId * 1;
  348. }
  349. if (this.$route.query.search) {
  350. this.$route.query.search instanceof Object ? this.topForm = this.$route.query.search : this.topForm = JSON.parse(this.$route.query.search);
  351. }
  352. if (this.$route.query.rules) {
  353. this.$route.query.rules instanceof Object ? this.rules = this.$route.query.rules : this.rules = JSON.parse(this.$route.query.rules);
  354. }
  355. this.getList();
  356. },
  357. getDate () {
  358. let obj = {
  359. search: this.searchForm.search || null,
  360. actualExercisesNumIsAchieve:
  361. this.searchForm.actualExercisesNumIsAchieve || null, // 训练次数
  362. exercisesMessageNumIsAchieve:
  363. this.searchForm.exercisesMessageNumIsAchieve || null, //评价
  364. exercisesMessageTimelyNumIsAchieve:
  365. this.searchForm.exercisesMessageTimelyNumIsAchieve || null, //及时评价
  366. exercisesReplyNumIsAchieve:
  367. this.searchForm.exercisesReplyNumIsAchieve || null, // 提交次数
  368. organIdList: this.searchForm.organIdList || null,
  369. teacherId: this.searchForm.teacherId,
  370. page: this.rules.page,
  371. rows: this.rules.limit,
  372. existVipCourse: this.searchForm.existVipCourse || null,
  373. existPracticeCourse: this.searchForm.existPracticeCourse || null,
  374. };
  375. if (this.searchForm.timer && this.searchForm.timer.length > 0) {
  376. obj.monday = this.searchForm.timer[0];
  377. obj.sunday = this.searchForm.timer[1];
  378. } else {
  379. this.$message.error("请选择时间段");
  380. return false;
  381. }
  382. if (this.searchForm.workTimer && this.searchForm.workTimer.length > 0) {
  383. obj.submitStartDate = this.searchForm.workTimer[0];
  384. obj.submitEndDate = this.searchForm.workTimer[1];
  385. }
  386. return obj;
  387. },
  388. getList () {
  389. let obj = this.getDate();
  390. if (!obj) return;
  391. findStudentExtracurricularExercisesSituations(obj).then(res => {
  392. if (res.code == 200) {
  393. this.tableList = res.data.rows;
  394. this.rules.total = res.data.total;
  395. }
  396. });
  397. },
  398. onReSet () {
  399. this.searchForm = {
  400. timer: [],
  401. search: null,
  402. actualExercisesNumIsAchieve: null, // 训练次数
  403. exercisesMessageNumIsAchieve: null, //评价
  404. exercisesMessageTimelyNumIsAchieve: null, //及时评价
  405. exercisesReplyNumIsAchieve: null, // 提交次数
  406. teacherId: null,
  407. existVipCourse: null
  408. };
  409. this.search();
  410. },
  411. onExport () {
  412. let url = "/api-web/export/exercisesSituations";
  413. let obj = this.getDate();
  414. const options = {
  415. method: "get",
  416. headers: {
  417. Authorization: getToken()
  418. },
  419. url,
  420. params: obj,
  421. responseType: "blob"
  422. };
  423. this.$confirm("您确定导出列表?", "提示", {
  424. confirmButtonText: "确定",
  425. cancelButtonText: "取消",
  426. type: "warning"
  427. })
  428. .then(() => {
  429. load.startLoading();
  430. axios(options)
  431. .then(res => {
  432. let blob = new Blob([res.data], {
  433. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
  434. type: "application/vnd.ms-excel;charset=utf-8"
  435. // word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  436. });
  437. let text = new Response(blob).text();
  438. text.then(res => {
  439. // 判断是否报错
  440. if (res.indexOf("code") != -1) {
  441. let json = JSON.parse(res);
  442. this.$message.error(json.msg);
  443. } else {
  444. let objectUrl = URL.createObjectURL(blob);
  445. let link = document.createElement("a");
  446. let nowTime = new Date();
  447. let ymd =
  448. nowTime.getFullYear() +
  449. "" +
  450. (nowTime.getMonth() + 1) +
  451. "" +
  452. nowTime.getDate() +
  453. "" +
  454. nowTime.getHours() +
  455. "" +
  456. nowTime.getMinutes();
  457. let fname = ymd + "服务指标";
  458. link.href = objectUrl;
  459. link.setAttribute("download", fname);
  460. document.body.appendChild(link);
  461. link.click();
  462. }
  463. });
  464. load.endLoading();
  465. })
  466. .catch(error => {
  467. this.$message.error("导出数据失败,请联系管理员");
  468. load.endLoading();
  469. });
  470. })
  471. .catch(() => { });
  472. },
  473. search () {
  474. this.rules.page = 1;
  475. this.getList();
  476. },
  477. getNowDateAndMonday (time) {
  478. let timestamp = new Date(time.replace(/-/g, "/")).getTime();
  479. let serverDate = new Date(time);
  480. if (serverDate.getDay() == 0) {
  481. timestamp -= 7 * 24 * 60 * 60 * 1000;
  482. }
  483. let mondayTime =
  484. timestamp - (serverDate.getDay() - 1) * 24 * 60 * 60 * 1000;
  485. let mondayData = new Date(mondayTime);
  486. //年
  487. let mondayY = mondayData.getFullYear();
  488. //月
  489. let mondayM =
  490. mondayData.getMonth() + 1 < 10
  491. ? "0" + (mondayData.getMonth() + 1)
  492. : mondayData.getMonth() + 1;
  493. //日
  494. let mondayD =
  495. mondayData.getDate() < 10
  496. ? "0" + mondayData.getDate()
  497. : mondayData.getDate();
  498. let str = mondayY + "-" + mondayM + "-" + mondayD;
  499. return str;
  500. },
  501. getNowDateAndSunday (time) {
  502. let timestamp = new Date(time.replace(/-/g, "/")).getTime();
  503. let serverDate = new Date(time);
  504. let num = 7 - serverDate.getDay();
  505. if (num == 7) {
  506. num = 0;
  507. }
  508. let sundayTiem = timestamp + num * 24 * 60 * 60 * 1000;
  509. let SundayData = new Date(sundayTiem);
  510. //年
  511. let tomorrowY = SundayData.getFullYear(); //月
  512. let tomorrowM =
  513. SundayData.getMonth() + 1 < 10
  514. ? "0" + (SundayData.getMonth() + 1)
  515. : SundayData.getMonth() + 1;
  516. //日
  517. let tomorrowD =
  518. SundayData.getDate() < 10
  519. ? "0" + SundayData.getDate()
  520. : SundayData.getDate();
  521. let str = tomorrowY + "-" + tomorrowM + "-" + tomorrowD;
  522. return str;
  523. },
  524. getWeekTime (val) {
  525. if (val && val.length > 0) {
  526. let start = this.getNowDateAndMonday(val[0]);
  527. let end = this.getNowDateAndSunday(val[1]);
  528. this.searchForm.timer.splice(0, 1, start);
  529. this.searchForm.timer.splice(1, 1, end);
  530. }
  531. },
  532. lookDetail (row) {
  533. // this.afterSchoolVisible = true;
  534. let rules = JSON.stringify(this.rules);
  535. let searchForm = JSON.stringify(this.searchForm);
  536. this.$router.push({
  537. path: "/operateManager/serverIndexDetail",
  538. query: {
  539. studentId: row.studentId,
  540. studentName: row.studentName,
  541. rules,
  542. searchForm,
  543. title: row.studentName,
  544. extracurricularExercisesId: "yes",
  545. startTime: this.searchForm.timer[0],
  546. endTime: this.searchForm.timer[1]
  547. }
  548. });
  549. }
  550. }
  551. };
  552. </script>
  553. <style lang='scss' scoped>
  554. .micon {
  555. position: absolute;
  556. top: 3px;
  557. right: 2px;
  558. }
  559. </style>