index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. <template>
  2. <div class="dashboard-container">
  3. <transition name="fade">
  4. <div class="left">
  5. <el-form :inline="true"
  6. :model="sectionForm"
  7. class="sectionForm">
  8. <el-form-item>
  9. <el-select v-model="sectionForm.section"
  10. placeholder="请选择分部"
  11. @change="chioseSection">
  12. <el-option v-for="(item,index) in brancheList"
  13. :key="index"
  14. :value="item.branchId"
  15. :label="item.branchName"></el-option>
  16. </el-select>
  17. </el-form-item>
  18. </el-form>
  19. <h2 v-if="MajorList.length > 0">所属乐团</h2>
  20. <ul>
  21. <!-- MajorList -->
  22. <li :class="activeMarjorId == item.id?'active':''"
  23. v-for="(item,index) in MajorList"
  24. :key="index"
  25. @click="chioseMajor(item.name,item.id,item.status)">{{ item.name }}</li>
  26. </ul>
  27. </div>
  28. </transition>
  29. <div class="right">
  30. <!-- 顶部收索框 -->
  31. <el-form :inline="true"
  32. class="topWrap"
  33. :model="topForm">
  34. <el-form-item label="学生姓名">
  35. <el-input v-model="topForm.team"
  36. placeholder="请输入学生名称" />
  37. </el-form-item>
  38. <el-form-item label="学生专业">
  39. <el-select v-model="topForm.major"
  40. placeholder="请输入学生专业">
  41. <el-option v-for="(item,index) in chioseList"
  42. :key="index"
  43. :value="item.subId"
  44. :label="item.subName"></el-option>
  45. </el-select>
  46. </el-form-item>
  47. <el-form-item label="学生状态">
  48. <el-select v-model="topForm.status"
  49. placeholder="请选择学生状态"
  50. clearable>
  51. <!-- // 1报名中,2缴费中,3报名截止,4已开团 -->
  52. <el-option :value="0"
  53. label="报名中"></el-option>
  54. <el-option :value="1"
  55. label="报名完成"></el-option>
  56. <el-option :value="2"
  57. label="报名失败"></el-option>
  58. </el-select>
  59. </el-form-item>
  60. <!-- <el-form-item label="学生">
  61. <el-input v-model="topForm.student"
  62. placeholder="请输入学生姓名" />
  63. </el-form-item>-->
  64. <el-button type="primary"
  65. icon="el-icon-search"
  66. plain
  67. @click="getstudentList">搜索</el-button>
  68. <el-button type="success"
  69. icon="el-icon-refresh"
  70. plain
  71. @click="resetStudentList">重置</el-button>
  72. <el-button icon="el-icon-s-tools"
  73. plain
  74. v-if="majorStatus == 1 || majorStatus == 2"
  75. @click="showFade('','','','')">批量调剂</el-button>
  76. <!-- v-if="majorStatus == 1" -->
  77. <el-button type='danger'
  78. icon='el-icon-position'
  79. v-show="paymentStatus"
  80. @click="getMoney">开启缴费</el-button>
  81. <el-button type='warning'
  82. icon="el-icon-news"
  83. v-if='this.majorId'
  84. @click='openUrl'>打开二维码</el-button>
  85. <el-button plain
  86. @click="exportis">导出</el-button>
  87. </el-form>
  88. <!-- 提示语 -->
  89. <p class="subMsg"
  90. v-if="!majorId">请先选择分部和乐团后,再查看学生列表或者搜索学生~</p>
  91. <!-- 列表 -->
  92. <div class="tableWrap"
  93. v-if="majorId">
  94. <el-table :data="tableData"
  95. style="width: 100%"
  96. id='tableid'
  97. @selection-change="handleSelectionChange">
  98. <el-table-column type="selection"
  99. :selectable='checkboxT'
  100. width="55"
  101. v-if='this.majorStatus <= 2'>
  102. </el-table-column>
  103. <el-table-column prop="city"
  104. align="center"
  105. label="所属分部"></el-table-column>
  106. <el-table-column prop="name"
  107. align="center"
  108. label="学生姓名"></el-table-column>
  109. <el-table-column prop="sex"
  110. align="center"
  111. label="性别"
  112. :formatter="filterSex"></el-table-column>
  113. <el-table-column prop="birthday"
  114. align="center"
  115. label="出生日期"
  116. :formatter="filterDate"></el-table-column>
  117. <el-table-column prop="class"
  118. align="center"
  119. label="班级"
  120. :formatter="filterClass"></el-table-column>
  121. <el-table-column prop="school"
  122. align="center"
  123. label="单位/学校"></el-table-column>
  124. <el-table-column prop="patriarchPhone"
  125. align="center"
  126. label="联系方式"></el-table-column>
  127. <el-table-column prop="subName"
  128. align="center"
  129. label="录取专业"></el-table-column>
  130. <el-table-column prop="patriarchName"
  131. align="center"
  132. label="家长姓名"></el-table-column>
  133. <el-table-column prop="patriarchUnit"
  134. align="center"
  135. label="家长工作单位"></el-table-column>
  136. <!-- <el-table-column prop="musical" align="center" label="乐器准备方式"></el-table-column> -->
  137. <!-- status -->
  138. <el-table-column prop="status"
  139. align="center"
  140. label="状态"
  141. :formatter="filterStatus"></el-table-column>
  142. <el-table-column prop="amount"
  143. align="center"
  144. label="实际缴费金额"></el-table-column>
  145. <el-table-column align="center"
  146. label="操作">
  147. <template slot-scope="scope">
  148. <div>
  149. <!-- 学生id crouseId subId -->
  150. <el-button type="primary"
  151. plain
  152. :disabled='!disabled'
  153. @click="showFade(scope.row.id,scope.row.courseId,scope.row.subId,scope.row.status)">调剂</el-button>
  154. </div>
  155. </template>
  156. </el-table-column>
  157. </el-table>
  158. <!-- 调剂弹出层 -->
  159. <el-dialog title="提示"
  160. :visible.sync="dialogVisible"
  161. width="30%">
  162. <span>请选择调剂乐团</span>
  163. <el-select v-model="reviseMajor"
  164. placeholder="请选择调剂课程"
  165. @change="reviseMajors">
  166. <el-option v-for="(item,index) in chioseList"
  167. :key="index"
  168. :value="item.subId+'-'+item.id"
  169. :label="item.subName"></el-option>
  170. </el-select>
  171. <span slot="footer"
  172. class="dialog-footer">
  173. <el-button @click="dialogVisible = false">取 消</el-button>
  174. <el-button type="primary"
  175. @click="submitRe">确 定</el-button>
  176. </span>
  177. </el-dialog>
  178. <!-- 分页器 -->
  179. <div class="paginationWrap">
  180. <el-pagination background
  181. class="pagination"
  182. layout="prev, pager, next"
  183. :total="total"
  184. :current-page.sync="currentPage"
  185. :page-size.sync="limit"
  186. @current-change="handleCurrentChange"></el-pagination>
  187. </div>
  188. </div>
  189. </div>
  190. <el-dialog title="二维码"
  191. :visible.sync="code"
  192. width="30%">
  193. <div class="wrap">
  194. <div id="qrCode"
  195. ref="qrCodeDiv"></div>
  196. </div>
  197. </el-dialog>
  198. <!-- 弹出框 -->
  199. <el-dialog title="提示:请输入短信模板"
  200. :visible.sync="isDialog"
  201. width="30%">
  202. <el-form v-model="dialogForm">
  203. <el-form-item>
  204. <el-input type="textarea"
  205. :disabled="isRadioDisabled"
  206. :rows="3"
  207. v-model="dialogForm.text"
  208. placeholder="请输入短信模板"></el-input>
  209. </el-form-item>
  210. </el-form>
  211. <div class="radioWrap"
  212. style="margin-top:20px">
  213. <el-radio v-model="radio"
  214. :label="1">线上</el-radio>
  215. <el-radio v-model="radio"
  216. :label="2">线下</el-radio>
  217. </div>
  218. <span slot="footer"
  219. class="dialog-footer">
  220. <el-button type="primary"
  221. @click="gotoMoneyok">确 定</el-button>
  222. </span>
  223. </el-dialog>
  224. </div>
  225. </template>
  226. <script>
  227. import qs from "qs";
  228. // import { loading } from "element-ui";
  229. import { scrollTo } from '@/utils/scroll-to'
  230. import QRCode from 'qrcodejs2'
  231. import {
  232. getAllMajor,
  233. getMusicTeams,
  234. getBranches,
  235. getStudentList,
  236. updateUser,
  237. updateClass
  238. } from "@/api/table";
  239. import { setTimeout } from "timers";
  240. export default {
  241. name: "dashboard",
  242. data () {
  243. return {
  244. paymentStatus: false, // 开启缴费开关
  245. topForm: {
  246. team: "",
  247. status: "",
  248. student: "",
  249. major: ''
  250. },
  251. sectionForm: {
  252. section: ""
  253. },
  254. MajorList: [], // 所有乐团集合
  255. tableData: [
  256. ],
  257. isMusic: true,
  258. dialogVisible: false,
  259. reviseMajor: "", // 选择的团名
  260. actionTearm: "", // 选中的乐团名字
  261. majorStatus: "", // 所选乐团的状态
  262. majorId: "", // 所选乐团的ID
  263. chioseList: [], // 所有调剂科目的集合
  264. sessionId: "",
  265. brancheList: [], // 所有分部集合
  266. limit: 20,
  267. total: 0,
  268. page: 1,
  269. studentId: "", // 学生id
  270. courseId: "", // 当前选中的课程
  271. subId: "", // 当前选中的项目
  272. disabled: true, // 判断单个调剂按钮能否点击
  273. activeMarjorId: '-1', // 选中乐团的id
  274. studentStatus: '-1', //单个学生调剂时学生状态
  275. isDialog: false, // 显示隐藏弹框
  276. radio: 2, // 线上线下的选择框
  277. isRadioDisabled: false,
  278. dialogForm: {
  279. text: ''
  280. },
  281. code: false,
  282. first: true,
  283. qrcodes: ''
  284. };
  285. },
  286. methods: {
  287. showFade (id, courseId, subId, status) {
  288. if (status == 1) {
  289. this.$message.error('此学生已报名成功,无法调剂');
  290. return;
  291. }
  292. if (id && courseId) {
  293. this.studentId = id;
  294. this.courseId = courseId;
  295. }
  296. this.subId = subId;
  297. this.dialogVisible = true;
  298. },
  299. // 获取分类选项卡
  300. getMajors () {
  301. // classid 乐团id
  302. getAllMajor(qs.stringify({ clazzId: this.majorId }))
  303. .then(res => {
  304. if (res.code == 200) {
  305. this.chioseList = res.data;
  306. }
  307. })
  308. .catch(res => {
  309. });
  310. },
  311. // 获取所有乐团列表
  312. getMusicTeam (id, row) {
  313. getMusicTeams(qs.stringify({ branchId: id, row, page: this.page })).then(
  314. res => {
  315. if (res.code == 200) {
  316. this.MajorList = res.data.rows;
  317. }
  318. }
  319. );
  320. },
  321. // 获取所有分部
  322. getBranches () {
  323. getBranches().then(res => {
  324. if (res.code == 200) {
  325. this.brancheList = res.data;
  326. }
  327. });
  328. },
  329. // 点击选择分部
  330. chioseSection (id) {
  331. // 查询分部列表
  332. // console.log(id);
  333. this.sessionId = id;
  334. this.getMusicTeam(id, 50);
  335. },
  336. // 点击分部下的乐团
  337. chioseMajor (name, id, status) {
  338. this.activeMarjorId = id;
  339. this.actionTearm = name;
  340. this.majorStatus = status;
  341. if (status == 3 || status == 4) {
  342. this.disabled = false;
  343. }
  344. // 判断乐团是否已经开启缴费
  345. if (status == 2 || status == 3 || status == 4) {
  346. this.paymentStatus = false
  347. } else {
  348. this.paymentStatus = true
  349. }
  350. this.majorId = id;
  351. // 发请求 获取学生列表数据
  352. this.getstudentList();
  353. // 获取分类选项卡
  354. this.getMajors();
  355. },
  356. // 获取学生列表(查询也用这个接口)
  357. getstudentList () {
  358. if (!this.majorId) {
  359. this.$message.error("请先选择分部与乐团在搜索学生");
  360. return;
  361. }
  362. getStudentList(
  363. qs.stringify({
  364. musicTeamId: this.majorId,
  365. name: this.topForm.team,
  366. status: this.topForm.status,
  367. subId: this.topForm.major,
  368. page: this.page,
  369. rows: this.limit
  370. })
  371. ).then(res => {
  372. this.tableData = res.data.rows;
  373. this.total = res.data.total;
  374. this.pageSize = res.data.limit;
  375. });
  376. },
  377. // 重置搜索
  378. resetStudentList () {
  379. this.topForm.team = "";
  380. this.topForm.status = "";
  381. this.topForm.major = "";
  382. this.page = 1;
  383. this.getstudentList();
  384. },
  385. // 性别分类过滤器
  386. filterSex (val) {
  387. let arr = ["男", "女"];
  388. return arr[val.sex];
  389. },
  390. // 时间格式化过滤器
  391. filterDate (val) {
  392. let str = "";
  393. val.birthday ? (str = val.birthday.split(" ")[0]) : (str = "");
  394. return str;
  395. },
  396. // 格式化班级
  397. filterClass (val) {
  398. return val.grade + val.gclass;
  399. },
  400. // 格式化状态
  401. filterStatus (val) {
  402. let arr = ["报名中", "报名完成", "报名失败"];
  403. return arr[val.status];
  404. },
  405. // 修改科目触发事件
  406. reviseMajors (val) {
  407. // 这里切割字符串 拿到想要的数据
  408. if (val) {
  409. this.subId = val.split('-')[0];
  410. this.crouseId = val.split('-')[1];
  411. }
  412. },
  413. // 确认修改
  414. submitRe () {
  415. // console.log(this.crouseId);
  416. updateUser(
  417. qs.stringify({
  418. courseId: this.crouseId,
  419. subId: this.subId,
  420. userId: this.studentId
  421. })
  422. ).then(res => {
  423. if (res.code == 200) {
  424. this.dialogVisible = false;
  425. this.$message.success(res.msg);
  426. this.reviseMajor = "";
  427. // 刷新列表
  428. this.getstudentList();
  429. }
  430. });
  431. },
  432. // 点击开始缴费 1报名中,2缴费中,3报名截止,4已开团
  433. getMoney () {
  434. this.isDialog = true;
  435. },
  436. handleCurrentChange (val) {
  437. this.page = val;
  438. // this.limit = pageSize;
  439. this.getstudentList();
  440. // if (this.autoScroll) {
  441. scrollTo(0, 800);
  442. // }
  443. },
  444. handleSelectionChange (val) {
  445. let str = '';
  446. if (val.length >= 2) {
  447. this.disabled = false;
  448. } else {
  449. this.disabled = true;
  450. }
  451. if (val.length > 0) {
  452. val.forEach(item => {
  453. str += item.id + ','
  454. })
  455. }
  456. str = str.substring(0, str.length - 1);
  457. this.studentId = str;
  458. },
  459. checkboxT (row) {
  460. // console.log(this.majorStatus > 2);
  461. if (row.status == 1 || this.majorStatus > 2) {
  462. return false;
  463. } else {
  464. return true;
  465. }
  466. },
  467. // 点击打开报名链接
  468. openUrl () {
  469. // debugger
  470. this.code = true;
  471. this.qrcode();
  472. // window.open(`https://pay.dayaedu.com/#/order?classId=${this.majorId}&schoolName=${this.actionTearm}`)
  473. },
  474. gotoMoneyok () {
  475. let val = this.dialogForm.text;
  476. if (this.radio != 1) {
  477. // 线上
  478. if (!val.trim()) {
  479. this.$message.error('请输入短信模板');
  480. return;
  481. }
  482. }
  483. updateClass(qs.stringify({ id: this.majorId, smsMsg: val, type: this.radio })).then(res => {
  484. if (res.code == 200) {
  485. this.$message.success("乐团报名成功请尽快缴费");
  486. setTimeout(() => {
  487. this.getstudentList();
  488. this.majorStatus = 2;
  489. this.isDialog = false;
  490. this.dialogForm.text = '';
  491. }, 1000);
  492. } else {
  493. this.$message.error(res.msg)
  494. }
  495. });
  496. },
  497. qrcode () {
  498. setTimeout(() => {
  499. this.qrcodes = new QRCode(document.getElementById("qrCode"), {
  500. width: 200, // 设置宽度,单位像素
  501. height: 200, // 设置高度,单位像素
  502. text: `http://testpay.dayaedu.com/#/order?classId=${this.majorId}&schoolName=${this.actionTearm}` // 设置二维码内容或跳转地址
  503. })
  504. }, 100)
  505. if (document.getElementById("qrCode")) {
  506. document.getElementById("qrCode").innerHTML = ''
  507. }
  508. },
  509. exportis () {
  510. // var curTbl = document.getElementById('tableid');
  511. // this.tableId = curTbl;
  512. // console.log(curTbl);
  513. console.log(this.tableData)
  514. if (this.tableData.length <= 0) {
  515. return false
  516. }
  517. this.method5('tableid');
  518. },
  519. // 导出
  520. getExplorer () {
  521. var explorer = window.navigator.userAgent;
  522. //ie
  523. if (explorer.indexOf("MSIE") >= 0) {
  524. return 'ie';
  525. }
  526. //firefox
  527. else if (explorer.indexOf("Firefox") >= 0) {
  528. return 'Firefox';
  529. }
  530. //Chrome
  531. else if (explorer.indexOf("Chrome") >= 0) {
  532. return 'Chrome';
  533. }
  534. //Opera
  535. else if (explorer.indexOf("Opera") >= 0) {
  536. return 'Opera';
  537. }
  538. //Safari
  539. else if (explorer.indexOf("Safari") >= 0) {
  540. return 'Safari';
  541. }
  542. },
  543. method5 (tableid) {
  544. if (this.getExplorer() == 'ie') {
  545. var curTbl = document.getElementById(tableid);
  546. var oXL = new ActiveXObject("Excel.Application");
  547. var oWB = oXL.Workbooks.Add();
  548. var xlsheet = oWB.Worksheets(1);
  549. var sel = document.body.createTextRange();
  550. sel.moveToElementText(curTbl);
  551. sel.select();
  552. sel.execCommand("Copy");
  553. xlsheet.Paste();
  554. oXL.Visible = true;
  555. try {
  556. var fname = oXL.Application.GetSaveAsFilename("哈哈哈.xls", "Excel Spreadsheets (*.xls), *.xls");
  557. } catch (e) {
  558. print("Nested catch caught " + e);
  559. } finally {
  560. oWB.SaveAs(fname);
  561. oWB.Close(savechanges = false);
  562. oXL.Quit();
  563. oXL = null;
  564. this.idTmr = window.setInterval("Cleanup();", 1);
  565. }
  566. }
  567. else {
  568. this.tableToExcel();
  569. }
  570. },
  571. Cleanup () {
  572. window.clearInterval(this.idTmr);
  573. this.CollectGarbage();
  574. },
  575. tableToExcel () {
  576. (function () {
  577. var uri = 'data:application/vnd.ms-excel;base64,',
  578. template = '<html><head><meta charset="UTF-8"></head><body><table>{table}</table></body></html>',
  579. base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) },
  580. format = function (s, c) {
  581. return s.replace(/{(\w+)}/g,
  582. function (m, p) { return c[p]; }) }
  583. // table name
  584. let table = document.getElementById('tableid')
  585. // || name
  586. var ctx = { worksheet: 'Worksheet', table: table.innerHTML }
  587. window.location.href = uri + base64(format(template, ctx))
  588. //
  589. // return function () {
  590. // }
  591. })()
  592. },
  593. },
  594. watch: {
  595. radio (val) {
  596. if (val == 1) {
  597. this.isRadioDisabled = true;
  598. } else {
  599. this.isRadioDisabled = false;
  600. }
  601. }
  602. },
  603. computed: {
  604. currentPage: {
  605. get () {
  606. return this.page
  607. },
  608. set (val) {
  609. this.$emit('update:page', val)
  610. }
  611. },
  612. },
  613. mounted () {
  614. // 获取所有分部
  615. this.getBranches();
  616. // 获取所有学生列表
  617. // this.getstudentList();
  618. }
  619. };
  620. </script>
  621. <style scoped>
  622. .dashboard-container {
  623. padding-left: 10px;
  624. display: flex;
  625. flex-direction: row;
  626. justify-content: flex-start;
  627. flex-wrap: nowrap;
  628. }
  629. .dashboard-container .left {
  630. width: 200px;
  631. min-height: 100vh;
  632. /* background-color: #14928a; */
  633. padding-top: 15px;
  634. border-right: 1px solid #ccc;
  635. }
  636. .dashboard-container .left h2 {
  637. margin-top: 15px;
  638. height: 40px;
  639. line-height: 40px;
  640. font-size: 18px;
  641. text-align: center;
  642. margin: 0;
  643. padding: 0;
  644. color: #333;
  645. }
  646. .dashboard-container .right {
  647. padding: 15px 0;
  648. width: calc(100% - 200px);
  649. }
  650. .topWrap {
  651. margin-left: 40px;
  652. }
  653. .fade-enter-active,
  654. .fade-leave-active {
  655. transition: opacity 0.5s;
  656. }
  657. .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  658. opacity: 0;
  659. }
  660. .left ul {
  661. margin: 0;
  662. padding: 0;
  663. }
  664. .left li {
  665. display: block;
  666. text-align: center;
  667. list-style: none;
  668. color: #333;
  669. font-size: 14px;
  670. line-height: 70px;
  671. cursor: pointer;
  672. }
  673. .left li.active {
  674. color: #ffc10d;
  675. }
  676. .paginationWrap {
  677. display: flex;
  678. flex-direction: row;
  679. justify-content: flex-end;
  680. }
  681. .pagination {
  682. margin-top: 20px;
  683. }
  684. .joinBtn {
  685. position: fixed;
  686. right: 30px;
  687. top: 700px;
  688. z-index: 100;
  689. }
  690. .sectionForm {
  691. display: flex;
  692. flex-direction: row;
  693. justify-content: center;
  694. }
  695. .subMsg {
  696. width: 100%;
  697. text-align: center;
  698. font-size: 14px;
  699. color: #ccc;
  700. margin-top: 100px;
  701. }
  702. .wrap {
  703. width: 100%;
  704. display: flex;
  705. flex-direction: column;
  706. align-items: center;
  707. }
  708. </style>