forecastName.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. <template>
  2. <div class="forecastName">
  3. <!-- <h2> m-container
  4. <el-page-header @back="onCancel" :content="teamName"></el-page-header>
  5. </h2> -->
  6. <!-- <p style="margin-bottom: 15px; font-size: 18px; font-weight: 400">
  7. 缴费截止时间:{{ '2020-12-12' | formatTimer }}
  8. </p> -->
  9. <div class="btnList">
  10. <auth
  11. :auths="['musicGroup/sendParentMeetingNotice']"
  12. v-if="isedit || $route.query.team_status == 'DRAFT'"
  13. >
  14. <el-button type="primary" @click="extendPaymentStatus = true"
  15. >预报名家长会通知</el-button
  16. >
  17. </auth>
  18. <auth :auths="['forecastName/forecastLink']" v-if="isedit">
  19. <el-button type="primary" @click="codeStatus = true"
  20. >预报名问卷</el-button
  21. >
  22. </auth>
  23. <auth :auths="['studentRegistration/preRegisterExport']">
  24. <el-button type="primary" @click="downloadFile"
  25. >预报名信息导出</el-button
  26. >
  27. </auth>
  28. <auth :auths="['studentRegistration/queryPreApplySubjectList']">
  29. <el-button type="primary" @click="subjectVisible = true"
  30. >意向统计</el-button
  31. >
  32. </auth>
  33. <auth :auths="['musicGroup/finishPreApply']">
  34. <el-button type="primary" @click="onPaymentGroup" v-if="isedit"
  35. >乐团缴费</el-button
  36. >
  37. </auth>
  38. <auth :auths="['musicGroup/finishPreApply/item']" v-if="isedit">
  39. <el-button type="primary" @click="onPaymentGroup(1)"
  40. >特色乐团缴费</el-button
  41. >
  42. </auth>
  43. <el-button type="primary" @click="codedetailStatus = true" v-if="isedit"
  44. >预报名H5统计</el-button
  45. >
  46. </div>
  47. <div class="m-core">
  48. <save-form
  49. :inline="true"
  50. @reset="onReSet"
  51. @submit="search"
  52. :model="searchForm"
  53. save-key="/forecastName"
  54. ref="searchForm"
  55. >
  56. <el-form-item prop="name">
  57. <el-input
  58. v-model.trim="searchForm.name"
  59. clearable
  60. @keyup.enter.native="
  61. e => {
  62. e.target.blur();
  63. $refs.searchForm.save();
  64. search();
  65. }
  66. "
  67. placeholder="学生编号/姓名/手机号"
  68. ></el-input>
  69. </el-form-item>
  70. <el-form-item prop="isAllowAdjust">
  71. <el-select
  72. v-model.trim="searchForm.isAllowAdjust"
  73. clearable
  74. placeholder="是否允许调剂"
  75. >
  76. <el-option label="是" :value="1"></el-option>
  77. <el-option label="否" :value="0"></el-option>
  78. </el-select>
  79. </el-form-item>
  80. <el-form-item prop="teacherRecommandSubjectId">
  81. <el-select
  82. clearable
  83. v-model="searchForm.teacherRecommandSubjectId"
  84. placeholder="老师推荐声部"
  85. >
  86. <el-option
  87. v-for="item in subjectList"
  88. :value="item.id"
  89. :label="item.name"
  90. :key="item.id"
  91. ></el-option>
  92. </el-select>
  93. </el-form-item>
  94. <el-form-item prop="selectionSubjectId">
  95. <el-select
  96. clearable
  97. v-model="searchForm.selectionSubjectId"
  98. placeholder="选报声部"
  99. >
  100. <el-option
  101. v-for="item in selects.subjects"
  102. :value="item.id"
  103. :label="item.name"
  104. :key="item.id"
  105. ></el-option>
  106. </el-select>
  107. </el-form-item>
  108. <el-form-item prop="subjectId">
  109. <el-select
  110. clearable
  111. v-model="searchForm.subjectId"
  112. placeholder="所选专业"
  113. >
  114. <el-option
  115. v-for="item in selects.subjects"
  116. :value="item.id"
  117. :label="item.name"
  118. :key="item.id"
  119. ></el-option>
  120. </el-select>
  121. </el-form-item>
  122. <!-- kitPurchaseMethod -->
  123. <el-form-item prop="kitPurchaseMethod">
  124. <el-select
  125. v-model.trim="searchForm.kitPurchaseMethod"
  126. clearable
  127. placeholder="乐器准备方式"
  128. >
  129. <el-option label="团购" value="GROUP"></el-option>
  130. <el-option label="自备" value="OWNED"></el-option>
  131. </el-select>
  132. </el-form-item>
  133. <el-form-item prop="cloudTeacherMethod">
  134. <el-select
  135. v-model.trim="searchForm.cloudTeacherMethod"
  136. clearable
  137. placeholder="系统意向"
  138. >
  139. <el-option label="团购" value="GROUP"></el-option>
  140. <el-option label="自备" value="OWNED"></el-option>
  141. </el-select>
  142. </el-form-item>
  143. <el-form-item>
  144. <el-button type="danger" native-type="seach">搜索</el-button>
  145. <el-button native-type="reset" type="primary">重置</el-button>
  146. </el-form-item>
  147. </save-form>
  148. <div class="tableWrap">
  149. <el-table
  150. style="width: 100%"
  151. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  152. :data="tableList"
  153. >
  154. <el-table-column align="center" prop="userId" label="学员编号">
  155. <template slot-scope="scope">
  156. <copy-text>{{ scope.row.userId }}</copy-text>
  157. </template>
  158. </el-table-column>
  159. <el-table-column
  160. align="center"
  161. prop="userName"
  162. label="学员姓名"
  163. ></el-table-column>
  164. <el-table-column align="center" prop="gender" label="性别">
  165. <template slot-scope="scope">
  166. {{ scope.row.gender ? "男" : "女" }}
  167. </template>
  168. </el-table-column>
  169. <el-table-column align="center" prop="phone" label="联系电话">
  170. <template slot-scope="scope">
  171. <copy-text>{{ scope.row.phone }}</copy-text>
  172. </template>
  173. </el-table-column>
  174. <el-table-column align="center" label="年级班级">
  175. <template slot-scope="scope">
  176. {{ scope.row.currentGrade }}{{ scope.row.currentClass }}
  177. </template>
  178. </el-table-column>
  179. <el-table-column
  180. align="center"
  181. prop="teacherRecommandSubjectId"
  182. label="老师推荐声部"
  183. >
  184. <template slot-scope="scope">
  185. {{
  186. scope.row.teacherRecommandSubjectId
  187. ? scope.row.teacherRecommandSubjectName
  188. : null
  189. }}
  190. {{
  191. !scope.row.teacherRecommandSubjectName &&
  192. scope.row.teacherRecommandSubjectId == 999
  193. ? "听从老师安排"
  194. : null
  195. }}
  196. {{
  197. scope.row.teacherRecommandSubjectId == -1 &&
  198. !scope.row.teacherRecommandSubjectName
  199. ? "无"
  200. : null
  201. }}
  202. </template>
  203. </el-table-column>
  204. <el-table-column
  205. align="center"
  206. prop="selectionSubjectId"
  207. label="选报声部"
  208. >
  209. <template slot-scope="scope">
  210. {{
  211. scope.row.selectionSubjectId
  212. ? scope.row.selectionSubjectName
  213. : null
  214. }}
  215. {{
  216. !scope.row.selectionSubjectName &&
  217. scope.row.selectionSubjectId == 999
  218. ? "听从老师安排"
  219. : null
  220. }}
  221. {{
  222. !scope.row.selectionSubjectId && !scope.row.selectionSubjectName
  223. ? "无"
  224. : null
  225. }}
  226. </template>
  227. </el-table-column>
  228. <!-- <el-table-column
  229. align="center"
  230. prop="subjectFirstName"
  231. label="选报声部1"
  232. >
  233. <template slot-scope="scope">
  234. {{
  235. scope.row.subjectFirstName ? scope.row.subjectFirstName : null
  236. }}
  237. {{
  238. !scope.row.subjectFirstName && scope.row.subjectFirst == 999
  239. ? "听从老师安排"
  240. : null
  241. }}
  242. {{
  243. !scope.row.subjectFirstName && !scope.row.subjectFirst
  244. ? "无"
  245. : null
  246. }}
  247. </template>
  248. </el-table-column>
  249. <el-table-column
  250. align="center"
  251. prop="subjectSecondName"
  252. label="选报声部2"
  253. >
  254. <template slot-scope="scope">
  255. {{
  256. scope.row.subjectSecondName ? scope.row.subjectSecondName : null
  257. }}
  258. {{
  259. !scope.row.subjectSecondName && scope.row.subjectSecond == 999
  260. ? "听从老师安排"
  261. : null
  262. }}
  263. {{
  264. !scope.row.subjectSecondName && !scope.row.subjectSecond
  265. ? "无"
  266. : null
  267. }}
  268. </template>
  269. </el-table-column> -->
  270. <!-- <el-table-column
  271. align="center"
  272. prop="isAllowAdjust"
  273. label="是否服从调剂"
  274. >
  275. <template slot-scope="scope">
  276. {{ scope.row.isAllowAdjust ? "是" : "否" }}
  277. </template>
  278. </el-table-column> -->
  279. <el-table-column align="center" label="乐器准备方式">
  280. <template slot-scope="scope">
  281. {{ scope.row.kitPurchaseMethod | instrumentType }}
  282. </template>
  283. </el-table-column>
  284. <el-table-column align="center" label="系统意向">
  285. <template slot-scope="scope">
  286. {{ scope.row.cloudTeacherMethod | instrumentType }}
  287. </template>
  288. </el-table-column>
  289. <el-table-column
  290. align="center"
  291. prop="courseScheduleId"
  292. width="150"
  293. label="操作"
  294. v-if="isedit"
  295. >
  296. <!-- :router="['/business/forecastName']" -->
  297. <template slot-scope="scope">
  298. <auth :auths="['visit/add/teamForecastName']">
  299. <el-button type="text" @click="addVisited(scope.row)"
  300. >新增回访</el-button
  301. >
  302. </auth>
  303. </template>
  304. </el-table-column>
  305. </el-table>
  306. <pagination
  307. save-key="/forecastName"
  308. sync
  309. :total.sync="pageInfo.total"
  310. :page.sync="pageInfo.page"
  311. :limit.sync="pageInfo.limit"
  312. :page-sizes="pageInfo.page_size"
  313. @pagination="getList"
  314. />
  315. </div>
  316. </div>
  317. <!-- 预报名链接 -->
  318. <qr-code
  319. v-model="codeStatus"
  320. title="预报名问卷"
  321. :codeUrl="codeUrl"
  322. @preLook="preLook"
  323. :ispreLook="true"
  324. />
  325. <!-- 预报名详情 -->
  326. <qr-code
  327. v-model="codedetailStatus"
  328. title="预报名H5统计"
  329. :codeUrl="detailUrl"
  330. />
  331. <!-- 发送家长会通知 -->
  332. <el-dialog
  333. title="预报名家长会通知"
  334. :visible.sync="extendPaymentStatus"
  335. @close="onClose('extendForm')"
  336. width="400px"
  337. >
  338. <parentsMeeting
  339. v-if="extendPaymentStatus"
  340. ref="extendForm"
  341. :extendForm="extendForm"
  342. :sysMsgStr="sysMsgStr"
  343. :msg="'确认后该短信将发送给已填写预报名问卷的学员'"
  344. />
  345. <div slot="footer" class="dialog-footer">
  346. <el-button @click="extendPaymentStatus = false">取 消</el-button>
  347. <el-button type="primary" @click="onExtendPayment('extendForm')"
  348. >确 定</el-button
  349. >
  350. </div>
  351. </el-dialog>
  352. <!-- 回访记录 -->
  353. <el-dialog
  354. title="新增回访"
  355. width="760px"
  356. v-if="visitVisible"
  357. :close-on-click-modal="false"
  358. :visible.sync="visitVisible"
  359. >
  360. <visit-model
  361. v-if="visitVisible"
  362. @close="visitVisible = false"
  363. :detail="visitDetail"
  364. @submited="getList"
  365. />
  366. </el-dialog>
  367. <!-- 回访记录 -->
  368. <el-dialog
  369. title="意向统计"
  370. width="600px"
  371. :close-on-click-modal="false"
  372. :visible.sync="subjectVisible"
  373. v-if="subjectVisible"
  374. >
  375. <intention-model v-if="subjectVisible" @close="subjectVisible = false" />
  376. </el-dialog>
  377. <el-dialog
  378. title="预览"
  379. width="500px"
  380. :close-on-click-modal="false"
  381. append-to-body
  382. :visible.sync="preLookVisible"
  383. >
  384. <iframe
  385. width="100%"
  386. height="600px"
  387. :src="codeUrl + '&look=true'"
  388. frameborder="0"
  389. ></iframe>
  390. </el-dialog>
  391. </div>
  392. </template>
  393. <script>
  394. import { getMusicGroupAddr } from "../teamDetail/api";
  395. import pagination from "@/components/Pagination/index";
  396. import qrCode from "@/components/QrCode/index";
  397. import { permission } from "@/utils/directivePage";
  398. import { vaildStudentUrl, vaildTeachingUrl } from "@/utils/validate";
  399. import { Export } from "@/utils/downLoadFile";
  400. import visitModel from "@/views/withdrawal-application/modals/visit";
  401. import intentionModel from "./modals/intention";
  402. import parentsMeeting from "./modals/parentsMeeting";
  403. import {
  404. queryPreApplyList,
  405. finishPreApply,
  406. sendParentMeetingNotice,
  407. getSysMessageConfig
  408. } from "./api";
  409. export default {
  410. name: "forecastName",
  411. components: {
  412. pagination,
  413. qrCode,
  414. visitModel,
  415. intentionModel,
  416. parentsMeeting
  417. },
  418. props: ["isedit"],
  419. data() {
  420. const query = this.$route.query;
  421. return {
  422. codedetailStatus: false,
  423. teamName: query.name || null,
  424. codeStatus: false,
  425. musicGroupId: query.id,
  426. codeUrl:
  427. vaildStudentUrl() +
  428. "/project/forecastName/index.html?musicGroupId=" +
  429. query.id,
  430. searchForm: {
  431. name: null,
  432. subjectId: null,
  433. teacherRecommandSubjectId: null,
  434. selectionSubjectId: null,
  435. isAllowAdjust: null,
  436. cloudTeacherMethod: null,
  437. kitPurchaseMethod: null
  438. },
  439. tableList: [],
  440. pageInfo: {
  441. // 分页规则
  442. limit: 10, // 限制显示条数
  443. page: 1, // 当前页
  444. total: 0, // 总条数
  445. page_size: [10, 20, 40, 50] // 选择限制显示条数
  446. },
  447. visitVisible: false,
  448. subjectVisible: false,
  449. visitDetail: null,
  450. extendPaymentStatus: false,
  451. extendForm: {
  452. meetingDate: null,
  453. address: null
  454. },
  455. extendRule: {
  456. meetingDate: [
  457. { required: true, message: "请选择家长会时间", trigger: "change" }
  458. ],
  459. address: [
  460. { required: true, message: "请输入家长会地址", trigger: "blur" }
  461. ]
  462. },
  463. preLookVisible: false,
  464. sysMsg: "",
  465. subjectList: [],
  466. tenantId: null
  467. };
  468. },
  469. async mounted() {
  470. this.tenantId = this.$helpers.tenantId;
  471. await this.$store.dispatch("setSubjects");
  472. // 获取短信推送模板
  473. this.subjectList = [...this.selects.subjects];
  474. this.subjectList.push({ id: -1, name: "无" });
  475. const rus = await getSysMessageConfig({
  476. type: "STUDENT_SMS_IM_MUSIC_GROUP_PARENT_MEETING_NOTICE"
  477. });
  478. this.sysMsg = rus.data?.content || "";
  479. this.getList();
  480. },
  481. methods: {
  482. permission,
  483. onReSet() {
  484. this.$refs["searchForm"].resetFields();
  485. this.search();
  486. },
  487. search() {
  488. this.pageInfo.page = 1;
  489. this.getList();
  490. },
  491. onCancel() {
  492. this.$store.dispatch("delVisitedViews", this.$route);
  493. this.$router.push({ path: "/teamList" });
  494. },
  495. downloadFile() {
  496. let params = this.searchForm;
  497. Export(
  498. this,
  499. {
  500. url: "/api-web/studentRegistration/preRegisterExport",
  501. params: {
  502. ...params,
  503. musicGroupId: this.musicGroupId
  504. },
  505. fileName: "预报名列表.xls"
  506. },
  507. "是否确认导出报表?"
  508. );
  509. },
  510. async getList() {
  511. try {
  512. const result = await queryPreApplyList({
  513. ...this.searchForm,
  514. musicGroupId: this.musicGroupId,
  515. page: this.pageInfo.page,
  516. rows: this.pageInfo.limit
  517. });
  518. this.tableList = result.data.rows;
  519. this.pageInfo.total = result.data.total;
  520. } catch (error) {}
  521. },
  522. async onPaymentGroup(type) {
  523. try {
  524. const { data } = await getMusicGroupAddr({
  525. musicGroupId: this.musicGroupId,
  526. page: 1,
  527. rows: 10
  528. });
  529. console.log(data, "data");
  530. if (Array.isArray(data.rows) && data.rows.length > 0) {
  531. this.$confirm("您是否确定开启乐团缴费?", "提示", {
  532. confirmButtonText: "确定",
  533. cancelButtonText: "取消",
  534. type: "warning"
  535. }).then(async () => {
  536. const result = await finishPreApply({
  537. isCheckStudentNum: type == 1 ? false : true,
  538. musicGroupId: this.musicGroupId
  539. });
  540. this.$store.dispatch("delVisitedViews", this.$route);
  541. this.$router.push({
  542. path: "/teamList"
  543. });
  544. });
  545. } else {
  546. this.$confirm("请先设置开团商品收货地址?", "提示", {
  547. confirmButtonText: "去设置",
  548. cancelButtonText: "取消",
  549. type: "warning"
  550. }).then(async () => {
  551. this.$listeners.changeActive("10");
  552. });
  553. }
  554. } catch (error) {}
  555. },
  556. addVisited(rows) {
  557. // 新增回访
  558. this.visitVisible = true;
  559. this.visitDetail = {
  560. musicGroupId: rows.musicGroupId,
  561. overview: "",
  562. purpose: "",
  563. userId: rows.userId,
  564. type: "",
  565. visitTime: "",
  566. visitType: "",
  567. feedback: "",
  568. realName: rows.userName
  569. };
  570. // this.visitDetail = rows
  571. },
  572. onClose(formName) {
  573. this.extendForm = {
  574. meetingDate: null,
  575. address: null
  576. };
  577. // this.$refs[formName].$refs[formName].resetFields();
  578. },
  579. onExtendPayment(formName) {
  580. // console.log(formName)
  581. // console.log(this.$refs)
  582. // return
  583. this.$refs[formName].$refs[formName].validate(async valid => {
  584. if (valid) {
  585. try {
  586. await this.$confirm("您是否确定发送家长会通知?", "提示", {
  587. confirmButtonText: "确定",
  588. cancelButtonText: "取消",
  589. type: "warning"
  590. });
  591. await sendParentMeetingNotice({
  592. ...this.extendForm,
  593. musicGroupId: this.musicGroupId
  594. });
  595. this.$message.success("家长会通知已发送");
  596. this.extendPaymentStatus = false;
  597. } catch (error) {}
  598. }
  599. });
  600. },
  601. applyDates() {
  602. return {
  603. firstDayOfWeek: 1,
  604. disabledDate(time) {
  605. if (end) {
  606. return new Date(end).getTime() - 86400000 >= time.getTime();
  607. } else {
  608. return time.getTime() + 86400000 < Date.now();
  609. //开始时间不选时,结束时间最大值小于等于当天
  610. }
  611. }
  612. };
  613. },
  614. preLook(val) {
  615. this.preLookVisible = true;
  616. }
  617. },
  618. computed: {
  619. sysMsgStr() {
  620. let strArr = this.sysMsg.split("{}");
  621. if (strArr.length == 3) {
  622. return `${strArr[0]}<span style="color:red">"${
  623. this.extendForm.meetingDate ? this.extendForm.meetingDate : "--"
  624. }"</span>${strArr[1]}<span style="color:red">"${
  625. this.extendForm.address ? this.extendForm.address : "--"
  626. }"</span>
  627. ${strArr[2]}`;
  628. } else {
  629. return ``;
  630. }
  631. },
  632. detailUrl() {
  633. return (
  634. vaildTeachingUrl() +
  635. "/#/preApplySubject?musicGroupId=" +
  636. this.$route.query.id +
  637. "&tenantId=" +
  638. this.tenantId
  639. );
  640. }
  641. }
  642. };
  643. </script>
  644. <style lang="less" scoped>
  645. .msgP {
  646. line-height: 24px;
  647. margin-top: 10px;
  648. }
  649. </style>