1、在线支付
This commit is contained in:
		
							
								
								
									
										335
									
								
								userinfo.html
									
									
									
									
									
								
							
							
						
						
									
										335
									
								
								userinfo.html
									
									
									
									
									
								
							| @ -16,6 +16,8 @@ | ||||
|     <link rel="stylesheet" href="static/css/public.css" /> | ||||
|     <!-- <link rel="stylesheet" href="static/translate/css/public.css?v=4"> --> | ||||
|     <link rel="stylesheet" href="static/css/layui.css" /> | ||||
|      <!-- <link rel="stylesheet" href="static/js/css/buefy.min.css"> --> | ||||
|      | ||||
|     <script src="static/js/jquery-1.11.0.min.js"></script> | ||||
|     <script src="static/js/axios.min.js"></script> | ||||
|     <script src="static/translate/js/echarts.min.js"></script> | ||||
| @ -26,6 +28,8 @@ | ||||
|     <script src="static/js/common.js"></script> | ||||
|     <script src="https://cdn.jsdelivr.net/npm/qrcode@1.4.4/build/qrcode.min.js"></script> | ||||
|     <script src="static/js/countdown.js"></script> | ||||
|      | ||||
|     <!-- <script src="static/js/buefy.min.js"></script> --> | ||||
|     <title>聚合翻译</title> | ||||
|     <script> | ||||
|       var _hmt = _hmt || []; | ||||
| @ -196,7 +200,7 @@ | ||||
|               <div class="cell"><span>{{item.price}}</span></div> | ||||
|               <div class="cell"> | ||||
|                 <div class="act"> | ||||
|                   <span class="recharge" @click="show">充值</span | ||||
|                   <span class="recharge" @click="show(item)">充值</span | ||||
|                   ><span class="view" @click="look(item.apiKey,index)" | ||||
|                     >查看API密钥</span | ||||
|                   > | ||||
| @ -297,27 +301,61 @@ | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="modal-overlay" style="display: none"> | ||||
|         <div class="service-modal"> | ||||
|           <div class="content"> | ||||
|             <div class="close" @click="close"></div> | ||||
|             <div class="contact">TRX BLOCK</div> | ||||
|             <div class="contact-user"> | ||||
|               <div class="contact-user-text">用户ID : {{userInfo.id}}</div> | ||||
|           <div class="modal"> | ||||
|             <button class="close-btn" @click="close">×</button> | ||||
|              <div | ||||
|                 class="modal-content" | ||||
|                 :style="loadingQr ? 'opacity: 0.4; pointer-events: none;' : ''" | ||||
|               > | ||||
|                 <h3 v-if="rechargeData.step === 1">Step 1: 输入购买数量</h3> | ||||
|                 <h3 v-else>Step 2: 支付信息</h3> | ||||
|  | ||||
|                 <!-- Step 1 --> | ||||
|                 <div v-if="rechargeData.step === 1" class="step"> | ||||
|                   <label>购买数量:</label> | ||||
|                   <input type="number" v-model.number="rechargeData.count" min="1" /> | ||||
|                 </div> | ||||
|  | ||||
|                 <!-- Step 2 --> | ||||
|                 <div v-else class="step"> | ||||
|                   <div class="qr-code"> | ||||
|                     <div id="qrcode"></div> | ||||
|                     <!-- <div v-if="loadingQr" class="loading-spinner"></div> --> | ||||
|                     <!-- <img v-else-if="qrCodeUrl" :src="qrCodeUrl" alt="二维码" | ||||
|                         @load="onQrLoadSuccess" @error="onQrLoadError" | ||||
|                         style="width: 100%; height: 100%; border-radius: 8px;" /> | ||||
|                     <span v-else style="font-size: 12px; color: #999;">加载失败</span> --> | ||||
|                   </div> | ||||
|                   <div class="wallet-info"> | ||||
|                     <p>主链:<strong>{{ rechargeData.blockChain }}</strong></p> | ||||
|                     <p>钱包地址: <strong>{{ rechargeData.receiveAddress }}</strong></p> | ||||
|                     <p>支付金额: <strong>{{ rechargeData.amount }} USDT</strong></p> | ||||
|                     <p> | ||||
|                       <countdown  :time="(rechargeData.expireUnix * 1000) - Date.now()" | ||||
|                         v-if="rechargeData.expireUnix && (rechargeData.expireUnix * 1000) > Date.now()" > | ||||
|                         <template slot-scope="props"> | ||||
|                           倒计时: | ||||
|                           <span v-if="props.minutes>0||props.hours>0||props.days>0">{{ props.minutes }} 分</span> | ||||
|                           <span v-if="props.seconds>0||props.minutes>0||props.hours>0||props.days>0">{{ props.seconds }} 秒</span>   | ||||
|                           <span v-if="props.days==0&&props.hours==0&&props.minutes==0&&props.seconds==0">订单已过期,请勿支付!</span> | ||||
|                         </template> | ||||
|                            | ||||
|                         </countdown> | ||||
|                     </p> | ||||
|                   </div> | ||||
|                 </div> | ||||
|  | ||||
|             <div class="btn-group"> | ||||
|               <!-- <button class="btn btn-secondary" @click="close">关闭</button> --> | ||||
|               <button class="btn btn-secondary" v-if="rechargeData.step === 2" @click="prevStep">上一步</button> | ||||
|               <button class="btn btn-primary" v-if="rechargeData.step === 1" :disabled="!rechargeData.count" @click="nextStep">下一步</button> | ||||
|             </div> | ||||
|             <div | ||||
|               id="qrcode" | ||||
|               style="text-align: center;height: 214px;" | ||||
|               class="border border-gray-200 rounded-lg p-2 flex justify-center items-center" | ||||
|             > | ||||
|               <!-- 二维码将在这里生成 --> | ||||
|               <!-- <p class="text-gray-500">点击按钮生成二维码</p> --> | ||||
|             </div> | ||||
|             <!-- <img | ||||
|               src="/static/picture/p23.jpg" | ||||
|               alt="" | ||||
|               class="qrcode-img" | ||||
|             /> --> | ||||
|             <p>{{receiveAddress}}</p> | ||||
|           </div> | ||||
|  | ||||
|           <!-- loading 遮罩层 --> | ||||
|           <div class="modal-loading-overlay" v-if="loadingQr"> | ||||
|             <div class="spinner"></div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
| @ -346,7 +384,167 @@ | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|     <style> | ||||
|         | ||||
|     .modal-overlay { | ||||
|       position: fixed; | ||||
|       inset: 0; | ||||
|       background: rgba(0, 0, 0, 0.4); | ||||
|       display: flex; | ||||
|       justify-content: center; | ||||
|       align-items: center; | ||||
|       z-index: 999; | ||||
|     } | ||||
|  | ||||
|     .modal { | ||||
|       background: #ffffff; | ||||
|       border-radius: 12px; | ||||
|       box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1); | ||||
|       padding: 24px 28px; | ||||
|       width: 400px; | ||||
|       max-width: 90%; | ||||
|       animation: fadeIn 0.3s ease; | ||||
|       position:relative; | ||||
|     } | ||||
|  | ||||
|     .modal-content { | ||||
|       transition: opacity 0.2s; | ||||
|     } | ||||
|  | ||||
|     .modal-loading-overlay { | ||||
|       position: absolute; | ||||
|       top: 0; left: 0; right: 0; bottom: 0; | ||||
|       background-color: rgba(255, 255, 255, 0.6); | ||||
|       display: flex; | ||||
|       justify-content: center; | ||||
|       align-items: center; | ||||
|       z-index: 10; | ||||
|       border-radius: 12px; | ||||
|     } | ||||
|  | ||||
|     .spinner { | ||||
|       border: 4px solid #f3f3f3; | ||||
|       border-top: 4px solid #409eff; | ||||
|       border-radius: 50%; | ||||
|       width: 32px; | ||||
|       height: 32px; | ||||
|       animation: spin 0.8s linear infinite; | ||||
|     } | ||||
|  | ||||
|     @keyframes fadeIn { | ||||
|       from { opacity: 0; transform: translateY(-20px); } | ||||
|       to { opacity: 1; transform: translateY(0); } | ||||
|     } | ||||
|  | ||||
|     .modal h3 { | ||||
|       margin-top: 0; | ||||
|       font-size: 20px; | ||||
|       color: #333; | ||||
|     } | ||||
|  | ||||
|     input[type="number"] { | ||||
|       width: 100%; | ||||
|       padding: 10px 12px; | ||||
|       font-size: 16px; | ||||
|       margin-top: 8px; | ||||
|       border: 1px solid #ccc; | ||||
|       border-radius: 6px; | ||||
|       transition: border-color 0.2s; | ||||
|     } | ||||
|  | ||||
|     input[type="number"]:focus { | ||||
|       border-color: #409eff; | ||||
|       outline: none; | ||||
|     } | ||||
|  | ||||
|     button{ | ||||
|       cursor: pointer; | ||||
|     } | ||||
|  | ||||
|     .step { | ||||
|       padding-top: 16px; | ||||
|       margin-bottom: 16px; | ||||
|     } | ||||
|  | ||||
|     .qr-code { | ||||
|       width: 150px; | ||||
|       height: 150px; | ||||
|       background: #f8f8f8; | ||||
|       border: 1px dashed #ccc; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
|       margin: 0 auto; | ||||
|       border-radius: 8px; | ||||
|     } | ||||
|  | ||||
|     .loading-spinner { | ||||
|       border: 3px solid #f3f3f3; | ||||
|       border-top: 3px solid #409eff; | ||||
|       border-radius: 50%; | ||||
|       width: 28px; | ||||
|       height: 28px; | ||||
|       animation: spin 0.8s linear infinite; | ||||
|     } | ||||
|  | ||||
|     @keyframes spin { | ||||
|       to { transform: rotate(360deg); } | ||||
|     } | ||||
|  | ||||
|     .btn-group { | ||||
|       display: flex; | ||||
|       justify-content: flex-end; | ||||
|       gap: 8px; | ||||
|       margin-top: 16px; | ||||
|     } | ||||
|  | ||||
|     .btn { | ||||
|       padding: 8px 16px; | ||||
|       border: none; | ||||
|       border-radius: 6px; | ||||
|       font-size: 14px; | ||||
|       transition: background-color 0.2s ease; | ||||
|     } | ||||
|  | ||||
|     .btn-primary { | ||||
|       background-color: #409eff; | ||||
|       color: #fff; | ||||
|     } | ||||
|  | ||||
|     .btn-primary:disabled { | ||||
|       background-color: #a0cfff; | ||||
|       cursor: not-allowed; | ||||
|     } | ||||
|  | ||||
|     .btn-secondary { | ||||
|       background-color: #e0e0e0; | ||||
|       color: #333; | ||||
|     } | ||||
|  | ||||
|     .wallet-info { | ||||
|       font-size: 14px; | ||||
|       color: #555; | ||||
|       text-align: center; | ||||
|       margin-top: 12px; | ||||
|     } | ||||
|  | ||||
|     .close-btn { | ||||
|   position: absolute; | ||||
|   top: 12px; | ||||
|   right: 12px; | ||||
|   background: transparent; | ||||
|   border: none; | ||||
|   font-size: 20px; | ||||
|   color: #999; | ||||
|   cursor: pointer; | ||||
|   transition: color 0.2s ease; | ||||
| } | ||||
| .close-btn:hover { | ||||
|   color: #333; | ||||
| } | ||||
|     </style> | ||||
|     <script type="text/javascript"> | ||||
|       // 工具函数:将十六进制颜色转换为 RGBA 格式 | ||||
|       function hexToRgba(hex, alpha) { | ||||
| @ -373,6 +571,18 @@ | ||||
|             token: "", | ||||
|             userMoney: 0, | ||||
|             userInfo: {}, | ||||
|             activeStep:"2", | ||||
|             showRecharge:false, | ||||
|             loadingQr:false, | ||||
|             rechargeData:{ | ||||
|               platformId:null, | ||||
|               name:null, | ||||
|               count:1, | ||||
|               amount:null, | ||||
|               receiveAddress:null, | ||||
|               step:1, | ||||
|               expireUnix:undefined | ||||
|             }, | ||||
|  | ||||
|             // ECharts 图表数据 | ||||
|             myChart: null, // 用于存储 ECharts 实例 | ||||
| @ -407,7 +617,7 @@ | ||||
|  | ||||
|           this.getUserPlatforms(); | ||||
|           this.getStatistics(); | ||||
|           this.getReceiveAddress(); | ||||
|           // this.getReceiveAddress(); | ||||
|         }, | ||||
|         beforeDestroy() { | ||||
|           // 销毁 ECharts 实例并移除事件监听器 | ||||
| @ -453,20 +663,20 @@ | ||||
|                 } | ||||
|               }); | ||||
|           }, | ||||
|           getReceiveAddress() { | ||||
|             axios | ||||
|               .get("/configKey/trx_receive_address", { | ||||
|                 headers: { Authorization: `Bearer ${this.token}` }, | ||||
|               }) | ||||
|               .then((res) => { | ||||
|                 if (res.data.code == 200) { | ||||
|                   this.receiveAddress = res.data.data.configValue; | ||||
|                   this.generateQRCode(); | ||||
|                 } else { | ||||
|                   layer.msg(response.data.msg); | ||||
|                 } | ||||
|               }); | ||||
|           }, | ||||
|           // getReceiveAddress() { | ||||
|           //   axios | ||||
|           //     .get("/configKey/trx_receive_address", { | ||||
|           //       headers: { Authorization: `Bearer ${this.token}` }, | ||||
|           //     }) | ||||
|           //     .then((res) => { | ||||
|           //       if (res.data.code == 200) { | ||||
|           //         this.receiveAddress = res.data.data.configValue; | ||||
|           //         this.generateQRCode(); | ||||
|           //       } else { | ||||
|           //         layer.msg(response.data.msg); | ||||
|           //       } | ||||
|           //     }); | ||||
|           // }, | ||||
|           getMemberAdvent(platformId){ | ||||
|             axios | ||||
|               .get("/tm-member/member-advent", { | ||||
| @ -540,11 +750,57 @@ | ||||
|                 '" >复制</i></div></div>', | ||||
|             }); | ||||
|           }, | ||||
|           show() { | ||||
|           show(item) { | ||||
|             $(".modal-overlay").fadeIn(); | ||||
|             this.rechargeData.platformId=item.platformId; | ||||
|             this.rechargeData.name=item.name; | ||||
|           }, | ||||
|           close() { | ||||
|             $(".modal-overlay").fadeOut(); | ||||
|             this.rechargeData={ | ||||
|               platformId:null, | ||||
|               name:null, | ||||
|               count:1, | ||||
|               amount:null, | ||||
|               receiveAddress:null, | ||||
|               step:1, | ||||
|               expireUnix:undefined | ||||
|           }; | ||||
|  | ||||
|           console.log(this.rechargeData); | ||||
|           }, | ||||
|           prevStep(){ | ||||
|       | ||||
|             this.rechargeData.step=1; | ||||
|              | ||||
|           }, | ||||
|           nextStep(){ | ||||
|             if(this.rechargeData.count<=0){ | ||||
|                layer.msg("数量不能小于0"); | ||||
|                return; | ||||
|             } | ||||
|             this.loadingQr=true; | ||||
|  | ||||
|             axios.post("/tm-member/recharge",this.rechargeData,{headers: { Authorization: `Bearer ${this.token}` }}) | ||||
|             .then(res => { | ||||
|               console.log("sss",res); | ||||
|               if(res.data.code===200){ | ||||
|                 this.rechargeData.step=2; | ||||
|                 this.rechargeData.amount=res.data.data.amount; | ||||
|                 this.rechargeData.receiveAddress=res.data.data.receiveAddress; | ||||
|                 this.rechargeData.blockChain=res.data.data.blockChain; | ||||
|                 this.rechargeData.expireUnix=res.data.data.expireUnix; | ||||
|                 let _that=this; | ||||
|  | ||||
|                 this.$nextTick(() => { | ||||
|                   _that.generateQRCode(_that.rechargeData.receiveAddress); | ||||
|                 }) | ||||
|               }else{ | ||||
|                 layer.msg(res.data.msg); | ||||
|               } | ||||
|             }).finally(() => { | ||||
|               this.loadingQr=false; | ||||
|               }); | ||||
|           }, | ||||
|           showRecord(platformId){ | ||||
|             $(".modal-overlay-record").fadeIn(); | ||||
| @ -779,11 +1035,12 @@ | ||||
|               this.myChart.resize(); | ||||
|             } | ||||
|           }, | ||||
|            generateQRCode() { | ||||
|             const text = this.receiveAddress.trim(); // 获取输入框内容并去除首尾空格 | ||||
|            generateQRCode(qrString) { | ||||
|             const text = qrString.trim(); // 获取输入框内容并去除首尾空格 | ||||
|             const qrcodeContainer = document.getElementById('qrcode'); | ||||
|  | ||||
|             if (text) { | ||||
|               console.log('container',qrcodeContainer) | ||||
|               // 1. 清空容器内的所有内容,包括旧的二维码或提示信息 | ||||
|               qrcodeContainer.innerHTML = '';  | ||||
|               this.showPlaceholder = false; | ||||
| @ -797,7 +1054,7 @@ | ||||
|  | ||||
|               // 3. 使用 QRCode.toCanvas 在新创建的 canvas 上生成二维码 | ||||
|               QRCode.toCanvas(canvasElement, text, { // 将 canvasElement 传递给 toCanvas | ||||
|                 width: 214, // 设置二维码宽度 | ||||
|                 width: 150, // 设置二维码宽度 | ||||
|                 color: { | ||||
|                   dark: '#000000',  // 二维码颜色 | ||||
|                   light:'#ffffff' // 背景颜色 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user