邃芒慧影、口播(PC) https://neuver.metavatar.cc/
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

712 рядки
19 KiB

  1. <template>
  2. <div class="page">
  3. <div class="commoditylIst">
  4. <el-scrollbar :always="true">
  5. <div class="scrollbar-flex-content">
  6. <div class="item" v-for="item in packageList" :key="item.typeDesc" :class="item.sellPriceRmb <= 0 ? 'dashed' : ''">
  7. <!-- @click="clickPayDialog(item)" -->
  8. <div>
  9. <div class="line" :style="`background-color:${ item.sellPriceRmb > 0 ? item.color : '#eee'} ;`"></div>
  10. <div class="info">
  11. <!-- 商品信息 -->
  12. <div class="content">
  13. <div class="titleBox">
  14. <!-- <p class="iconText" v-if="item.sellPriceRmb <= 0" >会员权益</p> -->
  15. <div class="title">
  16. {{ item.title }}
  17. </div>
  18. </div>
  19. <template v-if="item.sellPriceRmb > 0">
  20. <div class="money">
  21. <span class="price">{{
  22. item.sellPriceRmb / 100
  23. }} ¥</span
  24. >/ <span style="text-decoration:line-through;"> {{ $t("store.priceRmb") }}{{ item.priceRmb / 100 }}</span>
  25. </div>
  26. <div class="time">
  27. {{ $t("store.glod") }}<span> {{ item.glod }}</span
  28. >
  29. </div>
  30. <div v-if="item.sellPriceRmb > 0" class="button" @click="clickPayDialog(item)" :style="`background-color: #f3af00 ;`">
  31. {{ $t("store.createOrder") }}
  32. </div>
  33. </template>
  34. </div>
  35. <!-- 商品权益 -->
  36. <div class="authority">
  37. <div v-html="item.detail"></div>
  38. </div>
  39. </div>
  40. </div>
  41. </div>
  42. </div>
  43. </el-scrollbar>
  44. <!-- 企业版 -->
  45. <!-- <div class="item" @click="showTalkUsDialog = true">
  46. <div class="mask" v-if="false">
  47. <el-icon><i-ep-Lock /></el-icon>
  48. </div>
  49. <div class="line" :style="`background-color:#000 ;`"></div>
  50. <div class="info">
  51. <div class="content" style="border-bottom: none">
  52. <div class="titleBox">
  53. <div class="title">
  54. {{ $t("shop.Ent") }}
  55. </div>
  56. </div>
  57. <div class="description">
  58. <div>
  59. {{ lanChange == "zh-cn" ? "所有权限" : "All Pro Benefits" }}
  60. </div>
  61. <div>
  62. {{
  63. lanChange == "zh-cn" ? "克隆数字双元" : "Clone DigItal Double"
  64. }}
  65. </div>
  66. <div>
  67. {{
  68. lanChange == "zh-cn" ? "专属定制头像" : "Customized Avatar"
  69. }}
  70. </div>
  71. <div>
  72. {{
  73. lanChange == "zh-cn"
  74. ? "专属定制声纹"
  75. : "Customized Voiceprint"
  76. }}
  77. </div>
  78. </div>
  79. <div v-if="true" class="button" :style="`background-color:#000 ;`">
  80. {{ $t("shop.talkUs") }}
  81. </div>
  82. <div v-else class="button" :style="`background-color:#000 ;`">
  83. {{ $t("shop.talkUs") }}
  84. </div>
  85. </div>
  86. </div>
  87. </div> -->
  88. </div>
  89. <!-- 对话框 v-if="false"-->
  90. <el-dialog v-model="showPayDialog" v-if="showPayDialog"
  91. :title="$t('store.payType')" width="300px">
  92. <div class="payDialog">
  93. <el-radio-group v-model="payVendor">
  94. <el-radio label="4" border>
  95. <img src="../../assets/img/alipay.png" alt="" />{{ $t("recharge.alipay") }}
  96. </el-radio>
  97. <el-radio label="2" border>
  98. <img src="../../assets/img/weChat.png" alt="" />{{ $t("recharge.weChat") }}
  99. </el-radio>
  100. </el-radio-group>
  101. </div>
  102. <!-- 二维码弹出框 -->
  103. <el-dialog
  104. v-model="orderCodeDialogShow"
  105. width="500px"
  106. append-to-body
  107. destroy-on-close
  108. @closed="clearCode"
  109. :close-on-click-modal="false"
  110. >
  111. <div class="orderCodeDialog" v-loading="loading"
  112. :element-loading-text="`${$t('store.pay')}`">
  113. <div class="codeImg">
  114. <my-Loading-Icon2
  115. v-if="!payCodeUrl && !iframeBody"
  116. ></my-Loading-Icon2>
  117. <!-- :callback="qrcode" -->
  118. <vue-qr v-if="payCodeUrl" :text="payCodeUrl" :size="280"></vue-qr>
  119. <iframe
  120. v-show="iframeBody"
  121. id="myIframe"
  122. width="210PX"
  123. height="205PX"
  124. frameborder="0"
  125. ></iframe>
  126. </div>
  127. <div class="tips">
  128. {{
  129. lanChange == "zh-cn"
  130. ? `扫描二维码进行付款`
  131. : `Scan the QR code for payment`
  132. }}
  133. </div>
  134. <!-- <div class="btnBox">
  135. <div @click="RefreshQR">
  136. {{ lanChange == "zh-cn" ? `刷新二维码` : `Refresh QR code` }}
  137. </div>
  138. </div> -->
  139. </div>
  140. </el-dialog>
  141. <template #footer>
  142. <span class="dialog-footer">
  143. <el-button size="small" @click="showPayDialog = false">{{ $t("store.cancel") }}</el-button>
  144. <el-button size="small" type="primary" @click="payConfirm">
  145. {{$t("store.confirm")}}
  146. </el-button>
  147. </span>
  148. </template>
  149. </el-dialog>
  150. <!-- 联系我们对话框 -->
  151. <talkUs
  152. :showTalkUsDialog="showTalkUsDialog"
  153. @updateShowTalkUsDialog="updateShowTalkUsDialog"
  154. ></talkUs>
  155. </div>
  156. </template>
  157. <script setup>
  158. //#region 导入
  159. import { getCurrentInstance, ref, onMounted } from "vue";
  160. import { packageInfoApi } from "@/apis/myStore";
  161. import { useI18n } from "vue-i18n";
  162. import talkUs from "@/components/talkUs.vue";
  163. import { useRoute, useRouter } from "vue-router";
  164. import { createOrderApi, createPayApi, getOrderStatusApi } from "@/apis/pay";
  165. import { orderDetailApi, findStatusApi } from '@/apis/myStore.js'
  166. import vueQr from 'vue-qr/src/packages/vue-qr.vue';
  167. const route = useRoute();
  168. const router = useRouter();
  169. const { locale } = useI18n();
  170. const lanChange = ref(locale);
  171. const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录
  172. //#endregion ------------------------------------
  173. const packageList = ref([]);
  174. async function getPackageList() {
  175. const res = await packageInfoApi();
  176. packageList.value = res.data;
  177. }
  178. const showPayDialog = ref(false); //套餐信息dialog显示隐藏
  179. const presentItme = reactive({}); //点击的套餐项
  180. // const presentItme = ref({}); //点击的套餐项
  181. function clickPayDialog(item) {
  182. presentItme.value = item;
  183. createOrder(item)
  184. showPayDialog.value = true;
  185. }
  186. //#endregion ------------------------------------
  187. //#region 点击套餐内的支付
  188. function showOrderCode(type) {
  189. orderCodeDialogShow.value = true;
  190. myPayVendor.value = type;
  191. createOrderFunc();
  192. }
  193. const orderCodeDialogShow = ref(false);
  194. const orderCodeUrl = ref(null);
  195. //#endregion ------------------------------------
  196. //#region 页面滚动
  197. const scrollContainerRef = ref(null);
  198. function handleWheel(event) {
  199. const scrollContainer = scrollContainerRef.value; // 获取滚动容器的引用
  200. const scrollAmount = 150; // 每次滚动的距离
  201. // 检查滚动方向
  202. if (event.deltaY > 0) {
  203. // 向右滚动
  204. scrollContainer.scrollLeft += scrollAmount;
  205. } else {
  206. // 向左滚动
  207. scrollContainer.scrollLeft -= scrollAmount;
  208. }
  209. event.preventDefault(); // 防止页面上下滚动
  210. }
  211. //#endregion ------------------------------------
  212. //#region 联系我们弹窗
  213. const showTalkUsDialog = ref(false);
  214. const updateShowTalkUsDialog = (newValue) => {
  215. showTalkUsDialog.value = newValue;
  216. };
  217. //#endregion ------------------------------------
  218. //#region 页面初始化
  219. onMounted(async () => {
  220. getPackageList();
  221. // createOrderFunc();
  222. });
  223. //#endregion ------------------------------------
  224. //#region 支付
  225. const myPayVendor = ref(null); // 2微信 4支付宝
  226. const payCodeUrl = ref(null); //付款二维码地址
  227. const payCodeImg = ref(null); //付款二维码图片
  228. // 支付失败处理
  229. function payErrorHandle() {
  230. orderCodeDialogShow.value = false;
  231. ElMessage.error(
  232. lanChange.value == "zh-cn"
  233. ? `获取订单失败,请重试`
  234. : `Failed to get the order, please try again`
  235. );
  236. }
  237. // 获取订单
  238. const myOrderNumber = ref(null); //订单号
  239. async function createOrderFunc() {
  240. const data = {
  241. productId: 30,
  242. };
  243. try {
  244. const res = await createOrderApi(data);
  245. if (res.code == 200) {
  246. myOrderNumber.value = res.data;
  247. createPayFunc(res.data);
  248. } else {
  249. payErrorHandle();
  250. }
  251. } catch (error) {
  252. payErrorHandle();
  253. }
  254. }
  255. // 获取订单详情
  256. let iframeBody = ref(null);
  257. const iframeDom = ref(null);
  258. const loading = ref(false)
  259. async function createPayFunc(orderNumber) {
  260. const data = {
  261. orderNumber,
  262. payVendor: payVendor.value,
  263. };
  264. try {
  265. const res = await createPayApi(data);
  266. if (res.code == 200) {
  267. // 支付宝获取iframe内容
  268. if (res.data.body) {
  269. orderCodeDialogShow.value = true;
  270. setTimeout(() => {
  271. iframeBody.value = res.data.body;
  272. iframeDom.value = document.getElementById("myIframe");
  273. iframeDom.value.srcdoc = iframeBody.value;
  274. }, 1000)
  275. }
  276. // 直接获取二维码
  277. if (res.data.codeUrl) {
  278. payCodeUrl.value = res.data.codeUrl;
  279. // showOrderCode(payVendor.value)
  280. orderCodeDialogShow.value = true;
  281. }
  282. // findStatus()
  283. await getStatusOfOrderFunc(orderNumber);
  284. } else {
  285. payErrorHandle();
  286. }
  287. } catch (error) {
  288. payErrorHandle();
  289. }
  290. }
  291. // 获取订单支付状态 payStatus 查询支付状态 0:待支付,2:支付中,3:已支付
  292. async function getStatusOfOrderFunc(orderNumber) {
  293. // if (
  294. // route.path != "/myStore" ||
  295. // orderCodeDialogShow.value == false ||
  296. // orderNumber != payVendor.value
  297. // ) {
  298. // return;
  299. // }
  300. try {
  301. // let payVendor = payVendor.value;
  302. let data = {
  303. orderNumber,
  304. payVendor: payVendor.value
  305. }
  306. const res = await findStatusApi(data);
  307. if (res.code == 200) {
  308. if (res.data.orderStatus == 1) { // 页面就不动,继续定时请求
  309. setTimeout(() => {
  310. getStatusOfOrderFunc(orderNumber);
  311. }, 3000);
  312. } else if (res.data.orderStatus == 2) { // 页面就不动, loading....的效果盖在二维码之前,继续定时请求
  313. loading.value = true
  314. setTimeout(() => {
  315. getStatusOfOrderFunc(orderNumber);
  316. }, 3000);
  317. } else if (res.data.orderStatus == 3) { // 提示支付成功,关闭当前页
  318. orderCodeDialogShow.value = false;
  319. showPayDialog.value = false
  320. ElMessage.success(
  321. lanChange.value == "zh-cn" ? `支付成功!` : `Payment is successful!`
  322. );
  323. } else { // 提示支付失败,关闭当前页
  324. ElMessage.success('支付失败');
  325. }
  326. } else {
  327. setTimeout(() => {
  328. getStatusOfOrderFunc(orderNumber);
  329. }, 3000);
  330. }
  331. } catch (error) {
  332. console.log(error, "error");
  333. ElMessage.error(
  334. lanChange.value == "zh-cn"
  335. ? `获取订单失败,请重试`
  336. : `Failed to get the order, please try again`
  337. );
  338. }
  339. }
  340. // 生成二维码
  341. // function qrcode() {
  342. // return;
  343. // }
  344. // 关闭二维码弹窗
  345. function clearCode() {
  346. myPayVendor.value = null; // 2微信 4支付宝
  347. payCodeUrl.value = null;
  348. iframeBody.value = null;
  349. showPayDialog.value = false;
  350. }
  351. // 刷新二维码
  352. function RefreshQR() {
  353. payCodeUrl.value = null;
  354. iframeBody.value = null;
  355. // createOrderFunc();
  356. createPayFunc(myOrderNumber.value);
  357. }
  358. //#endregion ------------------------------------
  359. //#region
  360. //#endregion ------------------------------------
  361. const payVendor = ref('4')
  362. const orderNumber = ref('')
  363. // 创建订单
  364. function createOrder(item) {
  365. createOrderApi({productId: item.id}).then(res => {
  366. orderNumber.value = res.data
  367. })
  368. }
  369. // 创建支付
  370. function payConfirm() {
  371. createPayFunc(orderNumber.value);
  372. }
  373. // 获取订单详情
  374. function getOrderDetail(item) {
  375. orderDetailApi(item.id).then(res => {
  376. })
  377. }
  378. //每隔一分钟运行一次保存方法
  379. // const timer = setInterval(()=>{
  380. // findStatus()
  381. // },1000)
  382. function findStatus() {
  383. let data = {
  384. orderNumber: '',
  385. payVendor: ''
  386. }
  387. findStatusApi(data).then(res => {
  388. if (res.data !== 2) { // 如果是2就不停的调,直到返回1、3、4
  389. clearInterval(timer);
  390. }
  391. })
  392. }
  393. </script>
  394. <style>
  395. .el-dialog {
  396. border-radius: 5px !important;
  397. }</style>
  398. <style lang="scss" scoped>
  399. .page {
  400. // min-width: calc(100vw - 210px);
  401. height: calc(100vh - 80px);
  402. width: 1690px;
  403. padding: 0px 20px 0 20px;
  404. background-color: #fff;
  405. border-radius: 25px 0 0;
  406. padding: 20px;
  407. user-select: none;
  408. overflow: hidden;
  409. ::-webkit-scrollbar {
  410. display: none;
  411. }
  412. }
  413. // 方案列表
  414. .commoditylIst {
  415. display: flex;
  416. justify-content: flex-start;
  417. overflow-x: scroll;
  418. padding: 30px 20px 20px 10px;
  419. max-width: 100%;
  420. .scrollbar-flex-content{
  421. display: flex;
  422. }
  423. .item {
  424. position: relative;
  425. width: 450px;
  426. // height: 680px;
  427. margin-left: 45px;
  428. background-color: #fffefd;
  429. flex-shrink: 0; /* 防止缩小宽度 */
  430. border: 1px solid #c0bfbd;
  431. border-radius: 20px;
  432. overflow: hidden;
  433. transition: all 0.2s;
  434. cursor: pointer;
  435. &.dashed {
  436. border: 1px dashed #c0bfbd;
  437. }
  438. &:hover {
  439. .mask {
  440. display: block;
  441. }
  442. }
  443. // 遮罩层
  444. .mask {
  445. position: absolute;
  446. top: 0;
  447. left: 0;
  448. display: none;
  449. width: 100%;
  450. height: 100%;
  451. line-height: 780px;
  452. font-size: 120px;
  453. font-weight: 900;
  454. text-align: center;
  455. background-color: rgba(0, 0, 0, 0.2);
  456. cursor: pointer;
  457. }
  458. .line {
  459. height: 20px;
  460. background-color: pink;
  461. cursor: pointer;
  462. }
  463. .info {
  464. padding: 20px;
  465. cursor: pointer;
  466. .content {
  467. // height: 220px;
  468. padding: 20px;
  469. border-bottom: 1px solid #c0bfbd;
  470. cursor: pointer;
  471. position: relative;
  472. .titleBox {
  473. display: flex;
  474. justify-content: space-between;
  475. }
  476. .iconText{
  477. font-size: 14px;
  478. position: absolute;
  479. left:-20px;
  480. top:0;
  481. transform: rotate(-45deg);
  482. background: rgb(243, 175, 0);
  483. padding: 3px 10px;
  484. color: #fff;
  485. }
  486. .title {
  487. font-size: 30px;
  488. font-weight: 700;
  489. width: 100%;
  490. margin-bottom: 10px;
  491. cursor: pointer;
  492. text-align: center;
  493. .el-icon {
  494. line-height: 30px;
  495. width: 40px;
  496. height: 40px;
  497. font-size: 40px;
  498. color: #000;
  499. text-align: center;
  500. vertical-align: sub;
  501. cursor: pointer;
  502. }
  503. }
  504. .money {
  505. margin-bottom: 10px;
  506. font-size: 20px;
  507. color: #7c7c7a;
  508. cursor: pointer;
  509. text-align: end;
  510. .price {
  511. font-size: 30px;
  512. color: #242625;
  513. cursor: pointer;
  514. }
  515. }
  516. .time {
  517. text-align: end;
  518. margin-bottom: 10px;
  519. font-size: 20px;
  520. color: #7c7c7a;
  521. cursor: pointer;
  522. margin-bottom: 20px;
  523. span {
  524. color: #242625;
  525. cursor: pointer;
  526. margin-right: 5px;
  527. padding-left: 10px;
  528. }
  529. }
  530. .button {
  531. width: 100%;
  532. height: 40px;
  533. font-size: 16px;
  534. border-radius: 10px;
  535. text-align: center;
  536. line-height: 40px;
  537. color: #fff;
  538. font-weight: 700;
  539. background-color: yellow;
  540. cursor: pointer;
  541. }
  542. .description {
  543. cursor: pointer;
  544. margin-top: 50px;
  545. margin-bottom: 30px;
  546. width: 100%;
  547. display: flex;
  548. flex-direction: column;
  549. align-items: center;
  550. font-size: 18px;
  551. color: #7c7c7a;
  552. > div {
  553. cursor: pointer;
  554. margin-bottom: 20px;
  555. }
  556. }
  557. }
  558. .authority {
  559. margin-top: 10px;
  560. &-item {
  561. display: flex;
  562. justify-content: space-between;
  563. cursor: pointer;
  564. font-weight: 400;
  565. font-size: 18px;
  566. padding: 5px 10px;
  567. color: #7c7c7a;
  568. span {
  569. cursor: pointer;
  570. color: #7c7c7a;
  571. margin-right: 30px;
  572. }
  573. i {
  574. font-size: 20px;
  575. font-style: normal;
  576. margin-right: 5px;
  577. background-image: -webkit-linear-gradient(
  578. left,
  579. #4b61dc,
  580. #15d1b8 25%,
  581. #4b61dc 50%,
  582. #15d1b8 75%,
  583. #4b61dc
  584. ) !important;
  585. -webkit-text-fill-color: transparent !important;
  586. -webkit-background-clip: text !important;
  587. background-clip: text !important;
  588. -webkit-background-size: 200% 100% !important;
  589. background-size: 200% 100% !important;
  590. }
  591. }
  592. }
  593. }
  594. &:hover {
  595. cursor: pointer;
  596. transform: translateY(-20px);
  597. box-shadow: #00000026 2px 2px 2px 2px;
  598. }
  599. }
  600. }
  601. // 支付弹窗
  602. .el-radio{
  603. width: 100px;
  604. img {
  605. vertical-align: middle;
  606. margin-right: 5px;
  607. width: 16px;
  608. }
  609. }
  610. // 二维码弹窗
  611. .orderCodeDialog {
  612. width: 100%;
  613. .codeImg {
  614. display: flex;
  615. margin: auto;
  616. // justify-content: space-evenly;
  617. align-items: center;
  618. width: 220PX;
  619. height: 220PX;
  620. border: 1px solid #ccc;
  621. border-radius: 15px;
  622. overflow: hidden;
  623. padding: 13px;
  624. img {
  625. width: 100%;
  626. height: 100%;
  627. }
  628. }
  629. .tips {
  630. padding-top: 10px;
  631. text-align: center;
  632. }
  633. .btnBox {
  634. padding: 15px 40px;
  635. display: flex;
  636. justify-content: space-evenly;
  637. > div {
  638. padding: 10px 20px;
  639. color: #000;
  640. background-color: #fff;
  641. border: #000 solid 1px;
  642. border-radius: 10px;
  643. transition: all 0.3s;
  644. cursor: pointer;
  645. &:hover {
  646. color: #fff;
  647. background-color: #000;
  648. }
  649. }
  650. }
  651. }
  652. // 联系我们弹窗
  653. .TalkUsDialog {
  654. display: flex;
  655. flex-direction: column;
  656. align-items: center;
  657. &-content {
  658. width: 100%;
  659. display: flex;
  660. justify-content: space-between;
  661. > div {
  662. width: 30%;
  663. display: flex;
  664. flex-direction: column;
  665. align-items: center;
  666. img {
  667. width: 100px;
  668. height: 100px;
  669. margin-bottom: 40px;
  670. }
  671. }
  672. .sendEmail {
  673. text-decoration: underline;
  674. cursor: pointer;
  675. }
  676. }
  677. .close {
  678. margin-top: 50px;
  679. width: 100px;
  680. height: 50px;
  681. font-size: 18px;
  682. line-height: 50px;
  683. text-align: center;
  684. border-radius: 15px;
  685. border: 2px solid #ccc;
  686. cursor: pointer;
  687. }
  688. }
  689. </style>