提交 5d7878b1 authored 作者: pengxiaohui's avatar pengxiaohui

调试购买下单页面接口

上级 c021d5ec
module.exports = {
domain: 'dev.ezijing.com',
url: 'https://learn-api.ezijing.com/api',
// apiBaseURL: 'https://zy2.ezijing.com/',
url: 'https://h5-shop2.ezijing.com/api',
webpack: {
externals: {
CKEDITOR: 'window.CKEDITOR',
......@@ -10,16 +9,16 @@ module.exports = {
regeneratorRuntime: 'window.regeneratorRuntime',
wx: 'window.wx',
WeixinJSBridge: 'window.WeixinJSBridge'
},
devServer: {
proxy: {
'/api/shop': {
target: 'http://172.16.3.11:8089',
changeOrigin: true,
pathRewrite: { '^/api/shop': '' }
}
}
}
// devServer: {
// proxy: {
// '/api/shop': {
// target: 'http://172.16.3.11:8089',
// changeOrigin: true,
// pathRewrite: { '^/api/shop': '' }
// }
// }
// }
},
ProvidePlugin: {},
others: {
......
......@@ -16,4 +16,13 @@ export function sendCode(data) {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data
})
}
// 通过手机号验证码注册并登陆
export function phoneCodeLogin(data) {
return httpRequest({
url: '/api/usercenter/user/register-and-login-by-mobile',
method: 'post',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data
})
}
\ No newline at end of file
......@@ -17,4 +17,10 @@ export function getGoodsList(data) {
*/
export function getGoodsSpecs(data) {
return httpRequest.post('/api/shop/commodity/spu/spec/value/search', data)
}
/**
* 创建订单
*/
export function createOrder(data) {
return httpRequest.post('/api/shop/order/add', data)
}
\ No newline at end of file
<template>
<van-popup v-model="popupVisiable" position="bottom" class="buy-popup" :style="{ height: '60%' }" >
<h5>手机号登录</h5>
<van-form :show-error="false" @failed="handFailed" @submit="handleSuccess">
<van-field v-model="form.phone" name="phone" label="手机号" placeholder="请输入您的手机号" :rules="[{ required: true, message: '请输入您的手机号' }, { pattern: /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/, message: '手机号格式有误' }]" clearable/>
<van-form :show-error="false" @submit="handleSuccess">
<van-field v-model="form.mobile" name="mobile" label="手机号" placeholder="请输入您的手机号" :rules="[{ required: true, message: '请输入您的手机号' }, { pattern: /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/, message: '手机号格式有误' }]" clearable/>
<van-field v-model="form.code" name="code" label="验证码" placeholder="请输入手机验证码" :rules="[{ required: true, message: '请输入手机验证码' }]" clearable>
<template #button>
<van-button class="code-btn" native-type="button" size="small" type="primary" color="#F8F8F8" :disabled="btnDisabled" id="checkedCode" @click="sendCode">获取验证码</van-button>
</template>
</van-field>
<div style="margin: 16px;">
<van-button type="primary" round block color="#C01540" size="small">登录</van-button>
<van-button type="primary" round block color="#C01540" size="small" :disabled="payBtnDisabled">登录</van-button>
</div>
</van-form>
</van-popup>
</template>
<script>
import { Toast } from 'vant'
import { phoneCodeLogin, sendCode } from '@/api/account'
import store from '@/store'
const MOBILE_REG = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/
export default {
props: {
......@@ -29,9 +31,10 @@ export default {
popupVisiable: this.value,
btnDisabled: false,
form: {
phone: '',
mobile: '',
code: ''
}
},
payBtnDisabled: false
}
},
watch: {
......@@ -47,16 +50,13 @@ export default {
}
},
methods: {
handFailed(val) {
console.log(val)
},
handleSuccess(val) {
console.log(val)
this.fetchPhoneCodeLogin()
},
sendCode() {
if (!this.form.phone) {
if (!this.form.mobile) {
Toast('请填写手机号')
} else if (!MOBILE_REG.test(this.form.phone)) {
} else if (!MOBILE_REG.test(this.form.mobile)) {
Toast('手机号格式错误')
} else {
this.fetchSendCode()
......@@ -80,7 +80,32 @@ export default {
}
}, 1000)
},
fetchSendCode() {}
fetchSendCode() {
const params = {
account: this.form.mobile,
service: 'ezijing.com'
}
sendCode(params).then(res => {
if (res && res.code === 0) {
Toast.success('验证码发送成功')
} else {
Toast.error(res.msg || '发送验证码失败')
}
})
},
fetchPhoneCodeLogin() {
this.payBtnDisabled = true
phoneCodeLogin(this.form).then(async res => {
if (res.code === 0) {
await store.dispatch('checkLogin')
Toast.success('登录成功')
this.$emit('input', false)
this.$emit('loginSuccess')
} else {
Toast.error(res.msg || '登录失败')
}
})
}
}
}
</script>
......
import store from '@/store'
export default class Before {
constructor(opt) {
this.opt = opt || {}
}
async update(to, from, next) {
// 设置游客用户信息
const { user_id: userId, student_id: studentId } = to.query
if (userId && studentId) {
store.commit('setGuestUser', { user_id: userId, student_id: studentId })
}
// 创建游客用户
// await store.dispatch('createGuestUser')
const isLogin = store.state.isLogin || (await store.dispatch('checkLogin'))
isLogin && wx.miniProgram.postMessage({ data: { token: store.state.token } })
if (to.meta.requiredLogin && !isLogin) {
store.state.isWeapp
? wx.miniProgram.redirectTo({ url: '/pages/login/index' })
: next(`/login?redirect_uri=${encodeURIComponent(window.location.href)}`)
return
}
next()
}
}
......@@ -8,7 +8,7 @@ import './style.scss' // 公共样式
import './assets/rem/rem.js'
import MetaInfo from 'vue-meta-info'
import createBefore from './components/beforeEnter'
import createBefore from './utils/beforeEnter'
// vant
import Vant from 'vant'
......
......@@ -2,11 +2,11 @@
<van-popup v-model="popupVisiable" position="bottom" class="buy-popup" :style="{ height: '60%' }" >
<div class="goods-card van-hairline--bottom">
<div class="thumb">
<img :src="goodsBuyInfo.thumb">
<img :src="thumb">
</div>
<div class="content">
<div class="price"><span>{{goodsBuyInfo.price}}</span></div>
<p class="surplus">剩余 {{goodsBuyInfo.surplus}}</p>
<div class="price"><span>{{price}}</span></div>
<p class="surplus">剩余 {{surplus}}</p>
</div>
</div>
<van-field label="规格" class="tag-item">
......@@ -53,9 +53,11 @@ export default {
goodsBuyInfo: {
thumb: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/shop-h5/goods_01.png',
price: '350.00',
surplus: 20,
count: 1
surplus: 20
},
thumb: '',
price: '',
surplus: 0,
spec: '',
specList: [],
form: {
......@@ -94,6 +96,7 @@ export default {
options: {
handler(nv) {
// const specs = nv.specs
this.thumb = nv.thumb
const fields = typeof nv.fields === 'string' ? JSON.parse(nv.fields) : undefined
if (Array.isArray(fields)) {
this.assembleFields(fields)
......@@ -112,24 +115,26 @@ export default {
},
methods: {
handleTagSelected(val) {
console.log(val)
this.goodsBuyInfo.price = val.price
this.goodsBuyInfo.surplus = val.stock
this.price = val.price
this.surplus = val.stock
},
handleSuccess(val) {
const fields = []
for (const key in val) {
if (val[key] && key.includes('field')) {
console.log(this.fieldsMap[key])
const obj = Object.assign({}, this.fieldsMap[key].sourceData, { value: val[key] })
fields.push(obj)
}
}
console.log(fields)
// const params = {
// shop_id: this.shop_id,
// spu_id: this.spu_id
// }
const params = {
shop_id: this.shop_id,
spu_id: this.spu_id,
sku_id: this.spec,
buy_count: this.form.count,
payment_method: '8',
app_button_text: JSON.stringify(fields)
}
this.$emit('placeOrder', params)
},
assembleFields(list) {
const fieldsMap = {}
......@@ -158,7 +163,6 @@ export default {
fieldsMap[field.key] = field
})
this.fieldsMap = fieldsMap
console.log(fieldsMap)
},
fetchGoodsSpecs() {
const params = {
......@@ -169,8 +173,8 @@ export default {
this.specList = res.data
const [first = {}] = res.data
this.spec = first.spec_value_ids
this.goodsBuyInfo.price = first.price
this.goodsBuyInfo.surplus = first.stock
this.price = first.price
this.surplus = first.stock
})
}
}
......
<template>
<div class="buy-container">
<van-swipe class="my-swipe" indicator-color="white">
<van-swipe-item class="video" v-if="details.main_chart_oss">
<video :src="details.main_chart_oss" controls="controls" @click="handleVideoClick" ref="video"></video>
<van-swipe-item class="video" v-if="details.main_chart_oss" @click="handleVideoClick">
<video :src="details.main_chart_oss" controls="controls" ref="video"></video>
<van-icon :name="videoPlay ? 'pause-circle-o':'play-circle-o'" />
</van-swipe-item>
<van-swipe-item v-for="item in imgList" :key="item.url">
......@@ -30,7 +30,7 @@
</div>
</div>
<div class="item shop-item">
<van-cell value="进点逛逛" is-link>
<van-cell value="进点逛逛" is-link @click="navShop(shopInfo.shop_id)">
<!-- 使用 title 插槽来自定义标题 -->
<template #title>
<img class="shop-logo" :src="shopInfo.shop_logo">
......@@ -41,14 +41,16 @@
<div class="bottom-bar">
<van-button type="primary" round block color="#C01540" size="small" @click="popupVisiable = true">立即购买</van-button>
</div>
<buy-popup v-model="popupVisiable" :options="popupOptions"/>
<phone-code-login-popup v-model="loginPopupVisiable" />
<buy-popup v-model="popupVisiable" :options="popupOptions" @placeOrder="handlePlaceOrder"/>
<phone-code-login-popup v-model="loginPopupVisiable" @loginSuccess="handleHasLogin"/>
</div>
</template>
<script>
import BuyPopup from './components/BuyPopup.vue'
import PhoneCodeLoginPopup from '@/components/PhoneCodeLoginPopup.vue'
import { getGoodsList, getShopList } from '@/api/common.js'
import { getGoodsList, getShopList, createOrder } from '@/api/common.js'
import store from '@/store'
import { mapGetters } from 'vuex'
export default {
components: { BuyPopup, PhoneCodeLoginPopup },
data() {
......@@ -59,18 +61,20 @@ export default {
details: {},
imgList: [],
shopInfo: {},
popupOptions: {}
popupOptions: {},
orderInfo: {}
}
},
computed: {
...mapGetters(['user']),
query() {
return this.$route.query
},
goods_id () {
return this.query.id || '6805043172159258624'
return this.query.goods_id || '6805043172159258624'
},
shop_id () {
return this.query.s_id || '6800681447305773056'
return this.query.shop_id || '6800681447305773056'
}
},
beforeMount() {
......@@ -87,6 +91,26 @@ export default {
}
this.videoPlay = !this.videoPlay
},
navShop(id) {
this.$router.push({ path: '/shop', query: { shop_id: id } })
},
async handlePlaceOrder(val) {
this.orderInfo = val
this.popupVisiable = false
const isLogin = store.state.isLogin || (await store.dispatch('checkLogin'))
if (isLogin) {
this.handleHasLogin()
} else {
this.loginPopupVisiable = true
}
},
handleHasLogin() {
const params = Object.assign({}, this.orderInfo)
params.customer_id = this.user.id
params.customer_phone = this.user.phone || ''
console.log(params)
this.fetchPlaceOrder(params)
},
fetchGoodsDetails() {
const params = {
shop_id: this.shop_id,
......@@ -102,7 +126,8 @@ export default {
}
this.popupOptions = {
specs: first.spec,
fields: first.app_button_text
fields: first.app_button_text,
thumb: this.imgList[0] ? this.imgList[0].url : ''
}
}
})
......@@ -117,6 +142,11 @@ export default {
this.shopInfo = first
}
})
},
fetchPlaceOrder(params) {
createOrder(params).then(res => {
console.log(res)
})
}
}
}
......
......@@ -38,10 +38,7 @@ export default {
components: { AppSearchBar },
data() {
return {
goodsList: [
{ price: '350.00', num: 2, desc: '紫荆-Kelley MSF五期班开学典礼晚宴', title: '紫荆-Kelley MSF五期班开学典礼晚宴', thumb: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/shop-h5/goods_01.png', id: '111', pay_count: 222 },
{ price: '10.00', num: 2, desc: '描述信息', title: '商品标题', thumb: 'https://img01.yzcdn.cn/vant/ipad.jpeg', id: '222', pay_count: 222 }
]
goodsList: []
}
},
computed: {
......@@ -52,7 +49,7 @@ export default {
},
methods: {
handleClick(val) {
this.$router.push({ path: 'buy', query: { id: val.spu_id, s_id: val.shop_id } })
this.$router.push({ path: 'buy', query: { spu_id: val.spu_id, shop_id: val.shop_id } })
},
imgJsonParse(val) {
if (typeof val === 'string' && typeof JSON.parse(val) === 'object') {
......
......@@ -3,7 +3,7 @@
<div class="search-bar">
<van-icon name="arrow-left" />
<van-search
v-model="value"
v-model="search"
shape="round"
size="small"
background="#f7f7f7"
......@@ -11,20 +11,51 @@
/>
</div>
<van-tabs v-model="active" sticky>
<van-tab title="标签 1"></van-tab>
<van-tab title="标签 2"></van-tab>
<van-tab title="标签 3"></van-tab>
<van-tab title="标签 4"></van-tab>
<van-tab title="全部"></van-tab>
<van-tab title="待付款"></van-tab>
<van-tab title="待发货"></van-tab>
<van-tab title="已完成"></van-tab>
</van-tabs>
<div class="content"></div>
<ul class="order-list">
<li class="order-item" v-for="item in list" :key="item.id">
<div class="thumb">
<img :src="item.thumb">
</div>
<div class="content">
<div class="status-row">{{item.status | statusFilter}}</div>
<div class="title-row">
<div class="title van-ellipsis">{{item.spu_name}}</div>
<div class="price">{{item.price}}</div>
</div>
<div class="spec-row">
<p class="spec">{{item.spec}}</p>
</div>
<div class="sum_pay">需付款¥{{item.sum_pay}}</div>
</div>
</li>
</ul>
</div>
</template>
<script>
const statusMap = {
0: '等待买家付款',
1: '卖家已发货',
2: '交易完成'
}
export default {
data() {
return {
search: '',
active: '',
list: []
list: [
{ price: '350.00', num: 2, desc: '紫荆-Kelley MSF五期班开学典礼晚宴', spu_name: '紫荆-Kelley MSF五期班开学典礼晚宴', thumb: 'https://webapp-pub.oss-cn-beijing.aliyuncs.com/shop-h5/goods_01.png', id: '111', pay_count: 222, status: 0, spec: '红,20', sum_pay: '700.00' },
{ price: '10.00', num: 1, desc: '描述信息', spu_name: '商品标题', thumb: 'https://img01.yzcdn.cn/vant/ipad.jpeg', id: '222', pay_count: 222, status: 1, spec: '红,L', sum_pay: '10.00' }
]
}
},
filters: {
statusFilter(val) {
return statusMap[val]
}
}
}
......@@ -52,4 +83,48 @@ export default {
}
}
}
.order-item{
background:#fff;
position:relative;
box-sizing:border-box;
padding:4vw 0 4vw 30vw;
height:36vw;
margin-top:15px;
border-radius:3px;
.thumb{
width:26vw;
height:26vw;
position:absolute;
left:0;
top:5vw;
img{
width:80%;
display:block;
margin:10% auto;
}
}
.content{
display:flex;
flex-direction:column;
height:100%;
padding-right:10px;
.status-row{
line-height:0.48rem;
color:#C01540;
text-align:right;
}
.title-row{
line-height:30px;
flex:1;
display:flex;
.price{
font-size:13px;
}
.title{
font-size:14px;
flex:1;
}
}
}
}
</style>
\ No newline at end of file
......@@ -6,6 +6,12 @@ export default [
name: 'Index',
component: () => import('../pages/home/index.vue')
},
/* 店铺 */
{
path: '/shop',
name: 'Shop',
component: () => import('../pages/home/index.vue')
},
/* 商品购买页 */
{
path: '/buy',
......
......@@ -35,9 +35,9 @@ httpRequest.interceptors.response.use(
function(response) {
const { data } = response
if (data.code) {
if (![1010, 1001].includes(data.code)) {
Toast.fail(data.msg || data.message)
}
// if (![1010, 1001].includes(data.code)) {
// Toast.fail(data.msg || data.message)
// }
return Promise.reject(data)
}
return data
......
import store from '@/store'
export default class Before {
constructor(opt) {
this.opt = opt || {}
}
async update(to, from, next) {
const isLogin = store.state.isLogin || (await store.dispatch('checkLogin'))
if (!isLogin) {
// window.location.href = `${webConf.others.loginUrl}?rd=${encodeURIComponent(window.location.href)}`
next()
}
next()
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论