小程序项目总结

184 阅读1分钟

省市区选择

  功能介绍:可以选择省市区,也可以反选,一开始就把数据全部拿来进行处理

// view页面
<view class="address-selection">
    <van-tabs active="{{active}}" animated sticky>
        <van-tab title="{{addressInfo.province.name}}" class="padding-left content">
            <scroll-view scroll-y style="height:{{scrollHeight}}rpx">
                <view wx:for="{{provinceList}}" wx:key="index">
                    <view bind:tap="chooseProvince" data-obj="{{item}}" class="item {{addressInfo.province.code===item.code ? 'select' : ''}}">
                        {{item.name}}<image src="{{selectAddress}}" wx:if="{{addressInfo.province.code===item.code}}" class="icon"></image>
                    </view>
                </view>
            </scroll-view>
        </van-tab>
        <van-tab title="{{addressInfo.city.name}}" disabled="{{addressInfo.province.name==='请选择'}}">
            <scroll-view scroll-y style="height:{{scrollHeight}}rpx">
                <view wx:for="{{cityList}}" wx:key="index">
                    <view bind:tap="chooseCity" data-obj="{{item}}" class="item {{addressInfo.city.code===item.code ? 'select' : ''}}">
                        {{item.name}}<image src="{{selectAddress}}" wx:if="{{addressInfo.city.code===item.code}}" class="icon"></image>
                    </view>
                </view>
            </scroll-view>
        </van-tab>
        <van-tab title="{{addressInfo.district.name}}" disabled="{{addressInfo.city.name==='请选择'}}">
            <scroll-view scroll-y style="height:{{scrollHeight}}rpx">
                <view wx:for="{{areaList}}" wx:key="index">
                    <view bind:tap="chooseArea" data-obj="{{item}}" class="item {{addressInfo.district.code===item.code ? 'select' : ''}}">
                        {{item.name}}<image src="{{selectAddress}}" wx:if="{{addressInfo.district.code===item.code}}" class="icon"></image>
                    </view>
                </view>
            </scroll-view>
        </van-tab>
        <van-tab title="{{addressInfo.street.name}}" disabled="{{addressInfo.street.name==='请选择'}}" wx:if="{{isShowStreet}}">
            <scroll-view scroll-y style="height:{{scrollHeight}}rpx">
                <view wx:for="{{streetList}}" wx:key="index">
                    <view bind:tap="chooseStreet" data-obj="{{item}}" class="item {{addressInfo.street.code===item.code ? 'select' : ''}}">
                        {{item.name}}<image src="{{selectAddress}}" wx:if="{{addressInfo.street.code===item.code}}" class="icon"></image>
                    </view>
                </view>
            </scroll-view>
        </van-tab>
    </van-tabs>
</view>
// js
const util = require('../../utils/util.js')
const api = require('../../config/api.js')
const wxUtil = require('../../utils/wxUtil.js')

