Payment.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <template>
  2. <div class="payment" v-if="data">
  3. <ul class="payment-left">
  4. <li
  5. v-for="(itemP, indexP) in payList"
  6. :key="indexP"
  7. @click="handleChangePay(itemP.type)"
  8. :class="[payType === itemP.type ? 'active' : '']"
  9. >
  10. <img :src="itemP.img" />
  11. <span>{{ itemP.label }}</span>
  12. </li>
  13. </ul>
  14. <div class="payment-right">
  15. <i class="el-icon-close" @click="closeDialogue"></i>
  16. <h2>{{ data.name || data.cn_title }}</h2>
  17. <h3>{{ data.org_name || "二十一世纪英文报" }}</h3>
  18. <p class="price">
  19. ¥{{
  20. data.hasOwnProperty("price_discount")
  21. ? data.price_discount
  22. : payAmount || data.price | cutMoneyFiter
  23. }}
  24. </p>
  25. <template v-if="payType === 'dui'">
  26. <el-input
  27. class="code"
  28. placeholder="在此输入兑换码"
  29. v-model="codeValue"
  30. maxlength="20"
  31. ></el-input>
  32. <a class="exchange" @click="handleExchange">兑换</a>
  33. <b class="tips">输入兑换码</b>
  34. </template>
  35. <div v-else v-loading="loading">
  36. <canvas
  37. id="QRCode_header"
  38. style="width: 338px; height: 338px; cursor: pointer"
  39. @click="handleRefresh"
  40. ></canvas>
  41. </div>
  42. <template v-if="payType === 'wei'">
  43. <b class="tips">请使用微信扫一扫</b>
  44. </template>
  45. <template v-else-if="payType === 'zhi'">
  46. <b class="tips">请使用支付宝扫一扫</b>
  47. </template>
  48. </div>
  49. <div class="toPage" v-if="showToPage">
  50. 此兑换码包含多种商品,请到个人中心统一兑换。<a @click="toPage">去兑换</a>
  51. <i class="el-icon-error" @click="showToPage = !showToPage"></i>
  52. </div>
  53. </div>
  54. </template>
  55. <script>
  56. //这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
  57. //例如:import 《组件名称》from ‘《组件路径》';
  58. import { cutMoneyFiter } from "@/utils/defined";
  59. import { getLogin } from "@/api/ajax";
  60. import QRCode from "qrcode";
  61. export default {
  62. //import引入的组件需要注入到对象中才能使用
  63. components: {},
  64. props: ["data", "payWay", "qr_code_url", "orderId", "order_amount"],
  65. filters: {
  66. cutMoneyFiter,
  67. },
  68. data() {
  69. //这里存放数据
  70. return {
  71. payList: [
  72. {
  73. img: require("../../../assets/duihuanma.png"),
  74. label: "兑换码",
  75. type: "dui",
  76. },
  77. {
  78. img: require("../../../assets/weixin.png"),
  79. label: "微信支付",
  80. type: "wei",
  81. },
  82. {
  83. img: require("../../../assets/zhifubao.png"),
  84. label: "支付宝",
  85. type: "zhi",
  86. },
  87. ], // 支付方式
  88. payType: "dui",
  89. codeValue: "", // 兑换码的值
  90. codeImg: "",
  91. payCode: {
  92. wei: "http://localhost:9970/#/people_manage",
  93. zhi: "http://localhost:9970/#/organize_manage",
  94. },
  95. opts: {
  96. errorCorrectionLevel: "H", //容错级别
  97. type: "image/png", //生成的二维码类型
  98. quality: 1, //二维码质量
  99. margin: 0, //二维码留白边距
  100. width: 330, //宽
  101. height: 330, //高
  102. text: "", //二维码内容
  103. color: {
  104. dark: "#333333", //前景色
  105. light: "#fff", //背景色
  106. },
  107. },
  108. timer: null,
  109. loading: false,
  110. payAmount: this.order_amount ? this.order_amount : null,
  111. showToPage: false, // 多条兑换码跳转去个人中心
  112. };
  113. },
  114. //计算属性 类似于data概念
  115. computed: {},
  116. //监控data中数据变化
  117. watch: {
  118. // data:{
  119. // handler(val, oldVal) {
  120. // const _this = this;
  121. // if (val) {
  122. //
  123. // }
  124. // },
  125. // // 深度观察监听
  126. // deep: true,
  127. // },
  128. },
  129. //方法集合
  130. methods: {
  131. // 支付方式
  132. handleChangePay(type) {
  133. this.payType = type;
  134. clearInterval(this.timer);
  135. if (type === "dui") {
  136. return false;
  137. }
  138. this.timer = setInterval(() => {
  139. this.getOrderStatus();
  140. }, 5000);
  141. this.loading = true;
  142. let MethodName = "/ShopServer/Client/OrderManager/UpdateOrderPayType";
  143. let data = {
  144. id: this.orderId,
  145. pay_type:
  146. this.payType === "wei" ? 3 : this.payType === "zhi" ? 4 : null,
  147. };
  148. getLogin(MethodName, data).then((res) => {
  149. if (res.status === 1) {
  150. this.payCode[this.payType] = res.qr_code_url;
  151. this.payAmount = res.order_amount;
  152. this.createQRCode();
  153. }
  154. });
  155. },
  156. createQRCode() {
  157. let msg = document.getElementById("QRCode_header");
  158. setTimeout(() => {
  159. QRCode.toCanvas(
  160. msg,
  161. this.payCode[this.payType],
  162. this.opts,
  163. function (error) {
  164. if (error) {
  165. console.log("二维码加载失败", error);
  166. this.$message.error("二维码加载失败");
  167. }
  168. }
  169. );
  170. this.loading = false;
  171. }, 1000);
  172. },
  173. closeDialogue() {
  174. clearInterval(this.timer);
  175. this.$emit("handleClose");
  176. },
  177. // 兑换
  178. handleExchange() {
  179. let MethodName = "/ShopServer/Client/OrderManager/UpdateOrderPayType";
  180. let data = {
  181. id: this.orderId,
  182. pay_type: 5,
  183. discount_code: this.codeValue.trim(),
  184. };
  185. getLogin(MethodName, data).then((res) => {
  186. if (res.status === 1) {
  187. if (this.$emit("handleSuccess")) {
  188. this.$emit("handleSuccess");
  189. } else {
  190. this.$emit("handleClose");
  191. }
  192. } else if (res.status === -6) {
  193. this.showToPage = true;
  194. }
  195. });
  196. },
  197. // 跳转到个人中心-兑换码
  198. toPage() {
  199. this.$router.push({
  200. path: "/peraonal",
  201. query: {
  202. headerConfig: this.$route.query.headerConfig
  203. ? this.$route.query.headerConfig
  204. : "",
  205. type: encodeURIComponent("duihuanma"),
  206. codeId: encodeURIComponent(this.codeValue.trim()),
  207. },
  208. });
  209. },
  210. handleRefresh() {
  211. let MethodName = "/ShopServer/Client/OrderManager/GetOrderNewPayQRCode";
  212. let data = {
  213. id: this.orderId,
  214. };
  215. getLogin(MethodName, data).then((res) => {
  216. if (res.status === 1) {
  217. this.payCode[this.payType] = res.qr_code_url;
  218. this.createQRCode();
  219. }
  220. });
  221. // this.payCode = {
  222. // wei: 'https://baidu.com',
  223. // zhi: 'https://xdf.cn'
  224. // }
  225. // this.createQRCode()
  226. },
  227. getOrderStatus() {
  228. let MethodName = "/ShopServer/Client/OrderManager/GetOrderPayStatus";
  229. let data = {
  230. id: this.orderId,
  231. };
  232. getLogin(MethodName, data).then((res) => {
  233. if (res.status === 1) {
  234. if (res.is_success === "true") {
  235. clearInterval(this.timer);
  236. if (this.$emit("handleSuccess")) {
  237. this.$emit("handleSuccess");
  238. } else {
  239. this.$emit("handleClose");
  240. }
  241. }
  242. }
  243. });
  244. },
  245. },
  246. //生命周期 - 创建完成(可以访问当前this实例)
  247. created() {
  248. this.payType = this.payWay;
  249. },
  250. //生命周期 - 挂载完成(可以访问DOM元素)
  251. mounted() {
  252. if (this.qr_code_url) {
  253. this.payCode[this.payType] = this.qr_code_url;
  254. this.createQRCode();
  255. this.timer = null;
  256. this.timer = setInterval(() => {
  257. this.getOrderStatus();
  258. }, 5000);
  259. }
  260. },
  261. //生命周期-创建之前
  262. beforeCreated() {},
  263. //生命周期-挂载之前
  264. beforeMount() {},
  265. //生命周期-更新之前
  266. beforUpdate() {},
  267. //生命周期-更新之后
  268. updated() {},
  269. //生命周期-销毁之前
  270. beforeDestory() {},
  271. //生命周期-销毁完成
  272. destoryed() {},
  273. //如果页面有keep-alive缓存功能,这个函数会触发
  274. activated() {},
  275. };
  276. </script>
  277. <style lang="scss" scoped>
  278. /* @import url(); 引入css类 */
  279. .payment {
  280. display: flex;
  281. &-left {
  282. background: #f5f5f5;
  283. width: 216px;
  284. padding: 24px;
  285. list-style: none;
  286. margin: 0;
  287. li {
  288. border: 1px solid #ebebeb;
  289. border-radius: 8px;
  290. background: #ffffff;
  291. margin-bottom: 16px;
  292. cursor: pointer;
  293. padding: 16px 24px;
  294. display: flex;
  295. align-items: center;
  296. img {
  297. width: 24px;
  298. margin-right: 8px;
  299. }
  300. span {
  301. color: rgba(0, 0, 0, 0.88);
  302. font-weight: 400;
  303. font-size: 18px;
  304. line-height: 26px;
  305. }
  306. &:hover {
  307. background: #eef3ff;
  308. }
  309. &.active {
  310. border-color: #3459d2;
  311. background: #eef3ff;
  312. }
  313. }
  314. }
  315. &-right {
  316. flex: 1;
  317. background: #ffffff;
  318. box-shadow: 0px 6px 30px 5px rgba(0, 0, 0, 0.05),
  319. 0px 16px 24px 2px rgba(0, 0, 0, 0.04),
  320. 0px 8px 10px -5px rgba(0, 0, 0, 0.08);
  321. position: relative;
  322. padding: 64px 80px;
  323. text-align: center;
  324. .el-icon-close {
  325. position: absolute;
  326. right: 16px;
  327. top: 16px;
  328. width: 16px;
  329. cursor: pointer;
  330. }
  331. h2 {
  332. margin: 0 0 2px 0;
  333. color: rgba(0, 0, 0, 0.88);
  334. font-weight: 400;
  335. font-size: 24px;
  336. line-height: 32px;
  337. }
  338. h3 {
  339. font-weight: 500;
  340. font-size: 14px;
  341. line-height: 22px;
  342. color: rgba(0, 0, 0, 0.4);
  343. margin: 0;
  344. }
  345. .price {
  346. font-weight: 700;
  347. font-size: 64px;
  348. line-height: 72px;
  349. color: #ec5e41;
  350. margin: 40px 0;
  351. }
  352. .code {
  353. height: 248px;
  354. width: 336px;
  355. background: #f5f5f5;
  356. border: 1px solid #ebebeb;
  357. border-radius: 16px;
  358. overflow: hidden;
  359. display: flex;
  360. align-items: center;
  361. align-content: center;
  362. }
  363. .exchange {
  364. background: #3459d2;
  365. border-radius: 40px;
  366. padding: 8px 40px;
  367. display: inline-block;
  368. margin-top: 40px;
  369. color: #ffffff;
  370. font-weight: 400;
  371. font-size: 24px;
  372. line-height: 32px;
  373. }
  374. .tips {
  375. font-weight: 400;
  376. font-size: 16px;
  377. line-height: 24px;
  378. color: rgba(0, 0, 0, 0.4);
  379. display: block;
  380. margin-top: 40px;
  381. }
  382. #QRCode_header {
  383. border: 1px solid #ebebeb;
  384. padding: 8px;
  385. }
  386. }
  387. }
  388. .toPage {
  389. position: fixed;
  390. top: 50%;
  391. left: 50%;
  392. width: 442px;
  393. height: 40px;
  394. margin-left: -221px;
  395. margin-top: -20px;
  396. border-radius: 4px;
  397. background: #000;
  398. padding: 8px 12px;
  399. z-index: 999;
  400. color: #fff;
  401. text-align: center;
  402. font-size: 16px;
  403. font-weight: 400;
  404. line-height: 24px;
  405. a {
  406. color: #20f53b;
  407. margin-left: 8px;
  408. }
  409. .el-icon-error {
  410. position: absolute;
  411. width: 24px;
  412. height: 24px;
  413. top: -12px;
  414. right: -12px;
  415. cursor: pointer;
  416. color: #000;
  417. }
  418. }
  419. </style>
  420. <style lang="scss">
  421. .payment {
  422. .code {
  423. .el-input__inner {
  424. border: none;
  425. background: none;
  426. height: 100%;
  427. text-align: center;
  428. color: rgba(0, 0, 0, 1);
  429. font-weight: 400;
  430. font-size: 20px;
  431. line-height: 28px;
  432. }
  433. }
  434. }
  435. </style>