Browse Source

[新增] 完成会员码页面UI

[新增] 生成二维码、条形码组件
master
邓平艺 4 years ago
parent
commit
e8353b1423
  1. 54
      components/lf-code/helper.js
  2. 2
      components/lf-code/index.js
  3. 87
      components/lf-code/lf-barcode.vue
  4. 84
      components/lf-code/lf-qrcode.vue
  5. 7
      pages.json
  6. 199
      pages/user/member/code.vue

54
components/lf-code/helper.js

@ -0,0 +1,54 @@
// 判断arr是否为一个数组,返回一个bool值
function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}
// 深度克隆
function deepClone(obj) {
// 对常见的“非”值,直接返回原来值
if ([null, undefined, NaN, false].includes(obj)) return obj;
if (typeof obj !== "object" && typeof obj !== 'function') {
//原始类型直接返回
return obj;
}
var o = isArray(obj) ? [] : {};
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
}
}
return o;
}
function getUUid(len = 32, firstU = true, radix = null) {
let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
let uuid = [];
radix = radix || chars.length;
if (len) {
// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
} else {
let r;
// rfc4122标准要求返回的uuid中,某些位为固定的字符
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
for (let i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
}
}
}
// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
if (firstU) {
uuid.shift();
return 'u' + uuid.join('');
} else {
return uuid.join('');
}
}
export {
deepClone,
getUUid
};

2
components/lf-code/index.js
File diff suppressed because it is too large
View File

87
components/lf-code/lf-barcode.vue

@ -0,0 +1,87 @@
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<canvas :canvas-id="item.id" :id="item.id" :style="{width:width,height: height}" v-for="(item,index) in listCode" :key="item.id" />
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<canvas :canvas-id="id" :id="id" :style="{width:width,height: height}" />
<!-- #endif -->
</view>
</template>
<script>
import QRCODE from './index.js';
import { getUUid, deepClone } from './helper.js'
export default {
name: 'WBarcode',
props:{
options:{
type: Object,
required: true,
default: () =>{
return {
}
}
}
},
data () {
return {
listCode: [],
id: getUUid(),
height: null,
width: null,
}
},
created() {
this.height = this.options.height + 'rpx';
this.width = this.options.width + 'rpx';
this.SpecialTreatment(this.options)
this.$nextTick(()=>{
this.generateCode();
})
},
watch: {
options:{
deep: true,
handler (val) {
this.height = val.height + 'rpx';
this.width = val.width + 'rpx';
this.SpecialTreatment(val)
// #ifdef H5
setTimeout(()=>{// h5canvas
this.generateCode();
},50)
// #endif
// #ifdef APP-NVUE || APP-PLUS || MP || QUICKAPP-WEBVIEW || QUICKAPP-WEBVIEW-HUAWEI || QUICKAPP-WEBVIEW-UNION
this.generateCode();
// #endif
}
}
},
methods: {
SpecialTreatment (val) {//canvas
// #ifdef MP-WEIXIN
let obj = deepClone(val);
this.id = obj.id = getUUid();
this.listCode = [obj]
// #endif
},
generateCode () {
try{
const parameter = {...this.options,id: this.id,ctx: this};
QRCODE.BarCode(parameter,(res)=>{
this.$emit('generate',res)
})
}catch(err){}
},
async saveImg (){
try{
const res = await QRCODE.SaveImg({id: this.id,width: this.width,height: this.width,ctx: this});
return res
}catch(e){}
}
}
}
</script>

84
components/lf-code/lf-qrcode.vue

@ -0,0 +1,84 @@
<template>
<view>
<!-- #ifdef MP-WEIXIN -->
<canvas :canvas-id="item.id" :id="item.id" :style="{width:size,height: size}" v-for="(item,index) in listCode" :key="item.id" />
<!-- #endif -->
<!-- #ifndef MP-WEIXIN -->
<canvas :canvas-id="id" :id="id" :style="{width:size,height: size}" />
<!-- #endif -->
</view>
</template>
<script>
import QRCODE from './index.js';
import { getUUid, deepClone } from './helper.js'
export default {
name: 'WQrcode',
props:{
options:{
type: Object,
required: true,
default: () =>{
return {
}
}
}
},
data () {
return {
listCode:[],
id: getUUid(),
size: null,
}
},
created() {
this.size = this.options.size + 'rpx';
this.SpecialTreatment(this.options)
this.$nextTick(()=>{
this.generateCode();
})
},
watch: {
options:{
deep: true,
handler (val) {
this.size = val.size +'rpx';
this.SpecialTreatment(val)
// #ifdef H5
setTimeout(()=>{// h5canvas
this.generateCode();
},50)
// #endif
// #ifdef APP-NVUE || APP-PLUS || MP || QUICKAPP-WEBVIEW || QUICKAPP-WEBVIEW-HUAWEI || QUICKAPP-WEBVIEW-UNION
this.generateCode();
// #endif
}
}
},
methods: {
SpecialTreatment (val) {//canvas
// #ifdef MP-WEIXIN
let obj = deepClone(val);
this.id = obj.id = getUUid();
this.listCode = [obj]
// #endif
},
generateCode () {
try{
const parameter = {...this.options,id: this.id,ctx: this};
QRCODE.QRCode(parameter,(res)=>{
this.$emit('generate',res)
})
}catch(err){}
},
async saveImg (){
try{
const res = await QRCODE.SaveImg({id: this.id,width: this.size,height: this.size,ctx: this});
return res
}catch(e){}
}
}
}
</script>

