Front end-"Build a small program version of the background management system

table of Contents

Effect preview

log in

WeChat login

Login pageLogin page WeChat authorized personal information
After authorizing personal information, authorize mobile phone number, and click Allow to log in

Account password login

Enter account password, log in

Home page

Home page

Home Search

search for

Details of the homepage

Details

Home page export

Export
Export

Channel volume statistics of the homepage

Channel volume statistics

Channel and channel management

Insert picture description here

Channel editing

Channel editing

Channel editor

Insert picture description here

Order management

Insert picture description here

Order editing of order management

Insert picture description here

Regional limit of order management

Insert picture description here

Regional configuration city selection for order management

Insert picture description here

Code preview

Code structure preview

Insert picture description here

Key points

log in

There are two ways to log in to this applet, namely WeChat authorized login and account password login. The account password login is relatively simple, so I won't say more.
Since this applet is not open to the public and only allowed for internal employees, not all WeChat account can log in after authorization. The mobile phone number and account password are in the same database table, and there are only mobile phone numbers registered in the background of the computer. Only allow WeChat authorized login.
Mobile phone number authorization login operation process:

  1. Click the WeChat login button on the page, WeChat will automatically pop up a pop-up window of officially authorized personal information
  2. Click “Allow” to pop up our customized authorized mobile phone number pop-up window, click “Authorize” to pop up the official authorized mobile phone number pop-up window
  3. After clicking Allow again, we get the mobile phone number. At this time, the mobile phone number is passed to the background to match the username and password, and the subsequent login steps are directly completed in the background

The logic flow of mobile phone number authorization login:

  1. The logic of logging in with a mobile phone number is to use the mobile phone number to match the account name and password in the background, and log in directly in the background with the account name and password after matching. Of course, the premise is how to obtain the mobile phone number, which is roughly divided into three steps, as follows
  2. Get sessionKey: parameters appid, secretkey, grantType, and code. The first three parameters are fixed and can be found in the WeChat applet background. The last code is returned by wx.login. On the page, click WeChat login to pop up the authorization personal information window and click to allow authorization. Then we call the WeChat wx.login({}) method, which will return openid and code. Opneid is temporarily not used, so leave it alone. We need to write an interface on our server to exchange this code for the sessionKey. Of course, you can also get the sessionKey by directly requesting the official interface in js with the code as a parameter. The sessionKey is then returned to the front end.
  3. Decrypt to get the mobile phone number: Parameters: encryptedData, iv, sessionKey. There must be a button to get the phone number on the page. After the user clicks it, the official authorization button will pop up. After clicking Allow authorization, the encrypted phone number string encryptedData will be obtained. This encryptedData string must be decrypted by iv and sessionKey. This decryption process can be done in js or on the java server side. After the decryption is completed, the mobile phone number is obtained. We have already obtained the sessionKey, how to get encryptedData and iv, just need a button button, open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber" These two attributes are officially fixed and cannot be modified:
<button class="cu-btn line-green text-green" style="margin-left:10px" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">确定</button>
  getPhoneNumber: function (e) {
    
    
    var that = this;
    var data = {
    
    
      encryptedData: e.detail.encryptedData,
      iv: e.detail.iv,
      sessionKey: that.data.session_key,
    }
    console.log(data);
    if (e.detail.errMsg == "getPhoneNumber:ok") {
    
    
      //  做解密的操作,可以直接js解密,也可以请求自己的后台服务器解密
    }
  },

Summary of the main points:
first authorize personal information to obtain the code, then obtain the sessionKey according to the code, and obtain the mobile phone number according to the sessionKey decryption string. The authorized personal information and mobile phone number can only be returned through the official button, and there is no interface for authorization.
There are at least two buttons on the page, one is to authorize personal information, the other is to authorize mobile phone number, first authorize personal information, then authorize mobile phone number. After clicking on authorized personal information, the official authorized personal information pop-up window will pop up. After allowing, click the authorized mobile phone number button, and then the officially authorized personal mobile phone number pop-up window will pop up. After clicking allow, you can get the encrypted string and iv, and then decrypt it.

Sidebar condition filter

A sidebar plug-in side is used here. The source of this plug-in cannot be found.
js:

