mirror of
https://github.com/sunniejs/vue-h5-template.git
synced 2025-06-11 02:59:16 +08:00
个人中心
This commit is contained in:
parent
f97484c725
commit
6014f11ee4
@ -3,6 +3,8 @@ NODE_ENV='development'
|
||||
VUE_APP_ENV = 'development'
|
||||
#base url
|
||||
BASE_URL = 'https://www.xxx.com/'
|
||||
#appid
|
||||
VUE_APP_WECHAT_APPID='wxc6086549532e9a60'
|
||||
# base api
|
||||
VUE_APP_BASE_API = '/dev-api'
|
||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||
|
@ -3,6 +3,8 @@ NODE_ENV='production'
|
||||
VUE_APP_ENV = 'production'
|
||||
#base url
|
||||
BASE_URL = https://www.top1buyer.com/
|
||||
#appid
|
||||
VUE_APP_WECHAT_APPID='wx6bb2125514b4c1ff'
|
||||
# base api
|
||||
VUE_APP_BASE_API = '/prod-api'
|
||||
|
||||
|
@ -2,8 +2,9 @@ NODE_ENV='production'
|
||||
# must start with VUE_APP_
|
||||
VUE_APP_ENV = 'staging'
|
||||
#base url
|
||||
#base url
|
||||
BASE_URL = https://www.top1buyer.com/
|
||||
#appid
|
||||
VUE_APP_WECHAT_APPID='wx6bb2125514b4c1ff'
|
||||
# base api
|
||||
VUE_APP_BASE_API = '/stage-api'
|
||||
|
||||
|
@ -224,7 +224,7 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
'space-before-blocks': [2, 'always'],
|
||||
'space-before-function-paren': [2, 'never'],
|
||||
'space-before-function-paren':0,
|
||||
'space-in-parens': [2, 'never'],
|
||||
'space-infix-ops': 2,
|
||||
'space-unary-ops': [
|
||||
|
@ -15,12 +15,15 @@
|
||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chenfengyuan/vue-qrcode": "^1.0.0",
|
||||
"axios": "0.18.0",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"good-storage": "^1.1.0",
|
||||
"js-cookie": "^2.2.0",
|
||||
"lib-flexible": "^0.3.2",
|
||||
"normalize.css": "7.0.0",
|
||||
"vant": "^1.6.19",
|
||||
"vue": "2.6.10",
|
||||
"vue": "^2.6.10",
|
||||
"vue-router": "3.0.6",
|
||||
"vuex": "3.1.0"
|
||||
},
|
||||
|
@ -1,14 +1,80 @@
|
||||
import qs from 'qs'
|
||||
import request from '@/utils/request'
|
||||
import { api } from '@/config'
|
||||
// 签名
|
||||
import _bale from '@/utils/package'
|
||||
// api
|
||||
const { common_api } = api
|
||||
|
||||
// 登录
|
||||
export function login(params) {
|
||||
return request({
|
||||
url: common_api + '/ruleCommon/queryrule',
|
||||
url: common_api + '/wechat/login.do',
|
||||
method: 'post',
|
||||
data: qs.stringify(params)
|
||||
data: qs.stringify(_bale('login', params))
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 登录接口请求token与userinfo
|
||||
* @param params
|
||||
* 入参 code:"021gj0OV1om5PU0k9VNV1VMQNV1gj0OK"
|
||||
* 返回 {
|
||||
* accessToken:'xxx',
|
||||
* refreshToken:'xxx',
|
||||
* userInfo:{}
|
||||
* }
|
||||
*/
|
||||
export function loginByCode(params) {
|
||||
return request({
|
||||
url: common_api + '/wechat/auth2',
|
||||
method: 'post',
|
||||
data: qs.stringify(_bale('auth2', params))
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 获取登录用户信息
|
||||
* @param params
|
||||
*/
|
||||
export function getUserInfo(params) {
|
||||
return request({
|
||||
url: common_api + '/user/get_user',
|
||||
method: 'post',
|
||||
data: qs.stringify(_bale('get_user', params))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 公众号会员中心
|
||||
* @param params
|
||||
*/
|
||||
export function getAccountInfo(params) {
|
||||
return request({
|
||||
url: common_api + '/wechat/selectVipUserInfo',
|
||||
method: 'post',
|
||||
data: qs.stringify(_bale('selectVipUserInfo', params))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送手机验证码
|
||||
* @param params
|
||||
*/
|
||||
export function sendCode(params) {
|
||||
return request({
|
||||
url: common_api + '/wechat/send_phone_code',
|
||||
method: 'post',
|
||||
data: qs.stringify(_bale('send_phone_code', params))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信公众号添加手机号
|
||||
* @param params
|
||||
*/
|
||||
export function bindPhoneNumber(params) {
|
||||
return request({
|
||||
url: common_api + '/wechat/addPhoneNumber',
|
||||
method: 'post',
|
||||
data: qs.stringify(_bale('addPhoneNumber', params))
|
||||
})
|
||||
}
|
||||
|
@ -1,12 +1,69 @@
|
||||
@import './variables.scss';
|
||||
@import './mixin.scss';
|
||||
body,
|
||||
div,
|
||||
span,
|
||||
header,
|
||||
footer,
|
||||
nav,
|
||||
section,
|
||||
aside,
|
||||
article,
|
||||
ul,
|
||||
dl,
|
||||
dt,
|
||||
dd,
|
||||
li,
|
||||
a,
|
||||
p,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
i,
|
||||
b,
|
||||
textarea,
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
figure,
|
||||
figcaption {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
font-style: normal;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
font-weight: normal;
|
||||
box-sizing: border-box;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
&:hover {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='button'],
|
||||
input[type='submit'],
|
||||
input[type='search'],
|
||||
input[type='reset'] {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
|
||||
Microsoft YaHei, Arial, sans-serif;
|
||||
}
|
||||
|
||||
label {
|
||||
@ -20,6 +77,7 @@ html {
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
background: #f4f5f7;
|
||||
}
|
||||
|
||||
*,
|
||||
@ -50,7 +108,7 @@ div:focus {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
content: ' ';
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
@ -58,5 +116,30 @@ div:focus {
|
||||
|
||||
// main-container global css
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
.van-hairline--top-bottom::after {
|
||||
border-width: 0!important;
|
||||
}
|
||||
.van-cell {
|
||||
line-height: 30px !important;
|
||||
.van-cell__title {
|
||||
font-size: 15px;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
.van-cell__left-icon,
|
||||
.van-cell__right-icon {
|
||||
line-height: 30px;
|
||||
color: #999999;
|
||||
}
|
||||
&:not(:last-child)::after {
|
||||
left: 0 !important;
|
||||
}
|
||||
}
|
||||
//模态框
|
||||
.modal-popup {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 10rem;
|
||||
min-width: 10rem;
|
||||
}
|
||||
|
BIN
src/assets/images/account/s-conpon@2x.png
Normal file
BIN
src/assets/images/account/s-conpon@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 311 B |
BIN
src/assets/images/account/s-ticket-qrcode@2x.png
Normal file
BIN
src/assets/images/account/s-ticket-qrcode@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
BIN
src/assets/images/account/s-ticket@2x.png
Normal file
BIN
src/assets/images/account/s-ticket@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 213 B |
BIN
src/assets/images/coupon/s-coupon-item@2x.png
Normal file
BIN
src/assets/images/coupon/s-coupon-item@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
184
src/components/VerificationCode.vue
Normal file
184
src/components/VerificationCode.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<!-- verificationCode.vue -->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<van-popup v-model="visible" class="modal-popup" position="right">
|
||||
<div class="verification-code-container">
|
||||
<div class="cell-box">
|
||||
<div class="cell-title">绑定手机号</div>
|
||||
<div class="cell-item">
|
||||
<div class="item-left">+86</div>
|
||||
<input 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="请输入验证码">
|
||||
<div :class="['registered-get-code',codeCountdown?'disabled-btn':'']" :disabled="codeCountdown" @click="sendMsgCode">
|
||||
{{ codeCountdown ? `${codeCountdown}后重新发送` : '发送验证码' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="['cell-btn',codeDisable?'disabled-btn':'']" @click="submit">确 定</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: 'MsgCode',
|
||||
components: {
|
||||
'van-popup': Popup
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
codeCountdown: 0,
|
||||
verifyCodeForm: {
|
||||
code: '',
|
||||
type: 3, // 验证码类型(1:注册/登录 2:订单/登录 3: 操作验证)
|
||||
account: ''
|
||||
},
|
||||
errMessage: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
codeDisable () {
|
||||
return this.verifyCodeForm.account === '' || this.verifyCodeForm.code === ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit () { // 确定提交
|
||||
if (!this.valid(true)) { // 验证
|
||||
return Toast({
|
||||
message: this.errMessage
|
||||
})
|
||||
}
|
||||
// 绑定手机
|
||||
bindPhoneNumber(this.verifyCodeForm).then(res => {
|
||||
// 绑定成功后关闭弹窗
|
||||
this.visible = false
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
sendMsgCode () { // 获取验证码
|
||||
if (!this.valid()) { // 验证
|
||||
return Toast({
|
||||
message: this.errMessage
|
||||
})
|
||||
}
|
||||
// 发送验证码
|
||||
sendCode({
|
||||
account: this.verifyCodeForm.account,
|
||||
type: this.verifyCodeForm.type
|
||||
}).then(res => {
|
||||
this.codeCountdown = 60
|
||||
const timer = setInterval(() => {
|
||||
if (this.codeCountdown <= 0) {
|
||||
this.codeCountdown = null
|
||||
clearInterval(timer)
|
||||
} else {
|
||||
this.codeCountdown--
|
||||
}
|
||||
}, 1000)
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
// 验证
|
||||
valid (validAll) {
|
||||
if (!Validate.mobile(this.verifyCodeForm.account)) {
|
||||
this.errMessage = '请输入正确的手机号'
|
||||
return false
|
||||
}
|
||||
// validAll为true时验证全部字段
|
||||
if (validAll) {
|
||||
if (!Validate.number(this.verifyCodeForm.code)) {
|
||||
this.errMessage = '请输入4位数字验证码'
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
.verification-code-container {
|
||||
padding: 25px;
|
||||
// height: 100%;
|
||||
// background: #fff;
|
||||
.cell-box {
|
||||
padding-top: 81px;
|
||||
.cell-title {
|
||||
line-height: 31px;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.cell-item {
|
||||
border-bottom: 1px solid #ececec;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 17px;
|
||||
height: 55px;
|
||||
.item-left {
|
||||
margin-left: 12px;
|
||||
width: 73px;
|
||||
}
|
||||
input {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
line-height: 44px;
|
||||
}
|
||||
.code-cell-warp {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
// .code-cell {
|
||||
// background: #fff;
|
||||
// position: relative;
|
||||
// }
|
||||
.registered-get-code {
|
||||
width: 95px;
|
||||
background: #ff3d3e;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
margin-left: 10px;
|
||||
border-radius: 15px;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.cell-btn {
|
||||
width: 315px;
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
margin-top: 80px;
|
||||
background: #ff3d3e;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
border-radius: 23px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.disabled-btn {
|
||||
background: #d9d9d9 !important;
|
||||
color: #fff !important;
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,9 +1,10 @@
|
||||
// 本地
|
||||
module.exports = {
|
||||
title: 'vue-h5-template',
|
||||
baseUrl:'http://localhost:9018',
|
||||
api: {
|
||||
base_api: 'https://xxx.xxx.com/admin',
|
||||
common_api: 'https://xxx.xxx.com/common'
|
||||
base_api: 'https://test.top1buyer.com/wx',
|
||||
common_api: 'https://test.top1buyer.com/wx'
|
||||
},
|
||||
// package appid,appSecret
|
||||
APPID: 'Pc690487e95992c395633866b',
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 正式
|
||||
module.exports = {
|
||||
title: 'vue-h5-template',
|
||||
baseUrl:'http://localhost:9018',
|
||||
api: {
|
||||
base_api: 'https://xxx.xxx.com/admin',
|
||||
common_api: 'https://xxx.xxx.com/common'
|
||||
|
@ -1,7 +1,8 @@
|
||||
module.exports = {
|
||||
title: 'vue-h5-template',
|
||||
baseUrl: 'https://test.top1buyer.com',
|
||||
api: {
|
||||
base_api: 'https://xxx.xxx.com/admin',
|
||||
base_api: 'https://test.top1buyer.com/wx',
|
||||
common_api: 'https://xxx.xxx.com/common'
|
||||
},
|
||||
// package appid,appSecret
|
||||
|
34
src/filters/filter.js
Normal file
34
src/filters/filter.js
Normal file
@ -0,0 +1,34 @@
|
||||
// 转为unicode 编码
|
||||
exports.encodeUnicode = str => {
|
||||
var res = []
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
res[i] = ('00' + str.charCodeAt(i).toString(16)).slice(-4)
|
||||
}
|
||||
return '\\u' + res.join('\\u')
|
||||
}
|
||||
|
||||
// 解码
|
||||
exports.decodeUnicode = str => {
|
||||
if (str === undefined || '') {
|
||||
return
|
||||
}
|
||||
str = str.replace(/\\/g, '%')
|
||||
return unescape(str)
|
||||
}
|
||||
/*
|
||||
* 格式化金钱
|
||||
*/
|
||||
exports.formatMoney = value => {
|
||||
return Number(value).toFixed(2)
|
||||
}
|
||||
exports.formatCentMoney = value => {
|
||||
if (value === undefined || '') {
|
||||
return
|
||||
}
|
||||
return Number(value / 100).toFixed(2)
|
||||
}
|
||||
// 昵称解码
|
||||
exports.formatName = nickname => {
|
||||
if (!nickname) return ''
|
||||
return decodeURIComponent(nickname)
|
||||
}
|
10
src/filters/index.js
Normal file
10
src/filters/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
import Vue from 'vue'
|
||||
import filter from './filter'
|
||||
|
||||
Object.keys(filter).forEach(k => Vue.filter(k, filter[k]))
|
||||
|
||||
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')
|
@ -7,6 +7,12 @@ import 'lib-flexible/flexible.js'
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
import router from './router'
|
||||
import '@/filters' // filters
|
||||
import '@/permission' // permission control
|
||||
import wechatAuth from './plugins/wechatAuth' // 微信登录插件
|
||||
Vue.use(wechatAuth, {
|
||||
appid: process.env.VUE_APP_WECHAT_APPID
|
||||
})
|
||||
Vue.config.productionTip = false
|
||||
|
||||
new Vue({
|
||||
|
57
src/permission.js
Normal file
57
src/permission.js
Normal file
@ -0,0 +1,57 @@
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import getPageTitle from '@/utils/get-page-title'
|
||||
import wechatAuth from './plugins/wechatAuth' // 微信登录插件
|
||||
const qs = require('qs')
|
||||
router.beforeEach((to, from, next) => {
|
||||
// next()
|
||||
console.log(store.getters.loginStatus)
|
||||
const loginStatus = Number(store.getters.loginStatus)
|
||||
// console.log(loginStatus === 1)
|
||||
document.title = getPageTitle(to.meta.title)
|
||||
if (loginStatus === 0) {
|
||||
// 微信未授权登录跳转到授权登录页面
|
||||
const url = window.location.href
|
||||
// 解决重复登录url添加重复的code与state问题
|
||||
const parseUrl = qs.parse(url.split('?')[1])
|
||||
let loginUrl
|
||||
if (parseUrl.code && parseUrl.state) {
|
||||
delete parseUrl.code
|
||||
delete parseUrl.state
|
||||
loginUrl = `${url.split('?')[0]}?${qs.stringify(parseUrl)}`
|
||||
} else {
|
||||
loginUrl = url
|
||||
}
|
||||
wechatAuth.redirect_uri = loginUrl
|
||||
store.dispatch('user/setLoginStatus', 1)
|
||||
window.location.href = wechatAuth.authUrl
|
||||
} else if (loginStatus === 1) {
|
||||
// 微信已经授权回调获取code
|
||||
try {
|
||||
wechatAuth.returnFromWechat(to.fullPath)
|
||||
} catch (err) {
|
||||
store.dispatch('user/setLoginStatus', 0)
|
||||
next()
|
||||
}
|
||||
// 重新赋值,不然获取不到code
|
||||
const code = wechatAuth.code
|
||||
store
|
||||
.dispatch('user/loginWechatAuth', code)
|
||||
.then(res => {
|
||||
console.log(res)
|
||||
if (res.status === 200) {
|
||||
store.dispatch('user/setLoginStatus', 2)
|
||||
} else {
|
||||
store.dispatch('user/setLoginStatus', 0)
|
||||
}
|
||||
next()
|
||||
})
|
||||
.catch(() => {
|
||||
store.dispatch('user/setLoginStatus', 0)
|
||||
next()
|
||||
})
|
||||
} else {
|
||||
//
|
||||
next()
|
||||
}
|
||||
})
|
108
src/plugins/wechatAuth.js
Normal file
108
src/plugins/wechatAuth.js
Normal file
@ -0,0 +1,108 @@
|
||||
const qs = require('qs')
|
||||
// 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
|
||||
const SCOPES = ['snsapi_base', 'snsapi_userinfo']
|
||||
|
||||
class VueWechatAuthPlugin {
|
||||
constructor() {
|
||||
this.appid = null
|
||||
this.redirect_uri = null
|
||||
this.scope = SCOPES[1]
|
||||
this._code = null
|
||||
this._redirect_uri = null
|
||||
}
|
||||
|
||||
install(Vue, options) {
|
||||
const wechatAuth = this
|
||||
this.setAppId(options.appid)
|
||||
Vue.mixin({
|
||||
created: function() {
|
||||
this.$wechatAuth = wechatAuth
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static makeState() {
|
||||
return (
|
||||
Math.random()
|
||||
.toString(36)
|
||||
.substring(2, 15) +
|
||||
Math.random()
|
||||
.toString(36)
|
||||
.substring(2, 15)
|
||||
)
|
||||
}
|
||||
|
||||
setAppId(appid) {
|
||||
this.appid = appid
|
||||
}
|
||||
|
||||
set redirect_uri(redirect_uri) {
|
||||
this._redirect_uri = encodeURIComponent(redirect_uri)
|
||||
}
|
||||
|
||||
get redirect_uri() {
|
||||
return this._redirect_uri
|
||||
}
|
||||
|
||||
get state() {
|
||||
return localStorage.getItem('wechat_auth:state')
|
||||
}
|
||||
|
||||
set state(state) {
|
||||
localStorage.setItem('wechat_auth:state', state)
|
||||
}
|
||||
|
||||
get authUrl() {
|
||||
if (this.appid === null) {
|
||||
throw new Error('appid must not be null')
|
||||
}
|
||||
if (this.redirect_uri === null) {
|
||||
throw new Error('redirect uri must not be null')
|
||||
}
|
||||
this.state = VueWechatAuthPlugin.makeState()
|
||||
return `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${
|
||||
this.appid
|
||||
}&redirect_uri=${this.redirect_uri}&response_type=code&scope=${
|
||||
this.scope
|
||||
}&state=${this.state}#wechat_redirect`
|
||||
}
|
||||
|
||||
returnFromWechat(redirect_uri) {
|
||||
const parsedUrl = qs.parse(redirect_uri.split('?')[1])
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
this.state = null
|
||||
this._code = parsedUrl.code
|
||||
} else {
|
||||
if (this.state === null) {
|
||||
throw new Error("You did't set state")
|
||||
}
|
||||
if (parsedUrl.state === this.state) {
|
||||
this.state = null
|
||||
this._code = parsedUrl.code
|
||||
} else {
|
||||
this.state = null
|
||||
throw new Error(`Wrong state: ${parsedUrl.state}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get code() {
|
||||
if (this._code === null) {
|
||||
throw new Error('Not get the code from wechat server!')
|
||||
}
|
||||
// console.log(this)
|
||||
// console.log('this._code: ' + this._code)
|
||||
const code = this._code
|
||||
this._code = null
|
||||
// console.log('code: ' + code)
|
||||
return code
|
||||
}
|
||||
}
|
||||
|
||||
const vueWechatAuthPlugin = new VueWechatAuthPlugin()
|
||||
|
||||
if (typeof window !== 'undefined' && window.Vue) {
|
||||
window.Vue.use(VueWechatAuthPlugin)
|
||||
}
|
||||
|
||||
export default vueWechatAuthPlugin
|
@ -5,6 +5,29 @@ Vue.use(Router)
|
||||
export const constantRoutes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/account'
|
||||
},
|
||||
{
|
||||
path: '/account',
|
||||
name: 'account',
|
||||
component: () => import('@/views/account/index'),
|
||||
meta: {
|
||||
title: '个人中心',
|
||||
keepAlive: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/coupon',
|
||||
name: 'coupon',
|
||||
component: () => import('@/views/account/coupon'),
|
||||
meta: {
|
||||
title: '优惠券',
|
||||
keepAlive: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
name: 'home',
|
||||
component: () => import('@/views/home/index'),
|
||||
meta: {
|
||||
keepAlive: false
|
||||
@ -14,7 +37,8 @@ export const constantRoutes = [
|
||||
|
||||
const createRouter = () =>
|
||||
new Router({
|
||||
// mode: 'history', // require service support
|
||||
mode: 'history', // require service support
|
||||
base: '/',
|
||||
scrollBehavior: () => ({ y: 0 }),
|
||||
routes: constantRoutes
|
||||
})
|
||||
|
@ -1,3 +1,7 @@
|
||||
const getters = {
|
||||
// user
|
||||
token: state => state.user.token,
|
||||
userInfo: state => state.user.userInfo,
|
||||
loginStatus: state => state.user.loginStatus
|
||||
}
|
||||
export default getters
|
||||
|
@ -2,12 +2,14 @@ import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import getters from './getters'
|
||||
import app from './modules/app'
|
||||
import user from './modules/user'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
app
|
||||
app,
|
||||
user
|
||||
},
|
||||
getters
|
||||
})
|
||||
|
82
src/store/modules/user.js
Normal file
82
src/store/modules/user.js
Normal file
@ -0,0 +1,82 @@
|
||||
import { login } from '@/api/user'
|
||||
import { loginByCode } from '@/api/user'
|
||||
import {
|
||||
saveToken,
|
||||
saveLoginStatus,
|
||||
saveUserInfo,
|
||||
removeToken,
|
||||
removeUserInfo,
|
||||
loadLoginStatus,
|
||||
loadToken,
|
||||
loadUserInfo
|
||||
} from '@/utils/cache'
|
||||
const state = {
|
||||
loginStatus: loadLoginStatus(), // 登录状态
|
||||
token: loadToken(), // token
|
||||
userInfo: loadUserInfo() // 用户登录信息
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
SET_USERINFO: (state, userInfo) => {
|
||||
state.userInfo = userInfo
|
||||
},
|
||||
SET_LOGIN_STATUS: (state, loginStatus) => {
|
||||
state.loginStatus = loginStatus
|
||||
},
|
||||
SET_TOKEN: (state, token) => {
|
||||
state.token = token
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
loginUrl({ commit }, path) {
|
||||
// const url = baseUrl + path
|
||||
return new Promise((resolve, reject) => {
|
||||
login({ redirectUri: path })
|
||||
.then(response => {
|
||||
resolve(response)
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 登录相关
|
||||
loginWechatAuth({ commit, state }, code) {
|
||||
const data = {
|
||||
code: code
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
loginByCode(data)
|
||||
.then(res => {
|
||||
console.log(res)
|
||||
commit('SET_USERINFO', saveUserInfo(res.data.user))
|
||||
commit('SET_TOKEN', saveToken(res.data.token))
|
||||
resolve(res)
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 设置状态
|
||||
setLoginStatus({ commit, state }, query) {
|
||||
if (query === 0 || query === 1) {
|
||||
// 上线打开注释,本地调试注释掉
|
||||
removeToken()
|
||||
removeUserInfo()
|
||||
}
|
||||
commit('SET_LOGIN_STATUS', saveLoginStatus(query))
|
||||
},
|
||||
// 保存用户个人信息
|
||||
setUserInfo({ commit, state }, query) {
|
||||
commit('SET_USERINFO', saveUserInfo(query))
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
48
src/utils/cache.js
Normal file
48
src/utils/cache.js
Normal file
@ -0,0 +1,48 @@
|
||||
import cookies from 'js-cookie'
|
||||
import storage from 'good-storage'
|
||||
|
||||
const LoginStatusKey = 'Login-Status' // 登录态 0未授权未登录 1授权未登录 2 登陆成功
|
||||
const TokenKey = 'Access-Token' // token
|
||||
const UserInfoKey = 'User-Info' // 用户信息 {} {...}
|
||||
|
||||
export function loadLoginStatus() {
|
||||
return cookies.get(LoginStatusKey) || 0
|
||||
}
|
||||
|
||||
export function saveLoginStatus(status) {
|
||||
cookies.set(LoginStatusKey, status, { expires: 7 })
|
||||
return status
|
||||
}
|
||||
|
||||
export function removeLoginStatus() {
|
||||
cookies.remove(LoginStatusKey)
|
||||
return ''
|
||||
}
|
||||
|
||||
export function loadToken() {
|
||||
return storage.get(TokenKey, '')
|
||||
}
|
||||
|
||||
export function saveToken(token) {
|
||||
storage.set(TokenKey, token)
|
||||
return token
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
storage.remove(TokenKey)
|
||||
return ''
|
||||
}
|
||||
|
||||
export function loadUserInfo() {
|
||||
return storage.get(UserInfoKey, {})
|
||||
}
|
||||
|
||||
export function saveUserInfo(userInfo) {
|
||||
storage.set(UserInfoKey, userInfo)
|
||||
return userInfo
|
||||
}
|
||||
|
||||
export function removeUserInfo() {
|
||||
storage.remove(UserInfoKey)
|
||||
return {}
|
||||
}
|
7
src/utils/get-page-title.js
Normal file
7
src/utils/get-page-title.js
Normal file
@ -0,0 +1,7 @@
|
||||
const title = '蚁小宝'
|
||||
export default function getPageTitle(pageTitle) {
|
||||
if (pageTitle) {
|
||||
return `${pageTitle} - ${title}`
|
||||
}
|
||||
return `${title}`
|
||||
}
|
@ -17,10 +17,10 @@ export function parseTime(time, cFormat) {
|
||||
if (typeof time === 'object') {
|
||||
date = time
|
||||
} else {
|
||||
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
|
||||
if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
|
||||
time = parseInt(time)
|
||||
}
|
||||
if ((typeof time === 'number') && (time.toString().length === 10)) {
|
||||
if (typeof time === 'number' && time.toString().length === 10) {
|
||||
time = time * 1000
|
||||
}
|
||||
date = new Date(time)
|
||||
@ -37,7 +37,9 @@ export function parseTime(time, cFormat) {
|
||||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||
let value = formatObj[key]
|
||||
// Note: getDay() returns 0 on Sunday
|
||||
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
|
||||
if (key === 'a') {
|
||||
return ['日', '一', '二', '三', '四', '五', '六'][value]
|
||||
}
|
||||
if (result.length > 0 && value < 10) {
|
||||
value = '0' + value
|
||||
}
|
||||
@ -108,3 +110,15 @@ export function param2Obj(url) {
|
||||
'"}'
|
||||
)
|
||||
}
|
||||
// 获取 localStorage
|
||||
export function getStorage(key) {
|
||||
return window.localStorage.getItem(key)
|
||||
}
|
||||
// 设置 localStorage
|
||||
export function setStorage(key, value) {
|
||||
return window.localStorage.setItem(key, value)
|
||||
}
|
||||
// 删除 localStorage
|
||||
export function removeStorage(key) {
|
||||
return Cookies.remove(key)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ service.interceptors.request.use(
|
||||
})
|
||||
}
|
||||
if (store.getters.token) {
|
||||
config.headers['X-Token'] = ''
|
||||
config.headers['ukey'] = store.getters.token
|
||||
}
|
||||
return config
|
||||
},
|
||||
@ -34,22 +34,17 @@ service.interceptors.request.use(
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
Toast.clear()
|
||||
// 如果是数据流
|
||||
if (response.config.responseType === 'arraybuffer') {
|
||||
return response.data
|
||||
} else {
|
||||
const res = response.data
|
||||
if (res.status !== 200) {
|
||||
// 登录超时,重新登录
|
||||
if (res.status === 401) {
|
||||
store.dispatch('FedLogOut').then(() => {
|
||||
location.reload()
|
||||
})
|
||||
}
|
||||
return Promise.reject(res || 'error')
|
||||
} else {
|
||||
return Promise.resolve(res)
|
||||
const res = response.data
|
||||
if (res.status && res.status !== 200) {
|
||||
// 登录超时,重新登录
|
||||
if (res.status === 401) {
|
||||
store.dispatch('FedLogOut').then(() => {
|
||||
location.reload()
|
||||
})
|
||||
}
|
||||
return Promise.reject(res || 'error')
|
||||
} else {
|
||||
return Promise.resolve(res)
|
||||
}
|
||||
},
|
||||
error => {
|
||||
|
@ -18,3 +18,14 @@ export function validUsername(str) {
|
||||
const valid_map = ['admin', 'editor']
|
||||
return valid_map.indexOf(str.trim()) >= 0
|
||||
}
|
||||
|
||||
/* 手机号*/
|
||||
export function mobile(str) {
|
||||
const reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/
|
||||
return reg.test(str)
|
||||
}
|
||||
/* 数字 */
|
||||
export function number(str) {
|
||||
const reg = /^\d{4}$/
|
||||
return reg.test(str)
|
||||
}
|
||||
|
129
src/views/account/coupon.vue
Normal file
129
src/views/account/coupon.vue
Normal file
@ -0,0 +1,129 @@
|
||||
<!-- 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="coupon-list-warpper">
|
||||
<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>
|
||||
</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>
|
||||
<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>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NavBar, Tab, Tabs } from 'vant'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'van-nav-bar': NavBar,
|
||||
'van-tabs': Tabs,
|
||||
'van-tab': Tab
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabActive: 0
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
mounted () { },
|
||||
methods: {}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
.coupon-tabs {
|
||||
.van-tab {
|
||||
font-size: 17px !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
}
|
||||
.coupon-list-warpper {
|
||||
padding: 12px;
|
||||
.coupon-item {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
margin-bottom: 12px;
|
||||
.coupon-amount-warp {
|
||||
width: 118px;
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
.coupon-detail {
|
||||
color: #666666;
|
||||
line-height: 30px;
|
||||
padding-left: 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
204
src/views/account/index.vue
Normal file
204
src/views/account/index.vue
Normal file
@ -0,0 +1,204 @@
|
||||
<!-- home.vue -->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="user-info-container">
|
||||
<div class="user-info-warpper">
|
||||
<div class="user-info">
|
||||
<img class="user-avatar" :src="vipInfo.userImg" alt="用户头像">
|
||||
<div class="user-info-center">
|
||||
<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>
|
||||
</div>
|
||||
<div class="account-info">
|
||||
<div class="account-info-item">
|
||||
<span class="account-amount"> ¥{{ vipInfo.availableBalance|formatCentMoney }}</span>
|
||||
<span class="account-label">余额</span>
|
||||
</div>
|
||||
<div class="account-info-item">
|
||||
<span class="account-amount">{{ vipInfo.userGold }}</span>
|
||||
<span class="account-label">金币</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<van-cell-group>
|
||||
<van-cell is-link>
|
||||
<div slot="title" class="account-cell">
|
||||
<span class="icon-ticket"></span>
|
||||
<span class="custom-text">我的入场券 </span>
|
||||
</div>
|
||||
</van-cell>
|
||||
<van-cell value-class="coupon-number" :value="vipInfo.couponAvailable+'张'" is-link to="/coupon">
|
||||
<div slot="title" class="account-cell">
|
||||
<span class="icon-coupon"></span>
|
||||
<span class="custom-text">优惠券 </span>
|
||||
</div>
|
||||
</van-cell>
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import VueQrcode from '@chenfengyuan/vue-qrcode'
|
||||
import { Popup, Cell, CellGroup } from 'vant'
|
||||
import VerificationCode from '@/components/VerificationCode'
|
||||
import { getAccountInfo } from '@/api/user'
|
||||
export default {
|
||||
components: {
|
||||
'van-cell-group': CellGroup,
|
||||
'van-cell': Cell,
|
||||
'msg-code': VerificationCode,
|
||||
'qrcode': VueQrcode,
|
||||
'van-popup': Popup
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
qrcodeVisible: false,
|
||||
codeVisible: false,
|
||||
vipInfo: {},
|
||||
qrSrc: ''
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
created () {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
// 获取初始数据
|
||||
async init () {
|
||||
// 获取全部的会员信息
|
||||
const { data } = await getAccountInfo()
|
||||
this.vipInfo = data.vipUserInfo
|
||||
},
|
||||
showQrcode (event) {
|
||||
this.qrSrc = event.target.currentSrc
|
||||
this.qrcodeVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang='scss' scoped>
|
||||
h1 {
|
||||
background: red;
|
||||
width: 375px;
|
||||
}
|
||||
.user-info-container {
|
||||
padding: 12px 12px 35px 12px;
|
||||
background: #ea1314;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
.user-info-warpper {
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 18px 16px 20px 16px;
|
||||
box-shadow: 0px 6px 12px 0px rgba(231, 231, 231, 0.5);
|
||||
.user-info {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #e9e9e9;
|
||||
padding-bottom: 18px;
|
||||
.user-avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 10px;
|
||||
background: #ddd;
|
||||
}
|
||||
.user-info-center {
|
||||
margin-left: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
.user-name {
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
}
|
||||
.user-code {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.qr-code {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
.account-info {
|
||||
display: flex;
|
||||
padding-top: 15px;
|
||||
.account-info-item {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
.account-amount {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
color: #ea1314;
|
||||
font-weight: 500;
|
||||
}
|
||||
.account-label {
|
||||
color: #666666;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:after {
|
||||
content: "";
|
||||
width: 425px;
|
||||
height: 75px;
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: -25px;
|
||||
z-index: 1;
|
||||
border-top-right-radius: 50px;
|
||||
border-top-left-radius: 50px;
|
||||
}
|
||||
}
|
||||
.account-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon-ticket {
|
||||
width: 22px;
|
||||
height: 19px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
background: url("../../assets/images/account/s-ticket@2x.png") no-repeat
|
||||
center center;
|
||||
background-size: cover;
|
||||
}
|
||||
.icon-coupon {
|
||||
width: 22px;
|
||||
height: 15px;
|
||||
margin-right: 10px;
|
||||
display: inline-block;
|
||||
background: url("../../assets/images/account/s-conpon@2x.png") no-repeat
|
||||
center center;
|
||||
background-size: cover;
|
||||
}
|
||||
.coupon-number {
|
||||
color: #ea1314;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -47,7 +47,8 @@ module.exports = {
|
||||
overlay: {
|
||||
warnings: false,
|
||||
errors: true
|
||||
}
|
||||
},
|
||||
disableHostCheck: true
|
||||
},
|
||||
configureWebpack: config => {
|
||||
// 为生产环境修改配置...
|
||||
@ -88,6 +89,7 @@ module.exports = {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
args[0].cdn = cdn.dev
|
||||
}
|
||||
console.log(args)
|
||||
return args
|
||||
})
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user