微信公众号,授权,券

This commit is contained in:
406803045 2019-06-06 09:17:06 +08:00
parent 6014f11ee4
commit ca44e7447a
29 changed files with 627 additions and 195 deletions

12
.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": [
[ "@babel/preset-env", {
"targets": {
"browsers": [ "last 1 version", "ie >= 11" ]
}
}]
],
"plugins": [
"@babel/plugin-transform-runtime"
]
}

View File

@ -4,6 +4,7 @@ VUE_APP_ENV = 'staging'
#base url
BASE_URL = https://www.top1buyer.com/
#appid
VUE_APP_WECHAT_APPID='wx6bb2125514b4c1ff'
# base api
VUE_APP_BASE_API = '/stage-api'

View File

@ -1,5 +1,6 @@
process.env.VUE_CLI_BABEL_TRANSPILE_MODULES = true
module.exports = {
presets: ['@vue/app'],
presets: [['@vue/app', { useBuiltIns: 'entry' }]],
plugins: [
[
'import',

View File

@ -3,7 +3,7 @@ const chalk = require('chalk')
// const config = require('../vue.config.js')
const rawArgv = process.argv.slice(2)
const args = rawArgv.join(' ')
// npm run preview -- --report
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
const report = rawArgv.includes('--report')

View File

@ -7,7 +7,7 @@
"scripts": {
"dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"build:sit": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
"lint": "eslint --ext .js,.vue src",
"test:unit": "jest --clearCache && vue-cli-service test:unit",
@ -15,8 +15,10 @@
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
},
"dependencies": {
"@babel/polyfill": "^7.4.4",
"@chenfengyuan/vue-qrcode": "^1.0.0",
"axios": "0.18.0",
"core-js": "^2.6.9",
"crypto-js": "^3.1.9-1",
"good-storage": "^1.1.0",
"js-cookie": "^2.2.0",
@ -52,6 +54,7 @@
"script-loader": "0.7.2",
"serve-static": "^1.13.2",
"svgo": "1.2.2",
"vconsole": "^2.5.2",
"vue-template-compiler": "2.6.10"
},
"engines": {

27
public/index.1.html Normal file
View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %>
<title><%= webpackConfig.name %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- 使用CDN加速的JS文件配置在vue.config.js下 -->
<% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -5,11 +5,6 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %>
<title><%= webpackConfig.name %></title>
</head>
<body>
@ -18,10 +13,6 @@
</noscript>
<div id="app"></div>
<!-- 使用CDN加速的JS文件配置在vue.config.js下 -->
<% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
<!-- built files will be auto injected -->
</body>
</html>

15
src/api/coupon.js Normal file
View File

@ -0,0 +1,15 @@
import qs from 'qs'
import request from '@/utils/request'
import { api } from '@/config'
// 签名
import _bale from '@/utils/package'
// api
// 查询我的优惠券
export function getCouponList(params) {
return request({
url: '/coupon/selectMyCoupon',
method: 'post',
data: qs.stringify(_bale('selectMyCoupon', params))
})
}

View File

@ -4,12 +4,10 @@ import { api } from '@/config'
// 签名
import _bale from '@/utils/package'
// api
const { common_api } = api
// 登录
export function login(params) {
return request({
url: common_api + '/wechat/login.do',
url: '/wechat/login.do',
method: 'post',
data: qs.stringify(_bale('login', params))
})
@ -17,16 +15,10 @@ export function login(params) {
/**
* 登录接口请求token与userinfo
* @param params
* 入参 code:"021gj0OV1om5PU0k9VNV1VMQNV1gj0OK"
* 返回 {
* accessToken:'xxx',
* refreshToken:'xxx',
* userInfo:{}
* }
*/
export function loginByCode(params) {
return request({
url: common_api + '/wechat/auth2',
url: '/wechat/auth2',
method: 'post',
data: qs.stringify(_bale('auth2', params))
})
@ -37,7 +29,7 @@ export function loginByCode(params) {
*/
export function getUserInfo(params) {
return request({
url: common_api + '/user/get_user',
url: '/user/get_user',
method: 'post',
data: qs.stringify(_bale('get_user', params))
})
@ -49,7 +41,7 @@ export function getUserInfo(params) {
*/
export function getAccountInfo(params) {
return request({
url: common_api + '/wechat/selectVipUserInfo',
url: '/wechat/selectVipUserInfo',
method: 'post',
data: qs.stringify(_bale('selectVipUserInfo', params))
})
@ -61,7 +53,7 @@ export function getAccountInfo(params) {
*/
export function sendCode(params) {
return request({
url: common_api + '/wechat/send_phone_code',
url: '/wechat/send_phone_code',
method: 'post',
data: qs.stringify(_bale('send_phone_code', params))
})
@ -73,7 +65,7 @@ export function sendCode(params) {
*/
export function bindPhoneNumber(params) {
return request({
url: common_api + '/wechat/addPhoneNumber',
url: '/wechat/addPhoneNumber',
method: 'post',
data: qs.stringify(_bale('addPhoneNumber', params))
})

View File

@ -118,7 +118,7 @@ div:focus {
.app-container {
}
.van-hairline--top-bottom::after {
border-width: 0!important;
border-width: 0 !important;
}
.van-cell {
line-height: 30px !important;
@ -143,3 +143,26 @@ div:focus {
max-width: 10rem;
min-width: 10rem;
}
.my-header {
position: relative;
width: 100%;
background: #fff;
border-bottom:1px solid #E9E9E9;
.back-icon {
position: absolute;
width: 44px;
height: 44px;
box-sizing: border-box;
background: url('../../assets/images/arrow-left.png') no-repeat center
center;
background-size: 70% 70%;
}
.header-title {
font-size: 17px;
font-weight: 600;
height: 44px;
line-height: 44px;
text-align: center;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,35 @@
<!-- ListEmpty.vue -->
<template>
<div class="list-empty">
<slot name='emptyImg'></slot>
<div class="empty-tips">{{tips}}</div>
</div>
</template>
<script>
export default {
name: 'ListEmpty',
props: {
tips: {
type: String,
default: ''
}
},
}
</script>
<style lang='scss' scoped>
.list-empty {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 55px;
.empty-tips {
color: #999999;
font-size: 17px;
line-height: 24px;
padding-top: 35px;
}
}
</style>

View File

@ -0,0 +1,134 @@
<!-- verificationCode.vue -->
<template>
<div class="app-container">
<!-- 二维码大图 -->
<van-popup v-model="visible" class="modal-popup">
<div class="qrcode-popup-container">
<div class="qrcode-close" @click="closePopup">
取消
</div>
<div class="qrcode-top">
{{title}}
</div>
<div class="qrcode-bottom">
<img class="qrcode-img" :src="src" alt="">
<div class="qrcode-tips" v-html="tips">
</div>
</div>
</div>
</van-popup>
</div>
</template>
<script>
import { Popup, Toast } from 'vant'
import * as Validate from '@/utils/validate'
import { bindPhoneNumber, sendCode } from '@/api/user'
export default {
name: 'QrCodePopup',
components: {
'van-popup': Popup
},
props: {
visible: {
type: Boolean,
default: false
},
src: {
type: String,
default: ''
},
title: {
type: String,
default: ''
},
tips: {
type: String,
default: ''
}
},
data () {
return {
}
},
methods: {
closePopup () {
this.$emit('close')
}
}
}
</script>
<style lang='scss' scoped>
.modal-popup {
width: 100%;
height: 100%;
background: #d43f36;
.qrcode-popup-container {
position: relative;
margin: 25px 27px;
background: #fff;
border-radius: 10px;
.qrcode-close {
color: #d43f36;
font-size: 16px;
position: absolute;
left: 0px;
top: 0px;
padding: 20px;
z-index: 100;
}
.qrcode-top {
position: relative;
height: 115px;
border-bottom: 2px dotted #dbdbdb;
display: flex;
justify-content: center;
align-items: center;
color: #333333;
font-size: 24px;
font-weight: 500;
&::before {
content: "";
width: 32px;
height: 32px;
background: #d43f36;
position: absolute;
bottom: -16px;
right: -16px;
border-radius: 50%;
}
&::after {
content: "";
width: 32px;
height: 32px;
background: #d43f36;
position: absolute;
bottom: -16px;
left: -16px;
border-radius: 50%;
}
}
.qrcode-bottom {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 25px 0 41px 0;
.qrcode-img {
height: 190px;
width: 190px;
}
.qrcode-tips {
font-size: 15px;
color: #666666;
width: 210px;
text-align: center;
margin-top: 17px;
line-height: 21px;
}
}
}
}
</style>

View File

@ -7,12 +7,12 @@
<div class="cell-title">绑定手机号</div>
<div class="cell-item">
<div class="item-left">+86</div>
<input v-model="verifyCodeForm.account" type="tel" placeholder="请输入手机号">
<input v-reset-page v-model="verifyCodeForm.account" type="tel" placeholder="请输入手机号">
</div>
<div class="cell-item">
<div class="item-left"> 验证码</div>
<div class="code-cell-warp">
<input v-model="verifyCodeForm.code" type="tel" placeholder="请输入验证码">
<input v-reset-page v-model="verifyCodeForm.code" type="tel" placeholder="请输入验证码">
<div :class="['registered-get-code',codeCountdown?'disabled-btn':'']" :disabled="codeCountdown" @click="sendMsgCode">
{{ codeCountdown ? `${codeCountdown}后重新发送` : '发送验证码' }}
</div>
@ -66,7 +66,10 @@ export default {
//
bindPhoneNumber(this.verifyCodeForm).then(res => {
//
this.visible = false
Toast({
message: '绑定成功'
})
this.$emit('close')
}).catch(() => {
})
},

View File

@ -3,7 +3,7 @@ module.exports = {
baseUrl: 'https://test.top1buyer.com',
api: {
base_api: 'https://test.top1buyer.com/wx',
common_api: 'https://xxx.xxx.com/common'
common_api: 'https://test.top1buyer.com/wx'
},
// package appid,appSecret
APPID: 'Pc690487e95992c395633866b',

View File

@ -1,5 +1,42 @@
/**
*格式化时间
*yyyy-MM-dd hh:mm:ss
*/
export function formatDate(time, fmt) {
if (time === undefined || '') {
return
}
const date = new Date(time)
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
(date.getFullYear() + '').substr(4 - RegExp.$1.length)
)
}
const o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
}
for (const k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
const str = o[k] + ''
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length === 1 ? str : padLeftZero(str)
)
}
}
return fmt
}
function padLeftZero(str) {
return ('00' + str).substr(str.length)
}
// 转为unicode 编码
exports.encodeUnicode = str => {
export function encodeUnicode(str) {
var res = []
for (var i = 0; i < str.length; i++) {
res[i] = ('00' + str.charCodeAt(i).toString(16)).slice(-4)
@ -8,7 +45,7 @@ exports.encodeUnicode = str => {
}
// 解码
exports.decodeUnicode = str => {
export function decodeUnicode(str) {
if (str === undefined || '') {
return
}
@ -18,17 +55,26 @@ exports.decodeUnicode = str => {
/*
* 格式化金钱
*/
exports.formatMoney = value => {
export function formatMoney(value) {
return Number(value).toFixed(2)
}
exports.formatCentMoney = value => {
export function formatCentMoney(value) {
if (value === undefined || '') {
return
}
return Number(value / 100).toFixed(2)
}
// 昵称解码
exports.formatName = nickname => {
export function formatName(nickname) {
if (!nickname) return ''
return decodeURIComponent(nickname)
}
// 折扣转换
export function formatPercent(percent_off) {
if (!percent_off) return ''
if (percent_off == 1) {
return '原价'
}
// 解决精度丢失问题
return Math.round(percent_off * 100) / 10
}

View File

@ -1,10 +1,12 @@
import Vue from 'vue'
import filter from './filter'
import * as filter from './filter'
Object.keys(filter).forEach(k => Vue.filter(k, filter[k]))
Vue.prototype.$formatDate = Vue.filter('formatDate')
Vue.prototype.$encodeUnicode = Vue.filter('encodeUnicode')
Vue.prototype.$decodeUnicode = Vue.filter('decodeUnicode')
Vue.prototype.$formatMoney = Vue.filter('formatMoney')
Vue.prototype.$formatCentMoney = Vue.filter('formatCentMoney')
Vue.prototype.$formatName = Vue.filter('formatName')
Vue.prototype.$formatPercent = Vue.filter('formatPercent')

View File

@ -1,5 +1,5 @@
import Vue from 'vue'
import '@babel/polyfill'
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
import '@/assets/css/index.scss' // global css
// 移动端适配
@ -8,11 +8,14 @@ import App from './App'
import store from './store'
import router from './router'
import '@/filters' // filters
import '@/utils/directives' // directives
import '@/permission' // permission control
import wechatAuth from './plugins/wechatAuth' // 微信登录插件
Vue.use(wechatAuth, {
appid: process.env.VUE_APP_WECHAT_APPID
})
import VCconsole from 'vconsole'
Vue.use(VCconsole)
Vue.config.productionTip = false
new Vue({

View File

@ -5,9 +5,14 @@ import wechatAuth from './plugins/wechatAuth' // 微信登录插件
const qs = require('qs')
router.beforeEach((to, from, next) => {
// next()
console.log(store.getters.loginStatus)
// store.dispatch('user/fedLogOut').then(() => {
// // location.reload()
// })
// store.dispatch('user/setLoginStatus', 0)
// alert(store.getters.loginStatus)
// return false
// alert(store.getters.loginStatus)
const loginStatus = Number(store.getters.loginStatus)
// console.log(loginStatus === 1)
document.title = getPageTitle(to.meta.title)
if (loginStatus === 0) {
// 微信未授权登录跳转到授权登录页面
@ -22,7 +27,9 @@ router.beforeEach((to, from, next) => {
} else {
loginUrl = url
}
// alert(loginUrl)
wechatAuth.redirect_uri = loginUrl
// 无论拒绝还是授权都设置成1
store.dispatch('user/setLoginStatus', 1)
window.location.href = wechatAuth.authUrl
} else if (loginStatus === 1) {
@ -31,27 +38,32 @@ router.beforeEach((to, from, next) => {
wechatAuth.returnFromWechat(to.fullPath)
} catch (err) {
store.dispatch('user/setLoginStatus', 0)
next()
location.reload()
// next()
}
// 同意授权 to.fullPath 携带code参数拒绝授权没有code参数
// alert(to.fullPath)
// 重新赋值不然获取不到code
const code = wechatAuth.code
store
.dispatch('user/loginWechatAuth', code)
.then(res => {
console.log(res)
if (res.status === 200) {
// alert(code)
if (code) {
store
.dispatch('user/loginWechatAuth', code)
.then(res => {
store.dispatch('user/setLoginStatus', 2)
} else {
next()
})
.catch(() => {
store.dispatch('user/setLoginStatus', 0)
}
next()
})
.catch(() => {
store.dispatch('user/setLoginStatus', 0)
next()
})
location.reload()
})
} else {
store.dispatch('user/setLoginStatus', 0)
location.reload()
}
} else {
//
// alert(to.fullPath)
next()
}
})

View File

@ -38,7 +38,7 @@ export const constantRoutes = [
const createRouter = () =>
new Router({
mode: 'history', // require service support
base: '/',
base: '/antpublic',
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})

View File

@ -71,6 +71,12 @@ const actions = {
// 保存用户个人信息
setUserInfo({ commit, state }, query) {
commit('SET_USERINFO', saveUserInfo(query))
},
// 登出
fedLogOut({ commit, state }, query) {
removeToken()
removeUserInfo()
commit('SET_LOGIN_STATUS', saveLoginStatus(0))
}
}

33
src/utils/directives.js Normal file
View File

@ -0,0 +1,33 @@
import Vue from 'vue'
Vue.directive('focus', {
inserted: function(el) {
// 获取焦点
el.focus()
}
})
Vue.directive('numberOnly', {
inserted: function(el) {
// 获取焦点
el.handler = function() {
el.value = el.value.replace(/[^\d]/g, '')
}
el.addEventListener('input', el.handler)
}
})
Vue.directive('resetPage', {
inserted: function(el) {
// 监听键盘收起事件
document.body.addEventListener('focusout', () => {
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
// 软键盘收起的事件处理
setTimeout(() => {
const scrollHeight =
document.documentElement.scrollTop || document.body.scrollTop || 0
window.scrollTo(0, Math.max(scrollHeight - 1, 0))
}, 100)
}
})
}
})

View File

@ -35,10 +35,14 @@ service.interceptors.response.use(
response => {
Toast.clear()
const res = response.data
if (res.status && res.status !== 200) {
Toast({
message: res.info
})
// 登录超时,重新登录
if (res.status === 401) {
store.dispatch('FedLogOut').then(() => {
store.dispatch('user/fedLogOut').then(() => {
location.reload()
})
}

View File

@ -1,129 +1,211 @@
<!-- coupon.vue -->
<template>
<div class="app-container">
<van-nav-bar title="我的优惠券" left-arrow @click-left="()=>{this.$router.push('/account')}" />
<van-tabs v-model="tabActive" class="coupon-tabs" :line-width="44" :line-height="1" color="#333333">
<van-tab title="未使用"></van-tab>
<van-tab title="已使用"></van-tab>
<van-tab title="已失效"></van-tab>
</van-tabs>
<div class="fixed">
<div class="my-header">
<div class="back-icon" @click="()=>{this.$router.push('/account')}"></div>
<div class="header-title">我的优惠券</div>
</div>
<van-tabs v-model="tabActive" @click="tabClick(tabActive)" class="coupon-tabs" :line-width="44" :line-height="1" color="#333333">
<van-tab title="未使用"></van-tab>
<van-tab title="已使用"></van-tab>
<van-tab title="已失效"></van-tab>
</van-tabs>
</div>
<div class="coupon-list-warpper">
<div class="coupon-item">
<div class="coupon-amount-warp">
<div class="coupon-amount-number">
<span class="rmb">¥</span>
<span>50</span>
<!-- foreach -->
<div v-for="(item,index) in couponList" :key="index" class="coupon-item">
<div class="coupon-main">
<div class="coupon-left">
<div class="coupon-amount-number">
<template v-if="item.couponType===3">
<span>{{ item.percentOff|formatPercent }}</span><span class="rmb"></span>
</template>
<template v-else>
<span class="rmb">¥</span><span>{{ item.couponAmount|formatCentMoney }}</span>
</template>
</div>
<div>
<span v-if="item.couponType===1">无门槛</span>
<span v-if="item.couponType===2">¥{{ item.availableAmount|formatCentMoney }}可用</span>
</div>
</div>
<div class="coupon-right">
<div class="coupon-info">
<div class="coupon-title">{{ item.couponName }}</div>
<div v-if="item.endType === 0" class="coupon-off-date">无使用期限</div>
<div v-else class="coupon-off-date"> {{ item.couponStart|formatDate("yyyy.MM.dd hh:mm:ss") }}-{{ item.couponEnd|formatDate("yyyy.MM.dd hh:mm:ss") }}</div>
</div>
<div class="coupon-detail" @click="showExpain(index)">
<span>详细信息</span>
<span :class="item.explainVisible?'coupon-arrow-up':'coupon-arrow-down'"></span>
</div>
</div>
<p><span>¥199可用</span></p>
</div>
<div class="coupon-info-warp">
<div class="coupon-info">
<div class="coupon-title">全场限时优惠</div>
<div class="off-date">2018.12.18 10:00:00</div>
</div>
<div class="coupon-detail">详细信息<span></span></div>
<div v-if="item.explainVisible" class="coupon-info-explain">
{{ item.couponExplain }}
</div>
</div>
<div class="coupon-item">
<div class="coupon-amount-warp">
<div class="coupon-amount-number">
<span class="rmb">¥</span>
<span>50</span>
</div>
<p><span>¥199可用</span></p>
<!-- foreach end-->
<!-- empty -->
<list-empty v-if="couponList.length===0" tips="您没有可用的优惠券哦">
<div slot="emptyImg" class="coupon_empty">
</div>
<div class="coupon-info-warp">
<div class="coupon-info">
<div class="coupon-title">全场限时优惠</div>
<div class="off-date">2018.12.18 10:00:00</div>
</div>
<div class="coupon-detail">详细信息<span></span></div>
</div>
</div>
</list-empty>
</div>
</div>
</template>
<script>
import { NavBar, Tab, Tabs } from 'vant'
import { Tab, Tabs } from 'vant'
import { getCouponList } from '@/api/coupon'
import ListEmpty from '@/components/ListEmpty'
export default {
components: {
'van-nav-bar': NavBar,
'van-tabs': Tabs,
'van-tab': Tab
'van-tab': Tab,
'list-empty': ListEmpty
},
data () {
return {
tabActive: 0
tabActive: 0,
couponList: [],
params: {
couponStatus: 0 // 0使1使2
},
explainShow: false
}
},
computed: {},
mounted () { },
methods: {}
mounted () {
this.fetchData()
},
methods: {
fetchData () {
getCouponList(this.params).then(res => {
this.couponList = res.data.couponList
})
},
//
showExpain (index) {
if (this.couponList[index].explainVisible) {
this.couponList[index].explainVisible = !this.couponList[index].explainVisible
} else {
this.$set(this.couponList[index], 'explainVisible', true)
}
},
// tab
tabClick (index) {
this.params.couponStatus = index
//
this.fetchData()
}
}
}
</script>
<style lang='scss'>
.coupon-tabs {
.van-tab {
font-size: 17px !important;
font-weight: 500 !important;
.fixed {
position: fixed;
z-index: 9999;
width: 100%;
.coupon-tabs {
.van-tab {
font-size: 17px !important;
font-weight: 500 !important;
}
}
}
.coupon-list-warpper {
padding: 12px;
padding: 98px 12px 0 12px;
height: 100vh;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
.coupon-item {
display: flex;
width: 100%;
height: 100px;
margin-bottom: 12px;
.coupon-amount-warp {
width: 118px;
.coupon-main {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: url("../../assets/images/coupon/s-coupon-item@2x.png")
no-repeat center center;
background-size: contain;
color: #fff;
.coupon-amount-number {
font-size: 30px;
.rmb {
font-size: 15px;
}
}
}
.coupon-info-warp {
display: flex;
flex-direction: column;
background: #fff;
flex: 1;
.coupon-info {
width: 100%;
.coupon-left {
width: 118px;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 12px 11px 9px 11px;
height: 70px;
border-bottom: 2px dotted #ddd;
.coupon-title {
font-size: 16px;
line-height: 23px;
color: #333333;
}
.off-date {
font-size: 10px;
line-height: 14px;
color: #999999;
align-items: center;
justify-content: center;
background: url("../../assets/images/coupon/s-coupon-item@2x.png")
no-repeat center center;
background-size: contain;
color: #fff;
.coupon-amount-number {
font-size: 30px;
line-height: 42px;
.rmb {
font-size: 15px;
}
}
}
.coupon-detail {
color: #666666;
line-height: 30px;
padding-left: 11px;
.coupon-right {
display: flex;
flex-direction: column;
background: #fff;
flex: 1;
.coupon-info {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 12px 11px 9px 11px;
height: 70px;
border-bottom: 2px dotted #ddd;
.coupon-title {
font-size: 16px;
line-height: 23px;
color: #333333;
}
.coupon-off-date {
font-size: 10px;
line-height: 14px;
color: #999999;
}
}
.coupon-detail {
color: #666666;
line-height: 30px;
padding: 0 11px;
display: flex;
justify-content: space-between;
align-items: center;
}
.coupon-arrow-down {
width: 22px;
height: 22px;
background: url("../../assets/images/coupon/s-coupon-detail-down@2x.png")
no-repeat center center;
background-size: contain;
}
.coupon-arrow-up {
width: 22px;
height: 22px;
background: url("../../assets/images/coupon/s-coupon-detail-up@2x.png")
no-repeat center center;
background-size: contain;
}
}
}
.coupon-info-explain {
background: #ffffff;
margin-top: 1px;
padding: 8px 12px;
color: #999999;
}
}
}
.coupon_empty {
width: 140px;
height: 105px;
background: url("../../assets/images/coupon/s-coupon-empty@2x.png") no-repeat
center center;
background-size: cover;
}
</style>

View File

@ -9,8 +9,8 @@
<div class="user-name">{{ vipInfo.nickName|formatName }}<span class="user-level"></span></div>
<div class="user-code">代购编号{{ vipInfo.userCode }}</div>
</div>
<div class="qrcode-warp" @click="showQrcode($event)">
<qrcode :value="vipInfo.userCode" tag="img" :options="{ width: 45,margin:0 }"></qrcode>
<div class="qrcode-warp" @click="showUserQrcode($event)">
<qrcode v-if="vipInfo.userPhone!==''" :value="vipInfo.userPhone" tag="img" :options="{ width: 145,margin:0 }"></qrcode>
</div>
</div>
<div class="account-info">
@ -42,49 +42,60 @@
</van-cell-group>
</div>
<!-- 绑定手机 -->
<msg-code :visible="codeVisible"></msg-code>
<!-- 二维码大图 -->
<van-popup v-model="qrcodeVisible" style="padding:10px;border-radius:10px">
<div class="popup-container">
<img :src="qrSrc" alt="">
</div>
</van-popup>
<msg-code :visible="codeVisible" @close="()=>{ codeVisible = false }"></msg-code>
<!-- 二维码 -->
<qrcode-popup :visible="qrcodeVisible" :src="qrSrc" :title="qrTitle" :tips="qrTips" @close="()=>{ qrcodeVisible = false }">
</qrcode-popup>
</div>
</template>
<script>
import VueQrcode from '@chenfengyuan/vue-qrcode'
import { Popup, Cell, CellGroup } from 'vant'
import { Cell, CellGroup } from 'vant'
import VerificationCode from '@/components/VerificationCode'
import QrCodePopup from '@/components/QrCodePopup'
import { getAccountInfo } from '@/api/user'
export default {
components: {
'van-cell-group': CellGroup,
'van-cell': Cell,
'msg-code': VerificationCode,
'qrcode': VueQrcode,
'van-popup': Popup
'qrcode-popup': QrCodePopup,
'qrcode': VueQrcode
},
data () {
return {
qrcodeVisible: false,
codeVisible: false,
vipInfo: {},
qrSrc: ''
qrSrc: '',
qrTitle: '',
qrTips: ''
}
},
computed: {},
created () {
computed: {
},
mounted () {
this.init()
},
methods: {
//
async init () {
init () {
//
const { data } = await getAccountInfo()
this.vipInfo = data.vipUserInfo
getAccountInfo().then(res => {
this.vipInfo = res.data.vipUserInfo
//
if (this.vipInfo && this.vipInfo.userPhone === '') {
this.codeVisible = true
}
})
},
showQrcode (event) {
//
showUserQrcode (event) {
this.qrSrc = event.target.currentSrc
this.qrTitle = '小蚁货仓会员码'
this.qrTips = '<p>会员码用于会员储值及支付</p> <p>请勿随意泄漏给</p>'
this.qrcodeVisible = true
}
}
@ -135,9 +146,13 @@ h1 {
font-size: 13px;
}
}
.qr-code {
.qrcode-warp {
width: 50px;
height: 50px;
img {
width: 100%;
height: 100%;
}
}
}
.account-info {

View File

@ -1,17 +1,15 @@
'use strict'
const path = require('path')
const defaultSettings = require('./src/config/index.js')
function resolve(dir) {
return path.join(__dirname, dir)
}
const name = defaultSettings.title || 'vue mobile template' // page title
const port = 9018 // dev port
const externals = {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
'mint-ui': 'MINT',
vant: 'vant',
axios: 'axios',
'crypto-js': 'CryptoJS'
}
@ -26,6 +24,7 @@ const cdn = {
build: {
css: ['https://cdn.jsdelivr.net/npm/vant@beta/lib/index.css'],
js: [
// 'https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.4.4/polyfill.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.6/vue-router.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js',
@ -36,7 +35,7 @@ const cdn = {
}
}
module.exports = {
publicPath: '/',
publicPath: process.env.NODE_ENV === 'production' ? '/antpublic/' : '/',
outputDir: 'dist',
assetsDir: 'static',
lintOnSave: process.env.NODE_ENV === 'development',
@ -50,29 +49,22 @@ module.exports = {
},
disableHostCheck: true
},
configureWebpack: config => {
// 为生产环境修改配置...
if (process.env.NODE_ENV === 'production') {
// externals里的模块不打包
Object.assign(config, {
externals: externals
})
}
// 为开发环境修改配置...
if (process.env.NODE_ENV === 'development') {
}
},
// configureWebpack: {
// name: name,
// resolve: {
// alias: {
// '@': resolve('src')
// }
// configureWebpack: config => {
// // 为生产环境修改配置...
// if (process.env.NODE_ENV === 'production') {
// // externals里的模块不打包
// Object.assign(config, {
// externals: externals
// })
// }
// // 为开发环境修改配置...
// if (process.env.NODE_ENV === 'development') {
// }
// },
chainWebpack(config) {
config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
config
// alias
config.resolve.alias
.set('@', resolve('src'))
@ -82,16 +74,16 @@ module.exports = {
/**
* 添加CDN参数到htmlWebpackPlugin配置中 详见public/index.html 修改
*/
config.plugin('html').tap(args => {
if (process.env.NODE_ENV === 'production') {
args[0].cdn = cdn.build
}
if (process.env.NODE_ENV === 'development') {
args[0].cdn = cdn.dev
}
console.log(args)
return args
})
// config.plugin('html').tap(args => {
// if (process.env.NODE_ENV === 'production') {
// args[0].cdn = cdn.build
// }
// if (process.env.NODE_ENV === 'development') {
// args[0].cdn = cdn.dev
// }
// console.log(args)
// return args
// })
// set preserveWhitespace
config.module