serverIndexList.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. <!-- -->
  2. <template>
  3. <div class="m-container">
  4. <h2>
  5. <div class="titleWrap">
  6. <div class="squrt"></div>
  7. 服务指标
  8. </div>
  9. <el-button
  10. type="text"
  11. icon="el-icon-question"
  12. @click="lookServerDetail"
  13. style="color: red"
  14. >服务指标规则</el-button
  15. >
  16. </h2>
  17. <div class="m-core">
  18. <save-form
  19. ref="searchForm"
  20. :inline="true"
  21. :model="searchForm"
  22. @submit="search"
  23. @reset="onReSet"
  24. >
  25. <el-form-item>
  26. <remote-search
  27. :commit="'setTeachers'"
  28. v-model="searchForm.teacherId"
  29. />
  30. </el-form-item>
  31. <el-form-item>
  32. <el-input
  33. v-model.trim="searchForm.search"
  34. @keyup.enter.native="search"
  35. clearable
  36. placeholder="学生姓名"
  37. ></el-input>
  38. </el-form-item>
  39. <el-form-item label="周次选择">
  40. <el-date-picker
  41. v-model.trim="searchForm.timer"
  42. style="width: 400px"
  43. type="daterange"
  44. :picker-options="{
  45. firstDayOfWeek: 1,
  46. }"
  47. value-format="yyyy-MM-dd"
  48. range-separator="至"
  49. start-placeholder="周次开始日期"
  50. end-placeholder="周次结束日期"
  51. @change="getWeekTime"
  52. ></el-date-picker>
  53. </el-form-item>
  54. <el-form-item>
  55. <el-button
  56. :type="isSearch ? 'primary' : 'info'"
  57. icon="el-icon-circle-plus-outline"
  58. @click="showMove = true"
  59. >更多选项</el-button
  60. >
  61. <el-button type="danger" native-type="submit">搜索</el-button>
  62. <el-button native-type="reset" type="primary">重置</el-button>
  63. <el-button
  64. @click="onExport"
  65. type="primary"
  66. v-permission="'export/exercisesSituations'"
  67. style="background: #14928a; border: 1px solid #14928a"
  68. >导出</el-button
  69. >
  70. </el-form-item>
  71. </save-form>
  72. <div class="tableWrap">
  73. <el-table
  74. style="width: 100%"
  75. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  76. :data="tableList"
  77. >
  78. <el-table-column align="center" prop="studentId" label="学员编号">
  79. <template slot-scope="scope">
  80. <div>
  81. <copy-text>{{ scope.row.studentId }}</copy-text>
  82. </div>
  83. </template>
  84. </el-table-column>
  85. <el-table-column align="center" prop="studentName" label="学生姓名">
  86. <template slot-scope="scope">
  87. <div>
  88. <copy-text>{{ scope.row.studentName }}</copy-text>
  89. </div>
  90. </template>
  91. </el-table-column>
  92. <el-table-column align="center" prop="organName" label="所属分部">
  93. <template slot-scope="scope">
  94. <div>
  95. <copy-text>{{ scope.row.organName }}</copy-text>
  96. </div>
  97. </template>
  98. </el-table-column>
  99. <el-table-column align="center" prop="groupNames" label="乐团名称">
  100. <template slot-scope="scope">
  101. <overflow-text
  102. width="100%"
  103. :text="scope.row.groupNames"
  104. ></overflow-text>
  105. </template>
  106. </el-table-column>
  107. <el-table-column align="center" prop="teacherName" label="指导老师">
  108. <template slot-scope="scope">
  109. <div>
  110. <copy-text>{{ scope.row.teacherName }}</copy-text>
  111. </div>
  112. </template>
  113. </el-table-column>
  114. <el-table-column
  115. align="center"
  116. prop="educationalTeacherName"
  117. label="乐团主管"
  118. ></el-table-column>
  119. <el-table-column
  120. align="center"
  121. prop="courseIds"
  122. width="100"
  123. label="服务课程"
  124. >
  125. <template slot-scope="scope">
  126. <copy-text>{{ scope.row.courseIds || "课外训练" }}</copy-text>
  127. </template>
  128. </el-table-column>
  129. <el-table-column align="center" label="预期作业布置">
  130. <template slot-scope="scope">
  131. <div>{{ scope.row.expectExercisesNum + "次" }}</div>
  132. </template>
  133. </el-table-column>
  134. <el-table-column align="center" width="120" prop>
  135. <template slot="header" slot-scope="scope">
  136. <p style="position: relative">
  137. 实际作业布置
  138. <el-tooltip placement="top" popper-class="mTooltip">
  139. <div slot="content">
  140. 以周为单位,每周服务指标指定的课程布置作业记一次实际作业布置
  141. </div>
  142. <!-- <img :src="imageIcon"
  143. class="micon el-tooltip"
  144. style="width:8px height:8px"
  145. alt /> -->
  146. <i
  147. class="el-icon-question"
  148. style="font-size: 18px; color: #f56c6c"
  149. ></i>
  150. </el-tooltip>
  151. </p>
  152. </template>
  153. <template slot-scope="scope">
  154. <div
  155. :style="
  156. scope.row.actualExercisesNum < scope.row.expectExercisesNum
  157. ? 'color:red'
  158. : ''
  159. "
  160. >
  161. {{ scope.row.actualExercisesNum + "次" }}
  162. </div>
  163. </template>
  164. </el-table-column>
  165. <el-table-column align="center" prop label="提交次数">
  166. <template slot-scope="scope">
  167. <div>{{ scope.row.exercisesReplyNum + "次" }}</div>
  168. </template>
  169. </el-table-column>
  170. <el-table-column align="center" prop label="评价次数">
  171. <template slot-scope="scope">
  172. <div
  173. :style="
  174. scope.row.exercisesMessageNum < scope.row.exercisesReplyNum
  175. ? 'color:red'
  176. : ''
  177. "
  178. >
  179. {{ scope.row.exercisesMessageNum + "次" }}
  180. </div>
  181. </template>
  182. </el-table-column>
  183. <el-table-column align="center" prop label="及时评价次数">
  184. <template slot-scope="scope">
  185. <div>{{ scope.row.exercisesMessageTimelyNum + "次" }}</div>
  186. </template>
  187. </el-table-column>
  188. <el-table-column align="center" label="VIP课">
  189. <template slot-scope="scope">
  190. <div>{{ scope.row.existVipCourse + "节" }}</div>
  191. </template>
  192. </el-table-column>
  193. <el-table-column align="center" label="付费网管课">
  194. <template slot-scope="scope">
  195. <div>{{ scope.row.existPracticeCourse + "节" }}</div>
  196. </template>
  197. </el-table-column>
  198. <el-table-column align="center" label="作业提交时间">
  199. <template slot-scope="scope">
  200. <div>{{ scope.row.lastSubmitTime }}</div>
  201. </template>
  202. </el-table-column>
  203. <el-table-column align="center" width="120" label="服务周期">
  204. <template slot-scope="scope">
  205. <div>{{ dayjs(scope.row.monday).format("YYYY-MM-DD") }}</div>
  206. <div>{{ dayjs(scope.row.sunday).format("YYYY-MM-DD") }}</div>
  207. </template>
  208. </el-table-column>
  209. <el-table-column align="center" label="操作">
  210. <!-- -->
  211. <template slot-scope="scope">
  212. <div v-if="scope.row.actualExercisesNum > 0">
  213. <el-button type="text" @click="lookDetail(scope.row)"
  214. >查看</el-button
  215. >
  216. </div>
  217. </template>
  218. </el-table-column>
  219. </el-table>
  220. <pagination
  221. sync
  222. :total.sync="rules.total"
  223. :page.sync="rules.page"
  224. :limit.sync="rules.limit"
  225. :page-sizes="rules.page_size"
  226. @pagination="getList"
  227. />
  228. </div>
  229. </div>
  230. <el-dialog title="服务指标规则说明" :visible.sync="lookServer">
  231. <div class="serverInfo">
  232. <p>作业布置&服务指标优先级:<span>声部课>VIP课>合奏课>网管课</span></p>
  233. <p>
  234. <span>周一凌晨</span> 系统根据学员的排课情况生成布置作业路径及服务指标
  235. </p>
  236. <p>
  237. <span>多次课程</span>
  238. 只布置一次作业、统计一次服务指标(多乐团、多组VIP网管课除外)
  239. </p>
  240. <el-table
  241. border
  242. style="margin-top: 30px"
  243. :data="infoList"
  244. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  245. :span-method="arraySpanMethod"
  246. >
  247. <el-table-column
  248. align="center"
  249. prop="row1"
  250. label="总体课程情况"
  251. ></el-table-column>
  252. <el-table-column
  253. align="center"
  254. prop="row2"
  255. label="本周课程情况"
  256. ></el-table-column>
  257. <el-table-column
  258. align="center"
  259. prop="row3"
  260. label="作业布置路径"
  261. ></el-table-column>
  262. <el-table-column
  263. align="center"
  264. prop="row4"
  265. label="服务指标统计"
  266. ></el-table-column>
  267. </el-table>
  268. <div class="infoWrap">
  269. <h4>其他情况:</h4>
  270. <p>
  271. 1.学员在 <span>多个乐团时</span> ,剩余课程中
  272. <span>本周有声部课</span> 的乐团布置作业,
  273. <span>都有</span> 则都布置,
  274. <span>都没有</span> 则根据表格中的逻辑布置
  275. </p>
  276. <p>
  277. 2.学员存在 <span>多组VIP课</span> 时,若课程组
  278. <span>老师相同</span> ,则仅布置一次作业(网管课同理)
  279. </p>
  280. <p>
  281. 3.学员存在 <span>多组VIP课</span> 时,若课程组
  282. <span>老师不同,本周有课</span>
  283. 的VIP课程组布置作业,多个课程组本周都有课则布置多次(网管课同理)
  284. </p>
  285. <p>
  286. 4.学员存在 <span>多组VIP课</span> 时,若课程组
  287. <span>老师不同,本周都没有课</span> ,则所有VIP老师
  288. <span>都布置</span> 课外训练, <span>都统计</span> 服务指标
  289. </p>
  290. </div>
  291. <div class="infoWrap">
  292. <h4>课程调整:</h4>
  293. <p>
  294. 本周 <span>课程调整时</span> ,重新根据该学员的
  295. <span>本周课程情况更新</span> 作业布置路径及服务指标
  296. 则根据表格中的逻辑布置
  297. </p>
  298. </div>
  299. <div class="infoWrap">
  300. <h4>服务指标:</h4>
  301. <p>服务指标按 <span>周为单位</span> 统计</p>
  302. <p>
  303. <span>周六周日</span> 的服务指标
  304. <span>延迟到下周二更新</span>
  305. 实际安排数据(即周日的作业课程,在周二23:59:59时前布置作业都算一次实际安排)
  306. </p>
  307. </div>
  308. <div class="infoWrap">
  309. <h4>服务指标开启/关闭:</h4>
  310. <p>学员新增课程时,自动开启服务指标,</p>
  311. <p>手动关闭服务指标的学员新增课程时,不会自动开启服务指标</p>
  312. <p>
  313. 学员退团、乐团关闭、VIP课程组结束、网管课课程组结束时,若学员不在任何【进行中】乐团【在读】,且无任何未开始课程(乐团课、VIP课、网管课),则关闭服务指标
  314. </p>
  315. </div>
  316. <div class="infoWrap">
  317. <h4>服务指标解释:</h4>
  318. <p><span>若本周学员有多次服务指标则生成多条数据</span></p>
  319. <p>
  320. 预期作业布置:本周内服务指标次数(即本周应该给该学员布置的作业次数)
  321. </p>
  322. <p>
  323. 实际作业布置:本周通过服务指标作业布置路径给该学员布置作业的次数
  324. </p>
  325. <p>提交次数:本周学员按照作业布置路径提交作业的次数</p>
  326. <p>评价次数:本周老师评价通过作业布置路径提交的作业的次数</p>
  327. <p>及时评价次数:学员提交作业后24小时内进行评价的次数</p>
  328. <p>VIP课:本周VIP课程课时数</p>
  329. <p>付费网管课:本周付费网管课课时数</p>
  330. <p>作业提交时间:学员提交作业的时间</p>
  331. <p>服务周期:本服务周期时间段</p>
  332. </div>
  333. </div>
  334. </el-dialog>
  335. <el-dialog
  336. title="更多选项"
  337. :visible.sync="showMove"
  338. v-if="showMove"
  339. width="700px"
  340. >
  341. <el-form
  342. :inline="true"
  343. class="searchForm"
  344. @submit="search"
  345. @reset="onReSet"
  346. ref="searchForm2"
  347. :model.sync="searchForm"
  348. label-width="120px"
  349. >
  350. <el-form-item prop="organId" label="分部">
  351. <el-select
  352. class="multiple"
  353. v-model.trim="searchForm.organIdList"
  354. filterable
  355. clearable
  356. placeholder="请选择分部"
  357. >
  358. <el-option
  359. v-for="(item, index) in selects.branchs"
  360. :key="index"
  361. :label="item.name"
  362. :value="item.id"
  363. ></el-option>
  364. </el-select>
  365. </el-form-item>
  366. <el-form-item label="实际作业布置">
  367. <el-select
  368. placeholder="实际作业布置"
  369. v-model="searchForm.actualExercisesNumIsAchieve"
  370. clearable
  371. >
  372. <el-option label="符合预期" value="1"></el-option>
  373. <el-option label="不符合预期" value="0"></el-option>
  374. </el-select>
  375. </el-form-item>
  376. <el-form-item label="服务是否异常">
  377. <el-select
  378. placeholder="服务是否异常"
  379. v-model="searchForm.serviceIsError"
  380. clearable
  381. >
  382. <el-option label="是" value="1"></el-option>
  383. </el-select>
  384. </el-form-item>
  385. <el-form-item label="提交次数">
  386. <el-select
  387. placeholder="提交次数"
  388. v-model="searchForm.exercisesReplyNumIsAchieve"
  389. clearable
  390. >
  391. <el-option label="符合预期" value="1"></el-option>
  392. <el-option label="不符合预期" value="0"></el-option>
  393. </el-select>
  394. </el-form-item>
  395. <el-form-item label="评价次数">
  396. <el-select
  397. placeholder="评价次数"
  398. v-model="searchForm.exercisesMessageNumIsAchieve"
  399. clearable
  400. >
  401. <el-option label="符合预期" value="1"></el-option>
  402. <el-option label="不符合预期" value="0"></el-option>
  403. </el-select>
  404. </el-form-item>
  405. <el-form-item label="及时评价">
  406. <el-select
  407. placeholder="及时评价"
  408. v-model="searchForm.exercisesMessageTimelyNumIsAchieve"
  409. clearable
  410. >
  411. <el-option label="符合预期" value="1"></el-option>
  412. <el-option label="不符合预期" value="0"></el-option>
  413. </el-select>
  414. </el-form-item>
  415. <el-form-item label="是否有VIP课">
  416. <el-select
  417. placeholder="是否有VIP课"
  418. v-model="searchForm.existVipCourse"
  419. clearable
  420. >
  421. <el-option label="是" value="1"></el-option>
  422. <el-option label="否" value="0"></el-option>
  423. </el-select>
  424. </el-form-item>
  425. <el-form-item label="有付费网管课">
  426. <el-select
  427. placeholder="是否有付费网管课"
  428. v-model="searchForm.existPracticeCourse"
  429. clearable
  430. >
  431. <el-option label="是" value="1"></el-option>
  432. <el-option label="否" value="0"></el-option>
  433. </el-select>
  434. </el-form-item>
  435. <el-form-item label="作业提交时间">
  436. <el-date-picker
  437. v-model.trim="searchForm.workTimer"
  438. style="width: 400px"
  439. type="daterange"
  440. :picker-options="{
  441. firstDayOfWeek: 1,
  442. }"
  443. value-format="yyyy-MM-dd"
  444. range-separator="至"
  445. start-placeholder="提交开始日期"
  446. end-placeholder="提交结束日期"
  447. ></el-date-picker>
  448. </el-form-item>
  449. </el-form>
  450. <span slot="footer" class="dialog-footer">
  451. <el-button @click="cancleMore">取 消</el-button>
  452. <el-button type="primary" @click="okMore">确 定</el-button>
  453. </span>
  454. </el-dialog>
  455. </div>
  456. </template>
  457. <script>
  458. import axios from "axios";
  459. import { getToken } from "@/utils/auth";
  460. import pagination from "@/components/Pagination/index";
  461. import load from "@/utils/loading";
  462. import dayjs from "dayjs";
  463. import { getEmployeeOrgan, getTeacher } from "@/api/buildTeam";
  464. import { infoList } from "./modals/infoList";
  465. import { findStudentExtracurricularExercisesSituations } from "@/api/afterSchool";
  466. // findStudentExtracurricularExercisesSituations
  467. let nowTime = new Date();
  468. nowTime =
  469. nowTime.getFullYear() +
  470. "-" +
  471. (nowTime.getMonth() + 1) +
  472. "-" +
  473. nowTime.getDate();
  474. export default {
  475. components: { pagination },
  476. data() {
  477. return {
  478. tableList: [],
  479. searchForm: {
  480. timer: [],
  481. search: null,
  482. organIdList: null,
  483. actualExercisesNumIsAchieve: null, // 训练次数
  484. exercisesMessageNumIsAchieve: null, //评价
  485. exercisesMessageTimelyNumIsAchieve: null, //及时评价
  486. exercisesReplyNumIsAchieve: null, // 提交次数
  487. teacherId: null,
  488. existVipCourse: null,
  489. existPracticeCourse: null,
  490. workTimer: [],
  491. serviceIsError: null,
  492. },
  493. organList: [],
  494. teacherList: [],
  495. rules: {
  496. // 分页规则
  497. limit: 10, // 限制显示条数
  498. page: 1, // 当前页
  499. total: 0, // 总条数
  500. page_size: [10, 20, 40, 50], // 选择限制显示条数
  501. },
  502. lookServer: false,
  503. infoList: infoList,
  504. showMove: false,
  505. // imageIcon: require("@/assets/images/base/warning.png"),
  506. };
  507. },
  508. //生命周期 - 创建完成(可以访问当前this实例)
  509. created() {
  510. // 设置默认为当前周
  511. this.searchForm.timer = [];
  512. this.searchForm.timer.push(this.getNowDateAndMonday(nowTime));
  513. this.searchForm.timer.push(this.getNowDateAndSunday(nowTime));
  514. },
  515. //生命周期 - 挂载完成(可以访问DOM元素)
  516. mounted() {
  517. this.$store.dispatch("setBranchs");
  518. // getTeacher().then((res) => {
  519. // if (res.code == 200) {
  520. // this.teacherList = res.data;
  521. // }
  522. // });
  523. // getEmployeeOrgan().then((res) => {
  524. // if (res.code == 200) {
  525. // this.organList = res.data;
  526. // }
  527. // });
  528. // 获取分部 老师
  529. this.init();
  530. },
  531. activated() {
  532. this.init();
  533. },
  534. methods: {
  535. dayjs,
  536. init() {
  537. if (this.$route.query.teacherId) {
  538. this.searchForm.teacherId = this.$route.query.teacherId * 1;
  539. }
  540. if (this.$route.query.search) {
  541. this.$route.query.search instanceof Object
  542. ? (this.topForm = this.$route.query.search)
  543. : (this.topForm = JSON.parse(this.$route.query.search));
  544. }
  545. if (this.$route.query.rules) {
  546. this.$route.query.rules instanceof Object
  547. ? (this.rules = this.$route.query.rules)
  548. : (this.rules = JSON.parse(this.$route.query.rules));
  549. }
  550. this.getList();
  551. },
  552. getDate() {
  553. let obj = {
  554. search: this.searchForm.search || null,
  555. actualExercisesNumIsAchieve:
  556. this.searchForm.actualExercisesNumIsAchieve || null, // 训练次数
  557. exercisesMessageNumIsAchieve:
  558. this.searchForm.exercisesMessageNumIsAchieve || null, //评价
  559. exercisesMessageTimelyNumIsAchieve:
  560. this.searchForm.exercisesMessageTimelyNumIsAchieve || null, //及时评价
  561. exercisesReplyNumIsAchieve:
  562. this.searchForm.exercisesReplyNumIsAchieve || null, // 提交次数
  563. organIdList: this.searchForm.organIdList || null,
  564. teacherId: this.searchForm.teacherId,
  565. page: this.rules.page,
  566. rows: this.rules.limit,
  567. existVipCourse: this.searchForm.existVipCourse || null,
  568. existPracticeCourse: this.searchForm.existPracticeCourse || null,
  569. serviceIsError: this.searchForm.serviceIsError || null,
  570. };
  571. if (this.searchForm.timer && this.searchForm.timer.length > 0) {
  572. obj.monday = this.searchForm.timer[0];
  573. obj.sunday = this.searchForm.timer[1];
  574. } else {
  575. this.$message.error("请选择周次");
  576. return false;
  577. }
  578. if (this.searchForm.workTimer && this.searchForm.workTimer.length > 0) {
  579. obj.submitStartDate = this.searchForm.workTimer[0];
  580. obj.submitEndDate = this.searchForm.workTimer[1];
  581. }
  582. return obj;
  583. },
  584. getList() {
  585. let obj = this.getDate();
  586. if (!obj) return;
  587. findStudentExtracurricularExercisesSituations(obj).then((res) => {
  588. if (res.code == 200) {
  589. this.tableList = res.data.rows;
  590. this.rules.total = res.data.total;
  591. }
  592. });
  593. },
  594. onReSet() {
  595. this.searchForm = {
  596. timer: [],
  597. search: null,
  598. actualExercisesNumIsAchieve: null, // 训练次数
  599. exercisesMessageNumIsAchieve: null, //评价
  600. exercisesMessageTimelyNumIsAchieve: null, //及时评价
  601. exercisesReplyNumIsAchieve: null, // 提交次数
  602. teacherId: null,
  603. existVipCourse: null,
  604. };
  605. this.searchForm.timer = [];
  606. this.searchForm.timer.push(this.getNowDateAndMonday(nowTime));
  607. this.searchForm.timer.push(this.getNowDateAndSunday(nowTime));
  608. this.search();
  609. },
  610. cancleMore() {
  611. // this.$refs.searchForm2.resetFields()
  612. this.showMove = false;
  613. },
  614. okMore() {
  615. this.getList();
  616. this.showMove = false;
  617. },
  618. onExport() {
  619. let url = "/api-web/export/exercisesSituations";
  620. let obj = this.getDate();
  621. const options = {
  622. method: "get",
  623. headers: {
  624. Authorization: getToken(),
  625. },
  626. url,
  627. params: obj,
  628. responseType: "blob",
  629. };
  630. this.$confirm("您确定导出列表?", "提示", {
  631. confirmButtonText: "确定",
  632. cancelButtonText: "取消",
  633. type: "warning",
  634. })
  635. .then(() => {
  636. load.startLoading();
  637. axios(options)
  638. .then((res) => {
  639. let blob = new Blob([res.data], {
  640. // type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
  641. type: "application/vnd.ms-excel;charset=utf-8",
  642. // word文档为application/msword,pdf文档为application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8
  643. });
  644. let text = new Response(blob).text();
  645. text.then((res) => {
  646. // 判断是否报错
  647. if (res.indexOf("code") != -1) {
  648. let json = JSON.parse(res);
  649. this.$message.error(json.msg);
  650. } else {
  651. let objectUrl = URL.createObjectURL(blob);
  652. let link = document.createElement("a");
  653. let nowTime = new Date();
  654. let ymd =
  655. nowTime.getFullYear() +
  656. "" +
  657. (nowTime.getMonth() + 1) +
  658. "" +
  659. nowTime.getDate() +
  660. "" +
  661. nowTime.getHours() +
  662. "" +
  663. nowTime.getMinutes();
  664. let fname = ymd + "服务指标.xls";
  665. link.href = objectUrl;
  666. link.setAttribute("download", fname);
  667. document.body.appendChild(link);
  668. link.click();
  669. }
  670. });
  671. load.endLoading();
  672. })
  673. .catch((error) => {
  674. this.$message.error("导出数据失败,请联系管理员");
  675. load.endLoading();
  676. });
  677. })
  678. .catch(() => {});
  679. },
  680. search() {
  681. this.rules.page = 1;
  682. this.$refs.searchForm.save(this.searchForm);
  683. this.getList();
  684. },
  685. getNowDateAndMonday(time) {
  686. let timestamp = new Date(time.replace(/-/g, "/")).getTime();
  687. let serverDate = new Date(time);
  688. if (serverDate.getDay() == 0) {
  689. timestamp -= 7 * 24 * 60 * 60 * 1000;
  690. }
  691. let mondayTime =
  692. timestamp - (serverDate.getDay() - 1) * 24 * 60 * 60 * 1000;
  693. let mondayData = new Date(mondayTime);
  694. //年
  695. let mondayY = mondayData.getFullYear();
  696. //月
  697. let mondayM =
  698. mondayData.getMonth() + 1 < 10
  699. ? "0" + (mondayData.getMonth() + 1)
  700. : mondayData.getMonth() + 1;
  701. //日
  702. let mondayD =
  703. mondayData.getDate() < 10
  704. ? "0" + mondayData.getDate()
  705. : mondayData.getDate();
  706. let str = mondayY + "-" + mondayM + "-" + mondayD;
  707. return str;
  708. },
  709. getNowDateAndSunday(time) {
  710. let timestamp = new Date(time.replace(/-/g, "/")).getTime();
  711. let serverDate = new Date(time);
  712. let num = 7 - serverDate.getDay();
  713. if (num == 7) {
  714. num = 0;
  715. }
  716. let sundayTiem = timestamp + num * 24 * 60 * 60 * 1000;
  717. let SundayData = new Date(sundayTiem);
  718. //年
  719. let tomorrowY = SundayData.getFullYear(); //月
  720. let tomorrowM =
  721. SundayData.getMonth() + 1 < 10
  722. ? "0" + (SundayData.getMonth() + 1)
  723. : SundayData.getMonth() + 1;
  724. //日
  725. let tomorrowD =
  726. SundayData.getDate() < 10
  727. ? "0" + SundayData.getDate()
  728. : SundayData.getDate();
  729. let str = tomorrowY + "-" + tomorrowM + "-" + tomorrowD;
  730. return str;
  731. },
  732. getWeekTime(val) {
  733. if (val && val.length > 0) {
  734. let start = this.getNowDateAndMonday(val[0]);
  735. let end = this.getNowDateAndSunday(val[1]);
  736. this.searchForm.timer.splice(0, 1, start);
  737. this.searchForm.timer.splice(1, 1, end);
  738. }
  739. },
  740. lookDetail(row) {
  741. // this.afterSchoolVisible = true;
  742. let rules = JSON.stringify(this.rules);
  743. let searchForm = JSON.stringify(this.searchForm);
  744. this.$router.push({
  745. path: "/operateManager/serverIndexDetail",
  746. query: {
  747. studentId: row.studentId,
  748. studentName: row.studentName,
  749. rules,
  750. searchForm,
  751. title: row.studentName,
  752. extracurricularExercisesId: "yes",
  753. startTime: this.searchForm.timer[0],
  754. endTime: this.searchForm.timer[1],
  755. },
  756. });
  757. },
  758. lookServerDetail() {
  759. this.lookServer = true;
  760. },
  761. arraySpanMethod({ row, column, rowIndex, columnIndex }) {
  762. if (columnIndex === 0) {
  763. if (rowIndex % 2 === 0) {
  764. return {
  765. rowspan: 2,
  766. colspan: 1,
  767. };
  768. } else {
  769. return {
  770. rowspan: 0,
  771. colspan: 0,
  772. };
  773. }
  774. }
  775. },
  776. },
  777. computed: {
  778. isSearch() {
  779. return (
  780. this.searchForm.organIdList ||
  781. this.searchForm.actualExercisesNumIsAchieve ||
  782. this.searchForm.exercisesReplyNumIsAchieve ||
  783. this.searchForm.exercisesMessageNumIsAchieve ||
  784. this.searchForm.exercisesMessageTimelyNumIsAchieve ||
  785. this.searchForm.existVipCourse ||
  786. this.searchForm.existPracticeCourse ||
  787. this.searchForm.workTimer?.length > 0 ||
  788. this.searchForm.serviceIsError
  789. );
  790. },
  791. },
  792. };
  793. </script>
  794. <style lang='scss' scoped>
  795. .micon {
  796. position: absolute;
  797. top: 3px;
  798. right: 2px;
  799. }
  800. .serverInfo {
  801. line-height: 30px;
  802. span {
  803. color: #333;
  804. font-weight: bold;
  805. }
  806. }
  807. .infoWrap {
  808. margin-top: 30px;
  809. span {
  810. color: red;
  811. font-weight: normal;
  812. }
  813. }
  814. .titleWrap {
  815. display: flex;
  816. flex-direction: row;
  817. justify-content: flex-start;
  818. align-items: center;
  819. }
  820. .m-container {
  821. h2 {
  822. justify-content: space-between;
  823. }
  824. }
  825. </style>