7
pages.json

@ -790,6 +790,13 @@
"navigationBarTitleText": "热门活动",
"navigationStyle": "custom"
}
},
{
"path" : "pages/user/member/code",
"style" : {
"navigationBarTitleText": "会员码",
"navigationStyle": "custom"
}
}
],
"globalStyle": {

199
pages/user/member/code.vue

@ -0,0 +1,199 @@
<template>
<view class="page">
<lf-nav title="会员码" bgColor="transparent" :spreadOut="false" titleColor="#fff" :showIcon="true"></lf-nav>
<view class="bg-viewleft"></view>
<view class="bg-viewright"></view>
<view class="content">
<view class="top">
<view class="lf-flex">
<view class="avatar">
<image src="https://picsum.photos/200"></image>
</view>
<view class="phone">182****5380</view>
</view>
<view class="card">
<text class="lf-iconfont icon--1"></text>
</view>
</view>
<view class="balance">余额 ¥1829.83</view>
<view class="barcode">
<lf-barcode :options="config.bar"></lf-barcode>
</view>
<view class="qrcode">
<lf-qrcode :options="config.qrc"></lf-qrcode>
</view>
<view class="tips">{{ num }}s后自动刷新</view>
</view>
</view>
</template>
<script>
import lfBarcode from '@/components/lf-code/lf-barcode.vue';
import lfQrcode from '@/components/lf-code/lf-qrcode.vue';
export default {
components: {
lfBarcode,
lfQrcode
},
data(){
return {
config: {
bar: {
code: 'E01181016286106',
color: '#000', //
bgColor: '#FFFFFF', //
width: 586, //
height: 210 //
},
qrc: {
code: "https://weixin.qq.com/g/AwYAAHO3aO4zlasEij6bLsk4hlZd5XNFkkBmqyS55mLPFxmn5c9PaI1omqLhd24fABCD23333",
size: 352, //
level: 4, // 04
bgColor: '#FFFFFF', //
// border: {
// color: ['#8A2387', '#F27121'], //
// lineWidth: 3, //
// },
// img: '/static/logo.png', //
// iconSize: 40, //
color: '#000000', //
}
},
timer: null,
num: 90
}
},
onLoad(){
this.refreshCode();
},
onUnload(){
if(this.timer){
clearInterval(this.timer);
this.timer = null;
}
},
methods: {
// rpx px
rpxTransformPx(num){
let systemInfo = uni.getSystemInfoSync();
let pxWidth = num / 750 * systemInfo.windowWidth;
return pxWidth;
},
// code
refreshCode(){
if(this.timer){
clearInterval(this.timer);
this.timer = null;
}
this.timer = setInterval(() => {
this.num--;
if(this.num <= 0){
clearInterval(this.timer);
this.timer = null;
this.num = 90;
this.refreshCode(); //
}
}, 1000);
}
}
}
</script>
<style>
page{
overflow: hidden;
}
</style>
<style lang="scss" scoped="scoped">
.page{
width: 100vw;
height: 100vh;
background: linear-gradient(270deg, #187B7A 0%, #2FAAA7 100%, #22A2A0 100%);
position: relative;
overflow: hidden;
.bg-viewleft{
position: absolute;
left: -100rpx;
top: 59rpx;
width: 585rpx;
height: 585rpx;
border-radius: 50%;
background-color: rgba(255,255,255,0.04);
}
.bg-viewright{
position: absolute;
right: -38rpx;
top: 102rpx;
width: 127rpx;
height: 127rpx;
border-radius: 50%;
background-color: rgba(255,255,255,0.04);
}
.content{
position: absolute;
top: 260rpx;
left: calc(50% - 343rpx);
width: 686rpx;
height: 986rpx;
background: #FFFFFF;
border-radius: 20rpx;
.top{
display: flex;
justify-content: space-between;
padding: 0 40rpx;
width: 100%;
box-sizing: border-box;
align-items: center;
margin-top: -20rpx;
.avatar{
width: 160rpx;
height: 160rpx;
border-radius: 50%;
background-color: #FFFFFF;
box-shadow: 0rpx 2rpx 8rpx 1rpx rgba(21, 113, 110, 0.2);
border: 5rpx solid #FFFFFF;
display: flex;
justify-content: center;
align-items: center;
margin-right: 20rpx;
&>image{
width: 148rpx;
height: 148rpx;
border-radius: 50%;
}
}
.phone{
font-size: 36rpx;
font-weight: bold;
color: #15716E;
}
.card{
padding: 10rpx 20rpx;
&>text{
font-size: 40rpx;
color: #15716E;
}
}
}
.balance{
font-size: 32rpx;
color: #555555;
text-align: center;
font-weight: bold;
margin-top: 60rpx;
line-height: 1;
}
.barcode, .qrcode{
display: flex;
justify-content: center;
margin-top: 30rpx;
}
.tips{
font-size: 24rpx;
color: #777777;
text-align: center;
margin-top: 30rpx;
}
}
}
</style>
Loading…
Cancel
Save