// components/side/index.js
var touchDot = 0; //触摸时的原点
var time = 0; //  时间记录,用于滑动时且时间小于1s则执行左右滑动
var interval = ''; // 记录/清理 时间记录
var nth = 0; // 设置活动菜单的index
var nthMax = 5; //活动菜单的最大个数
var tmpFlag = true; // 判断左右华东超出菜单最大值时不再执行滑动事件
Component({
    
    
    properties: {
    
    
        //是否有遮罩
        mask: {
    
    
            type: Boolean,
            value: true
        },
        //是否全屏
        fullScreen: {
    
    
            type: Boolean,
            value: false,
        },
        //类型 左侧 右侧
        type: {
    
    
            type: String,
            value: 'left'
        },
        //背景色
        background: {
    
    
            type: String,
            value: '#fff'
        },
        //是否显示头部
        header: {
    
    
            type: Boolean,
            value: true
        },
        name: {
    
    
            type: String,
            value: ''
        }
    },

    data: {
    
    
        maskDisplay: 'none', //遮罩层隐藏
        //侧边菜单的一些属性
        sideHeight: 0,
        sideRight: 0,
        sideLeft: 0,
        sideWidth: 0,
        sideAnimation: {
    
    }, //动画

    },
    options: {
    
    
        multipleSlots: true //使其可以使用多个slot,用name区分
    },
    lifetimes: {
    
    
        attached() {
    
    
            // 在组件实例进入页面节点树时执行
            this.init()
        },
        detached() {
    
    
            // 在组件实例被从页面节点树移除时执行
        }
    },
    pageLifetimes: {
    
    
        show() {
    
    }
    },
    methods: {
    
    
        //初始化
        init() {
    
    
            let that = this;
            let type = that.data.type;
            let rate = that.data.fullScreen ? 1 : 0.7
            wx.getSystemInfo({
    
    
                success: function(res) {
    
    
                    that.setData({
    
    
                        sideHeight: res.windowHeight + 'px',
                        sideWidth: res.windowWidth * rate + 'px'
                    });
                    switch (type) {
    
    
                        case 'left':
                            that.setData({
    
    
                                sideRight: res.windowWidth + 'px'
                            })
                            break;
                        case 'right':
                            that.setData({
    
    
                                sideLeft: res.windowWidth + 'px'
                            })
                    }
                }
            });
        },
        //侧栏展开
        sideUp() {
    
    
            this.setData({
    
    
                maskDisplay: 'block',
            });
            var animation = wx.createAnimation({
    
    
                duration: 600,
                timingFunction: 'linear'
            });

            let type = this.data.type;
            switch (type) {
    
    
                case 'left':
                    animation.translateX('100%').step();
                    this.setData({
    
    
                        sideAnimation: animation.export()
                    });
                    break;
                case 'right':
                    animation.translateX('-100%').step();
                    this.setData({
    
    
                        sideAnimation: animation.export()
                    });
            }


        },
        //侧栏关闭
        sideDown() {
    
    
            this.setData({
    
    
                maskDisplay: 'none',
            });
            var animation = wx.createAnimation({
    
    
                duration: 800,
                timingFunction: 'linear'
            });
            let type = this.data.type;
            switch (type) {
    
    
                case 'left':
                    animation.translateX('-100%').step();
                    this.setData({
    
    
                        sideAnimation: animation.export()
                    });
                    break;
                case 'right':
                    animation.translateX('100%').step();
                    this.setData({
    
    
                        sideAnimation: animation.export()
                    });
            }

        },
        //展开
        openSide: function() {
    
    
            this.sideUp();
            this.triggerEvent('open');
        },

        //点击遮罩 收起
        colseSide: function() {
    
    
            this.sideDown();
            this.triggerEvent('close');
        },
        preventTouchMove() {
    
    },

        // 触摸开始事件
        touchStart: function(e) {
    
    
            touchDot = e.touches[0].pageX; // 获取触摸时的原点
            // 使用js计时器记录时间
            interval = setInterval(function() {
    
    
                time++;
            }, 100);
        },
        // 触摸移动事件
        touchMove: function(e) {
    
    
            var touchMove = e.touches[0].pageX;
            let type = this.data.type;
            switch (type) {
    
    
                case 'left':
                    // 向左滑动
                    if (touchMove - touchDot <= -40 && time < 10) {
    
     this.colseSide(); }
                    break;
                case 'right':
                    // 向右滑动
                    if (touchMove - touchDot >= 40 && time < 10) {
    
    
                        this.colseSide();
                    }
            }
            // touchDot = touchMove; //每移动一次把上一次的点作为原点(好像没啥用)
        },
        // 触摸结束事件
        touchEnd: function(e) {
    
    
            clearInterval(interval); // 清除setInterval
            time = 0;
            tmpFlag = true; // 回复滑动事件
        }
    }
});

json

{
    
    
  "component": true,
  "usingComponents": {
    
    }
}

wxml

<!-- components/side/index.wxml -->
<view wx:if="{
    
    {mask}}" class="side-mask" style="display:{
    
    {maskDisplay}};" bindtap="colseSide" catchtouchmove='preventTouchMove'></view>
<view class="side-board" style="background:{
    
    {background}};right: {
    
    {type == 'left' ?  sideRight:''}};left: {
    
    {type == 'right' ? sideLeft:''}};width: {
    
    {sideWidth}};height:{
    
    {sideHeight}};" animation="{
    
    {sideAnimation}}" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd">
  <scroll-view style="width: {
    
    {sideWidth}};height:{
    
    {sideHeight}};">
    <view wx:if="{
    
    {header}}" class="side-header">
      <view class="side-name">{
    
    {
    
    name}}</view>
  
    </view>
    <view class="side-content">
      <slot name='content'></slot>
    </view>
  </scroll-view>
</view>

wxss

/* components/side/index.wxss */

.side-mask {
    
    
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 3000;
}

.side-board {
    
    
    position: fixed;
    top: 80rpx;
    background: #f8f8f8;
    z-index: 3999;
    display: flex;
    flex-direction: column;
    border-radius: 20px 0 0 20px;
}

.side-header {
    
    
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    margin: 10px 0;
    padding: 10px 0;
    border-bottom: 1px solid #f8f8f8;
}

.icon-clear {
    
    
    margin: 0 20px;
}

.side-name {
    
    
    display: flex;
    justify-content: flex-start;
    margin: 0 20px;
}

.side-content {
    
    
    margin: 0 10px;
}

::-webkit-scrollbar {
    
    
    width: 0;
    height: 0;
    color: transparent;
}

Referenced page:
json:

{
    
    
  "usingComponents": {
    
    
    "side": "../components/side/index"
}
}

wxml

<side id="side" type='right' name="导出条件筛选" bind:close="closeSide">
// 内容
</side>

js:

 this.side = this.selectComponent("#side");
 this.side.openSide();//打开侧边栏
 this.side.colseSide();//关闭侧边栏

Guess you like

Origin blog.csdn.net/nienianzhi1744/article/details/107317716