index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. <template>
  2. <div class="m-right-block fr mh576">
  3. <div class="right-block-bd ng-scope" ui-view="myStudyContent" style="position: relative;">
  4. <div class="panel-tit clear">
  5. <p class="fl">推荐课程</p>
  6. <ul class="fr tips-intro" style="color:royalblue" @mouseover="showTip=true" @mouseleave="showTip=false">
  7. <li class="fs15 tit" style="margin-right: 20px;">
  8. <i class="p-ico questiong-ico" style="margin-right: 0px;" /> 温馨提醒
  9. </li>
  10. </ul>
  11. <div class="fr tip-card" v-show="showTip">
  12. <div class="p20">
  13. <h3>温馨提醒:</h3>
  14. <h2 style="margin: 8px; 0 16px 0px;">一、福建省内可报</h2>
  15. <h4 style="margin: 8px;">1.施工现场专业人员</h4>
  16. <h4 style="margin: 8px;">2.20周岁以上,且男性小于60周岁,女性小于55周岁。</h4>
  17. <h2 style="margin:8px 0 16px 0px;">二、宁德内可报:</h2>
  18. <h4 style="margin: 8px;">1.安全生产管理人员</h4>
  19. <h4 style="margin: 8px;">2.建筑施工特种作业人员</h4>
  20. <h4 style="margin: 8px;">3.企业安全生产培训</h4>
  21. </div>
  22. </div>
  23. </div>
  24. <el-row class="pt-line mt20">
  25. <el-col :span="4" :xs="12">
  26. <el-button :class="{type_active : type==''}" class="type_item" type="text" @click="type=''">所有</el-button>
  27. </el-col>
  28. <el-col :span="item.span" :xs="12" v-for="item in typeList" :key="item.id" v-if="item.isOpen && !item.link">
  29. <el-button :class="{type_active:item.name==type }" class="type_item" type="text"
  30. @click="type=item.name">{{item.name}}</el-button>
  31. </el-col>
  32. </el-row>
  33. <ul class="pt-line mt20" v-if="ndList.length>1">
  34. <li style="float: left;font-size: 16px;margin: 4px;padding: 4px;">
  35. <span>课程年度:</span>
  36. </li>
  37. <li style="float: left;">
  38. <span :class="{type_active:nd==''}" class="nav-btn-years" @click="nd=''">所有</span>
  39. </li>
  40. <li v-for="item in ndList" style="float: left;">
  41. <span :class="{type_active:item==nd }" class="nav-btn-years" @click="nd=item">{{item}} </span>
  42. </li>
  43. <li style="float: left;">
  44. <input type="text" style="line-height: 1;padding: 10px" v-model="filterName"
  45. class="ui-ipt ng-pristine ng-valid filterName" placeholder="输入名字查找">
  46. </li>
  47. </ul>
  48. <ul class="m-course-list clear mt10 classlist">
  49. <li v-for="(item,index) in list.slice(page*size-size, page*size)" :key="item.course_id"
  50. class="pt-sola mt20 pb10">
  51. <div>
  52. <span v-if="item.isFinish==1" class="p-ico2 ico-passed"></span>
  53. <div class="img">
  54. <img :src="item.tb">
  55. <div class="year-label">
  56. <span v-if="item.is_pay==0 && item.buyImg =='' && item.payNo == ''">
  57. 还未购买
  58. </span>
  59. <span v-else-if="item.is_pay == 2 && item.is_import ==9">
  60. 预购买中
  61. </span>
  62. <span v-else-if="item.is_pay==0" style="background-color: orange;">
  63. 等待审核
  64. </span>
  65. <span v-else-if="item.is_pay==2" style="background-color: #78335F;">申请驳回</span>
  66. <span v-else-if="!item.is_pass"
  67. style="background-color: blue;padding: 2px;border-radius: 2px;">在学习中</span>
  68. <span v-else style="background-color: green;padding: 2px;border-radius: 2px;">已经完成</span>
  69. </div>
  70. <div class="hover-block">
  71. <div class="mask-bg"></div>
  72. <el-button @click="gotoPlay(item.course_id)" v-if="item.is_pay==1"
  73. class="ui-btn btn-blue">进入学习</el-button>
  74. <el-button @click="goPay(item)" v-else-if="item.is_pay==2 || !!item.buyImg"
  75. class="ui-btn btn-w">补充材料</el-button>
  76. <el-button @click="goPay(item)" v-else-if="item.payErr" class="ui-btn btn-gr">申请购买</el-button>
  77. <el-button @click="goPay(item)" v-else class="ui-btn btn-o">购买课程</el-button>
  78. </div>
  79. </div>
  80. <div class="tit"><a>{{item.displayName || item.name}}</a>
  81. </div>
  82. <div class="info">
  83. <p class="w1"><span class="p-ico c1"></span> {{item.type}} </p>
  84. <p class="w2"><span class="p-ico c2"></span>{{item.nd||'2020'}}</p>
  85. <p class="w1">
  86. <span class="p-ico c5"></span> ¥{{item.fee/100}}元
  87. </p>
  88. <p class="w2">
  89. <span class="p-ico c3"></span> {{item.xs/10}}学时
  90. </p>
  91. </div>
  92. </div>
  93. </li>
  94. </ul>
  95. <div v-if="list.length==0" class="tc mt20 red">
  96. <span style="color: red;padding:40px;font-size: 26px;">已经最后一页了</span>
  97. </div>
  98. <el-pagination class="m-pages" @current-change="(page)=>{this.page=page}" :current-page="page" :page-size="size"
  99. layout="total, prev, pager, next" :total="list.length">
  100. </el-pagination>
  101. </div>
  102. <el-dialog title="申请开通课程" :visible.sync="buyCourseDialog" width="550px" top="100px" align="left">
  103. <template v-if="!showPay">
  104. <el-form label-width="100px" :inline="false" :model="buyForm" :rules="rules"
  105. ref="elForm">
  106. <el-form-item label="账户余额" prop="balance" >
  107. <p style="margin-left: 20px;font-size: 16px;">
  108. <span v-if="userInfo.balance>=buyForm.fee" style="color: green;"> ¥{{userInfo.balance/100}}元</span>
  109. <span v-else style="color: red;"> ¥{{userInfo.balance/100}}元</span>
  110. </p>
  111. </el-form-item>
  112. <el-form-item label="报考岗位" prop="courseName">
  113. <el-input type="text" placeholder="报考岗位" v-model="buyForm.courseName+'-'+buyForm.nd"
  114. style="width: 360px;" />
  115. </el-form-item>
  116. <el-form-item label="证书编号" prop="rzCode">
  117. <el-input v-model="buyForm.rzCode" type="text" style="width: 360px;">
  118. <template #suffix>
  119. <el-button @click="openShowAllRzcodeDialog" type="text" style="margin-right: 10px;">修改</el-button>
  120. </template>
  121. </el-input>
  122. </el-form-item>
  123. <el-divider></el-divider>
  124. <h3 class="tc" style="margin-bottom: 16px;">发票信息</h3>
  125. <el-form-item label="是否需要开票">
  126. <el-radio-group v-model="buyForm.needInvoice">
  127. <el-radio :label="1">是</el-radio>
  128. <el-radio :label="0">否</el-radio>
  129. </el-radio-group>
  130. </el-form-item>
  131. <template v-if="buyForm.needInvoice">
  132. <el-form-item label="开票类型">
  133. <el-radio-group v-model="buyForm.invoiceType">
  134. <el-radio label="personal">个人</el-radio>
  135. <el-radio label="enterprise">企业</el-radio>
  136. </el-radio-group>
  137. </el-form-item>
  138. <el-form-item label="发票抬头" prop="title">
  139. <el-input v-model="buyForm.title" :placeholder="buyForm.invoiceType === 'enterprise'?'请输入单位名称':'请输入真实名字'" style="width: 360px;"></el-input>
  140. </el-form-item>
  141. <el-form-item label="手机号码" prop="phone">
  142. <el-input v-model="buyForm.phone" placeholder="请输入手机号码" style="width: 360px;"></el-input>
  143. </el-form-item>
  144. <el-form-item label="邮箱地址" prop="email">
  145. <el-input v-model="buyForm.email" placeholder="请输入邮箱地址" style="width: 360px;"></el-input>
  146. </el-form-item>
  147. </template>
  148. <el-divider></el-divider>
  149. <h2 class="tc"> 本课程费用: <strong style="color: red;"> {{buyForm.fee/100}} 元 </strong> </h2>
  150. <el-form-item label-width="0" style="margin: 30px auto;text-align: center;">
  151. <el-button @click="cancelBuyCourse">取 消</el-button>
  152. <el-button @click="generatePayQrcode" type="primary">提交订单</el-button>
  153. <el-button v-if="userInfo.balance >= buyForm.fee" @click="doAccountPay" type="success">余额付款</el-button>
  154. </el-form-item>
  155. </el-form>
  156. </template>
  157. <template v-if="showPay">
  158. <h2 class="tc"> 本课程费用: <strong style="color: red;"> {{buyForm.fee/100}} 元 </strong> </h2>
  159. <div style="width: 300px; margin: 20px auto;">
  160. <img :src="wxPayUrl" width="300px" @click="showImg(wxPayUrl)">
  161. </div>
  162. <p class="tc">请使用微信扫码支付</p>
  163. <el-row class="tc fc">
  164. <el-button @click="cancelBuyCourse">关 闭</el-button>
  165. </el-row>
  166. </template>
  167. </el-dialog>
  168. <el-dialog append-to-body close-on-click-modal :visible.sync="showImgDialog" style="margin-top: 0px;"
  169. :width="width">
  170. <img :src="imgUrl" @load="onLoad" alt="" />
  171. </el-dialog>
  172. <el-dialog append-to-body close-on-click-modal :visible.sync="showAllRzcodeDialog" width="1024">
  173. <el-table v-if="buyForm.list.length>0" :data="buyForm.list" border>
  174. <el-table-column label="证书编号" prop="certificateNum" align="center" />
  175. <el-table-column label="岗位名称" prop="positionName" align="center" />
  176. <el-table-column label="证书状态" prop="certificateStatus" align="center" />
  177. <el-table-column label="发证机关" prop="certificateOrgan" align="center" />
  178. <el-table-column label="发证时间" prop="startTime" align="center" />
  179. <el-table-column label="选择" prop="reviewTime" align="center">
  180. <template slot-scope="{row}">
  181. <el-button @click="selectRzcode(row)" type="primary">选择</el-button>
  182. </template>
  183. </el-table-column>
  184. </el-table>
  185. </el-dialog>
  186. </div>
  187. </template>
  188. <script>
  189. import {
  190. httpServer
  191. } from "@/components/httpServer/httpServer.js";
  192. import {
  193. MessageBox
  194. } from "element-ui";
  195. import {
  196. parseTime
  197. } from "@/utils";
  198. import DoUpload from '@/components/upload/index.vue'
  199. import exampleImg from '@/assets/template.png'
  200. import {curDatetime} from '@/utils/date.js'
  201. import {
  202. mapGetters,
  203. mapActions
  204. } from "vuex";
  205. export default {
  206. name: "Index",
  207. data() {
  208. return {
  209. page: 1,
  210. size: 6,
  211. total: 0,
  212. stage: 0,
  213. isCompanyPay: 0,
  214. showTip: false,
  215. width: "",
  216. type: '',
  217. filterName: '',
  218. list: [],
  219. nd: new Date().getFullYear() + '',
  220. ndList: [],
  221. allList: [],
  222. isCommitment: "",
  223. buyCourseDialog: false,
  224. showExample: false,
  225. showImgDialog: false,
  226. showAllRzcodeDialog: false,
  227. showPay: false,
  228. buyForm: {
  229. payType:'wx',
  230. rzCode: '',
  231. email: '',
  232. title: '',
  233. phone: '',
  234. courseName: '',
  235. list: [],
  236. fee: 0,
  237. courseId: '',
  238. needInvoice: 0,
  239. invoiceType: 'personal'
  240. },
  241. imgUrl: '',
  242. qrcodeUrl: "",
  243. wxPayUrl:"",
  244. aliPayUrl:"",
  245. outTradeNo: "",
  246. courseFee: 0,
  247. title: '',
  248. timer: null,
  249. tickCount: 0,
  250. listLoading: false,
  251. media: {},
  252. commitmentDialog: false,
  253. exampleImg: exampleImg,
  254. rules: {
  255. rzCode: [{
  256. required: true,
  257. message: '请输入证书编号'
  258. }],
  259. payNo: [{
  260. required: true,
  261. message: '请输入订单编号后六位'
  262. }],
  263. title: [{
  264. required: true,
  265. message: '抬头必须填写'
  266. }],
  267. email: [{
  268. required: true,
  269. message: '请输入有效邮箱'
  270. },
  271. {
  272. type: 'string',
  273. message: '邮箱格式不正确',
  274. trigger: 'blur',
  275. transform(value) {
  276. value = value.trim();
  277. if (!/^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)) {
  278. return true
  279. } else {}
  280. }
  281. }
  282. ],
  283. company: [{
  284. required: true,
  285. message: '请输入单位名称'
  286. }],
  287. phone: [{
  288. required: true,
  289. message: '请输入手机号码'
  290. }, {
  291. pattern: /^1[3-9]\d{9}$/,
  292. message: '手机号码格式不正确',
  293. trigger: 'blur'
  294. }],
  295. courseName: [{
  296. required: true,
  297. message: '请输入报考岗位'
  298. }]
  299. },
  300. errorImg: 'this.src="' + require('../../../assets/images/no-data_hash5abcd2ef62.png') + '"'
  301. };
  302. },
  303. computed: {
  304. ...mapGetters("user", ["typeList", "userInfo"])
  305. },
  306. components: {
  307. DoUpload
  308. },
  309. filters: {
  310. dateFilter(val) {
  311. return parseTime(val, '{y}-{m}-{d}')
  312. }
  313. },
  314. watch: {
  315. type(val) {
  316. this.page = 1
  317. this.nd = new Date().getFullYear() + ''
  318. this.filterData()
  319. },
  320. nd(val) {
  321. this.filterData()
  322. },
  323. filterName() {
  324. this.page = 1
  325. this.filterData()
  326. }
  327. },
  328. beforeMount() {
  329. this.type = this.$route.query.type || ''
  330. this.getData();
  331. },
  332. beforeDestroy() {
  333. if (this.timer) window.clearInterval(this.timer);
  334. },
  335. methods: {
  336. showImg(url) {
  337. if (!url) return;
  338. this.imgUrl = url;
  339. this.showImgDialog = true;
  340. },
  341. closeDialog() {
  342. if (this.timer) window.clearInterval(this.timer);
  343. },
  344. onLoad(e) {
  345. const img = e.target;
  346. let width = 0;
  347. if (img.fileSize > 0 || (img.width > 1 && img.height > 1)) {
  348. width = img.width + 40;
  349. }
  350. this.width = width + "px";
  351. },
  352. initTimer() {
  353. if (this.timer) window.clearInterval(this.timer);
  354. this.tickCount = 0;
  355. this.timer = window.setInterval(() => {
  356. this.tickCount++;
  357. this.tickTimer();
  358. }, 3000);
  359. },
  360. tickTimer() {
  361. if (this.tickCount > 100) {
  362. if (this.timer) window.clearInterval(this.timer);
  363. this.$message.warning("支付超时,请重新支付");
  364. this.buyCourseDialog = false;
  365. return;
  366. }
  367. let outTradeNo = this.outTradeNo;
  368. httpServer("weixin.isPayOk", { outTradeNo }).then((res) => {
  369. if (res.code == 200 && !!res.data) {
  370. if (this.timer) window.clearInterval(this.timer);
  371. this.$message.successMsg("支付成功", 2);
  372. this.buyCourseDialog = false;
  373. this.getData();
  374. }
  375. });
  376. },
  377. doAccountPay(){
  378. let param = Object.assign({}, this.buyForm);
  379. httpServer("weixin.doAccountPay", {courseId}).then((res) => {
  380. if (res.code != 200) return;
  381. this.$message.successMsg("支付成功", 2);
  382. this.buyCourseDialog = false;
  383. this.getData();
  384. });
  385. },
  386. generatePayQrcode() {
  387. console.log('generatePayQrcode')
  388. let payType = this.buyForm.payType;
  389. let apiName = payType === 'wx' ? "weixin.DoWxpay" : "weixin.DoaliPay";
  390. let {
  391. courseId,
  392. courseName,
  393. title,
  394. email,
  395. phone,
  396. needInvoice,
  397. invoiceType
  398. } = this.buyForm;
  399. let param = {
  400. courseId,
  401. title,
  402. phone,
  403. email,
  404. needInvoice,
  405. invoiceType
  406. };
  407. httpServer(apiName, param).then((res) => {
  408. if (res.code != 200) return;
  409. let { outTradeNo, showUrl } = res.data;
  410. this.outTradeNo = outTradeNo;
  411. if (payType === 'wx') {
  412. this.wxPayUrl = showUrl;
  413. } else {
  414. this.aliPayUrl = showUrl;
  415. }
  416. this.showPay = true
  417. this.initTimer();
  418. });
  419. },
  420. getData() {
  421. let param = {
  422. size: 1000,
  423. trainType: 2,
  424. from: 0
  425. }
  426. httpServer("course.getcoursemarket", param).then((res) => {
  427. if (res.code == 200) {
  428. this.allList = res.data.list;
  429. this.filterData()
  430. }
  431. });
  432. },
  433. filterData() {
  434. let nd = this.nd || '';
  435. let filterName = this.filterName || '';
  436. let type = this.type || ''
  437. this.ndList = [];
  438. this.list = [];
  439. for (let i in this.allList) {
  440. let item = this.allList[i];
  441. if (type != '' && item.type != type) continue;
  442. if (this.ndList.indexOf(item.nd) == -1) {
  443. this.ndList.push(item.nd);
  444. }
  445. if (filterName!='' && item.name.indexOf(filterName) == -1) continue;
  446. if (nd != '' && item.nd != nd) continue;
  447. this.list.push(item)
  448. }
  449. },
  450. cancelBuyCourse() {
  451. if (this.timer) window.clearInterval(this.timer);
  452. this.$refs["elForm"] && this.$refs["elForm"].resetFields();
  453. this.buyCourseDialog = false
  454. this.showPay = false;
  455. },
  456. openShowAllRzcodeDialog() {
  457. this.showAllRzcodeDialog = true;
  458. },
  459. selectRzcode(row) {
  460. this.buyForm.rzCode = row.certificateNum;
  461. this.showAllRzcodeDialog = false;
  462. },
  463. gotoDetail(courseId) {
  464. this.$router.push(`/main/course/${courseId}`);
  465. },
  466. goPay(item) {
  467. this.showPay = false;
  468. this.buyForm = Object.assign(this.buyForm, item)
  469. this.buyForm.phone = this.userInfo.phone;
  470. this.buyForm.temp = item;
  471. this.buyForm.courseName = item.name;
  472. this.buyForm.courseId = item.course_id;
  473. this.buyForm.fee = item.fee;
  474. // 检查
  475. httpServer("weixin.docheckpay", {
  476. courseId: item.course_id
  477. }).then((res) => {
  478. if (res.code != 200) return;
  479. Object.assign(this.buyForm, res.data);
  480. this.buyCourseDialog = true;
  481. });
  482. },
  483. gotoPlay(item) {
  484. let courseId = item.courseId;
  485. if( curDatetime() < item.startDate){
  486. this.$message.warning("还未到学习时间");
  487. return
  488. }
  489. this.$router.push({name:'play', params:{courseId}})
  490. },
  491. handleCurrentChange(page) {
  492. this.page = page;
  493. this.filterData()
  494. }
  495. },
  496. };
  497. </script>
  498. <style>
  499. @import "../../../assets/css/content.css";
  500. @import "../../../assets/css/course.css";
  501. @import url("./index.css");
  502. .buyForm-title {
  503. width: 90px;
  504. padding: 2px;
  505. text-align: center;
  506. }
  507. .commitment-header {
  508. font-size: 16px;
  509. text-align: left;
  510. }
  511. .commitment {
  512. text-indent: 30px;
  513. margin-top: 20px;
  514. font-size: 16px;
  515. line-height: 200%;
  516. }
  517. .commitment-footer {
  518. margin-top: 30px;
  519. text-indent: 50px;
  520. font-size: 16px;
  521. text-align: left;
  522. }
  523. .commitment-content {
  524. font-size: 16px;
  525. }
  526. .tip-card {
  527. border-radius: 20px;
  528. font-size: 14px;
  529. float: right;
  530. width: 420px;
  531. right: 20px;
  532. position: absolute;
  533. top: 50px;
  534. color: white;
  535. background-color: #7fbae4;
  536. z-index: 1000;
  537. }
  538. .tips-intro {
  539. color: #468cf2;
  540. cursor: pointer;
  541. position: relative;
  542. }
  543. </style>