Page({
    data: {
        active: 0, // 选中的tab
        addressInfo: {
            province: { name: '请选择', code: '' }, // 选中的省
            city: { name: '请选择', code: '' }, // 选中的市
            district: { name: '请选择', code: '' }, // 选中的区
            street: { name: '请选择', code: '' } // 选中的街道
        },
        provinceList: [], // 省份列表
        cityList: [], // 市列表
        areaList: [], // 区列表
        streetList: [], // 街道列表
        isShowStreet: false, // 是否显示街道
        options: {},
        scrollHeight: 0,
        selectAddress: `${api.imgUrl}/login/selectAddress.png`
    },
    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function(options) {
        this.setData({ options })
        if (options.type === 'street') {
            this.setData({ isShowStreet: true })
            if (options.streetCode) {
                this.setData({
                    ['addressInfo.street']: { name: options.streetName, code: options.streetCode }
                })
                this.getStreetList(options)
            } else {
                this.handleAddress()
            }
        } else {
            let code = options.type === '2' ? wx.getStorageSync('replaceAddressInfo').district.code || '' : wx.getStorageSync('addressInfo').district.code || ''
            this.handleAddress(code ? 'areaCode' : '', code)
        }
        wxUtil.getClientHeight().then((res) => {
            this.setData({ scrollHeight: res - 100 })
        })
    },
    /**
     * 获取街道数据
     */
    getStreetList(options) {
        util.request(api.regionList, { parentCode: options.areaCode }).then(res => {
            if (res.code === 0) {
                this.setData({ streetList: res.data })
                this.handleAddress('areaCode', options.areaCode)
            }
        })
    },
    /**
     * 处理省市区街道数据
     */
    handleAddress(type, code) {
        let [provinceList, cityList, areaList] = [
            [],
            [],
            []
        ]
        let addressList = wx.getStorageSync('allAddressList')
        for (let item of addressList) {
            provinceList.push({ name: item.name, code: item.code })
            for (let i of item.children) {
                if (type === 'proviceCode' && item.code === code) {
                    cityList.push({ name: i.name, code: i.code })
                }
                for (let o of i.children) {
                    if (type === 'cityCode' && i.code === code) {
                        areaList.push({ name: o.name, code: o.code })
                    }
                    if (type === 'areaCode' && o.code === code) {
                        for (let p of item.children) {
                            cityList.push({ name: p.name, code: p.code })
                        }
                        for (let a of i.children) {
                            areaList.push({ name: a.name, code: a.code })
                        }
                        this.setData({
                            cityList,
                            areaList,
                            ['addressInfo.province']: { name: item.name, code: item.code },
                            ['addressInfo.city']: { name: i.name, code: i.code },
                            ['addressInfo.district']: { name: o.name, code: o.code },
                            active: this.data.isShowStreet ? 3 : 2
                        })
                    }
                }
            }
        }
        this.setData({ provinceList })
        if (type === 'proviceCode') {
            this.setData({ cityList })
        } else if (type === 'cityCode') {
            this.setData({ areaList })
        }
 },
 /**
     * 省份选择
     * 
     */
    chooseProvince(e) {
        let obj = e.target.dataset.obj
        this.setData({
            ['addressInfo.province']: { name: obj.name, code: obj.code },
            ['addressInfo.city']: { name: '请选择', code: '' },
            ['addressInfo.district']: { name: '请选择', code: '' },
            ['addressInfo.street']: { name: '请选择', code: '' },
            active: 1
        })
        this.handleAddress('proviceCode', obj.code)
    },
    /**
     * 市选择
     */
    chooseCity(e) {
        let obj = e.target.dataset.obj
        this.setData({ active: 1 })
        this.setData({
            ['addressInfo.city']: { name: obj.name, code: obj.code },
            ['addressInfo.district']: { name: '请选择', code: '' },
            ['addressInfo.street']: { name: '请选择', code: '' },
            active: 2
        })
        this.handleAddress('cityCode', obj.code)
    },
    /**
     * 区选择
     */
    chooseArea(e) {
        let obj = e.target.dataset.obj
        if (this.data.isShowStreet) {
            obj.areaCode = obj.code
            this.setData({ active: 2 })
            this.setData({
                ['addressInfo.district']: { name: obj.name, code: obj.code },
                ['addressInfo.street']: { name: '请选择', code: '' },
                active: 3
            })
            this.getStreetList(obj)
        } else {
            this.setData({
                ['addressInfo.district']: { name: obj.name, code: obj.code }
            })
            let addressObj = this.data.addressInfo
            util.request(api.geoCoder, {
                address: addressObj.province.name + addressObj.city.name + addressObj.district.name
            }).then(res => {
                if (res.code === 0) {
                    if (this.data.options.type === '2') {
                        wx.setStorageSync('replaceAddressInfo', addressObj)
                        wx.setStorageSync('replaceLocation', `${res.data.lat},${res.data.lng}`)
                        wx.navigateBack({ delta: 1 })
                    } else {
                        wx.setStorageSync('isSave', true)
                        wx.setStorageSync('addressInfo', addressObj)
                        wx.setStorageSync('replaceAddressInfo', addressObj)
                        wx.setStorageSync('mapLocation', `${res.data.lat},${res.data.lng}`)
                        wx.getSetting({
                            success: (result) => {
                                if (result.authSetting['scope.userLocation'] === false) {
                                    wx.setStorageSync('location', `${res.data.lat},${res.data.lng}`)
                                }
                                wx.navigateBack({ delta: 1 })
                            }
                        })
                    }
                }
            })
        }
    },
    /**
     * 街道选择
     */
    chooseStreet(e) {
        let obj = e.target.dataset.obj
        this.setData({
            ['addressInfo.street']: { name: obj.name, code: obj.code }
        })
        let curPages = getCurrentPages()
        let prevPage = curPages[curPages.length - 2]
        let data = this.data.addressInfo
        prevPage.setData({
            isShowStreet: false,
            ['addressInfo.provinceName']: data.province.name,
            ['addressInfo.cityName']: data.city.name,
            ['addressInfo.areaName']: data.district.name,
            ['addressInfo.streetName']: data.street.name,
            ['addressInfo.provinceCode']: data.province.code,
            ['addressInfo.cityCode']: data.city.code,
            ['addressInfo.areaCode']: data.district.code,
            ['addressInfo.streetCode']: data.street.code,
            ['addressInfo.address']: data.province.name + data.city.name + data.district.name + data.street.name
        })
        wx.navigateBack({ delta: 1 })
    }
点击生成海报并保存到手机
//点击生成海报按钮
    generatePosters() {
        if (wx.getStorageSync('fromFriendCircle')) {
            return wx.showToast({ title: '请前往小程序使用完整服务', icon: 'none' })
        }
        let str = JSON.stringify({
            shopNo: this.data.shopNo || ''
        })
        util.request(api.longToShort, { url: str }, 'POST', '', 'application/x-www-form-urlencoded').then(res => {
            if (res.code === 0) {
                let self = this
                let appId = 'wxb0a7f7ab522f1f20'
                let params = {
                    appId,
                    scene: res.data,
                    page: 'pages/caseDetail/caseDetail',
                    width: 300
                }
                wx.showLoading({ title: '图片生成中...' })
                util.request(api.generateMiniCode, params, 'POST').then(res => {
                    if (res.code === 0) {
                        self.setData({ imgData: res.data })
                        wx.downloadFile({
                            url: self.data.programDetail.picUrls[0],
                            success(res) {
                                self.drawCanvas(res.tempFilePath)
                            }
                        })
                    } else {
                        wx.hideLoading()
                    }
                }).catch(() => wx.hideLoading())
            }
        })
    },
    /**
     * 绘制canvas
     */
    drawCanvas(tempFilePath) {
        let self = this
        const ctx = wx.createCanvasContext('myCanvas')
        ctx.setFillStyle('#ffffff')
        ctx.fillRect(0, 0, 255, 1000)
        ctx.drawImage(tempFilePath, 28, 13, 200, 200)
            // 价格
        ctx.setFontSize(12)
        ctx.setFillStyle('#FF3B30')
        ctx.textAlign = 'start'
        ctx.stroke()
            // ctx.setFontSize(18)
        ctx.font = "bold 18px arial"
        ctx.setFillStyle('#FF3B30')
        ctx.textAlign = 'start'
        ctx.stroke()
            // spu名称
        ctx.setFontSize(13)
        ctx.setFillStyle('#333333')

        let str = self.data.programDetail.title
        let lineWidth = 0
        let limitWidth = 220 // 计算canvas的宽度
        let initHeight = 255 // 绘制字体距离canvas顶部初始的高度
        let lastSubStrIndex = 0 // 每次开始截取的字符串的索引
        self.getWeixinImg().then((result) => {
            wx.hideLoading()
            self.setData({ base64Img: result, isShowOverlay: true, isShowSheet: false })
            ctx.drawImage(result, 21, 62, 62)
            ctx.setFontSize(11)
            ctx.setFillStyle('#999999')
            ctx.textAlign = 'start'
            ctx.fillText('长按识别图中二维码', 100, 300)
            ctx.stroke()
            self.setData({ canvasHeight: 363 })
                // 绘制打印
                // 异步方法,绘制结束再绑定,不会出坑
            setTimeout(() => {
                ctx.draw(false, () => {
                    wx.canvasToTempFilePath({
                        canvasId: 'myCanvas',
                        success(res) {
                            self.setData({ posterImg: res.tempFilePath })
                        },
                        fail(err) {
                            console.log('图片地址失败', err)
                        }
                    }, self)
                })
                wx.hideLoading()
            }, 500)
        }).catch(() => wx.hideLoading())
    },
    /**
     * 将base64转为image
     */
    getWeixinImg() {
        const fsm = wx.getFileSystemManager()
        return new Promise((resolve, reject) => {
            let number = Math.random()
            const filePath = wx.env.USER_DATA_PATH + `/pic${number}.png`
            fsm.writeFile({
                filePath: filePath,
                data: wx.base64ToArrayBuffer(this.data.imgData),
                encoding: 'binary',
                success() {
                    resolve(filePath)
                },
                fail(err) {
                    reject(new Error('ERROR_BASE64SRC_WRITE'))
                }
            })
        })
    },
    /**
     * 点击下载图片
     */
    downPic() {
        let self = this
        let fileManager = wx.getFileSystemManager()
        let number = Math.random()
        fileManager.writeFile({
            filePath: wx.env.USER_DATA_PATH + `/pic${number}.png`,
            data: self.data.imgData,
            encoding: 'base64',
            success: response => {
                wx.getSetting({
                    success: (result) => {
                        if (result.authSetting['scope.writePhotosAlbum'] === false) {
                            wx.showModal({
                                title: '是否授权保存图片',
                                content: '需要保存图片或视频到你的相册',
                                confirmText: '授权',
                                cancelText: '拒绝',
                                success(res) {
                                    if (res.confirm) {
                                        wx.openSetting({
                                            success: function() {
                                                console.log('开启')
                                            }
                                        })
                                    }
                                    if (res.cancel) {
                                        util.showErrorToast('图片保存失败')
                                    }
                                }
                            })
                        } else if (result.authSetting['scope.writePhotosAlbum'] === true) {
                            self.saveImage()
                        } else if (result.authSetting['scope.writePhotosAlbum'] === undefined) {
                            self.saveImage()
                        }
                    }
                })
            }
        })
    },
    /**
     * 保存到相册
     */
    saveImage() {
        wx.saveImageToPhotosAlbum({
            filePath: this.data.posterImg,
            success() {
                util.showErrorToast('已保存到相册,可以去发图啦')
            },
            fail() {
                util.showErrorToast('图片保存失败')
            }
        })
    }
小程序请求封装
/**
 * 封封微信的的request
 */
function request(url, data = {}, method = "GET", Authorization, type) {
    let token = wx.getStorageSync('token')
    let Bearer = token ? `Bearer ${token}` : undefined
    return new Promise(function(resolve, reject) {
        wx.request({
            url: url,
            data: data,
            method: method,
            header: {
                'Content-Type': type ? type : 'application/json',
                'X-Litemall-Token': token,
                Authorization: Authorization ? Authorization : Bearer
            },
            success: function(res) {
                if (res.data.code == 401 || res.data.code == 403) {
                    clearTimeout(timeout)
                    timeout = setTimeout(() => {
                        wx.navigateTo({ url: '/pages/auth/login/login' })
                    }, 600)
                    return
                }
                if (res.data.code !== 0) {
                    let isSkip = false
                    let pages = getCurrentPages()
                    let view = pages[pages.length - 1]
                    if ((view && view.__route__ === 'pages/indexPage/indexPage' && res.data.code === 10300) ||
                        (view && view.__route__ === 'pages/home/goodsDetail/goodsDetail' && res.data.code === 6003) || res.data.code === 30105) isSkip = true
                    if (!isSkip) showErrorToast(res.data.msg || res.data.message)
                }
                if (res.statusCode == 200) {
                    resolve(res.data)
                } else {
                    reject(res.errMsg)
                }
            },
            fail: function(err) {
                showErrorToast('网络异常,请稍后再试')
                reject(err)
            }
        })
    })
}