zoukankan      html  css  js  c++  java
  • 二维码收款——前端UI

    线下店铺一般使用的店铺收款码,有银行提供的,有通联的,结合语音播报,方便快捷,下面我们来做一个类似的属于自己收款系统

    本系列文章分3部分

    1. 前端UI
    2. 后端系统
    3. 通知系统

    UI界面直接借鉴微信(哈哈),如下图

     前端使用Vue,3个文件,pay.html,pay.js,pay.css

    简要说明

    1. 数字键盘使用table标签布局,可以完美的模拟微信键盘的效果,按键按下时有高亮效果,通过js控制只能输入有效的数值
    2. 请求时URL中带有商户号参数,例如xxx.com/pay.html?mercNo=xxx,mercNo就是商户号,商户信息包含商户名,商户LOGO,请求商户信息后,显示出来
    <html>
      <head>
        <meta charset="utf-8" />
        <meta
          name="viewport"
          content="width=device-width, initial-scale=1.0, user-scalable=no"
        />
        <title>付款</title>
        <link
          rel="stylesheet"
          href="https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css"
        />
        <link rel="stylesheet" href="pay.css" />
        <script src="../js/common.js"></script>
        <style type="text/css">
          [v-cloak] {
            display: none;
          }
        </style>
      </head>
      <body>
        <div class="w-warp" id="main" v-cloak>
          <div class="info">
            <div class="text">
              <h4>付款给</h4>
              <p style="color: gray">{{mercInfo.mercName}}</p>
            </div>
            <div class="head"><img :src="mercInfo.mercLogo" width="60px" height="60px" /></div>
          </div>
          <div class="amount">
            <h5>金额</h5>
            <div class="input">
              <p class="symbol"></p>
              <p class="placeholder" v-if="!activeInput">输入金额</p>
              <p class="num" v-else>{{validNum}}</p>
            </div>
          </div>
          <div class="addmemo">
            <p @click="showMemoDialog=true">{{memo.length>0 ? memo : '添加备注'}}</p>
          </div>
          <div class="keyboard">
            <table cellspacing="8" >
              <tr>
                <td @click="onKeyboard(1)" @touchstart="keyHighlight['1']=true" @touchend="keyHighlight['1']=false" :class="{'keyhighlight': keyHighlight['1']}">1</td>
                <td @click="onKeyboard(2)" @touchstart="keyHighlight['2']=true" @touchend="keyHighlight['2']=false" :class="{'keyhighlight': keyHighlight['2']}">2</td>
                <td @click="onKeyboard(3)" @touchstart="keyHighlight['3']=true" @touchend="keyHighlight['3']=false" :class="{'keyhighlight': keyHighlight['3']}">3</td>
                <td style=" 22%;" @click="onKeyboard('DEL')" @touchstart="keyHighlight['DEL']=true" @touchend="keyHighlight['DEL']=false" :class="{'keyhighlight': keyHighlight['DEL']}">DEL</td>
              </tr>
              <tr>
                <td @click="onKeyboard(4)" @touchstart="keyHighlight['4']=true" @touchend="keyHighlight['4']=false" :class="{'keyhighlight': keyHighlight['4']}">4</td>
                <td @click="onKeyboard(5)" @touchstart="keyHighlight['5']=true" @touchend="keyHighlight['5']=false" :class="{'keyhighlight': keyHighlight['5']}">5</td>
                <td @click="onKeyboard(6)" @touchstart="keyHighlight['6']=true" @touchend="keyHighlight['6']=false" :class="{'keyhighlight': keyHighlight['6']}">6</td>
                <td rowspan="3" class="paybtn" @click="onKeyboard('pay')" @touchstart="keyHighlight['pay']=true" @touchend="keyHighlight['pay']=false" :class="{'paybtnhighlight': keyHighlight['pay']}">付款</td>
              </tr>
              <tr>
                <td @click="onKeyboard(7)" @touchstart="keyHighlight['7']=true" @touchend="keyHighlight['7']=false" :class="{'keyhighlight': keyHighlight['7']}">7</td>
                <td @click="onKeyboard(8)" @touchstart="keyHighlight['8']=true" @touchend="keyHighlight['8']=false" :class="{'keyhighlight': keyHighlight['8']}">8</td>
                <td @click="onKeyboard(9)" @touchstart="keyHighlight['9']=true" @touchend="keyHighlight['9']=false" :class="{'keyhighlight': keyHighlight['9']}">9</td>
              </tr>
              <tr>
                <td colspan="2" @click="onKeyboard(0)" @touchstart="keyHighlight['0']=true" @touchend="keyHighlight['0']=false" :class="{'keyhighlight': keyHighlight['0']}">0</td>
                <td @click="onKeyboard('.')" @touchstart="keyHighlight['.']=true" @touchend="keyHighlight['.']=false" :class="{'keyhighlight': keyHighlight['.']}">.</td>
              </tr>
            </table>
          </div>
    
          <!-- 备注输入框 -->
          <van-dialog v-model="showMemoDialog" confirm-button-color='#1aad19'>
            <van-field v-model="memo" label="备注" placeholder="输入备注" size='large'/>
          </van-dialog>
    
          </div>
        </div>
      </body>
    
      <!-- 引入 Vue 和 Vant 的 JS 文件 -->
      <script src="https://cdn.jsdelivr.net/npm/vue@2.6/dist/vue.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js"></script>
      <script src="../js/config.js"></script>
      <script src="pay.js"></script>
    
    </html>
    new Vue({
      el: '#main',
      data: {
        activeInput: false, //激活输入
        inputText: [], //输入的字符队列
        validNum: 0, //有效的输入数字
        keyHighlight: {
          1: false,
          2: false,
          3: false,
          4: false,
          5: false,
          6: false,
          7: false,
          8: false,
          9: false,
          0: false,
          '.': false,
          DEL: false,
          pay: false,
        }, //键盘高亮
        showMemoDialog: false, //显示备注输入框
        memo: '',
        mercInfo: {}, //商户信息
      },
      created() {},
      mounted() {
        //商户号
        let mercNo = getQueryVariable('mercNo');
        refu.get(`/a/merc/info?mercNo=${mercNo}`).then((res) => {
          this.mercInfo = res.result;
        });
      },
      methods: {
        //验证金额是否有效
        validNumber(t) {
          var reg = /((^[1-9]\d*)|^0)(\.\d{0,2}){0,1}$/;
          return reg.test(t);
        },
    
        //点击键盘
        onKeyboard(key) {
          if (key == 'DEL') {
            this.inputText.pop();
            if (this.inputText.length > 0) {
              var s = this.inputText.join('');
              this.validNum = s;
            } else {
              this.validNum = 0;
              this.activeInput = false;
            }
            return;
          }
          if (key == 'pay') {
            console.log('输入金额:', this.validNum);
            if (this.validNum == '0') return;
            let amount = parseFloat(this.validNum);
            if (!this.testWeixinOk()) {
              refu.toast('请在微信内打开');
              return;
            }
            //发起支付请求
            this.requestPay(this.mercInfo.mercNo, amount, this.memo).then((res) => {
              this.invokeWxpayJsApi(res.result);
            });
            return;
          }
          this.inputText.push(key);
          var s = this.inputText.join('');
          if (this.validNumber(s)) {
            this.validNum = s;
            this.activeInput = true;
          } else {
            this.inputText.pop();
          }
        },
    
        //发起支付请求
        async requestPay(mercNo, amount, memo) {
          let param = {
            mercNo: mercNo,
            amount: amount,
            memo: memo,
            channel: 'wxpay',
          };
          return await refu.post('/a/create/pay/order', param);
        },
    
        //检测微信环境
        testWeixinOk() {
          return typeof WeixinJSBridge != 'undefined';
        },
    
        //拉起微信支付
        invokeWxpayJsApi(param) {
          WeixinJSBridge.invoke('getBrandWCPayRequest', param, function (res) {
            if (res.err_msg === 'get_brand_wcpay_request:ok') {
              // 使用以上方式判断前端返回,微信团队郑重提示:
              // res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
              window.location.href = SiteInfo.paySuccessRedirect;
            }
          });
        },
      },
      filters: {},
      computed: {},
    });
    body {
      background: #ededed;
      margin: 0;
    }
    
    p,
    h4 {
      margin: 0.5rem 0rem;
    }
    
    .w-warp {
      display: flex;
      flex-direction: column;
      height: 100%;
    }
    
    .info {
      display: flex;
      padding: 1rem 1rem;
      align-items: center;
    }
    
    .info .text {
      flex-grow: 1;
    }
    
    .info .head {
      flex-grow: 0;
    }
    
    .amount {
      flex-grow: 1;
      padding: 0.5rem 1rem;
      background-color: white;
      border-top-left-radius: 0.8rem;
      border-top-right-radius: 0.8rem;
    }
    
    .amount .input {
      display: flex;
      align-items: flex-end;
      font-size: 30px;
      font-weight: bold;
      border-bottom: solid 1px lightgray;
    }
    
    .input .symbol {
      margin: 0.5rem 0.6rem 0.5rem 0rem;
    }
    
    .input .placeholder {
      font-weight: normal;
      color: lightgray;
    }
    
    .addmemo {
      display: flex;
      justify-content: center;
      color: #726f89;
      background: white;
      padding: 1rem 0;
      font-size: 16px;
    }
    
    .keyboard table {
      width: 100%;
    }
    
    .keyboard td {
      font-size: 18;
      font-weight: bold;
      background: white;
      border-radius: 10px;
      border: none;
      text-align: center;
      padding: 0.8rem 0rem;
    }
    
    .keyboard .keyhighlight {
      background: #dedede;
    }
    
    .keyboard .paybtn {
      background: #1aad19;
      color: white;
    }
    
    .keyboard .paybtnhighlight {
      background: #07ae56;
    }

    下一篇,后端API

     

  • 相关阅读:
    HttpServletRequest
    实现重定向
    HttpServletResponse
    Servlet简介和ServletContext
    JavaWeb 之 Http
    JavaWeb 之 Cookie
    Pycharm2019.3.2专业版激活
    How to Use Arrays and Vectors
    软件工程学习心得
    MySQL 连接
  • 原文地址:https://www.cnblogs.com/ieinstein/p/15756010.html
Copyright © 2011-2022 走看看