50 changed files with 0 additions and 10178 deletions
@ -1,11 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'article.category/list' |
|
||||
} |
|
||||
|
|
||||
// 页面数据
|
|
||||
export function list() { |
|
||||
return request.get(api.list) |
|
||||
} |
|
||||
@ -1,17 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'article/list', |
|
||||
detail: 'article/detail' |
|
||||
} |
|
||||
|
|
||||
// 文章列表
|
|
||||
export function list(param, option) { |
|
||||
return request.get(api.list, param, option) |
|
||||
} |
|
||||
|
|
||||
// 文章详情
|
|
||||
export function detail(articleId) { |
|
||||
return request.get(api.detail, { articleId }) |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'balance.log/list' |
|
||||
} |
|
||||
|
|
||||
// 余额账单明细
|
|
||||
export const list = (param) => { |
|
||||
return request.get(api.list, param) |
|
||||
} |
|
||||
@ -1,35 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'cart/list', |
|
||||
total: 'cart/total', |
|
||||
add: 'cart/add', |
|
||||
update: 'cart/update', |
|
||||
clear: 'cart/clear' |
|
||||
} |
|
||||
|
|
||||
// 购物车列表
|
|
||||
export const list = () => { |
|
||||
return request.get(api.list, {}, { load: false }) |
|
||||
} |
|
||||
|
|
||||
// 购物车商品总数量
|
|
||||
export const total = () => { |
|
||||
return request.get(api.total, {}, { load: false }) |
|
||||
} |
|
||||
|
|
||||
// 加入购物车
|
|
||||
export const add = (goodsId, goodsSkuId, goodsNum) => { |
|
||||
return request.post(api.add, { goodsId, goodsSkuId, goodsNum }) |
|
||||
} |
|
||||
|
|
||||
// 更新购物车商品数量
|
|
||||
export const update = (goodsId, goodsSkuId, goodsNum) => { |
|
||||
return request.post(api.update, { goodsId, goodsSkuId, goodsNum }, { isPrompt: false }) |
|
||||
} |
|
||||
|
|
||||
// 删除购物车中指定记录
|
|
||||
export const clear = (cartIds = []) => { |
|
||||
return request.post(api.clear, { cartIds }) |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'category/list' |
|
||||
} |
|
||||
|
|
||||
// 页面数据
|
|
||||
export function list() { |
|
||||
return request.get(api.list) |
|
||||
} |
|
||||
@ -1,19 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
order: 'checkout/order', |
|
||||
submit: 'checkout/submit', |
|
||||
} |
|
||||
|
|
||||
// mode: 结算模式 (buyNow立即购买 cart购物车)
|
|
||||
|
|
||||
// 结算台订单信息
|
|
||||
export const order = (mode, param) => { |
|
||||
return request.get(api.order, { mode, ...param }) |
|
||||
} |
|
||||
|
|
||||
// 结算台订单提交
|
|
||||
export const submit = (mode, data) => { |
|
||||
return request.post(api.submit, { mode, ...data }) |
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'comment/list', |
|
||||
listRows: 'comment/listRows', |
|
||||
total: 'comment/total' |
|
||||
} |
|
||||
|
|
||||
// 商品评价列表
|
|
||||
export const list = (goodsId, param, option) => { |
|
||||
return request.get(api.list, { ...param, goodsId }, option) |
|
||||
} |
|
||||
|
|
||||
// 商品评价列表 (限制数量, 用于商品详情页展示)
|
|
||||
export const listRows = (goodsId, limit = 5) => { |
|
||||
return request.get(api.listRows, { goodsId, limit }) |
|
||||
} |
|
||||
|
|
||||
// 商品评分总数
|
|
||||
export const total = (goodsId) => { |
|
||||
return request.get(api.total, { goodsId }) |
|
||||
} |
|
||||
@ -1,16 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'coupon/list' |
|
||||
} |
|
||||
|
|
||||
// 优惠券列表
|
|
||||
export const list = (param, option) => { |
|
||||
const options = { |
|
||||
isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示)
|
|
||||
load: true, //(默认 true 说明:本接口是否提示加载动画)
|
|
||||
...option |
|
||||
} |
|
||||
return request.get(api.list, param, options) |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'express/list' |
|
||||
} |
|
||||
|
|
||||
// 物流公司列表
|
|
||||
export const list = (param) => { |
|
||||
return request.get(api.list, param) |
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'goods/list', |
|
||||
detail: 'goods/detail', |
|
||||
specData: 'goods/specData' |
|
||||
} |
|
||||
|
|
||||
// 商品列表
|
|
||||
export const list = param => { |
|
||||
return request.get(api.list, param) |
|
||||
} |
|
||||
|
|
||||
// 商品详情
|
|
||||
export const detail = goodsId => { |
|
||||
return request.get(api.detail, { goodsId }) |
|
||||
} |
|
||||
|
|
||||
// 获取商品规格数据
|
|
||||
export const specData = (goodsId) => { |
|
||||
return request.get(api.specData, { goodsId }) |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'goods.service/list' |
|
||||
} |
|
||||
|
|
||||
// 商品评价列表
|
|
||||
export function list(goodsId) { |
|
||||
return request.get(api.list, { goodsId }) |
|
||||
} |
|
||||
@ -1,22 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'myCoupon/list', |
|
||||
receive: 'myCoupon/receive' |
|
||||
} |
|
||||
|
|
||||
// 我的优惠券列表
|
|
||||
export const list = (param, option) => { |
|
||||
const options = { |
|
||||
isPrompt: true, //(默认 true 说明:本接口抛出的错误是否提示)
|
|
||||
load: true, //(默认 true 说明:本接口是否提示加载动画)
|
|
||||
...option |
|
||||
} |
|
||||
return request.get(api.list, param, options) |
|
||||
} |
|
||||
|
|
||||
// 领取优惠券
|
|
||||
export const receive = (couponId, data) => { |
|
||||
return request.post(api.receive, { couponId, ...couponId, data }) |
|
||||
} |
|
||||
@ -1,47 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
todoCounts: 'order/todoCounts', |
|
||||
list: 'order/list', |
|
||||
detail: 'order/detail', |
|
||||
express: 'order/express', |
|
||||
cancel: 'order/cancel', |
|
||||
receipt: 'order/receipt', |
|
||||
pay: 'order/pay' |
|
||||
} |
|
||||
|
|
||||
// 当前用户待处理的订单数量
|
|
||||
export function todoCounts(param, option) { |
|
||||
return request.get(api.todoCounts, param, option) |
|
||||
} |
|
||||
|
|
||||
// 我的订单列表
|
|
||||
export function list(param, option) { |
|
||||
return request.get(api.list, param, option) |
|
||||
} |
|
||||
|
|
||||
// 订单详情
|
|
||||
export function detail(orderId, param) { |
|
||||
return request.get(api.detail, { orderId, ...param }) |
|
||||
} |
|
||||
|
|
||||
// 获取物流信息
|
|
||||
export function express(orderId, param) { |
|
||||
return request.get(api.express, { orderId, ...param }) |
|
||||
} |
|
||||
|
|
||||
// 取消订单
|
|
||||
export function cancel(orderId, data) { |
|
||||
return request.post(api.cancel, { orderId, ...data }) |
|
||||
} |
|
||||
|
|
||||
// 确认收货
|
|
||||
export function receipt(orderId, data) { |
|
||||
return request.post(api.receipt, { orderId, ...data }) |
|
||||
} |
|
||||
|
|
||||
// 立即支付
|
|
||||
export function pay(orderId, payType, param) { |
|
||||
return request.get(api.pay, { orderId, payType, ...param }) |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'recharge.order/list' |
|
||||
} |
|
||||
|
|
||||
// 我的充值记录列表
|
|
||||
export const list = (param) => { |
|
||||
return request.get(api.list, param) |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'recharge.plan/list' |
|
||||
} |
|
||||
|
|
||||
// 充值套餐列表
|
|
||||
export const list = (param) => { |
|
||||
return request.get(api.list, param) |
|
||||
} |
|
||||
@ -1,35 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
list: 'refund/list', |
|
||||
goods: 'refund/goods', |
|
||||
apply: 'refund/apply', |
|
||||
detail: 'refund/detail', |
|
||||
delivery: 'refund/delivery' |
|
||||
} |
|
||||
|
|
||||
// 售后单列表
|
|
||||
export const list = (param, option) => { |
|
||||
return request.get(api.list, param, option) |
|
||||
} |
|
||||
|
|
||||
// 订单商品详情
|
|
||||
export const goods = (orderGoodsId, param) => { |
|
||||
return request.get(api.goods, { orderGoodsId, ...param }) |
|
||||
} |
|
||||
|
|
||||
// 申请售后
|
|
||||
export const apply = (orderGoodsId, data) => { |
|
||||
return request.post(api.apply, { orderGoodsId, form: data }) |
|
||||
} |
|
||||
|
|
||||
// 售后单详情
|
|
||||
export const detail = (orderRefundId, param) => { |
|
||||
return request.get(api.detail, { orderRefundId, ...param }) |
|
||||
} |
|
||||
|
|
||||
// 用户发货
|
|
||||
export const delivery = (orderRefundId, data) => { |
|
||||
return request.post(api.delivery, { orderRefundId, form: data }) |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
import request from '@/utils/request' |
|
||||
|
|
||||
// api地址
|
|
||||
const api = { |
|
||||
image: 'upload/image' |
|
||||
} |
|
||||
|
|
||||
// 图片上传
|
|
||||
export const image = files => { |
|
||||
// 文件上传大小, 2M
|
|
||||
const maxSize = 1024 * 1024 * 2 |
|
||||
// 执行上传
|
|
||||
return new Promise((resolve, reject) => { |
|
||||
request.urlFileUpload({ files, maxSize }) |
|
||||
.then(result => resolve(result.map(item => item.data.fileInfo.file_id), result)) |
|
||||
.catch(reject) |
|
||||
}) |
|
||||
} |
|
||||
@ -1,331 +0,0 @@ |
|||||
<template> |
|
||||
<!-- 打卡日历页面 --> |
|
||||
<view class='all'> |
|
||||
<view class="bar"> |
|
||||
<!-- 上一个月 --> |
|
||||
<view class="previous" @click="handleCalendar(0)"> |
|
||||
<button class="barbtn">上一月</button> |
|
||||
</view> |
|
||||
<!-- 显示年月 --> |
|
||||
<view class="date">{{cur_year || "--"}} 年 {{cur_month || "--"}} 月</view> |
|
||||
<!-- 下一个月 --> |
|
||||
<view class="next" @click="handleCalendar(1)"> |
|
||||
<button class="barbtn">下一月</button> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 显示星期 --> |
|
||||
<view class="week"> |
|
||||
<view class="week_ri" v-for="(item,index) in weeks_ch" :key="index">{{item}}</view> |
|
||||
</view> |
|
||||
<view class="myDateTable"> |
|
||||
<view v-for="(item,j) in days" :key="j" class='dateCell'> |
|
||||
<view v-if="item.date==undefined || item.date == null" class='cell'> |
|
||||
<text :decode="true"> </text> |
|
||||
</view> |
|
||||
<view v-else @click="clickSignUp(item.date)"> |
|
||||
<!-- 已订餐到日期 --> |
|
||||
<view v-if="item.isSign == 5" class='cell yellow' style="background: #0000a8;color: #ffffff;"> |
|
||||
<text>{{item.date}}</text> |
|
||||
</view> |
|
||||
<view class="cell white bg-red" style="background: #0000e7;color: #ffffff;" v-else-if="item.isSign == 2"> |
|
||||
<text>{{item.date}}</text> |
|
||||
</view> |
|
||||
<!-- 点击的日期 --> |
|
||||
<view class="cell white bg-red" style="background: #ffaa7f;color: #ffffff;" v-else-if="item.isSign == 3"> |
|
||||
<text>{{item.date}}</text> |
|
||||
</view> |
|
||||
<!-- 今天的日期 --> |
|
||||
<view v-else-if="item.date == today" class='cell yellow curday' style="color: #fa2299;">{{item.date}}</view> |
|
||||
<!-- 当前日期之后 --> |
|
||||
<view class="whiteColor cell" v-else> |
|
||||
<text>{{item.date}}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 活动列表 --> |
|
||||
<view class="actlist"> |
|
||||
<view class="act-item"> |
|
||||
<view class="act-title">五月端午,邀你去踏青</view> |
|
||||
<view class="act-desc">端午时节,踏青开始</view> |
|
||||
</view> |
|
||||
|
|
||||
<view class="act-item"> |
|
||||
<view class="act-title">五月端午,邀你去踏青</view> |
|
||||
<view class="act-desc">端午时节,踏青开始</view> |
|
||||
</view> |
|
||||
|
|
||||
<view class="act-item"> |
|
||||
<view class="act-title">五月端午,邀你去踏青</view> |
|
||||
<view class="act-desc">端午时节,踏青开始</view> |
|
||||
</view> |
|
||||
|
|
||||
|
|
||||
|
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
|
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
days: [],//日历 |
|
||||
SignUp: [{'type':1,t:1},{'type':2,t:10}],//已经订餐 |
|
||||
cur_year: 0, //当前选的年 |
|
||||
cur_month: 0, //当前选的月 |
|
||||
today: parseInt(new Date().getDate()), //今天 |
|
||||
toMonth: parseInt(new Date().getMonth() + 1), //本月 |
|
||||
toYear: parseInt(new Date().getFullYear()), //本年 |
|
||||
weeks_ch: ['日', '一', '二', '三', '四', '五', '六'], |
|
||||
}; |
|
||||
}, |
|
||||
props: { |
|
||||
//年 |
|
||||
sendYear: { |
|
||||
type: Number, |
|
||||
default: new Date().getFullYear() |
|
||||
}, |
|
||||
//月 |
|
||||
sendMonth: { |
|
||||
type: Number, |
|
||||
default: new Date().getMonth() + 1 |
|
||||
}, |
|
||||
}, |
|
||||
created() { |
|
||||
this.cur_year = this.sendYear;//年 |
|
||||
this.cur_month = this.sendMonth;//月 |
|
||||
this.calculateEmptyGrids(this.cur_year, this.cur_month); |
|
||||
this.calculateDays(this.cur_year, this.cur_month); |
|
||||
//网络请求 |
|
||||
this.onJudgeSign(this.SignUp); |
|
||||
}, |
|
||||
methods: { |
|
||||
// 获取当月共多少天 |
|
||||
getThisMonthDays(year, month) { |
|
||||
return new Date(year, month, 0).getDate() |
|
||||
}, |
|
||||
// 获取当月第一天星期几 |
|
||||
getFirstDayOfWeek(year, month) { |
|
||||
return new Date(Date.UTC(year, month - 1, 1)).getDay(); |
|
||||
}, |
|
||||
// 计算当月1号前空了几个格子,把它填充在days数组的前面 |
|
||||
calculateEmptyGrids(year, month) { |
|
||||
//计算每个月时要清零 |
|
||||
this.days = []; |
|
||||
const firstDayOfWeek = this.getFirstDayOfWeek(year, month); |
|
||||
if (firstDayOfWeek > 0) { |
|
||||
for (let i = 0; i < firstDayOfWeek; i++) { |
|
||||
var obj = { |
|
||||
date: null, |
|
||||
isSign: false |
|
||||
} |
|
||||
this.days.push(obj); |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
// 绘制当月天数占的格子,并把它放到days数组中 |
|
||||
calculateDays(year, month) { |
|
||||
const thisMonthDays = this.getThisMonthDays(year, month); |
|
||||
for (let i = 1; i <= thisMonthDays; i++) { |
|
||||
var obj = { |
|
||||
date: i, |
|
||||
isSign: false |
|
||||
} |
|
||||
this.days.push(obj); |
|
||||
} |
|
||||
//console.log(this.days); |
|
||||
}, |
|
||||
//匹配判断当月与当月哪些日子订餐 |
|
||||
onJudgeSign(date) { |
|
||||
var signs = date; |
|
||||
var daysArr = this.days; |
|
||||
//日期相同,订过餐 |
|
||||
for(var i=0;i<signs.length;i++){ |
|
||||
for (var j=0; j<daysArr.length;j++) { |
|
||||
if (daysArr[j].date == signs[i]['t']) { |
|
||||
if(signs[i]['type'] == 1){ |
|
||||
daysArr[j].isSign = 2;//订一餐 |
|
||||
}else{ |
|
||||
daysArr[j].isSign = 5;//订两餐 |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
this.days = daysArr; |
|
||||
}, |
|
||||
// 切换控制年月,上一个月,下一个月 |
|
||||
handleCalendar(type) { |
|
||||
const cur_year = parseInt(this.cur_year); |
|
||||
const cur_month = parseInt(this.cur_month); |
|
||||
var newMonth; |
|
||||
var newYear = cur_year; |
|
||||
if (type === 0) { //上个月 |
|
||||
newMonth = cur_month - 1; |
|
||||
if (newMonth < 1) { |
|
||||
newYear = cur_year - 1; |
|
||||
newMonth = 12; |
|
||||
} |
|
||||
} else { |
|
||||
newMonth = cur_month + 1; |
|
||||
if (newMonth > 12) { |
|
||||
newYear = cur_year + 1; |
|
||||
newMonth = 1; |
|
||||
} |
|
||||
} |
|
||||
this.calculateEmptyGrids(newYear, newMonth); |
|
||||
this.calculateDays(newYear, newMonth); |
|
||||
|
|
||||
//网络请求 |
|
||||
this.SignUp =[{'type':1,t:3},{'type':2,t:11}],//已经订餐 |
|
||||
this.onJudgeSign(this.SignUp); |
|
||||
|
|
||||
this.cur_year = newYear; |
|
||||
this.cur_month = newMonth; |
|
||||
|
|
||||
// this.SignUp = []; //清空 |
|
||||
this.$emit('dateChange',this.cur_year+"-"+this.cur_month); //传给调用模板页面去拿新数据 |
|
||||
}, |
|
||||
//点击日期 |
|
||||
clickSignUp(t){ |
|
||||
// console.log(this.cur_year)//年 |
|
||||
// console.log(this.cur_month)//月 |
|
||||
var t = t;//点击的天 |
|
||||
|
|
||||
var signs = this.SignUp; |
|
||||
|
|
||||
var daysArr = this.days; |
|
||||
//日期相同,订过餐,点击的日期 |
|
||||
for(var i=0;i<signs.length;i++){ |
|
||||
for (var j=0; j<daysArr.length;j++) { |
|
||||
if (daysArr[j].date == signs[i]['t']) { |
|
||||
if(signs[i]['type'] == 1){ |
|
||||
daysArr[j].isSign = 2;//订一餐 |
|
||||
}else{ |
|
||||
daysArr[j].isSign = 5;//订两餐 |
|
||||
} |
|
||||
} |
|
||||
if(t == daysArr[j].date){ |
|
||||
daysArr[j].isSign = 3 |
|
||||
} |
|
||||
if(daysArr[j].isSign != 2 && t != daysArr[j].date && daysArr[j].isSign != 5){ |
|
||||
daysArr[j].isSign = 1; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
this.days = daysArr; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="less" scoped> |
|
||||
|
|
||||
.all .bar { |
|
||||
display: flex; |
|
||||
flex-direction: row; |
|
||||
justify-content: space-between; |
|
||||
padding: 10rpx; |
|
||||
} |
|
||||
|
|
||||
.bar .barbtn { |
|
||||
height: 30px; |
|
||||
line-height: 30px; |
|
||||
font-size: 12px; |
|
||||
} |
|
||||
/* 星期 */ |
|
||||
.all .week { |
|
||||
display: flex; |
|
||||
/* flex-direction: row; */ |
|
||||
/* justify-content: space-between; */ |
|
||||
padding: 20rpx; |
|
||||
border-radius: 10px; |
|
||||
background-color: #fff; |
|
||||
width: 90%; |
|
||||
margin-left: 2%; |
|
||||
} |
|
||||
.week_ri{ |
|
||||
margin-left: 19rpx; |
|
||||
padding: 0 48rpx 0 0; |
|
||||
} |
|
||||
.myDateTable { |
|
||||
margin: 2.5vw; |
|
||||
border-radius: 10px; |
|
||||
background: #fff; |
|
||||
} |
|
||||
.myDateTable .dateCell { |
|
||||
width: 11vw; |
|
||||
padding: 1vw; |
|
||||
display: inline-block; |
|
||||
text-align: center; |
|
||||
font-size: 16px; |
|
||||
} |
|
||||
|
|
||||
.dateCell .cell { |
|
||||
display: flex; |
|
||||
border-radius: 50%; |
|
||||
height: 9vw; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.greenColor { |
|
||||
color: #01b90b; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
|
|
||||
.bgWhite { |
|
||||
background-color: #fff; |
|
||||
} |
|
||||
|
|
||||
.bgGray { |
|
||||
background-color: rgba(255, 255, 255, 0.42); |
|
||||
} |
|
||||
|
|
||||
.bgBlue { |
|
||||
font-size: 14px; |
|
||||
background-color: #4b95e6; |
|
||||
} |
|
||||
|
|
||||
.redColor { |
|
||||
color: #ff0000; |
|
||||
} |
|
||||
.curday{ |
|
||||
color: #fa2209; |
|
||||
font-size: 36rpx; |
|
||||
font-weight: 600; |
|
||||
} |
|
||||
|
|
||||
.TipArea{ |
|
||||
word-break:break-all; |
|
||||
word-wrap:break-word; |
|
||||
|
|
||||
font-size: 14px; |
|
||||
padding: 10px; |
|
||||
} |
|
||||
.impTip{ |
|
||||
display: inline-block; |
|
||||
color: #ff0000; |
|
||||
} |
|
||||
|
|
||||
.actlist{ |
|
||||
padding: 10rpx; |
|
||||
|
|
||||
.act-item{ |
|
||||
padding:20rpx; |
|
||||
color: #333; |
|
||||
border-bottom: #ccc 1px solid; |
|
||||
margin-top: 20rpx; |
|
||||
background: #fff; |
|
||||
|
|
||||
.act-title{ |
|
||||
font-size: 36rpx; |
|
||||
line-height: 1.8; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,500 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<!-- 页面顶部 --> |
|
||||
<view v-if="list.length" class="head-info"> |
|
||||
<view class="cart-total"> |
|
||||
<text>共</text> |
|
||||
<text class="active">{{ total }}</text> |
|
||||
<text>件商品</text> |
|
||||
</view> |
|
||||
<view class="cart-edit" @click="handleToggleMode"> |
|
||||
<view v-if="mode == 'normal'" class="normal"> |
|
||||
<text class="icon iconfont icon-bianji"></text> |
|
||||
<text>编辑</text> |
|
||||
</view> |
|
||||
<view v-if="mode == 'edit'" class="edit"> |
|
||||
<text>完成</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 购物车商品列表 --> |
|
||||
<view v-if="list.length" class="cart-list"> |
|
||||
<view class="cart-item" v-for="(item, index) in list" :key="index"> |
|
||||
<label class="item-radio" @click.stop="handleCheckItem(item.id)"> |
|
||||
<radio class="radio" color="#fa2209" :checked="inArray(item.id, checkedIds)" /> |
|
||||
</label> |
|
||||
<view class="goods-image" @click="onTargetGoods(item.goods_id)"> |
|
||||
<image class="image" :src="item.goods.goods_image" mode="scaleToFill"></image> |
|
||||
</view> |
|
||||
<view class="item-content"> |
|
||||
<view class="goods-title" @click="onTargetGoods(item.goods_id)"> |
|
||||
<text class="twoline-hide">{{ item.goods.goods_name }}</text> |
|
||||
</view> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in item.goods.skuInfo.goods_props" :key="idx"> |
|
||||
<text>{{ props.value.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="item-foot"> |
|
||||
<view class="goods-price"> |
|
||||
<text class="unit">¥</text> |
|
||||
<text class="value">{{ item.goods.skuInfo.goods_price }}</text> |
|
||||
</view> |
|
||||
<view class="stepper"> |
|
||||
<u-number-box :min="1" :value="item.goods_num" :step="1" @change="onChangeStepper($event, item)" /> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 购物车数据为空 --> |
|
||||
<empty v-if="!list.length" :isLoading="isLoading" :custom-style="{ padding: '180rpx 50rpx' }" tips="您的购物车是空的, 快去逛逛吧"> |
|
||||
<view slot="slot" class="empty-ipt" @click="onTargetIndex"> |
|
||||
<text>去逛逛</text> |
|
||||
</view> |
|
||||
</empty> |
|
||||
<!-- 底部操作栏 --> |
|
||||
<view v-if="list.length" class="footer-fixed"> |
|
||||
<label class="all-radio" @click="handleCheckAll"> |
|
||||
<radio class="radio" color="#fa2209" :checked="checkedIds.length > 0 && checkedIds.length === list.length" /> |
|
||||
<text>全选</text> |
|
||||
</label> |
|
||||
<view class="total-info"> |
|
||||
<text>合计:</text> |
|
||||
<view class="goods-price"> |
|
||||
<text class="unit">¥</text> |
|
||||
<text class="value">{{ totalPrice }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="cart-action"> |
|
||||
<view class="btn-wrapper"> |
|
||||
<!-- dev:下面的disabled条件使用checkedIds.join方式判断 --> |
|
||||
<!-- dev:通常情况下vue项目使用checkedIds.length更合理, 但是length属性在微信小程序中不起作用 --> |
|
||||
<view v-if="mode == 'normal'" class="btn-item btn-main" :class="{ disabled: checkedIds.join() == '' }" @click="handleOrder()"> |
|
||||
<text>去结算 {{ checkedIds.length > 0 ? `(${checkedIds.length})` : '' }}</text> |
|
||||
</view> |
|
||||
<view v-if="mode == 'edit'" class="btn-item btn-main" :class="{ disabled: !checkedIds.length }" @click="handleDelete()"> |
|
||||
<text>删除</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { inArray, arrayIntersect, debounce } from '@/utils/util' |
|
||||
import { checkLogin, setCartTotalNum, setCartTabBadge } from '@/core/app' |
|
||||
import * as CartApi from '@/api/cart' |
|
||||
import Empty from '@/components/empty' |
|
||||
|
|
||||
const CartIdsIndex = 'CartIds' |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
Empty |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
inArray, |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 当前模式: normal正常 edit编辑 |
|
||||
mode: 'normal', |
|
||||
// 购物车商品列表 |
|
||||
list: [], |
|
||||
// 购物车商品总数量 |
|
||||
total: null, |
|
||||
// 选中的商品ID记录 |
|
||||
checkedIds: [], |
|
||||
// 选中的商品总金额 |
|
||||
totalPrice: '0.00' |
|
||||
} |
|
||||
}, |
|
||||
watch: { |
|
||||
// 监听选中的商品 |
|
||||
checkedIds: { |
|
||||
handler(val) { |
|
||||
// 计算合计金额 |
|
||||
this.onCalcTotalPrice() |
|
||||
// 记录到缓存中 |
|
||||
uni.setStorageSync(CartIdsIndex, val) |
|
||||
}, |
|
||||
immediate: false |
|
||||
}, |
|
||||
// 监听购物车商品总数量 |
|
||||
total(val) { |
|
||||
// 缓存并设置角标 |
|
||||
setCartTotalNum(val) |
|
||||
setCartTabBadge() |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面显示 |
|
||||
*/ |
|
||||
onShow(options) { |
|
||||
// 获取购物车商品列表 |
|
||||
checkLogin() ? this.getCartList() : this.isLoading = false |
|
||||
// 获取缓存中的选中记录 |
|
||||
this.checkedIds = uni.getStorageSync(CartIdsIndex) |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 计算合计金额 (根据选中的商品) |
|
||||
onCalcTotalPrice() { |
|
||||
const app = this |
|
||||
// 选中的商品记录 |
|
||||
const checkedList = app.list.filter(item => inArray(item.id, app.checkedIds)) |
|
||||
// 计算总金额 |
|
||||
let tempPrice = 0; |
|
||||
checkedList.forEach(item => { |
|
||||
// 商品单价, 为了方便计算先转换单位为分 (整数) |
|
||||
const unitPrice = item.goods.skuInfo.goods_price * 100 |
|
||||
tempPrice += unitPrice * item.goods_num |
|
||||
}) |
|
||||
app.totalPrice = (tempPrice / 100).toFixed(2) |
|
||||
}, |
|
||||
|
|
||||
// 获取购物车商品列表 |
|
||||
getCartList() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
CartApi.list() |
|
||||
.then(result => { |
|
||||
app.list = result.data.list |
|
||||
app.total = result.data.cartTotal |
|
||||
// 清除checkedIds中无效的ID |
|
||||
app.onClearInvalidId() |
|
||||
}) |
|
||||
.finally(() => app.isLoading = false) |
|
||||
}, |
|
||||
|
|
||||
// 清除checkedIds中无效的ID |
|
||||
onClearInvalidId() { |
|
||||
const app = this |
|
||||
const listIds = app.list.map(item => item.id) |
|
||||
app.checkedIds = arrayIntersect(listIds, app.checkedIds) |
|
||||
}, |
|
||||
|
|
||||
// 切换当前模式 |
|
||||
handleToggleMode() { |
|
||||
this.mode = this.mode == 'normal' ? 'edit' : 'normal' |
|
||||
}, |
|
||||
|
|
||||
// 监听步进器更改事件 |
|
||||
onChangeStepper({ value }, item) { |
|
||||
// 这里是组织首次启动时的执行 |
|
||||
if (item.goods_num == value) return |
|
||||
// 记录一个节流函数句柄 |
|
||||
if (!item.debounceHandle) { |
|
||||
item.oldValue = item.goods_num |
|
||||
item.debounceHandle = debounce(this.onUpdateCartNum, 500) |
|
||||
} |
|
||||
// 更新商品数量 |
|
||||
item.goods_num = value |
|
||||
// 提交更新购物车数量 (节流) |
|
||||
item.debounceHandle(item, item.oldValue, value) |
|
||||
}, |
|
||||
|
|
||||
// 提交更新购物车数量 |
|
||||
onUpdateCartNum(item, oldValue, newValue) { |
|
||||
const app = this |
|
||||
CartApi.update(item.goods_id, item.goods_sku_id, newValue) |
|
||||
.then(result => { |
|
||||
// 更新商品数量 |
|
||||
app.total = result.data.cartTotal |
|
||||
// 重新计算合计金额 |
|
||||
app.onCalcTotalPrice() |
|
||||
// 清除节流函数句柄 |
|
||||
item.debounceHandle = null |
|
||||
}) |
|
||||
.catch(err => { |
|
||||
// 还原商品数量 |
|
||||
item.goods_num = oldValue |
|
||||
setTimeout(() => app.$toast(err.errMsg), 10) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 跳转到商品详情页 |
|
||||
onTargetGoods(goodsId) { |
|
||||
this.$navTo('pages/goods/detail', { goodsId }) |
|
||||
}, |
|
||||
|
|
||||
// 点击去逛逛按钮, 跳转到首页 |
|
||||
onTargetIndex() { |
|
||||
this.$navTo('pages/index/index') |
|
||||
}, |
|
||||
|
|
||||
// 选中商品 |
|
||||
handleCheckItem(cartId) { |
|
||||
const { checkedIds } = this |
|
||||
const index = checkedIds.findIndex(id => id === cartId) |
|
||||
index < 0 ? checkedIds.push(cartId) : checkedIds.splice(index, 1) |
|
||||
}, |
|
||||
|
|
||||
// 全选事件 |
|
||||
handleCheckAll() { |
|
||||
const { checkedIds, list } = this |
|
||||
this.checkedIds = checkedIds.length === list.length ? [] : list.map(item => item.id) |
|
||||
}, |
|
||||
|
|
||||
// 结算选中的商品 |
|
||||
handleOrder() { |
|
||||
const app = this |
|
||||
if (app.checkedIds.length) { |
|
||||
const cartIds = app.checkedIds.join() |
|
||||
app.$navTo('pages/checkout/index', { mode: 'cart', cartIds }) |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 删除选中的商品弹窗事件 |
|
||||
handleDelete() { |
|
||||
const app = this |
|
||||
if (!app.checkedIds.length) { |
|
||||
return false |
|
||||
} |
|
||||
uni.showModal({ |
|
||||
title: '友情提示', |
|
||||
content: '您确定要删除该商品吗?', |
|
||||
showCancel: true, |
|
||||
success({ confirm }) { |
|
||||
// 确认删除 |
|
||||
confirm && app.onClearCart() |
|
||||
} |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 确认删除商品 |
|
||||
onClearCart() { |
|
||||
const app = this |
|
||||
CartApi.clear(app.checkedIds) |
|
||||
.then(result => { |
|
||||
app.getCartList() |
|
||||
app.handleToggleMode() |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style> |
|
||||
page { |
|
||||
background: #f5f5f5; |
|
||||
} |
|
||||
</style> |
|
||||
<style lang="scss" scoped> |
|
||||
// 页面顶部 |
|
||||
.head-info { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
padding: 4rpx 30rpx; |
|
||||
// background-color: #fff; |
|
||||
height: 80rpx; |
|
||||
|
|
||||
.cart-total { |
|
||||
font-size: 28rpx; |
|
||||
color: #333; |
|
||||
|
|
||||
.active { |
|
||||
color: #FA2209; |
|
||||
margin: 0 2rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.cart-edit { |
|
||||
padding-left: 20rpx; |
|
||||
|
|
||||
.icon { |
|
||||
margin-right: 12rpx; |
|
||||
} |
|
||||
|
|
||||
.edit { |
|
||||
color: #fa2209; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 购物车列表 |
|
||||
.cart-list { |
|
||||
padding: 0 16rpx 110rpx 16rpx; |
|
||||
} |
|
||||
|
|
||||
.cart-item { |
|
||||
background: #fff; |
|
||||
border-radius: 12rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
padding: 30rpx 16rpx; |
|
||||
margin-bottom: 24rpx; |
|
||||
|
|
||||
|
|
||||
.item-radio { |
|
||||
width: 56rpx; |
|
||||
height: 80rpx; |
|
||||
line-height: 80rpx; |
|
||||
margin-right: 10rpx; |
|
||||
text-align: center; |
|
||||
|
|
||||
.radio { |
|
||||
transform: scale(0.76) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-image { |
|
||||
width: 200rpx; |
|
||||
height: 200rpx; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
border-radius: 8rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.item-content { |
|
||||
flex: 1; |
|
||||
padding-left: 24rpx; |
|
||||
|
|
||||
.goods-title { |
|
||||
font-size: 28rpx; |
|
||||
max-height: 76rpx; |
|
||||
} |
|
||||
|
|
||||
.goods-props { |
|
||||
margin-top: 14rpx; |
|
||||
height: 40rpx; |
|
||||
color: #ababab; |
|
||||
font-size: 24rpx; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
display: inline-block; |
|
||||
margin-right: 14rpx; |
|
||||
padding: 4rpx 16rpx; |
|
||||
border-radius: 12rpx; |
|
||||
background-color: #F5F5F5; |
|
||||
width: auto; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.item-foot { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
margin-top: 20rpx; |
|
||||
|
|
||||
.goods-price { |
|
||||
vertical-align: bottom; |
|
||||
color: $uni-text-color-active; |
|
||||
|
|
||||
.unit { |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
|
|
||||
.value { |
|
||||
font-size: 32rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 空数据按钮 |
|
||||
.empty-ipt { |
|
||||
width: 220rpx; |
|
||||
margin: 0 auto; |
|
||||
font-size: 32rpx; |
|
||||
height: 64rpx; |
|
||||
line-height: 64rpx; |
|
||||
text-align: center; |
|
||||
color: #fff; |
|
||||
border-radius: 50rpx; |
|
||||
background: linear-gradient(to right, #f9211c, #ff6335); |
|
||||
} |
|
||||
|
|
||||
// 底部操作栏 |
|
||||
.footer-fixed { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
height: 96rpx; |
|
||||
background: #fff; |
|
||||
padding: 0 30rpx; |
|
||||
position: fixed; |
|
||||
bottom: var(--window-bottom); |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
z-index: 11; |
|
||||
|
|
||||
.all-radio { |
|
||||
width: 140rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
|
|
||||
.radio { |
|
||||
margin-bottom: -4rpx; |
|
||||
transform: scale(0.76) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.total-info { |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: flex-end; |
|
||||
padding-right: 30rpx; |
|
||||
|
|
||||
.goods-price { |
|
||||
vertical-align: bottom; |
|
||||
color: #fa2209; |
|
||||
|
|
||||
.unit { |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
|
|
||||
.value { |
|
||||
font-size: 32rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.cart-action { |
|
||||
width: 200rpx; |
|
||||
|
|
||||
.btn-wrapper { |
|
||||
height: 100%; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.btn-item { |
|
||||
flex: 1; |
|
||||
font-size: 28rpx; |
|
||||
height: 72rpx; |
|
||||
line-height: 72rpx; |
|
||||
text-align: center; |
|
||||
color: #fff; |
|
||||
border-radius: 50rpx; |
|
||||
} |
|
||||
|
|
||||
// 立即购买按钮 |
|
||||
.btn-main { |
|
||||
background: linear-gradient(to right, #f9211c, #ff6335); |
|
||||
|
|
||||
// 禁用按钮 |
|
||||
&.disabled { |
|
||||
background: #ff9779; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</style> |
|
||||
@ -1,402 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<!-- 一级分类 --> |
|
||||
<scroll-view class="cate-left" :scroll-y="true" :style="{ height: `${scrollHeight}px` }" @touchmove.stop.prevent> |
|
||||
<text class="type-nav" :class="{ selected: curIndex == -1 }" @click="handleSelectNav(-1)">全部</text> |
|
||||
<text class="type-nav" :class="{ selected: curIndex == index }" v-for="(item, index) in list" :key="index" @click="handleSelectNav(index)">{{ item.name }}</text> |
|
||||
</scroll-view> |
|
||||
|
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption" :bottombar="false" @up="upCallback"> |
|
||||
|
|
||||
<view class="cate-content"> |
|
||||
|
|
||||
<!-- 子分类 --> |
|
||||
<view v-if="subCateList.length" class="sub-cate-list clearfix" :class="{ 'display-fold': !showSubCate }" @touchmove.stop.prevent> |
|
||||
<view class="nav-icon" @click="handleShowSubCate"> |
|
||||
<text class="iconfont" :class="[ showSubCate ? 'icon-arrow-up' : 'icon-arrow-down' ]"></text> |
|
||||
</view> |
|
||||
<view class="sub-cate-item" :class="{ selected: curIndex2 == -1 }" @click="handleSelectSubCate(-1)"> |
|
||||
<text>全部</text> |
|
||||
</view> |
|
||||
<view class="sub-cate-item" v-for="(item, index) in subCateList" :key="index" :class="{ selected: curIndex2 == index }" @click="handleSelectSubCate(index)"> |
|
||||
<text>{{ item.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商品列表 --> |
|
||||
<view class="goods-list"> |
|
||||
<view class="goods-item--container" v-for="(item, index) in goodsList.data" :key="index"> |
|
||||
<view class="goods-item" @click="onTargetGoods(item.goods_id)"> |
|
||||
<!-- 商品图片 --> |
|
||||
<view class="goods-item_left"> |
|
||||
<image class="image" :src="item.goods_image"></image> |
|
||||
</view> |
|
||||
<view class="goods-item_right"> |
|
||||
<!-- 商品标题 --> |
|
||||
<view class="goods-name"> |
|
||||
<text class="twoline-hide">{{ item.goods_name }}</text> |
|
||||
</view> |
|
||||
<!-- 商品信息 --> |
|
||||
<view class="goods-item_desc"> |
|
||||
<view class="desc_footer"> |
|
||||
<view class="item-prices oneline-hide"> |
|
||||
<text class="price_x">¥{{ item.goods_price_min }}</text> |
|
||||
<text v-if="item.line_price_min > 0" class="price_y">¥{{ item.line_price_min }}</text> |
|
||||
</view> |
|
||||
<add-cart-btn v-if="setting.showAddCart" :btnStyle="setting.cartStyle" @click="handleAddCart(item)" /> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 遮罩层 --> |
|
||||
<view class="mask" v-show="showSubCate" @touchmove.stop.prevent @click="handleShowSubCate"></view> |
|
||||
<!-- 加入购物车组件 --> |
|
||||
<AddCartPopup ref="AddCartPopup" @addCart="onUpdateCartTabBadge" /> |
|
||||
|
|
||||
</view> |
|
||||
</mescroll-body> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import { getEmptyPaginateObj, getMoreListData, setCartTabBadge } from '@/core/app' |
|
||||
import { PageCategoryStyleEnum } from '@/common/enum/store/page/category' |
|
||||
import Empty from '@/components/empty' |
|
||||
import AddCartBtn from '@/components/add-cart-btn' |
|
||||
import AddCartPopup from '@/components/add-cart-popup' |
|
||||
import { rpx2px } from '@/utils/util' |
|
||||
import * as GoodsApi from '@/api/goods' |
|
||||
|
|
||||
const pageSize = 15 |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody, |
|
||||
Empty, |
|
||||
AddCartBtn, |
|
||||
AddCartPopup |
|
||||
}, |
|
||||
mixins: [MescrollMixin], |
|
||||
props: { |
|
||||
// 分类列表 |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: [] |
|
||||
}, |
|
||||
// 分类设置 |
|
||||
setting: { |
|
||||
type: Object, |
|
||||
default: () => {} |
|
||||
}, |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
PageCategoryStyleEnum, |
|
||||
// 列表高度 |
|
||||
scrollHeight: 0, |
|
||||
// 一级分类:指针 |
|
||||
curIndex: -1, |
|
||||
// 是否显示子分类 |
|
||||
showSubCate: false, |
|
||||
// 二级分类:指针 |
|
||||
curIndex2: -1, |
|
||||
// 商品列表 |
|
||||
goodsList: getEmptyPaginateObj(), |
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于3条才显示无更多数据 |
|
||||
noMoreSize: 3, |
|
||||
// 返回顶部 |
|
||||
toTop: { right: 30, bottom: 48, zIndex: 9 } |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
created() { |
|
||||
// 设置分类列表高度 |
|
||||
this.setListHeight() |
|
||||
}, |
|
||||
computed: { |
|
||||
// 二级分类列表 |
|
||||
subCateList() { |
|
||||
if (this.list[this.curIndex] && this.list[this.curIndex].children) { |
|
||||
return this.list[this.curIndex].children |
|
||||
} |
|
||||
return [] |
|
||||
} |
|
||||
}, |
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getGoodsList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 获取商品列表 |
|
||||
* @param {Number} pageNo 页码 |
|
||||
*/ |
|
||||
getGoodsList(pageNo = 1) { |
|
||||
const app = this |
|
||||
const categoryId = app.getCategoryId() |
|
||||
return new Promise((resolve, reject) => { |
|
||||
GoodsApi.list({ categoryId, page: pageNo }, { load: false }) |
|
||||
.then(result => { |
|
||||
const newList = result.data.list |
|
||||
app.goodsList.data = getMoreListData(newList, app.goodsList, pageNo) |
|
||||
app.goodsList.last_page = newList.last_page |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
.catch(reject) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 获取当前选择的分类ID |
|
||||
getCategoryId() { |
|
||||
const app = this |
|
||||
if (app.curIndex2 > -1) { |
|
||||
return app.subCateList[app.curIndex2].category_id |
|
||||
} |
|
||||
return app.curIndex > -1 ? app.list[app.curIndex].category_id : 0 |
|
||||
}, |
|
||||
|
|
||||
// 设置列表内容的高度 |
|
||||
setListHeight() { |
|
||||
const { windowHeight } = uni.getSystemInfoSync() |
|
||||
this.scrollHeight = windowHeight - rpx2px(88) |
|
||||
}, |
|
||||
|
|
||||
// 一级分类:选中分类 |
|
||||
handleSelectNav(index) { |
|
||||
this.curIndex = index |
|
||||
this.onRefreshList() |
|
||||
this.showSubCate = false |
|
||||
this.curIndex2 = -1 |
|
||||
}, |
|
||||
|
|
||||
// 二级分类:选中分类 |
|
||||
handleSelectSubCate(index) { |
|
||||
this.curIndex2 = index |
|
||||
this.showSubCate = false |
|
||||
this.onRefreshList() |
|
||||
}, |
|
||||
|
|
||||
// 刷新列表数据 |
|
||||
onRefreshList() { |
|
||||
this.goodsList = getEmptyPaginateObj() |
|
||||
setTimeout(() => this.mescroll.resetUpScroll(), 120) |
|
||||
}, |
|
||||
|
|
||||
// 跳转至商品列表页 |
|
||||
onTargetGoods(goodsId) { |
|
||||
this.$navTo('pages/goods/detail', { goodsId }) |
|
||||
}, |
|
||||
|
|
||||
// 点击加入购物车 |
|
||||
handleAddCart(item) { |
|
||||
this.$refs.AddCartPopup.handle(item) |
|
||||
}, |
|
||||
|
|
||||
// 更新购物车角标 |
|
||||
onUpdateCartTabBadge() { |
|
||||
console.log('onUpdateCartTabBadge') |
|
||||
setCartTabBadge() |
|
||||
}, |
|
||||
|
|
||||
// 切换子分类显示状态 |
|
||||
handleShowSubCate() { |
|
||||
this.showSubCate = !this.showSubCate |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.container { |
|
||||
padding-left: 173rpx; |
|
||||
} |
|
||||
|
|
||||
// 分类内容 |
|
||||
.cate-content { |
|
||||
z-index: 1; |
|
||||
background: #fff; |
|
||||
padding-top: 88rpx; |
|
||||
min-height: 300rpx; |
|
||||
} |
|
||||
|
|
||||
// 一级分类+二级分类 20 |
|
||||
.cate-left { |
|
||||
position: fixed; |
|
||||
top: calc(88rpx + var(--window-top)); |
|
||||
left: var(--window-left); |
|
||||
bottom: var(--window-bottom); |
|
||||
width: 173rpx; |
|
||||
height: 100%; |
|
||||
background: #f8f8f8; |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
// 左侧一级分类 |
|
||||
.type-nav { |
|
||||
position: relative; |
|
||||
height: 90rpx; |
|
||||
z-index: 10; |
|
||||
display: block; |
|
||||
font-size: 26rpx; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
|
|
||||
&.selected { |
|
||||
background: #fff; |
|
||||
border-right: none; |
|
||||
font-size: 28rpx; |
|
||||
color: #fa2209; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品列表 |
|
||||
.goods-list { |
|
||||
background: #fff; |
|
||||
position: relative; |
|
||||
} |
|
||||
|
|
||||
.goods-item { |
|
||||
padding: 28rpx 22rpx; |
|
||||
display: flex; |
|
||||
} |
|
||||
|
|
||||
.goods-item_left { |
|
||||
position: relative; |
|
||||
background: #fff; |
|
||||
margin-right: 20rpx; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 180rpx; |
|
||||
height: 180rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-item_right { |
|
||||
position: relative; |
|
||||
flex: 1; |
|
||||
|
|
||||
.goods-name { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
min-height: 68rpx; |
|
||||
font-size: 28rpx; |
|
||||
line-height: 1.3; |
|
||||
color: #333; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-item_desc { |
|
||||
margin-top: 20rpx; |
|
||||
|
|
||||
.people { |
|
||||
margin-right: 14rpx; |
|
||||
} |
|
||||
|
|
||||
.desc_footer { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
right: 0rpx; |
|
||||
bottom: 0rpx; |
|
||||
min-height: 44rpx; |
|
||||
|
|
||||
.item-prices { |
|
||||
padding-right: 6rpx; |
|
||||
|
|
||||
.price_x { |
|
||||
margin-right: 14rpx; |
|
||||
color: rgb(240, 60, 60); |
|
||||
font-size: 28rpx; |
|
||||
} |
|
||||
|
|
||||
.price_y { |
|
||||
color: #999; |
|
||||
text-decoration: line-through; |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 子分类 |
|
||||
.sub-cate-list { |
|
||||
background-color: #fff; |
|
||||
width: 100%; |
|
||||
z-index: 9; |
|
||||
padding: 8rpx 40rpx 0 14rpx; |
|
||||
overflow: hidden; |
|
||||
position: sticky; |
|
||||
top: calc(88rpx + var(--window-top)); |
|
||||
|
|
||||
&.display-fold { |
|
||||
height: 86rpx; |
|
||||
} |
|
||||
|
|
||||
.nav-icon { |
|
||||
position: absolute; |
|
||||
right: 16rpx; |
|
||||
top: 12rpx; |
|
||||
font-size: 32rpx; |
|
||||
} |
|
||||
|
|
||||
.sub-cate-item { |
|
||||
float: left; |
|
||||
background: #f8f8f8; |
|
||||
padding: 10rpx 30rpx; |
|
||||
margin-right: 22rpx; |
|
||||
margin-bottom: 24rpx; |
|
||||
font-size: 26rpx; |
|
||||
border-radius: 14rpx; |
|
||||
border: 1rpx solid #f8f8f8; |
|
||||
|
|
||||
&.selected { |
|
||||
color: #fa2209; |
|
||||
border: 1rpx solid #fa2209; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 子分类遮罩层 |
|
||||
.mask { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
bottom: 0; |
|
||||
right: 0; |
|
||||
left: 0; |
|
||||
z-index: 8; |
|
||||
background-color: rgba(0, 0, 0, 0.4); |
|
||||
transition: all 0.3s ease-in-out 0s; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,110 +0,0 @@ |
|||||
<template> |
|
||||
<view class="primary"> |
|
||||
<!-- 一级分类(大图) 10 --> |
|
||||
<view v-if="list.length > 0 && display == PageCategoryStyleEnum.ONE_LEVEL_BIG.value" class="cate-content"> |
|
||||
<view class="cate-wrapper cate_style__10 clearfix"> |
|
||||
<view class="cate-item" v-for="(item, index) in list" :key="index" @click="onTargetGoodsList(item.category_id)"> |
|
||||
<image v-if="item.image" class="image" mode="widthFix" :src="item.image.preview_url"></image> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 一级分类(小图) 11 --> |
|
||||
<view v-if="list.length > 0 && display == PageCategoryStyleEnum.ONE_LEVEL_SMALL.value" class="cate-content"> |
|
||||
<view class="cate-wrapper cate_style__11 clearfix"> |
|
||||
<view class="cate-item" v-for="(item, index) in list" :key="index" @click="onTargetGoodsList(item.category_id)"> |
|
||||
<image v-if="item.image" class="image" mode="widthFix" :src="item.image.preview_url"></image> |
|
||||
<view class="cate-name">{{ item.name }}</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<empty v-if="!list.length" :tips="'亲,暂无商品分类' + display" /> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { PageCategoryStyleEnum } from '@/common/enum/store/page/category' |
|
||||
import Empty from '@/components/empty' |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
Empty |
|
||||
}, |
|
||||
props: { |
|
||||
// 分类页样式 |
|
||||
display: { |
|
||||
type: Number, |
|
||||
default: 10 |
|
||||
}, |
|
||||
// 分类列表 |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: [] |
|
||||
} |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
PageCategoryStyleEnum, |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 跳转至商品列表页 |
|
||||
onTargetGoodsList(categoryId) { |
|
||||
this.$navTo('pages/goods/list', { categoryId }) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
// 分类内容 |
|
||||
.cate-content { |
|
||||
z-index: 1; |
|
||||
background: #fff; |
|
||||
padding-top: 96rpx; |
|
||||
|
|
||||
.cate-wrapper { |
|
||||
padding: 0 20rpx 20rpx 20rpx; |
|
||||
box-sizing: border-box; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 一级分类(大图) 10 |
|
||||
.cate_style__10 .cate-item { |
|
||||
margin-bottom: 20rpx; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: auto; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 一级分类(小图) 11 |
|
||||
.cate_style__11 .cate-item { |
|
||||
float: left; |
|
||||
padding: 25rpx; |
|
||||
width: 33.3333%; |
|
||||
text-align: center; |
|
||||
box-sizing: border-box; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 33vw; |
|
||||
margin-bottom: 12rpx; |
|
||||
} |
|
||||
|
|
||||
.cate-name { |
|
||||
font-size: 28rpx; |
|
||||
color: #555; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,180 +0,0 @@ |
|||||
<template> |
|
||||
<view v-if="list.length > 0" class="secondary"> |
|
||||
<!-- 二级分类 20 --> |
|
||||
<view class="cate-content"> |
|
||||
<!-- 左侧 一级分类 --> |
|
||||
<scroll-view class="cate-left" :scroll-y="true" :style="{ height: `${scrollHeight}px` }"> |
|
||||
<text class="type-nav" :class="{ selected: curIndex == index }" v-for="(item, index) in list" :key="index" |
|
||||
@click="handleSelectNav(index)">{{ item.name }}</text> |
|
||||
</scroll-view> |
|
||||
<!-- 右侧 二级分类 --> |
|
||||
<scroll-view class="cate-right" :scroll-top="scrollTop" :scroll-y="true" :style="{ height: `${scrollHeight}px` }"> |
|
||||
<view v-if="list[curIndex]" class="cate-right-cont"> |
|
||||
<view class="cate-two-box"> |
|
||||
<view class="cate-cont-box"> |
|
||||
<view class="flex-three" v-for="(item, idx) in list[curIndex].children" :key="idx" @click="onTargetGoodsList(item.category_id)"> |
|
||||
<view class="cate-img-padding"> |
|
||||
<view v-if="item.image" class="cate-img"> |
|
||||
<image class="image" mode="scaleToFill" :src="item.image.preview_url"></image> |
|
||||
</view> |
|
||||
</view> |
|
||||
<text class="name oneline-hide">{{ item.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</scroll-view> |
|
||||
</view> |
|
||||
<empty v-if="!list.length" /> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { PageCategoryStyleEnum } from '@/common/enum/store/page/category' |
|
||||
import Empty from '@/components/empty' |
|
||||
import { rpx2px } from '@/utils/util' |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
Empty |
|
||||
}, |
|
||||
props: { |
|
||||
// 分类列表 |
|
||||
list: { |
|
||||
type: Array, |
|
||||
default: [] |
|
||||
}, |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
PageCategoryStyleEnum, |
|
||||
// 列表高度 |
|
||||
scrollHeight: 0, |
|
||||
// 一级分类:指针 |
|
||||
curIndex: 0, |
|
||||
// 内容区竖向滚动条位置 |
|
||||
scrollTop: 0, |
|
||||
} |
|
||||
}, |
|
||||
created() { |
|
||||
// 设置分类列表高度 |
|
||||
this.setListHeight() |
|
||||
}, |
|
||||
methods: { |
|
||||
|
|
||||
// 设置列表内容的高度 |
|
||||
setListHeight() { |
|
||||
const { windowHeight } = uni.getSystemInfoSync() |
|
||||
this.scrollHeight = windowHeight - rpx2px(96) |
|
||||
}, |
|
||||
|
|
||||
// 一级分类:选中分类 |
|
||||
handleSelectNav(index) { |
|
||||
this.curIndex = index |
|
||||
this.scrollTop = 0 |
|
||||
}, |
|
||||
|
|
||||
// 跳转至商品列表页 |
|
||||
onTargetGoodsList(categoryId) { |
|
||||
this.$navTo('pages/goods/list', { categoryId }) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
// 分类内容 |
|
||||
.cate-content { |
|
||||
display: flex; |
|
||||
z-index: 1; |
|
||||
background: #fff; |
|
||||
padding-top: 96rpx; |
|
||||
} |
|
||||
|
|
||||
// 一级分类+二级分类 20 |
|
||||
.cate-left { |
|
||||
height: 100%; |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
flex: 0 0 23%; |
|
||||
background: #f8f8f8; |
|
||||
color: #444; |
|
||||
} |
|
||||
|
|
||||
.cate-right { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
height: 100%; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.cate-right-cont { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
flex-flow: row wrap; |
|
||||
align-content: flex-start; |
|
||||
padding-top: 15rpx; |
|
||||
|
|
||||
.cate-two-box { |
|
||||
width: 100%; |
|
||||
padding: 0 10px; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 左侧一级分类 |
|
||||
.type-nav { |
|
||||
position: relative; |
|
||||
height: 90rpx; |
|
||||
z-index: 10; |
|
||||
display: block; |
|
||||
font-size: 26rpx; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
|
|
||||
&.selected { |
|
||||
background: #fff; |
|
||||
color: #fa2209; |
|
||||
border-right: none; |
|
||||
font-size: 28rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 右侧二级分类 |
|
||||
.cate-cont-box { |
|
||||
margin-bottom: 30rpx; |
|
||||
padding-bottom: 10rpx; |
|
||||
background: #fff; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.name { |
|
||||
display: block; |
|
||||
padding-bottom: 30rpx; |
|
||||
text-align: center; |
|
||||
font-size: 26rpx; |
|
||||
color: #444444; |
|
||||
} |
|
||||
|
|
||||
.cate-img-padding { |
|
||||
padding: 16rpx 16rpx 4rpx 16rpx; |
|
||||
} |
|
||||
|
|
||||
.cate-img { |
|
||||
position: relative; |
|
||||
width: 100%; |
|
||||
padding-top: 100%; |
|
||||
|
|
||||
.image { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
border-radius: 10rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</style> |
|
||||
@ -1,165 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<!-- 搜索框 --> |
|
||||
<search class="search" tips="搜索商品" @event="$navTo('pages/search/index')" /> |
|
||||
|
|
||||
<!-- 一级分类 --> |
|
||||
<primary v-if="setting.style == PageCategoryStyleEnum.ONE_LEVEL_BIG.value || setting.style == PageCategoryStyleEnum.ONE_LEVEL_SMALL.value" |
|
||||
:display="setting.style" :list="list" /> |
|
||||
|
|
||||
<!-- 二级分类 --> |
|
||||
<secondary v-if="setting.style == PageCategoryStyleEnum.TWO_LEVEL.value" :list="list" /> |
|
||||
|
|
||||
<!-- 分类+商品 --> |
|
||||
<commodity v-if="setting.style == PageCategoryStyleEnum.COMMODITY.value" ref="mescrollItem" :list="list" :setting="setting" /> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollCompMixin from '@/components/mescroll-uni/mixins/mescroll-comp' |
|
||||
import { setCartTabBadge } from '@/core/app' |
|
||||
import SettingKeyEnum from '@/common/enum/setting/Key' |
|
||||
import { PageCategoryStyleEnum } from '@/common/enum/store/page/category' |
|
||||
import SettingModel from '@/common/model/Setting' |
|
||||
import * as CategoryApi from '@/api/category' |
|
||||
import Empty from '@/components/empty' |
|
||||
import Search from '@/components/search' |
|
||||
import Primary from './components/primary' |
|
||||
import Secondary from './components/secondary' |
|
||||
import Commodity from './components/commodity' |
|
||||
|
|
||||
// 最后一次刷新时间 |
|
||||
let lastRefreshTime; |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
Search, |
|
||||
Empty, |
|
||||
Primary, |
|
||||
Secondary, |
|
||||
Commodity |
|
||||
}, |
|
||||
mixins: [MescrollCompMixin], |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
PageCategoryStyleEnum, |
|
||||
// 分类列表 |
|
||||
list: [], |
|
||||
// 分类模板设置 |
|
||||
setting: {}, |
|
||||
// 正在加载中 |
|
||||
isLoading: true |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad() { |
|
||||
// 加载页面数据 |
|
||||
this.onRefreshPage() |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面显示 |
|
||||
*/ |
|
||||
onShow() { |
|
||||
// 每间隔5分钟自动刷新一次页面数据 |
|
||||
const curTime = new Date().getTime() |
|
||||
if ((curTime - lastRefreshTime) > 5 * 60 * 1000) { |
|
||||
this.onRefreshPage() |
|
||||
} |
|
||||
}, |
|
||||
methods: { |
|
||||
|
|
||||
// 刷新页面 |
|
||||
onRefreshPage() { |
|
||||
// 记录刷新时间 |
|
||||
lastRefreshTime = new Date().getTime() |
|
||||
// 获取页面数据 |
|
||||
this.getPageData() |
|
||||
// 更新购物车角标 |
|
||||
setCartTabBadge() |
|
||||
}, |
|
||||
|
|
||||
// 获取页面数据 |
|
||||
getPageData() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
Promise.all([ |
|
||||
// 获取分类模板设置 |
|
||||
// 优化建议: 可以将此处的false改为true 启用缓存 |
|
||||
SettingModel.data(false), |
|
||||
// 获取分类列表 |
|
||||
CategoryApi.list() |
|
||||
]) |
|
||||
.then(result => { |
|
||||
// 初始化分类模板设置 |
|
||||
app.initSetting(result[0]) |
|
||||
// 初始化分类列表数据 |
|
||||
app.initCategory(result[1]) |
|
||||
}) |
|
||||
.finally(() => app.isLoading = false) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 初始化分类模板设置 |
|
||||
* @param {Object} result |
|
||||
*/ |
|
||||
initSetting(setting) { |
|
||||
this.setting = setting[SettingKeyEnum.PAGE_CATEGORY_TEMPLATE.value] |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 初始化分类列表数据 |
|
||||
* @param {Object} result |
|
||||
*/ |
|
||||
initCategory(result) { |
|
||||
this.list = result.data.list |
|
||||
}, |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 设置分享内容 |
|
||||
*/ |
|
||||
onShareAppMessage() { |
|
||||
const app = this |
|
||||
return { |
|
||||
title: _this.templet.shareTitle, |
|
||||
path: '/pages/category/index?' + app.$getShareUrlParams() |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 分享到朋友圈 |
|
||||
* 本接口为 Beta 版本,暂只在 Android 平台支持,详见分享到朋友圈 (Beta) |
|
||||
* https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share-timeline.html |
|
||||
*/ |
|
||||
onShareTimeline() { |
|
||||
const app = this |
|
||||
return { |
|
||||
title: _this.templet.shareTitle, |
|
||||
path: '/pages/category/index?' + app.$getShareUrlParams() |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style> |
|
||||
page { |
|
||||
background: #fff; |
|
||||
} |
|
||||
</style> |
|
||||
<style lang="scss" scoped> |
|
||||
// 搜索框 |
|
||||
.search { |
|
||||
position: fixed; |
|
||||
top: var(--window-top); |
|
||||
left: var(--window-left); |
|
||||
right: var(--window-right); |
|
||||
z-index: 9; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,523 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container p-bottom" v-if="order.goodsList.length"> |
|
||||
|
|
||||
<!-- 快递配送:配送地址 --> |
|
||||
<view v-if="curDelivery == DeliveryTypeEnum.EXPRESS.value" @click="onSelectAddress" class="flow-delivery"> |
|
||||
<view class="flow-delivery__detail dis-flex flex-y-center"> |
|
||||
<view class="detail-location dis-flex"> |
|
||||
<text class="iconfont icon-dingwei"></text> |
|
||||
</view> |
|
||||
<view class="detail-content flex-box"> |
|
||||
<block v-if="order.address"> |
|
||||
<view class="detail-content__title dis-flex"> |
|
||||
<text class="f-30">{{ order.address.name }}</text> |
|
||||
<text class="detail-content__title-phone f-28">{{ order.address.phone }}</text> |
|
||||
</view> |
|
||||
<view class="address detail-content__describe"> |
|
||||
<text class="region" v-for="(region, idx) in order.address.region" :key="idx">{{ region }}</text> |
|
||||
<text class="detail">{{ order.address.detail }}</text> |
|
||||
</view> |
|
||||
</block> |
|
||||
<block v-else> |
|
||||
<view class="detail-content__describe dis-flex"> |
|
||||
<text class="col-6">请选择配送地址</text> |
|
||||
</view> |
|
||||
</block> |
|
||||
</view> |
|
||||
<view class="detail-arrow dis-flex"> |
|
||||
<text class="iconfont icon-arrow-right"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商品列表 --> |
|
||||
<view class="m-top20"> |
|
||||
<view class="checkout_list" v-for="(item, index) in order.goodsList" :key="index"> |
|
||||
<view class="flow-shopList dis-flex" data-index="index" @click="onTargetGoods(item.goods_id)"> |
|
||||
<!-- 商品图片 --> |
|
||||
<view class="flow-list-left"> |
|
||||
<image mode="scaleToFill" :src="item.goods_image"></image> |
|
||||
</view> |
|
||||
<view class="flow-list-right flex-box"> |
|
||||
<!-- 商品名称 --> |
|
||||
<text class="goods-name twoline-hide">{{ item.goods_name }}</text> |
|
||||
<!-- 商品规格 --> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in item.skuInfo.goods_props" :key="idx"> |
|
||||
<text class="group-name">{{ props.group.name }}: </text> |
|
||||
<text>{{ props.value.name }};</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 商品数量和单价 --> |
|
||||
<view class="flow-list-cont dis-flex flex-x-between flex-y-center"> |
|
||||
<text class="small">×{{ item.total_num }}</text> |
|
||||
<text class="flow-cont" :class="[item.is_user_grade ? 'price-delete' : '']">¥{{ item.goods_price }}</text> |
|
||||
</view> |
|
||||
<!-- 会员折扣价 --> |
|
||||
<view v-if="item.is_user_grade" class="grade-price"> |
|
||||
<text>会员折扣价:¥{{ item.grade_goods_price }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="flow-num-box b-f"> |
|
||||
<text>共{{ order.orderTotalNum }}件商品,合计:</text> |
|
||||
<text class="flow-money col-m">¥{{ order.orderTotalPrice }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商品金额 --> |
|
||||
<view class="flow-all-money b-f m-top20"> |
|
||||
<view class="flow-all-list dis-flex"> |
|
||||
<text class="flex-five">订单总金额:</text> |
|
||||
<view class="flex-five t-r"> |
|
||||
<text class="col-m">¥{{ order.orderTotalPrice }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 优惠券 --> |
|
||||
<view class="flow-all-list dis-flex"> |
|
||||
<text class="flex-five">优惠券:</text> |
|
||||
<view class="flex-five t-r"> |
|
||||
<view v-if="order.couponList.length > 0" @click="handleShowPopup()"> |
|
||||
<text class="col-m" v-if="order.couponId > 0">-¥{{ order.couponMoney }}</text> |
|
||||
<text class="col-m" v-else>有{{ order.couponList.length }}张优惠券</text> |
|
||||
<text class="right-arrow iconfont icon-arrow-right"></text> |
|
||||
</view> |
|
||||
<text v-else class="">无优惠券可用</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 积分抵扣 --> |
|
||||
<view v-if="order.isAllowPoints" class="points flow-all-list dis-flex flex-y-center"> |
|
||||
<view class="block-left flex-five" @click="handleShowPoints()"> |
|
||||
<text class="title">可用{{ setting.points_name }}抵扣:</text> |
|
||||
<text class="iconfont icon-help"></text> |
|
||||
</view> |
|
||||
<view class="flex-five dis-flex flex-x-end flex-y-center"> |
|
||||
<text class="points-money col-m">-¥{{ order.pointsMoney }}</text> |
|
||||
<u-switch v-model="isUsePoints" size="48" active-color="#07c160" @change="getOrderData()"></u-switch> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 配送费用 --> |
|
||||
<view v-if="curDelivery == DeliveryTypeEnum.EXPRESS.value" class="dis-flex flow-all-list"> |
|
||||
<text class="flex-five">配送费用:</text> |
|
||||
<view class="flex-five t-r"> |
|
||||
<view v-if="order.address"> |
|
||||
<text class="col-m" v-if="order.isIntraRegion">+¥{{ order.expressPrice }}</text> |
|
||||
<text v-else>不在配送范围</text> |
|
||||
</view> |
|
||||
<view v-else> |
|
||||
<text class="col-7">请先选择配送地址</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 支付方式 --> |
|
||||
<view class="pay-method flow-all-money b-f m-top20"> |
|
||||
<view class="flow-all-list dis-flex"> |
|
||||
<text class="flex-five">支付方式</text> |
|
||||
</view> |
|
||||
<!-- 微信支付 --> |
|
||||
<!-- #ifdef MP-WEIXIN --> |
|
||||
<view class="pay-item dis-flex flex-x-between" @click="handleSelectPayType(PayTypeEnum.WECHAT.value)"> |
|
||||
<view class="item-left dis-flex flex-y-center"> |
|
||||
<view class="item-left_icon wechat"> |
|
||||
<text class="iconfont icon-wechat-pay"></text> |
|
||||
</view> |
|
||||
<view class="item-left_text"> |
|
||||
<text>{{ PayTypeEnum.WECHAT.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="item-right col-m" v-if="curPayType == PayTypeEnum.WECHAT.value"> |
|
||||
<text class="iconfont icon-check"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- #endif --> |
|
||||
<!-- 余额支付 --> |
|
||||
<view class="pay-item dis-flex flex-x-between" @click="handleSelectPayType(PayTypeEnum.BALANCE.value)"> |
|
||||
<view class="item-left dis-flex flex-y-center"> |
|
||||
<view class="item-left_icon balance"> |
|
||||
<text class="iconfont icon-balance-pay"></text> |
|
||||
</view> |
|
||||
<view class="item-left_text"> |
|
||||
<text>{{ PayTypeEnum.BALANCE.name }}</text> |
|
||||
</view> |
|
||||
<view class="user-balance"> |
|
||||
<text>(可用¥{{ personal.balance }}元)</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="item-right col-m" v-if="curPayType == PayTypeEnum.BALANCE.value"> |
|
||||
<text class="iconfont icon-check"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 买家留言 --> |
|
||||
<view class="flow-all-money b-f m-top20"> |
|
||||
<view class="ipt-wrapper dis-flex flow-all-list"> |
|
||||
<input v-model="remark" placeholder="选填:买家留言(50字以内)"></input> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 提交订单 --> |
|
||||
<view class="flow-fixed-footer b-f m-top10"> |
|
||||
<view class="dis-flex chackout-box"> |
|
||||
<view class="chackout-left pl-12">实付款: |
|
||||
<text class="col-m">¥{{ order.orderPayPrice }}</text> |
|
||||
</view> |
|
||||
<view class="chackout-right" @click="onSubmitOrder()"> |
|
||||
<view class="flow-btn f-32" :class="{ disabled }">提交订单</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 积分说明弹窗 --> |
|
||||
<u-modal v-model="showPoints" :title="`${setting.points_name}说明`"> |
|
||||
<scroll-view class="points-content" :scroll-y="true"> |
|
||||
<text>{{ setting.points_describe }}</text> |
|
||||
</scroll-view> |
|
||||
</u-modal> |
|
||||
|
|
||||
<!-- 优惠券弹出框 --> |
|
||||
<u-popup v-model="showPopup" mode="bottom"> |
|
||||
<view class="popup__coupon"> |
|
||||
<view class="coupon__title f-30">选择优惠券</view> |
|
||||
<!-- 优惠券列表 --> |
|
||||
<view class="coupon-list"> |
|
||||
<scroll-view :scroll-y="true" style="height: 565rpx;"> |
|
||||
<view class="coupon-item" v-for="(item, index) in order.couponList" :key="index"> |
|
||||
<view class="item-wrapper" |
|
||||
:class="[item.is_apply ? 'color-' + CouponColors[index % CouponColors.length] : 'color-gray']" |
|
||||
@click="handleSelectCoupon(index)"> |
|
||||
<view class="coupon-type">{{ CouponTypeEnum[item.coupon_type].name }}</view> |
|
||||
<view class="tip dis-flex flex-dir-column flex-x-center"> |
|
||||
<view v-if="item.coupon_type == CouponTypeEnum.FULL_DISCOUNT.value"> |
|
||||
<text class="f-30">¥</text> |
|
||||
<text class="money">{{ item.reduce_price }}</text> |
|
||||
</view> |
|
||||
<text class="money" |
|
||||
v-if="item.coupon_type == CouponTypeEnum.DISCOUNT.value">{{ item.discount }}折</text> |
|
||||
<text class="pay-line">满{{ item.min_price }}元可用</text> |
|
||||
</view> |
|
||||
<view class="split-line"></view> |
|
||||
<view class="content dis-flex flex-dir-column flex-x-between"> |
|
||||
<view class="title">{{ item.name }}</view> |
|
||||
<view class="bottom dis-flex flex-y-center"> |
|
||||
<view class="time flex-box"> |
|
||||
<block v-if="item.start_time === item.end_time">{{ item.start_time }}</block> |
|
||||
<block v-else>{{ item.start_time }}~{{ item.end_time }}</block> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</scroll-view> |
|
||||
</view> |
|
||||
<!-- 不使用优惠券 --> |
|
||||
<view class="coupon__do_not dis-flex flex-y-center flex-x-center"> |
|
||||
<view class="control dis-flex flex-y-center flex-x-center" @click="handleNotUseCoupon()"> |
|
||||
<text class="f-26">不使用优惠券</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</u-popup> |
|
||||
|
|
||||
</view> |
|
||||
|
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as Verify from '@/utils/verify' |
|
||||
import * as CheckoutApi from '@/api/checkout' |
|
||||
import { CouponTypeEnum } from '@/common/enum/coupon' |
|
||||
import DeliveryTypeEnum from '@/common/enum/order/DeliveryType' |
|
||||
import PayTypeEnum from '@/common/enum/order/PayType' |
|
||||
import { wxPayment } from '@/core/app' |
|
||||
|
|
||||
const CouponColors = ['red', 'blue', 'violet', 'yellow'] |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
DeliveryTypeEnum, |
|
||||
PayTypeEnum, |
|
||||
CouponTypeEnum, |
|
||||
// 当前页面参数 |
|
||||
options: {}, |
|
||||
// 优惠券颜色组 |
|
||||
CouponColors, |
|
||||
// 当前选中的配送方式 |
|
||||
curDelivery: null, |
|
||||
// 当前选中的支付方式 |
|
||||
curPayType: PayTypeEnum.BALANCE.value, |
|
||||
// 选择的优惠券 |
|
||||
selectCouponId: 0, |
|
||||
// 是否使用积分抵扣 |
|
||||
isUsePoints: false, |
|
||||
// 买家留言 |
|
||||
remark: '', |
|
||||
// 禁用submit按钮 |
|
||||
disabled: false, |
|
||||
// 是否显示积分说明 |
|
||||
showPoints: false, |
|
||||
// 是否显示优惠券弹窗 |
|
||||
showPopup: false, |
|
||||
// 按钮禁用 |
|
||||
disabled: false, |
|
||||
// 订单信息 (从后端api中获取) |
|
||||
order: { |
|
||||
// 商品列表 |
|
||||
goodsList: [], |
|
||||
// 优惠券列表 |
|
||||
couponList: [], |
|
||||
// 是否存在收货地址 |
|
||||
existAddress: false, |
|
||||
// 默认收货地址 |
|
||||
address: null, |
|
||||
// 是否存在收货地址 |
|
||||
existAddress: false, |
|
||||
// 当前用户收货城市是否存在配送规则中 |
|
||||
isIntraRegion: true, |
|
||||
// 是否存在错误 |
|
||||
hasError: false, |
|
||||
// 错误信息 |
|
||||
errorMsg: '' |
|
||||
}, |
|
||||
// 个人信息 |
|
||||
personal: {}, |
|
||||
// 商城设置 |
|
||||
setting: {} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
this.options = options |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面显示 |
|
||||
*/ |
|
||||
onShow() { |
|
||||
// 获取当前订单信息 |
|
||||
this.getOrderData() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取订单数据 |
|
||||
getOrderData() { |
|
||||
const app = this |
|
||||
// 请求的参数 |
|
||||
const params = { |
|
||||
delivery: app.curDelivery || 0, |
|
||||
couponId: app.selectCouponId || 0, |
|
||||
isUsePoints: app.isUsePoints ? 1 : 0, |
|
||||
} |
|
||||
// 请求api |
|
||||
CheckoutApi.order(app.options.mode, app.getRequestParam()) |
|
||||
.then(result => { |
|
||||
app.initData(result.data) |
|
||||
}) |
|
||||
.catch(err => err) |
|
||||
}, |
|
||||
|
|
||||
// 初始化数据 |
|
||||
initData({ order, setting, personal }) { |
|
||||
const app = this |
|
||||
app.order = order |
|
||||
app.personal = personal |
|
||||
app.setting = setting |
|
||||
// 显示错误信息 |
|
||||
if (order.hasError) { |
|
||||
app.$toast(order.errorMsg) |
|
||||
} |
|
||||
// 当前选择的配送方式 |
|
||||
app.curDelivery = order.delivery |
|
||||
// 如果只有一种配送方式则不显示选项卡 |
|
||||
app.isShowTab = setting.deliveryType.length > 1 |
|
||||
// 当前选择支付方式 (如果是微信小程序默认使用微信支付) |
|
||||
if (app.$platform === 'MP-WEIXIN') { |
|
||||
app.curPayType = PayTypeEnum.WECHAT.value |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 获取api请求的参数 |
|
||||
getRequestParam() { |
|
||||
const app = this |
|
||||
const { options } = app |
|
||||
// 结算模式的固定参数 |
|
||||
const modeParam = {} |
|
||||
// 结算模式: 立即购买 |
|
||||
if (options.mode === 'buyNow') { |
|
||||
modeParam.goodsId = options.goodsId |
|
||||
modeParam.goodsNum = options.goodsNum |
|
||||
modeParam.goodsSkuId = options.goodsSkuId |
|
||||
} |
|
||||
// 结算模式: 购物车 |
|
||||
if (options.mode === 'cart') { |
|
||||
modeParam.cartIds = options.cartIds |
|
||||
} |
|
||||
// 订单结算参数(用户选择) |
|
||||
const orderParam = { |
|
||||
delivery: app.curDelivery || 0, |
|
||||
couponId: app.selectCouponId || 0, |
|
||||
isUsePoints: app.isUsePoints ? 1 : 0, |
|
||||
} |
|
||||
return { ...orderParam, ...modeParam } |
|
||||
}, |
|
||||
|
|
||||
// 显示积分说明 |
|
||||
handleShowPoints() { |
|
||||
this.showPoints = true |
|
||||
}, |
|
||||
|
|
||||
// 显示优惠券弹窗 |
|
||||
handleShowPopup() { |
|
||||
this.showPopup = true |
|
||||
}, |
|
||||
|
|
||||
// 选择优惠券 |
|
||||
handleSelectCoupon(index) { |
|
||||
const app = this |
|
||||
const { couponList } = app.order |
|
||||
// 当前选择的优惠券 |
|
||||
const couponItem = couponList[index] |
|
||||
// 判断是否在适用范围 |
|
||||
if (!couponItem.is_apply) { |
|
||||
app.$toast(couponItem.not_apply_info) |
|
||||
return |
|
||||
} |
|
||||
// 记录选中的优惠券id |
|
||||
app.selectCouponId = couponItem.user_coupon_id |
|
||||
// 重新获取订单信息 |
|
||||
app.getOrderData() |
|
||||
// 隐藏优惠券弹层 |
|
||||
app.showPopup = false |
|
||||
}, |
|
||||
|
|
||||
// 不使用优惠券 |
|
||||
handleNotUseCoupon() { |
|
||||
const app = this |
|
||||
app.selectCouponId = 0 |
|
||||
// 重新获取订单信息 |
|
||||
app.getOrderData() |
|
||||
// 隐藏优惠券弹层 |
|
||||
app.showPopup = false |
|
||||
}, |
|
||||
|
|
||||
// 选择支付方式 |
|
||||
handleSelectPayType(value) { |
|
||||
this.curPayType = value |
|
||||
}, |
|
||||
|
|
||||
// 快递配送:选择收货地址 |
|
||||
onSelectAddress() { |
|
||||
this.$navTo('pages/address/index', { from: 'checkout' }) |
|
||||
}, |
|
||||
|
|
||||
// 跳转到商品详情页 |
|
||||
onTargetGoods(goodsId) { |
|
||||
this.$navTo('pages/goods/detail', { goodsId }) |
|
||||
}, |
|
||||
|
|
||||
// 订单提交 |
|
||||
onSubmitOrder() { |
|
||||
const app = this |
|
||||
if (app.disabled) { |
|
||||
return false |
|
||||
} |
|
||||
// 表单验证 |
|
||||
if (!app.onVerifyFrom()) { |
|
||||
return false |
|
||||
} |
|
||||
// 按钮禁用 |
|
||||
app.disabled = true |
|
||||
// 请求api |
|
||||
CheckoutApi.submit(app.options.mode, app.getFormData()) |
|
||||
.then(result => app.onSubmitCallback(result)) |
|
||||
.catch(err => { |
|
||||
if (err.result) { |
|
||||
const errData = err.result.data |
|
||||
if (errData.is_created) { |
|
||||
app.navToMyOrder() |
|
||||
return false |
|
||||
} |
|
||||
} |
|
||||
app.disabled = false |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 订单提交成功后回调 |
|
||||
onSubmitCallback(result) { |
|
||||
const app = this |
|
||||
// 发起微信支付 |
|
||||
if (result.data.payType == PayTypeEnum.WECHAT.value) { |
|
||||
wxPayment(result.data.payment) |
|
||||
.then(() => app.$success('支付成功')) |
|
||||
.catch(err => app.$error('订单未支付')) |
|
||||
.finally(() => { |
|
||||
app.disabled = false |
|
||||
app.navToMyOrder() |
|
||||
}) |
|
||||
} |
|
||||
// 余额支付 |
|
||||
if (result.data.payType == PayTypeEnum.BALANCE.value) { |
|
||||
app.$success('支付成功') |
|
||||
app.disabled = false |
|
||||
app.navToMyOrder() |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 跳转到我的订单(等待1秒) |
|
||||
navToMyOrder() { |
|
||||
setTimeout(() => { |
|
||||
this.$navTo('pages/order/index') |
|
||||
}, 1000) |
|
||||
}, |
|
||||
|
|
||||
// 表单提交的数据 |
|
||||
getFormData() { |
|
||||
const app = this |
|
||||
const { options } = app |
|
||||
// 表单数据 |
|
||||
const form = { |
|
||||
delivery: app.curDelivery, |
|
||||
payType: app.curPayType, |
|
||||
couponId: app.selectCouponId || 0, |
|
||||
isUsePoints: app.isUsePoints ? 1 : 0, |
|
||||
remark: app.remark || '', |
|
||||
} |
|
||||
// 创建订单-立即购买 |
|
||||
if (options.mode === 'buyNow') { |
|
||||
form.goodsId = options.goodsId |
|
||||
form.goodsNum = options.goodsNum |
|
||||
form.goodsSkuId = options.goodsSkuId |
|
||||
} |
|
||||
// 创建订单-购物车结算 |
|
||||
if (options.mode === 'cart') { |
|
||||
form.cartIds = options.cartIds || null |
|
||||
} |
|
||||
return form |
|
||||
}, |
|
||||
|
|
||||
// 表单验证 |
|
||||
onVerifyFrom() { |
|
||||
const app = this |
|
||||
if (app.hasError) { |
|
||||
app.$toast(app.errorMsg) |
|
||||
return false |
|
||||
} |
|
||||
return true |
|
||||
}, |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
@import "./style.scss"; |
|
||||
</style> |
|
||||
@ -1,445 +0,0 @@ |
|||||
|
|
||||
// 配送信息 |
|
||||
.flow-delivery { |
|
||||
padding: 34rpx 30rpx; |
|
||||
background: #fff url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANYAAAANCAYAAADVGpDCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA4ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3Yjk4M2ExYy1jMDhkLTQ1OTktYTI0Ny1kZjNjYzdiYTQ5ZTgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDQwNkY3RkU5N0NGMTFFNUI3N0M4NTU4MzM2RjlFODIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDQwNkY3RkQ5N0NGMTFFNUI3N0M4NTU4MzM2RjlFODIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowNzgwZWI1NS03OGFhLTQzOTUtODQ4OC1lOWI5YmVlYTY1ZDciIHN0UmVmOmRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo1OTRiYzUyMy1jMzc3LTExNzgtYTdkZS04NGY3YmM1ZGIxMDMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz556PLxAAACBElEQVR42tyaSyhEYRTHP48imlKibDQeSSlkSlEWLCRFsZNH5FE2FqQ8ErIRC9lIkTwXSpMkWWChhEJCSnlkoUZGSsr78f98n43CMFPu/Z/6NZuZ2zn33/+cb869XkmLx8IDEQaGQJbgiytQDSY3MyL+LYnL/HxPXSoHDIJQQq2WQQk4Dbbb/yUB29LJ+6e3B66VB3ZITbUIEqSpCGoJBP1ghtBUD6ARpEtTGSEhXzd+awE9oJzQUPegWdf3QlBPMhgDMYRa7YNisGWkpP5qrBQtVBShUHugUE9hs4fUtwG0utlEjRivoA/Ug1sj3vjffr8FNJEK1auPFHcE9UTq5pdK2PwcoAzMG7mjuRrRYEIfK9jiDJSCBZJ6ynSTsBBqNQ0qgdPISbq6vJCFbJOaagrEk5gqWNczRGiqG1Ah1LLMafRkf5pYIUKtZnMJDXUNasAIST2ZYFioRx9ssQaKwJFZEv5uYmWDXVJTrYBEElP562PfPKGpnkAbSDOTqb6aWAGgW6iHol5kQj2CdtAJngnqkc1hHMQRNr9DPaXWzZj8Z2PZtFCxhEIdaKE2CGqRJ4060AH8CLUaALX6f5VpBZLhI9SaeZXQVHKNLt84SCIxVbhQi5YuQlNd6OVElZlN9TGxrGBUn2PZ4lyoTdIsST0FQj0UDSLUak6ot3gcBLVY3wQYAJoVXxmNERajAAAAAElFTkSuQmCC') bottom left repeat-x; |
|
||||
background-size: 120rpx auto; |
|
||||
|
|
||||
.detail-location { |
|
||||
font-size: 36rpx; |
|
||||
} |
|
||||
.detail-content { |
|
||||
padding: 0 20rpx; |
|
||||
.detail-content__title-phone { |
|
||||
margin-left: 10rpx; |
|
||||
} |
|
||||
.detail-content__describe { |
|
||||
font-size: 28rpx; |
|
||||
color: #777; |
|
||||
} |
|
||||
} |
|
||||
.detail-content__title { |
|
||||
margin-bottom: 6rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 买家留言 |
|
||||
.flow-all-money { |
|
||||
.ipt-wrapper { |
|
||||
input { |
|
||||
font-size: 28rpx; |
|
||||
width: 100%; |
|
||||
height: 75rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品列表 |
|
||||
.checkout_list { |
|
||||
padding: 20rpx 30rpx 4rpx 30rpx; |
|
||||
background: #fff; |
|
||||
border-bottom: 1rpx solid rgb(248, 248, 248); |
|
||||
.flow-shopList { |
|
||||
padding: 5rpx 0 10rpx; |
|
||||
border-bottom: 1rpx solid rgb(248, 248, 248); |
|
||||
&:last-child { |
|
||||
border-bottom: 0; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.flow-header-left { |
|
||||
padding-left: 90rpx; |
|
||||
} |
|
||||
|
|
||||
/* 会员价 */ |
|
||||
.flow-shopList { |
|
||||
|
|
||||
.flow-list-right { |
|
||||
.flow-cont { |
|
||||
|
|
||||
&.price-delete { |
|
||||
font-size: 26rpx; |
|
||||
color: #777; |
|
||||
text-decoration: line-through; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.grade-price { |
|
||||
padding-top: 8rpx; |
|
||||
font-size: 28rpx; |
|
||||
color: #ff495e; |
|
||||
text-align: right; |
|
||||
} |
|
||||
|
|
||||
.goods-name{ |
|
||||
font-size: 28rpx; |
|
||||
color: #333; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
/* 优惠券选择 */ |
|
||||
.popup__coupon { |
|
||||
width: 750rpx; |
|
||||
background: #fff; |
|
||||
box-sizing: border-box; |
|
||||
padding: 30rpx; |
|
||||
|
|
||||
.coupon__do_not { |
|
||||
.control { |
|
||||
width: 90%; |
|
||||
height: 72rpx; |
|
||||
margin-bottom: 24rpx; |
|
||||
color: #888; |
|
||||
border: 1rpx solid #e3e3e3; |
|
||||
border-radius: 10rpx; |
|
||||
/* #ifdef H5 */ |
|
||||
max-width: 1120rpx; |
|
||||
/* #endif */ |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.coupon__title { |
|
||||
text-align: center; |
|
||||
margin-bottom: 30rpx; |
|
||||
} |
|
||||
|
|
||||
.coupon-list { |
|
||||
/* #ifdef H5 */ |
|
||||
max-width: 1120rpx; |
|
||||
margin: 0 auto; |
|
||||
/* #endif */ |
|
||||
} |
|
||||
|
|
||||
.coupon-item { |
|
||||
overflow: hidden; |
|
||||
margin-bottom: 22rpx; |
|
||||
} |
|
||||
|
|
||||
.item-wrapper { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
background: #fff; |
|
||||
border-radius: 8rpx; |
|
||||
color: #fff; |
|
||||
height: 180rpx; |
|
||||
|
|
||||
.coupon-type { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
z-index: 10; |
|
||||
width: 128rpx; |
|
||||
padding: 6rpx 0; |
|
||||
background: #a771ff; |
|
||||
font-size: 20rpx; |
|
||||
text-align: center; |
|
||||
color: #ffffff; |
|
||||
transform: rotate(45deg); |
|
||||
transform-origin: 64rpx 64rpx; |
|
||||
} |
|
||||
|
|
||||
&.color-blue { |
|
||||
background: linear-gradient(-125deg, #57bdbf, #2f9de2); |
|
||||
} |
|
||||
|
|
||||
&.color-red { |
|
||||
background: linear-gradient(-128deg, #ff6d6d, #ff3636); |
|
||||
} |
|
||||
|
|
||||
&.color-violet { |
|
||||
background: linear-gradient(-113deg, #ef86ff, #b66ff5); |
|
||||
|
|
||||
.coupon-type { |
|
||||
background: #55b5ff; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&.color-yellow { |
|
||||
background: linear-gradient(-141deg, #f7d059, #fdb054); |
|
||||
} |
|
||||
|
|
||||
&.color-gray { |
|
||||
background: linear-gradient(-113deg, #bdbdbd, #a2a1a2); |
|
||||
|
|
||||
.coupon-type { |
|
||||
background: #9e9e9e; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.content { |
|
||||
flex: 1; |
|
||||
padding: 30rpx 20rpx; |
|
||||
border-radius: 16rpx 0 0 16rpx; |
|
||||
|
|
||||
.title { |
|
||||
font-size: 32rpx; |
|
||||
} |
|
||||
|
|
||||
.bottom { |
|
||||
.time { |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
|
|
||||
.receive { |
|
||||
height: 46rpx; |
|
||||
width: 122rpx; |
|
||||
line-height: 46rpx; |
|
||||
text-align: center; |
|
||||
border: 1rpx solid #fff; |
|
||||
border-radius: 30rpx; |
|
||||
color: #fff; |
|
||||
font-size: 24rpx; |
|
||||
|
|
||||
&.state { |
|
||||
border: none; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.tip { |
|
||||
position: relative; |
|
||||
flex: 0 0 32%; |
|
||||
text-align: center; |
|
||||
border-radius: 0 16rpx 16rpx 0; |
|
||||
|
|
||||
.money { |
|
||||
font-weight: bold; |
|
||||
font-size: 52rpx; |
|
||||
} |
|
||||
|
|
||||
.pay-line { |
|
||||
font-size: 22rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.split-line { |
|
||||
position: relative; |
|
||||
flex: 0 0 0; |
|
||||
border-left: 4rpx solid #fff; |
|
||||
margin: 0 10rpx 0 6rpx; |
|
||||
background: #fff; |
|
||||
|
|
||||
&:before, |
|
||||
{ |
|
||||
border-radius: 0 0 16rpx 16rpx; |
|
||||
top: 0; |
|
||||
} |
|
||||
|
|
||||
&:after { |
|
||||
border-radius: 16rpx 16rpx 0 0; |
|
||||
bottom: 0; |
|
||||
} |
|
||||
|
|
||||
&:before, |
|
||||
&:after { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
width: 24rpx; |
|
||||
height: 12rpx; |
|
||||
background: #f7f7f7; |
|
||||
left: -14rpx; |
|
||||
z-index: 1; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
/* 积分抵扣 */ |
|
||||
.points { |
|
||||
|
|
||||
.title { |
|
||||
margin-right: 5rpx; |
|
||||
} |
|
||||
|
|
||||
.icon-help { |
|
||||
font-size: 28rpx; |
|
||||
} |
|
||||
|
|
||||
.points-money { |
|
||||
margin-right: 20rpx; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
/* 支付方式 */ |
|
||||
.pay-method { |
|
||||
|
|
||||
.pay-item { |
|
||||
padding: 24rpx 0; |
|
||||
font-size: 28rpx; |
|
||||
border-bottom: 1rpx solid rgb(248, 248, 248); |
|
||||
|
|
||||
.item-left_icon { |
|
||||
margin-right: 20rpx; |
|
||||
font-size: 32rpx; |
|
||||
|
|
||||
&.wechat { |
|
||||
color: #00c800; |
|
||||
} |
|
||||
|
|
||||
&.balance { |
|
||||
color: #ff9700; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.user-balance { |
|
||||
margin-left: 20rpx; |
|
||||
font-size: 26rpx; |
|
||||
// color: #464646; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 商品规格 |
|
||||
.goods-props { |
|
||||
padding-top: 10rpx; |
|
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
float: left; |
|
||||
.group-name { |
|
||||
margin-right: 6rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 右侧箭头 |
|
||||
.right-arrow { |
|
||||
margin-left: 16rpx; |
|
||||
// color: #777; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
|
|
||||
// 底部操作栏 |
|
||||
.flow-fixed-footer { |
|
||||
position: fixed; |
|
||||
bottom: var(--window-bottom); |
|
||||
left: var(--window-left); |
|
||||
right: var(--window-right); |
|
||||
// width: 100%; |
|
||||
background: #fff; |
|
||||
border-top: 1px solid #eee; |
|
||||
z-index: 11; |
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: calc(constant(safe-area-inset-bottom) + var(--window-bottom)); |
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + var(--window-bottom)); |
|
||||
|
|
||||
.chackout-left { |
|
||||
font-size: 28rpx; |
|
||||
line-height: 92rpx; |
|
||||
color: #777; |
|
||||
flex: 4; |
|
||||
padding-left: 12px; |
|
||||
} |
|
||||
|
|
||||
.chackout-right { |
|
||||
font-size: 34rpx; |
|
||||
flex: 2; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 提交按钮 |
|
||||
.flow-btn { |
|
||||
background: linear-gradient(to right, #f9211c, #ff6335); |
|
||||
color: #fff; |
|
||||
text-align: center; |
|
||||
line-height: 92rpx; |
|
||||
display: block; |
|
||||
font-size: 28rpx; |
|
||||
// 禁用按钮 |
|
||||
&.disabled { |
|
||||
background: #ff9779; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 积分说明 |
|
||||
.points-content { |
|
||||
padding: 30rpx 48rpx; |
|
||||
font-size: 28rpx; |
|
||||
line-height: 50rpx; |
|
||||
text-align: left; |
|
||||
color: #606266; |
|
||||
height: 620rpx; |
|
||||
box-sizing: border-box; |
|
||||
} |
|
||||
|
|
||||
/* 共几件商品 */ |
|
||||
.flow-num-box { |
|
||||
font-size: 28rpx; |
|
||||
color: #777; |
|
||||
padding: 16rpx 24rpx; |
|
||||
text-align: right; |
|
||||
} |
|
||||
|
|
||||
/* app.scss */ |
|
||||
.flow-shopList { |
|
||||
padding: 18rpx 0; |
|
||||
|
|
||||
.flow-list-left { |
|
||||
margin-right: 20rpx; |
|
||||
|
|
||||
image { |
|
||||
width: 180rpx; |
|
||||
height: 180rpx; |
|
||||
border: 1rpx solid #eee; |
|
||||
background: #fff; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.flow-list-right { |
|
||||
|
|
||||
.flow-cont { |
|
||||
font-size: 28rpx; |
|
||||
color: #fa2209; |
|
||||
} |
|
||||
|
|
||||
.small { |
|
||||
font-size: 26rpx; |
|
||||
color: #777; |
|
||||
} |
|
||||
|
|
||||
.flow-list-cont { |
|
||||
padding-top: 10rpx; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.flow-all-money { |
|
||||
padding: 0 24rpx; |
|
||||
color: #444; |
|
||||
|
|
||||
.flow-all-list { |
|
||||
font-size: 28rpx; |
|
||||
padding: 20rpx 0; |
|
||||
border-bottom: 1rpx solid rgb(248, 248, 248); |
|
||||
} |
|
||||
|
|
||||
.flow-all-list:last-child { |
|
||||
border-bottom: none; |
|
||||
} |
|
||||
|
|
||||
.flow-all-list-cont { |
|
||||
font-size: 28rpx; |
|
||||
padding: 10rpx 0; |
|
||||
} |
|
||||
|
|
||||
.flow-arrow { |
|
||||
justify-content: flex-end; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
@ -1,274 +0,0 @@ |
|||||
<template> |
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption" @up="upCallback"> |
|
||||
<!-- tab栏 --> |
|
||||
<u-tabs :list="tabs" :is-scroll="false" :current="curTab" active-color="#FA2209" :duration="0.2" @change="onChangeTab" /> |
|
||||
|
|
||||
<!-- 商品评价列表 --> |
|
||||
<view class="comment-list"> |
|
||||
<view class="comment-item" v-for="(item, index) in list.data" :key="index"> |
|
||||
<view class="item-head"> |
|
||||
<!-- 用户信息 --> |
|
||||
<view class="user-info"> |
|
||||
<avatar-image class="user-avatar" :url="item.user.avatar_url" :width="50" /> |
|
||||
<text class="user-name f-26">{{ item.user.nick_name }}</text> |
|
||||
</view> |
|
||||
<!-- 评星 --> |
|
||||
<u-rate active-color="#f4a213" :current="rates[item.score]" :disabled="true" /> |
|
||||
<!-- 评价日期--> |
|
||||
<view class="flex-box f-22 col-9 t-r">{{ item.create_time }}</view> |
|
||||
</view> |
|
||||
<!-- 评价内容 --> |
|
||||
<view class="item-content m-top20"> |
|
||||
<text class="f-26">{{ item.content }}</text> |
|
||||
</view> |
|
||||
<!-- 评价图片 --> |
|
||||
<view class="images-list clearfix" v-if="item.images.length"> |
|
||||
<view class="image-preview" v-for="(image, imgIdx) in item.images" :key="imgIdx"> |
|
||||
<image class="image" mode="aspectFill" :src="image.image_url" @click="onPreviewImages(index, imgIdx)"></image> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 商品规格 --> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in item.orderGoods.goods_props" :key="idx"> |
|
||||
<text class="group-name">{{ props.group.name }}: </text> |
|
||||
<text>{{ props.value.name }};</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</mescroll-body> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import AvatarImage from '@/components/avatar-image' |
|
||||
import { getEmptyPaginateObj, getMoreListData } from '@/core/app' |
|
||||
import * as CommentApi from '@/api/comment' |
|
||||
|
|
||||
const pageSize = 15 |
|
||||
const tabs = [{ |
|
||||
name: `全部`, |
|
||||
scoreType: -1 |
|
||||
}, { |
|
||||
name: `好评`, |
|
||||
scoreType: 10 |
|
||||
}, { |
|
||||
name: `中评`, |
|
||||
scoreType: 20 |
|
||||
}, { |
|
||||
name: `差评`, |
|
||||
scoreType: 30 |
|
||||
}] |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody, |
|
||||
AvatarImage |
|
||||
}, |
|
||||
mixins: [MescrollMixin], |
|
||||
data() { |
|
||||
return { |
|
||||
// 当前商品ID |
|
||||
goodsId: null, |
|
||||
// 当前标签索引 |
|
||||
curTab: 0, |
|
||||
// 评价列表数据 |
|
||||
list: getEmptyPaginateObj(), |
|
||||
// 评价总数量 |
|
||||
total: { all: 0, negative: 0, praise: 0, review: 0 }, |
|
||||
// 评星数据转换 |
|
||||
rates: { 10: 5, 20: 3, 30: 1 }, |
|
||||
// 标签栏数据 |
|
||||
tabs, |
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于4条才显示无更多数据 |
|
||||
noMoreSize: 4, |
|
||||
// 空布局 |
|
||||
empty: { |
|
||||
tip: '亲,暂无相关商品评价' |
|
||||
} |
|
||||
}, |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 记录属性值 |
|
||||
this.goodsId = options.goodsId |
|
||||
// 获取指定评分总数 |
|
||||
this.getTotal() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getCommentList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
// 加载评价列表数据 |
|
||||
getCommentList(pageNo = 1) { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
CommentApi.list(app.goodsId, { scoreType: app.getScoreType(), page: pageNo }, { load: false }) |
|
||||
.then(result => { |
|
||||
// 合并新数据 |
|
||||
const newList = result.data.list |
|
||||
app.list.data = getMoreListData(newList, app.list, pageNo) |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 评分类型 |
|
||||
getScoreType() { |
|
||||
return this.tabs[this.curTab].scoreType |
|
||||
}, |
|
||||
|
|
||||
// 获取指定评分总数 |
|
||||
getTotal() { |
|
||||
const app = this |
|
||||
CommentApi.total(app.goodsId) |
|
||||
.then(result => { |
|
||||
// tab标签内容 |
|
||||
const total = result.data.total |
|
||||
app.getTabs(total) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 获取tab标签内容 |
|
||||
getTabs(total) { |
|
||||
const tabs = this.tabs |
|
||||
tabs[0].name = `全部(${total.all})` |
|
||||
tabs[1].name = `好评(${total.praise})` |
|
||||
tabs[2].name = `中评(${total.review})` |
|
||||
tabs[3].name = `差评(${total.negative})` |
|
||||
}, |
|
||||
|
|
||||
// 切换标签项 |
|
||||
onChangeTab(index) { |
|
||||
const app = this |
|
||||
// 设置当前选中的标签 |
|
||||
app.curTab = index |
|
||||
// 刷新评价列表 |
|
||||
app.onRefreshList() |
|
||||
}, |
|
||||
|
|
||||
// 刷新评价列表 |
|
||||
onRefreshList() { |
|
||||
this.list = getEmptyPaginateObj() |
|
||||
setTimeout(() => { |
|
||||
this.mescroll.resetUpScroll() |
|
||||
}, 120) |
|
||||
}, |
|
||||
|
|
||||
// 预览评价图片 |
|
||||
onPreviewImages(dataIdx, imgIndex) { |
|
||||
const app = this |
|
||||
const images = app.list.data[dataIdx].images |
|
||||
const imageUrls = images.map(item => item.image_url) |
|
||||
uni.previewImage({ |
|
||||
current: imageUrls[imgIndex], |
|
||||
urls: imageUrls |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.comment-item { |
|
||||
padding: 30rpx; |
|
||||
box-sizing: border-box; |
|
||||
border-bottom: 1rpx solid #f7f7f7; |
|
||||
background: #fff; |
|
||||
} |
|
||||
|
|
||||
.item-head { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
|
|
||||
// 用户信息 |
|
||||
.user-info { |
|
||||
margin-right: 15rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
|
|
||||
.user-avatar { |
|
||||
margin-right: 15rpx; |
|
||||
} |
|
||||
|
|
||||
.user-name { |
|
||||
color: #999; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 评价内容 |
|
||||
.item-content { |
|
||||
font-size: 30rpx; |
|
||||
color: #333; |
|
||||
margin: 16rpx 0; |
|
||||
} |
|
||||
|
|
||||
// 评价图片 |
|
||||
.images-list { |
|
||||
&::after { |
|
||||
clear: both; |
|
||||
content: " "; |
|
||||
display: table; |
|
||||
} |
|
||||
|
|
||||
.image-preview { |
|
||||
float: left; |
|
||||
margin-bottom: 15rpx; |
|
||||
margin-right: 15rpx; |
|
||||
|
|
||||
&:nth-child(3n+0) { |
|
||||
margin-right: 0; |
|
||||
} |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 220rpx; |
|
||||
height: 220rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品规格 |
|
||||
.goods-props { |
|
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
float: left; |
|
||||
|
|
||||
.group-name { |
|
||||
margin-right: 6rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,250 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<view v-if="list.length" class="coupon-list"> |
|
||||
<view class="coupon-item" v-for="(item, index) in list" :key="index"> |
|
||||
<view class="item-wrapper" |
|
||||
:class="[ item.state.value ? 'color-' + color[index % color.length] : 'color-gray' ]"> |
|
||||
<view class="coupon-type">{{ CouponTypeEnum[item.coupon_type].name }}</view> |
|
||||
<view class="tip dis-flex flex-dir-column flex-x-center"> |
|
||||
<view v-if="item.coupon_type == CouponTypeEnum.FULL_DISCOUNT.value"> |
|
||||
<text class="f-30">¥</text> |
|
||||
<text class="money">{{ item.reduce_price }}</text> |
|
||||
</view> |
|
||||
<text class="money" v-if="item.coupon_type == CouponTypeEnum.DISCOUNT.value">{{ item.discount }}折</text> |
|
||||
<text class="pay-line">满{{ item.min_price }}元可用</text> |
|
||||
</view> |
|
||||
<view class="split-line"></view> |
|
||||
<view class="content dis-flex flex-dir-column flex-x-between"> |
|
||||
<view class="title oneline-hide">{{ item.name }}</view> |
|
||||
<view class="bottom dis-flex flex-y-center"> |
|
||||
<view class="time flex-box"> |
|
||||
<text v-if="item.expire_type == 10">领取{{ item.expire_day }}天内有效</text> |
|
||||
<text v-if="item.expire_type == 20"> |
|
||||
<block v-if="item.start_time === item.end_time">{{ item.start_time }} 当天有效</block> |
|
||||
<block v-else>{{ item.start_time }}~{{ item.end_time }}</block> |
|
||||
</text> |
|
||||
</view> |
|
||||
<view class="receive" v-if="item.state.value" @click="receive(item.coupon_id)"> |
|
||||
<text>立即领取</text> |
|
||||
</view> |
|
||||
<view v-else class="receive state"> |
|
||||
<text>{{ item.state.text }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<empty v-if="!list.length" :isLoading="isLoading" /> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as CouponApi from '@/api/coupon' |
|
||||
import * as MyCouponApi from '@/api/myCoupon' |
|
||||
import { CouponTypeEnum } from '@/common/enum/coupon' |
|
||||
import Empty from '@/components/empty' |
|
||||
|
|
||||
const color = ['red', 'blue', 'violet', 'yellow'] |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
Empty |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
CouponTypeEnum, |
|
||||
// 颜色组 |
|
||||
color, |
|
||||
// 优惠券列表 |
|
||||
list: [], |
|
||||
// 正在加载中 |
|
||||
isLoading: true |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 获取优惠券列表 |
|
||||
this.getCouponList() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 获取优惠券列表 |
|
||||
* @param {bool} load 是否显示loading弹窗 |
|
||||
*/ |
|
||||
getCouponList(load = true) { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
CouponApi.list({}, { load }) |
|
||||
.then(result => { |
|
||||
app.list = result.data.list |
|
||||
}) |
|
||||
.finally(() => app.isLoading = false) |
|
||||
}, |
|
||||
|
|
||||
// 立即领取 |
|
||||
receive(couponId) { |
|
||||
const app = this |
|
||||
MyCouponApi.receive(couponId) |
|
||||
.then(result => { |
|
||||
// 显示领取成功提示 |
|
||||
app.$success(result.message) |
|
||||
// 刷新优惠券列表 |
|
||||
app.getCouponList(false) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.coupon-list { |
|
||||
padding: 20rpx; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.coupon-item { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
margin-bottom: 22rpx; |
|
||||
} |
|
||||
|
|
||||
.item-wrapper { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
background: #fff; |
|
||||
border-radius: 8rpx; |
|
||||
color: #fff; |
|
||||
height: 180rpx; |
|
||||
|
|
||||
.coupon-type { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
z-index: 10; |
|
||||
width: 128rpx; |
|
||||
padding: 3px 0; |
|
||||
background: #a771ff; |
|
||||
font-size: 20rpx; |
|
||||
text-align: center; |
|
||||
color: #ffffff; |
|
||||
transform: rotate(45deg); |
|
||||
transform-origin: 64rpx 64rpx; |
|
||||
} |
|
||||
|
|
||||
&.color-blue { |
|
||||
background: linear-gradient(-125deg, #57bdbf, #2f9de2); |
|
||||
} |
|
||||
|
|
||||
&.color-red { |
|
||||
background: linear-gradient(-128deg, #ff6d6d, #ff3636); |
|
||||
} |
|
||||
|
|
||||
&.color-violet { |
|
||||
background: linear-gradient(-113deg, #ef86ff, #b66ff5); |
|
||||
|
|
||||
.coupon-type { |
|
||||
background: #55b5ff; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&.color-yellow { |
|
||||
background: linear-gradient(-141deg, #f7d059, #fdb054); |
|
||||
} |
|
||||
|
|
||||
&.color-gray { |
|
||||
background: linear-gradient(-113deg, #bdbdbd, #a2a1a2); |
|
||||
|
|
||||
.coupon-type { |
|
||||
background: #9e9e9e; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.content { |
|
||||
flex: 1; |
|
||||
padding: 30rpx 20rpx; |
|
||||
border-radius: 8px 0 0 8px; |
|
||||
|
|
||||
.title { |
|
||||
width: 400rpx; |
|
||||
font-size: 32rpx; |
|
||||
} |
|
||||
|
|
||||
.bottom { |
|
||||
.time { |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
|
|
||||
.receive { |
|
||||
height: 46rpx; |
|
||||
width: 122rpx; |
|
||||
line-height: 46rpx; |
|
||||
text-align: center; |
|
||||
border: 1px solid #fff; |
|
||||
border-radius: 30rpx; |
|
||||
color: #fff; |
|
||||
font-size: 24rpx; |
|
||||
|
|
||||
&.state { |
|
||||
border: none; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.tip { |
|
||||
position: relative; |
|
||||
flex: 0 0 32%; |
|
||||
text-align: center; |
|
||||
border-radius: 0 8px 8px 0; |
|
||||
|
|
||||
.money { |
|
||||
font-weight: bold; |
|
||||
font-size: 52rpx; |
|
||||
} |
|
||||
|
|
||||
.pay-line { |
|
||||
font-size: 22rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.split-line { |
|
||||
position: relative; |
|
||||
flex: 0 0 0; |
|
||||
border-left: 4rpx solid #fff; |
|
||||
margin: 0 5px 0 3px; |
|
||||
background: #fff; |
|
||||
|
|
||||
&:before, |
|
||||
{ |
|
||||
border-radius: 0 0 16rpx 16rpx; |
|
||||
top: 0; |
|
||||
} |
|
||||
|
|
||||
&:after { |
|
||||
border-radius: 16rpx 16rpx 0 0; |
|
||||
bottom: 0; |
|
||||
} |
|
||||
|
|
||||
&:before, |
|
||||
&:after { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
width: 24rpx; |
|
||||
height: 12rpx; |
|
||||
background: #f7f7f7; |
|
||||
left: -14rpx; |
|
||||
z-index: 1; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,120 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<!-- 店铺页面组件 --> |
|
||||
<Page :items="items" /> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as Api from '@/api/page' |
|
||||
import Page from '@/components/page' |
|
||||
|
|
||||
const App = getApp() |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
Page |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
// 页面参数 |
|
||||
options: {}, |
|
||||
// 页面属性 |
|
||||
page: {}, |
|
||||
// 页面元素 |
|
||||
items: [] |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 当前页面参数 |
|
||||
this.options = options |
|
||||
// 加载页面数据 |
|
||||
this.getPageData() |
|
||||
}, |
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 加载页面数据 |
|
||||
* @param {Object} callback |
|
||||
*/ |
|
||||
getPageData(callback) { |
|
||||
const app = this |
|
||||
const pageId = app.options.pageId || 0 |
|
||||
Api.detail(pageId) |
|
||||
.then(result => { |
|
||||
// 设置页面数据 |
|
||||
const { data: { pageData } } = result |
|
||||
app.page = pageData.page |
|
||||
app.items = pageData.items |
|
||||
// 设置顶部导航栏栏 |
|
||||
app.setPageBar(); |
|
||||
}) |
|
||||
.finally(() => callback && callback()) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 设置顶部导航栏 |
|
||||
*/ |
|
||||
setPageBar() { |
|
||||
const { page } = this |
|
||||
// 设置页面标题 |
|
||||
uni.setNavigationBarTitle({ |
|
||||
title: page.params.title |
|
||||
}) |
|
||||
// 设置navbar标题、颜色 |
|
||||
uni.setNavigationBarColor({ |
|
||||
frontColor: page.style.titleTextColor === 'white' ? '#ffffff' : '#000000', |
|
||||
backgroundColor: page.style.titleBackgroundColor |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 下拉刷新 |
|
||||
*/ |
|
||||
onPullDownRefresh() { |
|
||||
// 获取首页数据 |
|
||||
this.getPageData(() => { |
|
||||
uni.stopPullDownRefresh() |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 分享当前页面 |
|
||||
*/ |
|
||||
onShareAppMessage() { |
|
||||
const app = this |
|
||||
const { page } = app |
|
||||
return { |
|
||||
title: page.params.share_title, |
|
||||
path: "/pages/index/index?" + app.$getShareUrlParams() |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 分享到朋友圈 |
|
||||
* 本接口为 Beta 版本,暂只在 Android 平台支持,详见分享到朋友圈 (Beta) |
|
||||
* https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share-timeline.html |
|
||||
*/ |
|
||||
onShareTimeline() { |
|
||||
const app = this |
|
||||
const { page } = app |
|
||||
return { |
|
||||
title: page.params.share_title, |
|
||||
path: "/pages/index/index?" + app.$getShareUrlParams() |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.container { |
|
||||
background: #fff; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,162 +0,0 @@ |
|||||
<template> |
|
||||
<!-- 商品评价 --> |
|
||||
<view v-if="!isLoading && list.length" class="goods-comment m-top20"> |
|
||||
<view class="item-title dis-flex"> |
|
||||
<view class="block-left flex-box"> |
|
||||
商品评价 (<text class="total">{{ total }}条</text>) |
|
||||
</view> |
|
||||
<view class="block-right"> |
|
||||
<text @click="onTargetToComment" class="show-more col-9">查看更多</text> |
|
||||
<text class="iconfont icon-arrow-right"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 评论列表 --> |
|
||||
<view class="comment-list"> |
|
||||
<view class="comment-item" v-for="(item, index) in list" :key="index"> |
|
||||
<view class="comment-item_row dis-flex flex-y-center"> |
|
||||
<view class="user-info dis-flex flex-y-center"> |
|
||||
<avatar-image class="user-avatar" :url="item.user.avatar_url" :width="50" /> |
|
||||
<text class="user-name">{{ item.user.nick_name }}</text> |
|
||||
</view> |
|
||||
<!-- 评星 --> |
|
||||
<view class="star-rating"> |
|
||||
<u-rate active-color="#f4a213" :current="rates[item.score]" :disabled="true" /> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="item-content m-top20"> |
|
||||
<text class="f-26 twoline-hide">{{ item.content }}</text> |
|
||||
</view> |
|
||||
<view class="comment-time">{{ item.create_time }}</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import AvatarImage from '@/components/avatar-image' |
|
||||
import * as CommentApi from '@/api/comment' |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
AvatarImage |
|
||||
}, |
|
||||
props: { |
|
||||
// 商品ID |
|
||||
goodsId: { |
|
||||
type: Number, |
|
||||
default: null |
|
||||
}, |
|
||||
// 加载多少条记录 默认2条 |
|
||||
limit: { |
|
||||
type: Number, |
|
||||
default: 2 |
|
||||
} |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 评星数据转换 |
|
||||
rates: { 10: 5, 20: 3, 30: 1 }, |
|
||||
// 评价列表数据 |
|
||||
list: [], |
|
||||
// 评价总数量 |
|
||||
total: 0 |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
created() { |
|
||||
// 加载评价列表数据 |
|
||||
this.getCommentList() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 加载评价列表数据 |
|
||||
getCommentList() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
CommentApi.listRows(app.goodsId, app.limit) |
|
||||
.then(result => { |
|
||||
app.list = result.data.list |
|
||||
app.total = result.data.total |
|
||||
}) |
|
||||
.catch(err => err) |
|
||||
.finally(() => app.isLoading = false) |
|
||||
}, |
|
||||
|
|
||||
// 跳转到评论列表页 |
|
||||
onTargetToComment() { |
|
||||
const app = this |
|
||||
app.$navTo('pages/comment/index', { goodsId: app.goodsId }) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.goods-comment { |
|
||||
padding: 20rpx 30rpx; |
|
||||
background-color: #fff; |
|
||||
} |
|
||||
|
|
||||
.item-title { |
|
||||
font-size: 28rpx; |
|
||||
margin-bottom: 25rpx; |
|
||||
|
|
||||
.total { |
|
||||
margin: 0 4rpx; |
|
||||
} |
|
||||
|
|
||||
.show-more { |
|
||||
margin-right: 8rpx; |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.comment-item { |
|
||||
padding: 15rpx 5rpx; |
|
||||
margin-bottom: 10rpx; |
|
||||
border-bottom: 1rpx solid #f5f5f5; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
border-bottom: none; |
|
||||
} |
|
||||
|
|
||||
.comment-item_row { |
|
||||
margin-bottom: 10rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.user-info { |
|
||||
margin-right: 15rpx; |
|
||||
|
|
||||
.user-avatar { |
|
||||
width: 50rpx; |
|
||||
height: 50rpx; |
|
||||
border-radius: 50%; |
|
||||
margin-right: 10rpx; |
|
||||
} |
|
||||
|
|
||||
.user-name { |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.item-content { |
|
||||
color: #333; |
|
||||
margin: 16rpx 0; |
|
||||
max-height: 76rpx; |
|
||||
line-height: 38rpx; |
|
||||
} |
|
||||
|
|
||||
.comment-time { |
|
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
margin-top: 10rpx; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,158 +0,0 @@ |
|||||
<template> |
|
||||
<view v-if="list.length" class="service-wrapper"> |
|
||||
<!-- 服务简述 --> |
|
||||
<view class="service-simple" @click="handlePopup"> |
|
||||
<view class="s-list"> |
|
||||
<view class="s-item" v-for="(item, index) in list" :key="index"> |
|
||||
<text class="item-icon iconfont icon-fuwu"></text> |
|
||||
<text class="item-val">{{ item.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 扩展箭头 --> |
|
||||
<view class="s-arrow f-26 col-9 t-r"> |
|
||||
<text class="iconfont icon-arrow-right"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 详情内容弹窗 --> |
|
||||
<u-popup v-model="showPopup" mode="bottom" :closeable="true" :border-radius="26"> |
|
||||
<view class="service-content"> |
|
||||
<view class="title">服务</view> |
|
||||
<scroll-view class="content-scroll" :scroll-y="true"> |
|
||||
<view class="s-list clearfix"> |
|
||||
<view class="s-item" v-for="(item, index) in list" :key="index"> |
|
||||
<text class="item-icon iconfont icon-fuwu"></text> |
|
||||
<view class="item-val">{{ item.name }}</view> |
|
||||
<view class="item-summary">{{ item.summary }}</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</scroll-view> |
|
||||
</view> |
|
||||
</u-popup> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as ServiceApi from '@/api/goods/service' |
|
||||
|
|
||||
export default { |
|
||||
props: { |
|
||||
// 商品ID |
|
||||
goodsId: { |
|
||||
type: Number, |
|
||||
default: null |
|
||||
} |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 显示详情内容弹窗 |
|
||||
showPopup: false, |
|
||||
// 服务列表数据 |
|
||||
list: [] |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
created() { |
|
||||
// 获取商品服务列表 |
|
||||
this.getServiceList() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取商品服务列表 |
|
||||
getServiceList() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
ServiceApi.list(app.goodsId) |
|
||||
.then(result => app.list = result.data.list) |
|
||||
.finally(() => app.isLoading = false) |
|
||||
}, |
|
||||
|
|
||||
// 显示弹窗 |
|
||||
handlePopup() { |
|
||||
this.showPopup = !this.showPopup |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.service-wrapper { |
|
||||
min-height: 24rpx; |
|
||||
margin-bottom: -24rpx; |
|
||||
} |
|
||||
|
|
||||
// 服务简述 |
|
||||
.service-simple { |
|
||||
padding: 24rpx 30rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
|
|
||||
.s-list { |
|
||||
flex: 1; |
|
||||
margin-left: -15rpx; |
|
||||
} |
|
||||
|
|
||||
.s-item { |
|
||||
float: left; |
|
||||
font-size: 26rpx; |
|
||||
margin: 8rpx 15rpx; |
|
||||
|
|
||||
.item-icon { |
|
||||
color: #FA2209; |
|
||||
} |
|
||||
|
|
||||
.item-val { |
|
||||
margin-left: 12rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 服务详细内容 |
|
||||
.service-content { |
|
||||
padding: 24rpx; |
|
||||
|
|
||||
.title { |
|
||||
font-size: 30rpx; |
|
||||
margin-bottom: 50rpx; |
|
||||
font-weight: bold; |
|
||||
text-align: center; |
|
||||
} |
|
||||
|
|
||||
.content-scroll { |
|
||||
min-height: 400rpx; |
|
||||
max-height: 760rpx; |
|
||||
} |
|
||||
|
|
||||
.s-list { |
|
||||
padding: 0 30rpx 0 80rpx; |
|
||||
} |
|
||||
|
|
||||
.s-item { |
|
||||
position: relative; |
|
||||
margin-bottom: 60rpx; |
|
||||
|
|
||||
.item-icon { |
|
||||
position: absolute; |
|
||||
top: 6rpx; |
|
||||
left: -50rpx; |
|
||||
color: #FA2209; |
|
||||
} |
|
||||
|
|
||||
.item-val { |
|
||||
font-size: 28rpx; |
|
||||
} |
|
||||
|
|
||||
.item-summary { |
|
||||
font-size: 26rpx; |
|
||||
margin-top: 20rpx; |
|
||||
color: #6d6d6d; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</style> |
|
||||
@ -1,173 +0,0 @@ |
|||||
<template> |
|
||||
<goods-sku-popup :value="value" @input="onChangeValue" border-radius="20" :localdata="goodsInfo" :mode="skuMode" |
|
||||
:maskCloseAble="true" @open="openSkuPopup" @close="closeSkuPopup" @add-cart="addCart" @buy-now="buyNow" |
|
||||
buyNowText="立即购买" /> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { setCartTotalNum } from '@/core/app' |
|
||||
import * as CartApi from '@/api/cart' |
|
||||
import GoodsSkuPopup from '@/components/goods-sku-popup' |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
GoodsSkuPopup |
|
||||
}, |
|
||||
model: { |
|
||||
prop: 'value', |
|
||||
event: 'input' |
|
||||
}, |
|
||||
props: { |
|
||||
// true 组件显示 false 组件隐藏 |
|
||||
value: { |
|
||||
Type: Boolean, |
|
||||
default: false |
|
||||
}, |
|
||||
// 模式 1:都显示 2:只显示购物车 3:只显示立即购买 |
|
||||
skuMode: { |
|
||||
type: Number, |
|
||||
default: 1 |
|
||||
}, |
|
||||
// 商品详情信息 |
|
||||
goods: { |
|
||||
type: Object, |
|
||||
default: {} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
data() { |
|
||||
return { |
|
||||
goodsInfo: {} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
created() { |
|
||||
const app = this |
|
||||
const { goods } = app |
|
||||
app.goodsInfo = { |
|
||||
_id: goods.goods_id, |
|
||||
name: goods.goods_name, |
|
||||
goods_thumb: goods.goods_image, |
|
||||
sku_list: app.getSkuList(), |
|
||||
spec_list: app.getSpecList() |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 监听组件显示隐藏 |
|
||||
onChangeValue(val) { |
|
||||
this.$emit('input', val) |
|
||||
}, |
|
||||
|
|
||||
// 整理商品SKU列表 |
|
||||
getSkuList() { |
|
||||
const app = this |
|
||||
const { goods: { goods_name, goods_image, skuList } } = app |
|
||||
const skuData = [] |
|
||||
skuList.forEach(item => { |
|
||||
skuData.push({ |
|
||||
_id: item.id, |
|
||||
goods_sku_id: item.goods_sku_id, |
|
||||
goods_id: item.goods_id, |
|
||||
goods_name: goods_name, |
|
||||
image: item.image_url ? item.image_url : goods_image, |
|
||||
price: item.goods_price * 100, |
|
||||
stock: item.stock_num, |
|
||||
spec_value_ids: item.spec_value_ids, |
|
||||
sku_name_arr: app.getSkuNameArr(item.spec_value_ids) |
|
||||
}) |
|
||||
}) |
|
||||
return skuData |
|
||||
}, |
|
||||
|
|
||||
// 获取sku记录的规格值列表 |
|
||||
getSkuNameArr(specValueIds) { |
|
||||
const app = this |
|
||||
const defaultData = ['默认'] |
|
||||
const skuNameArr = [] |
|
||||
if (specValueIds) { |
|
||||
specValueIds.forEach((valueId, groupIndex) => { |
|
||||
const specValueName = app.getSpecValueName(valueId, groupIndex) |
|
||||
skuNameArr.push(specValueName) |
|
||||
}) |
|
||||
} |
|
||||
return skuNameArr.length ? skuNameArr : defaultData |
|
||||
}, |
|
||||
|
|
||||
// 获取指定的规格值名称 |
|
||||
getSpecValueName(valueId, groupIndex) { |
|
||||
const app = this |
|
||||
const { goods: { specList } } = app |
|
||||
const res = specList[groupIndex].valueList.find(specValue => { |
|
||||
return specValue.spec_value_id == valueId |
|
||||
}) |
|
||||
return res.spec_value |
|
||||
}, |
|
||||
|
|
||||
// 整理规格数据 |
|
||||
getSpecList() { |
|
||||
const { goods: { specList } } = this |
|
||||
const defaultData = [{ name: '默认', list: [{ name: '默认' }] }] |
|
||||
const specData = [] |
|
||||
specList.forEach(group => { |
|
||||
const children = [] |
|
||||
group.valueList.forEach(specValue => { |
|
||||
children.push({ name: specValue.spec_value }) |
|
||||
}) |
|
||||
specData.push({ |
|
||||
name: group.spec_name, |
|
||||
list: children |
|
||||
}) |
|
||||
}) |
|
||||
return specData.length ? specData : defaultData |
|
||||
}, |
|
||||
|
|
||||
// sku组件 开始----------------------------------------------------------- |
|
||||
openSkuPopup() { |
|
||||
// console.log("监听 - 打开sku组件") |
|
||||
}, |
|
||||
|
|
||||
closeSkuPopup() { |
|
||||
// console.log("监听 - 关闭sku组件") |
|
||||
}, |
|
||||
|
|
||||
// 加入购物车按钮 |
|
||||
addCart(selectShop) { |
|
||||
const app = this |
|
||||
const { goods_id, goods_sku_id, buy_num } = selectShop |
|
||||
CartApi.add(goods_id, goods_sku_id, buy_num) |
|
||||
.then(result => { |
|
||||
// 显示成功 |
|
||||
app.$toast(result.message) |
|
||||
// 隐藏当前弹窗 |
|
||||
app.onChangeValue(false) |
|
||||
// 购物车商品总数量 |
|
||||
const cartTotal = result.data.cartTotal |
|
||||
// 缓存购物车数量 |
|
||||
setCartTotalNum(cartTotal) |
|
||||
// 传递给父级 |
|
||||
app.$emit('addCart', cartTotal) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 立即购买 |
|
||||
buyNow(selectShop) { |
|
||||
// 跳转到订单结算页 |
|
||||
this.$navTo('pages/checkout/index', { |
|
||||
mode: 'buyNow', |
|
||||
goodsId: selectShop.goods_id, |
|
||||
goodsSkuId: selectShop.goods_sku_id, |
|
||||
goodsNum: selectShop.buy_num |
|
||||
}) |
|
||||
// 隐藏当前弹窗 |
|
||||
this.onChangeValue(false) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
|
|
||||
</style> |
|
||||
@ -1,146 +0,0 @@ |
|||||
<template> |
|
||||
<!-- 商品图片 --> |
|
||||
<view class="images-swiper"> |
|
||||
<swiper class="swiper-box" :autoplay="autoplay" :duration="duration" :indicator-dots="indicatorDots" |
|
||||
:interval="interval" :circular="true" @change="setCurrent"> |
|
||||
<!-- 主图视频 --> |
|
||||
<swiper-item v-if="video"> |
|
||||
<view class="slide-video"> |
|
||||
<video id="myVideo" class="video" :poster="videoCover.preview_url" :src="video.external_url" controls |
|
||||
x5-playsinline playsinline webkit-playsinline webkit-playsinline x5-video-player-type="h5" |
|
||||
x5-video-player-fullscreen x5-video-orientation="portrait" :enable-progress-gesture="false" |
|
||||
@play="onVideoPlay"></video> |
|
||||
</view> |
|
||||
</swiper-item> |
|
||||
<!-- 轮播图片 --> |
|
||||
<swiper-item v-for="(item, index) in images" :key="index" @click="onPreviewImages(index)"> |
|
||||
<view class="slide-image"> |
|
||||
<image class="image" :draggable="false" :src="item.preview_url"></image> |
|
||||
</view> |
|
||||
</swiper-item> |
|
||||
</swiper> |
|
||||
<view class="swiper-count"> |
|
||||
<text>{{ currentIndex }}</text> |
|
||||
<text>/</text> |
|
||||
<text>{{ images.length + (video ? 1 : 0) }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
export default { |
|
||||
props: { |
|
||||
// 主图视频 |
|
||||
video: { |
|
||||
type: Object, |
|
||||
default () { |
|
||||
return null |
|
||||
} |
|
||||
}, |
|
||||
// 主图视频封面 |
|
||||
videoCover: { |
|
||||
type: Object, |
|
||||
default () { |
|
||||
return null |
|
||||
} |
|
||||
}, |
|
||||
// 图片轮播 |
|
||||
images: { |
|
||||
type: Array, |
|
||||
default: [] |
|
||||
} |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
indicatorDots: true, // 是否显示面板指示点 |
|
||||
autoplay: true, // 是否自动切换 |
|
||||
interval: 4000, // 自动切换时间间隔 |
|
||||
duration: 800, // 滑动动画时长 |
|
||||
currentIndex: 1, // 轮播图指针 |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 事件:视频开始播放 |
|
||||
onVideoPlay(e) { |
|
||||
this.autoplay = false |
|
||||
}, |
|
||||
|
|
||||
// 设置轮播图当前指针 数字 |
|
||||
setCurrent({ detail }) { |
|
||||
const app = this |
|
||||
app.currentIndex = detail.current + 1 |
|
||||
}, |
|
||||
|
|
||||
// 浏览商品图片 |
|
||||
onPreviewImages(index) { |
|
||||
const app = this |
|
||||
const imageUrls = [] |
|
||||
app.images.forEach(item => { |
|
||||
imageUrls.push(item.preview_url); |
|
||||
}); |
|
||||
uni.previewImage({ |
|
||||
current: imageUrls[index], |
|
||||
urls: imageUrls |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
// swiper组件 |
|
||||
.images-swiper { |
|
||||
position: relative; |
|
||||
} |
|
||||
|
|
||||
.swiper-box { |
|
||||
width: 100%; |
|
||||
height: 100vw; |
|
||||
|
|
||||
/* #ifdef H5 */ |
|
||||
max-width: 480px; |
|
||||
max-height: 480px; |
|
||||
margin: 0 auto; |
|
||||
/* #endif */ |
|
||||
|
|
||||
// 主图视频 |
|
||||
.slide-video { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
|
|
||||
.video { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 图片轮播 |
|
||||
.slide-image { |
|
||||
position: relative; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// swiper计数 |
|
||||
.swiper-count { |
|
||||
position: absolute; |
|
||||
right: 36rpx; |
|
||||
bottom: 72rpx; |
|
||||
padding: 2rpx 18rpx; |
|
||||
background: rgba(0, 0, 0, 0.363); |
|
||||
border-radius: 50rpx; |
|
||||
color: #fff; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,227 +0,0 @@ |
|||||
.container { |
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
// 110 - 18 + 4 |
|
||||
padding-bottom: calc(constant(safe-area-inset-bottom) + 106rpx + 6rpx); |
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 106rpx + 6rpx); |
|
||||
} |
|
||||
|
|
||||
// 商品信息 |
|
||||
.goods-info { |
|
||||
background: #fff; |
|
||||
padding: 25rpx 30rpx; |
|
||||
} |
|
||||
|
|
||||
.info-item__top { |
|
||||
min-height: 40rpx; |
|
||||
margin-bottom: 20rpx; |
|
||||
line-height: 1; |
|
||||
} |
|
||||
|
|
||||
.floor-price__samll { |
|
||||
font-size: 26rpx; |
|
||||
line-height: 1; |
|
||||
color: #FA2209; |
|
||||
margin-bottom: -10rpx; |
|
||||
} |
|
||||
|
|
||||
// 商品价 |
|
||||
.floor-price { |
|
||||
color: #FA2209; |
|
||||
margin-right: 15rpx; |
|
||||
font-size: 42rpx; |
|
||||
} |
|
||||
|
|
||||
.original-price { |
|
||||
font-size: 26rpx; |
|
||||
text-decoration: line-through; |
|
||||
color: #959595; |
|
||||
margin-right: 15rpx; |
|
||||
margin-bottom: -6rpx; |
|
||||
} |
|
||||
|
|
||||
// 会员价标签 |
|
||||
.user-grade { |
|
||||
background: #3c3c3c; |
|
||||
border-radius: 6rpx; |
|
||||
padding: 8rpx 14rpx; |
|
||||
margin-right: 15rpx; |
|
||||
font-size: 24rpx; |
|
||||
color: #EEE0C3; |
|
||||
} |
|
||||
|
|
||||
.goods-sales { |
|
||||
font-size: 24rpx; |
|
||||
color: #959595; |
|
||||
} |
|
||||
|
|
||||
.info-item__name .goods-name { |
|
||||
font-size: 30rpx; |
|
||||
} |
|
||||
|
|
||||
/* 商品分享 */ |
|
||||
|
|
||||
.goods-share__line { |
|
||||
border-left: 1rpx solid #f4f4f4; |
|
||||
height: 60rpx; |
|
||||
margin: 0 30rpx; |
|
||||
} |
|
||||
|
|
||||
.goods-share .share-btn { |
|
||||
line-height: normal; |
|
||||
padding: 0; |
|
||||
background: none; |
|
||||
border-radius: 0; |
|
||||
box-shadow: none; |
|
||||
font-size: 8pt; |
|
||||
border: none; |
|
||||
color: #191919; |
|
||||
} |
|
||||
|
|
||||
.goods-share .share-btn::after { |
|
||||
border: none; |
|
||||
} |
|
||||
|
|
||||
.goods-share .share__icon { |
|
||||
font-size: 40rpx; |
|
||||
margin-bottom: 5rpx; |
|
||||
} |
|
||||
|
|
||||
// 商品卖点 |
|
||||
.info-item_selling-point { |
|
||||
margin-top: 8rpx; |
|
||||
font-size: 24rpx; |
|
||||
color: #808080; |
|
||||
} |
|
||||
|
|
||||
// 选择商品规格 |
|
||||
.goods-choice { |
|
||||
padding: 26rpx 30rpx; |
|
||||
font-size: 28rpx; |
|
||||
|
|
||||
.spec-list { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
|
|
||||
.spec-name { |
|
||||
margin-right: 10rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品详情 |
|
||||
.goods-content .item-title { |
|
||||
padding: 26rpx 30rpx; |
|
||||
font-size: 28rpx; |
|
||||
} |
|
||||
|
|
||||
// 底部操作栏 |
|
||||
.footer-fixed { |
|
||||
position: fixed; |
|
||||
bottom: var(--window-bottom); |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
display: flex; |
|
||||
z-index: 11; |
|
||||
box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24); |
|
||||
background: #fff; |
|
||||
|
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: constant(safe-area-inset-bottom); |
|
||||
padding-bottom: env(safe-area-inset-bottom); |
|
||||
} |
|
||||
|
|
||||
.footer-container { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
height: 106rpx; |
|
||||
} |
|
||||
|
|
||||
// 快捷菜单 |
|
||||
.foo-item-fast { |
|
||||
box-sizing: border-box; |
|
||||
min-width: 214rpx; |
|
||||
line-height: 1; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: space-evenly; |
|
||||
margin-right: 12rpx; |
|
||||
|
|
||||
.fast-item { |
|
||||
position: relative; |
|
||||
padding: 4rpx 0; |
|
||||
line-height: 1; |
|
||||
text-align: center; |
|
||||
width: 84rpx; |
|
||||
|
|
||||
&--cart { |
|
||||
margin-left: 6rpx; |
|
||||
.fast-icon { margin-left: -12rpx; } |
|
||||
} |
|
||||
|
|
||||
// 角标 |
|
||||
.fast-badge { |
|
||||
display: inline-block; |
|
||||
box-sizing: border-box; |
|
||||
min-width: 16px; |
|
||||
padding: 0 3px; |
|
||||
color: #fff; |
|
||||
font-weight: 500; |
|
||||
font-size: 12px; |
|
||||
font-family: -apple-system-font, Helvetica Neue, Arial, sans-serif; |
|
||||
line-height: 1.2; |
|
||||
text-align: center; |
|
||||
background-color: #ee0a24; |
|
||||
border: 1px solid #fff; |
|
||||
border-radius: 999px; |
|
||||
} |
|
||||
|
|
||||
.fast-badge--fixed { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
transform-origin: 100% |
|
||||
} |
|
||||
|
|
||||
.fast-icon { |
|
||||
font-size: 44rpx; |
|
||||
margin-bottom: 8rpx; |
|
||||
} |
|
||||
|
|
||||
.fast-text { |
|
||||
font-size: 22rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 操作按钮 |
|
||||
.foo-item-btn { |
|
||||
flex: 1; |
|
||||
|
|
||||
.btn-wrapper { |
|
||||
height: 100%; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.btn-item { |
|
||||
flex: 1; |
|
||||
font-size: 28rpx; |
|
||||
height: 72rpx; |
|
||||
margin-right: 16rpx; |
|
||||
color: #fff; |
|
||||
border-radius: 50rpx; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
// 立即购买按钮 |
|
||||
.btn-item-main { |
|
||||
background: linear-gradient(to right, #f9211c, #ff6335); |
|
||||
} |
|
||||
|
|
||||
// 购物车按钮 |
|
||||
.btn-item-deputy { |
|
||||
background: linear-gradient(to right, #ffa600, #ffbb00); |
|
||||
} |
|
||||
} |
|
||||
@ -1,290 +0,0 @@ |
|||||
<template> |
|
||||
<view v-show="!isLoading" class="container"> |
|
||||
<!-- 商品图片轮播 --> |
|
||||
<SlideImage v-if="!isLoading" :video="goods.video" :videoCover="goods.videoCover" :images="goods.goods_images" /> |
|
||||
|
|
||||
<!-- 商品信息 --> |
|
||||
<view v-if="!isLoading" class="goods-info m-top20"> |
|
||||
<!-- 价格、销量 --> |
|
||||
<view class="info-item info-item__top dis-flex flex-x-between flex-y-end"> |
|
||||
<view class="block-left dis-flex flex-y-center"> |
|
||||
<!-- 商品售价 --> |
|
||||
<text class="floor-price__samll">¥</text> |
|
||||
<text class="floor-price">{{ goods.goods_price_min }}</text> |
|
||||
<!-- 会员价标签 --> |
|
||||
<view v-if="goods.is_user_grade" class="user-grade"> |
|
||||
<text>会员价</text> |
|
||||
</view> |
|
||||
<!-- 划线价 --> |
|
||||
<text v-if="goods.line_price_min > 0" class="original-price">¥{{ goods.line_price_min }}</text> |
|
||||
</view> |
|
||||
<view class="block-right dis-flex"> |
|
||||
<!-- 销量 --> |
|
||||
<view class="goods-sales"> |
|
||||
<text>已售{{ goods.goods_sales }}件</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 标题、分享 --> |
|
||||
<view class="info-item info-item__name dis-flex flex-y-center"> |
|
||||
<view class="goods-name flex-box"> |
|
||||
<text class="twoline-hide">{{ goods.goods_name }}</text> |
|
||||
</view> |
|
||||
<!-- #ifdef MP-WEIXIN --> |
|
||||
<view class="goods-share__line"></view> |
|
||||
<view class="goods-share"> |
|
||||
<button class="share-btn dis-flex flex-dir-column" open-type="share"> |
|
||||
<text class="share__icon iconfont icon-fenxiang"></text> |
|
||||
<text class="f-24">分享</text> |
|
||||
</button> |
|
||||
</view> |
|
||||
<!-- #endif --> |
|
||||
</view> |
|
||||
<!-- 商品卖点 --> |
|
||||
<view v-if="goods.selling_point" class="info-item info-item_selling-point"> |
|
||||
<text>{{ goods.selling_point }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 选择商品规格 --> |
|
||||
<view v-if="goods.spec_type == 20" class="goods-choice m-top20 b-f" @click="onShowSkuPopup(1)"> |
|
||||
<view class="spec-list"> |
|
||||
<view class="flex-box"> |
|
||||
<text class="col-8">选择:</text> |
|
||||
<text class="spec-name" v-for="(item, index) in goods.specList" :key="index">{{ item.spec_name }}</text> |
|
||||
</view> |
|
||||
<view class="f-26 col-9 t-r"> |
|
||||
<text class="iconfont icon-arrow-right"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商品服务 --> |
|
||||
<Service v-if="!isLoading" :goods-id="goodsId" /> |
|
||||
|
|
||||
<!-- 商品SKU弹窗 --> |
|
||||
<SkuPopup v-if="!isLoading" v-model="showSkuPopup" :skuMode="skuMode" :goods="goods" @addCart="onAddCart" /> |
|
||||
|
|
||||
<!-- 商品评价 --> |
|
||||
<Comment v-if="!isLoading" :goods-id="goodsId" :limit="2" /> |
|
||||
|
|
||||
<!-- 商品描述 --> |
|
||||
<view v-if="!isLoading" class="goods-content m-top20"> |
|
||||
<view class="item-title b-f"> |
|
||||
<text>商品描述</text> |
|
||||
</view> |
|
||||
<block v-if="goods.content != ''"> |
|
||||
<view class="goods-content__detail b-f"> |
|
||||
<mp-html :content="goods.content" /> |
|
||||
</view> |
|
||||
</block> |
|
||||
<empty v-else tips="亲,暂无商品描述" /> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 底部选项卡 --> |
|
||||
<view class="footer-fixed"> |
|
||||
<view class="footer-container"> |
|
||||
<!-- 导航图标 --> |
|
||||
<view class="foo-item-fast"> |
|
||||
<!-- 首页 --> |
|
||||
<view class="fast-item fast-item--home" @click="onTargetHome"> |
|
||||
<view class="fast-icon"> |
|
||||
<text class="iconfont icon-shouye"></text> |
|
||||
</view> |
|
||||
<view class="fast-text"> |
|
||||
<text>首页</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 客服 (仅微信小程序端显示) --> |
|
||||
<!-- #ifdef MP-WEIXIN --> |
|
||||
<button class="btn-normal" open-type="contact"> |
|
||||
<view class="fast-item"> |
|
||||
<view class="fast-icon"> |
|
||||
<text class="iconfont icon-kefu1"></text> |
|
||||
</view> |
|
||||
<view class="fast-text"> |
|
||||
<text>客服</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</button> |
|
||||
<!-- #endif --> |
|
||||
<!-- 购物车 --> |
|
||||
<view class="fast-item fast-item--cart" @click="onTargetCart"> |
|
||||
<view v-if="cartTotal > 0" class="fast-badge fast-badge--fixed">{{ cartTotal > 99 ? '99+' : cartTotal }} |
|
||||
</view> |
|
||||
<view class="fast-icon"> |
|
||||
<text class="iconfont icon-gouwuche"></text> |
|
||||
</view> |
|
||||
<view class="fast-text"> |
|
||||
<text>购物车</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 操作按钮 --> |
|
||||
<view class="foo-item-btn"> |
|
||||
<view class="btn-wrapper"> |
|
||||
<view class="btn-item btn-item-deputy" @click="onShowSkuPopup(2)"> |
|
||||
<text>加入购物车</text> |
|
||||
</view> |
|
||||
<view class="btn-item btn-item-main" @click="onShowSkuPopup(3)"> |
|
||||
<text>立即购买</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 快捷导航 --> |
|
||||
<!-- <shortcut bottom="120rpx" /> --> |
|
||||
|
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as GoodsApi from '@/api/goods' |
|
||||
import * as CartApi from '@/api/cart' |
|
||||
// import Shortcut from '@/components/shortcut' |
|
||||
import SlideImage from './components/SlideImage' |
|
||||
import SkuPopup from './components/SkuPopup' |
|
||||
import Comment from './components/Comment' |
|
||||
import Service from './components/Service' |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
// Shortcut, |
|
||||
SlideImage, |
|
||||
SkuPopup, |
|
||||
Comment, |
|
||||
Service |
|
||||
}, |
|
||||
data() { |
|
||||
return { |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 当前商品ID |
|
||||
goodsId: null, |
|
||||
// 商品详情 |
|
||||
goods: {}, |
|
||||
// 购物车总数量 |
|
||||
cartTotal: 0, |
|
||||
// 显示/隐藏SKU弹窗 |
|
||||
showSkuPopup: false, |
|
||||
// 模式 1:都显示 2:只显示购物车 3:只显示立即购买 |
|
||||
skuMode: 1 |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 记录商品ID |
|
||||
this.goodsId = parseInt(options.goodsId) |
|
||||
// 加载页面数据 |
|
||||
this.onRefreshPage() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 刷新页面数据 |
|
||||
onRefreshPage() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
Promise.all([app.getGoodsDetail(), app.getCartTotal()]) |
|
||||
.finally(() => app.isLoading = false) |
|
||||
}, |
|
||||
|
|
||||
// 获取商品信息 |
|
||||
getGoodsDetail() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
GoodsApi.detail(app.goodsId) |
|
||||
.then(result => { |
|
||||
app.goods = result.data.detail |
|
||||
resolve(result) |
|
||||
}) |
|
||||
.catch(reject) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 获取购物车总数量 |
|
||||
getCartTotal() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
CartApi.total() |
|
||||
.then(result => { |
|
||||
app.cartTotal = result.data.cartTotal |
|
||||
resolve(result) |
|
||||
}) |
|
||||
.catch(reject) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 更新购物车数量 |
|
||||
onAddCart(total) { |
|
||||
this.cartTotal = total |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 显示/隐藏SKU弹窗 |
|
||||
* @param {skuMode} 模式 1:都显示 2:只显示购物车 3:只显示立即购买 |
|
||||
*/ |
|
||||
onShowSkuPopup(skuMode = 1) { |
|
||||
this.skuMode = skuMode |
|
||||
this.showSkuPopup = !this.showSkuPopup |
|
||||
}, |
|
||||
|
|
||||
// 跳转到首页 |
|
||||
onTargetHome(e) { |
|
||||
this.$navTo('pages/index/index') |
|
||||
}, |
|
||||
|
|
||||
// 跳转到购物车页 |
|
||||
onTargetCart() { |
|
||||
this.$navTo('pages/cart/index') |
|
||||
}, |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 分享当前页面 |
|
||||
*/ |
|
||||
onShareAppMessage() { |
|
||||
const app = this |
|
||||
// 构建页面参数 |
|
||||
const params = app.$getShareUrlParams({ |
|
||||
goodsId: app.goodsId, |
|
||||
}) |
|
||||
return { |
|
||||
title: app.goods.goods_name, |
|
||||
path: `/pages/goods/detail?${params}` |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 分享到朋友圈 |
|
||||
* 本接口为 Beta 版本,暂只在 Android 平台支持,详见分享到朋友圈 (Beta) |
|
||||
* https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share-timeline.html |
|
||||
*/ |
|
||||
onShareTimeline() { |
|
||||
const app = this |
|
||||
// 构建页面参数 |
|
||||
const params = app.$getShareUrlParams({ |
|
||||
goodsId: app.goodsId, |
|
||||
}) |
|
||||
return { |
|
||||
title: app.goods.goods_name, |
|
||||
path: `/pages/goods/detail?${params}` |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style> |
|
||||
page { |
|
||||
background: #fafafa; |
|
||||
} |
|
||||
</style> |
|
||||
<style lang="scss" scoped> |
|
||||
@import "./detail.scss"; |
|
||||
</style> |
|
||||
@ -1,463 +0,0 @@ |
|||||
<template> |
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ native: true }" @down="downCallback" :up="upOption" @up="upCallback"> |
|
||||
<!-- 页面头部 --> |
|
||||
<view class="header"> |
|
||||
<search class="search" :tips="options.search ? options.search : '搜索商品'" @event="handleSearch" /> |
|
||||
<!-- 切换列表显示方式 --> |
|
||||
<view class="show-view" @click="handleShowView"> |
|
||||
<text class="iconfont icon-view-tile" v-if="showView"></text> |
|
||||
<text class="iconfont icon-view-list" v-else></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 排序标签 --> |
|
||||
<view class="store-sort"> |
|
||||
<view class="sort-item" :class="{ active: sortType === 'all' }" @click="handleSortType('all')"> |
|
||||
<text>综合</text> |
|
||||
</view> |
|
||||
<view class="sort-item" :class="{ active: sortType === 'sales' }" @click="handleSortType('sales')"> |
|
||||
<text>销量</text> |
|
||||
</view> |
|
||||
<view class="sort-item sort-item-price" :class="{ active: sortType === 'price' }" @click="handleSortType('price')"> |
|
||||
<text>价格</text> |
|
||||
<view class="price-arrow"> |
|
||||
<view class="icon up" :class="{ active: sortType === 'price' && !sortPrice }"> |
|
||||
<text class="iconfont icon-arrow-up"></text> |
|
||||
</view> |
|
||||
<view class="icon down" :class="{ active: sortType === 'price' && sortPrice }"> |
|
||||
<text class="iconfont icon-arrow-down"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商品列表 --> |
|
||||
<view class="goods-list clearfix" :class="['column-' + (showView ? '1' : '2')]"> |
|
||||
<view class="goods-item" v-for="(item, index) in list.data" :key="index" @click="onTargetDetail(item.goods_id)"> |
|
||||
<!-- 单列显示 --> |
|
||||
<view v-if="showView" class="dis-flex"> |
|
||||
<!-- 商品图片 --> |
|
||||
<view class="goods-item_left"> |
|
||||
<image class="image" :src="item.goods_image"></image> |
|
||||
</view> |
|
||||
<view class="goods-item_right"> |
|
||||
<!-- 商品名称 --> |
|
||||
<view class="goods-name"> |
|
||||
<text class="twoline-hide">{{ item.goods_name }}</text> |
|
||||
</view> |
|
||||
<view class="goods-item_desc"> |
|
||||
<!-- 商品卖点 --> |
|
||||
<view class="desc-selling_point dis-flex"> |
|
||||
<text class="oneline-hide">{{ item.selling_point }}</text> |
|
||||
</view> |
|
||||
<!-- 商品销量 --> |
|
||||
<view class="desc-goods_sales dis-flex"> |
|
||||
<text>已售{{ item.goods_sales }}件</text> |
|
||||
</view> |
|
||||
<!-- 商品价格 --> |
|
||||
<view class="desc_footer"> |
|
||||
<text class="price_x">¥{{ item.goods_price_min }}</text> |
|
||||
<text class="price_y col-9" v-if="item.line_price_min > 0">¥{{ item.line_price_min }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 多列显示 --> |
|
||||
<view v-else class=""> |
|
||||
<!-- 商品图片 --> |
|
||||
<view class="goods-image"> |
|
||||
<image class="image" mode="aspectFill" :src="item.goods_image"></image> |
|
||||
</view> |
|
||||
<view class="detail"> |
|
||||
<!-- 商品标题 --> |
|
||||
<view class="goods-name"> |
|
||||
<text class="twoline-hide">{{ item.goods_name }}</text> |
|
||||
</view> |
|
||||
<!-- 商品价格 --> |
|
||||
<view class="detail-price oneline-hide"> |
|
||||
<text class="goods-price f-30 col-m">¥{{ item.goods_price_min }}</text> |
|
||||
<text v-if="item.line_price_min > 0" class="line-price col-9 f-24">¥{{ item.line_price_min }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</mescroll-body> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import * as GoodsApi from '@/api/goods' |
|
||||
import { getEmptyPaginateObj, getMoreListData } from '@/core/app' |
|
||||
import Search from '@/components/search' |
|
||||
|
|
||||
const pageSize = 15 |
|
||||
const showViewKey = 'GoodsList-ShowView'; |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody, |
|
||||
Search |
|
||||
}, |
|
||||
|
|
||||
mixins: [MescrollMixin], |
|
||||
|
|
||||
data() { |
|
||||
return { |
|
||||
showView: false, // 列表显示方式 (true列表、false平铺) |
|
||||
sortType: 'all', // 排序类型 |
|
||||
sortPrice: false, // 价格排序 (true高到低 false低到高) |
|
||||
options: {}, // 当前页面参数 |
|
||||
list: getEmptyPaginateObj(), // 商品列表数据 |
|
||||
|
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于4条才显示无更多数据 |
|
||||
noMoreSize: 4, |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 记录options |
|
||||
this.options = options |
|
||||
// 设置默认列表显示方式 |
|
||||
this.setShowView() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getGoodsList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
// 设置默认列表显示方式 |
|
||||
setShowView() { |
|
||||
this.showView = uni.getStorageSync(showViewKey) || false |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 获取商品列表 |
|
||||
* @param {number} pageNo 页码 |
|
||||
*/ |
|
||||
getGoodsList(pageNo = 1) { |
|
||||
const app = this |
|
||||
console.log(app.options) |
|
||||
const param = { |
|
||||
sortType: app.sortType, |
|
||||
sortPrice: Number(app.sortPrice), |
|
||||
categoryId: app.options.categoryId || 0, |
|
||||
goodsName: app.options.search || '', |
|
||||
page: pageNo |
|
||||
} |
|
||||
return new Promise((resolve, reject) => { |
|
||||
GoodsApi.list(param) |
|
||||
.then(result => { |
|
||||
// 合并新数据 |
|
||||
const newList = result.data.list |
|
||||
app.list.data = getMoreListData(newList, app.list, pageNo) |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
.catch(reject) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 切换排序方式 |
|
||||
handleSortType(newSortType) { |
|
||||
const app = this |
|
||||
const newSortPrice = newSortType === 'price' ? !app.sortPrice : true |
|
||||
app.sortType = newSortType |
|
||||
app.sortPrice = newSortPrice |
|
||||
// 刷新列表数据 |
|
||||
app.list = getEmptyPaginateObj() |
|
||||
app.mescroll.resetUpScroll() |
|
||||
}, |
|
||||
|
|
||||
// 切换列表显示方式 |
|
||||
handleShowView() { |
|
||||
const app = this |
|
||||
app.showView = !app.showView |
|
||||
uni.setStorageSync(showViewKey, app.showView) |
|
||||
}, |
|
||||
|
|
||||
// 跳转商品详情页 |
|
||||
onTargetDetail(goodsId) { |
|
||||
this.$navTo('pages/goods/detail', { goodsId }) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 商品搜索 |
|
||||
*/ |
|
||||
handleSearch() { |
|
||||
const searchPageUrl = 'pages/search/index' |
|
||||
// 判断来源页面 |
|
||||
let pages = getCurrentPages() |
|
||||
if (pages.length > 1 && |
|
||||
pages[pages.length - 2].route === searchPageUrl) { |
|
||||
uni.navigateBack() |
|
||||
return |
|
||||
} |
|
||||
// 跳转到商品搜索页 |
|
||||
this.$navTo(searchPageUrl) |
|
||||
} |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
|
|
||||
/** |
|
||||
* 设置分享内容 |
|
||||
*/ |
|
||||
onShareAppMessage() { |
|
||||
// 构建分享参数 |
|
||||
return { |
|
||||
title: "全部分类", |
|
||||
path: "/pages/category/index?" + this.$getShareUrlParams() |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 分享到朋友圈 |
|
||||
* 本接口为 Beta 版本,暂只在 Android 平台支持,详见分享到朋友圈 (Beta) |
|
||||
* https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share-timeline.html |
|
||||
*/ |
|
||||
onShareTimeline() { |
|
||||
// 构建分享参数 |
|
||||
return { |
|
||||
title: "全部分类", |
|
||||
path: "/pages/category/index?" + this.$getShareUrlParams() |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
// 页面头部 |
|
||||
.header { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
background-color: #fff; |
|
||||
|
|
||||
// 搜索框 |
|
||||
.search { |
|
||||
flex: 1; |
|
||||
} |
|
||||
|
|
||||
// 切换显示方式 |
|
||||
.show-view { |
|
||||
width: 60rpx; |
|
||||
height: 60rpx; |
|
||||
line-height: 60rpx; |
|
||||
font-size: 36rpx; |
|
||||
color: #505050; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 排序组件 |
|
||||
.store-sort { |
|
||||
position: sticky; |
|
||||
top: var(--window-top); |
|
||||
display: flex; |
|
||||
padding: 20rpx 0; |
|
||||
font-size: 28rpx; |
|
||||
background: #fff; |
|
||||
color: #000; |
|
||||
z-index: 99; |
|
||||
|
|
||||
.sort-item { |
|
||||
flex-basis: 33.3333%; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
height: 50rpx; |
|
||||
|
|
||||
&.active { |
|
||||
color: #e49a3d; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.sort-item-price .price-arrow { |
|
||||
margin-left: 20rpx; |
|
||||
font-size: 24rpx; |
|
||||
color: #000; |
|
||||
|
|
||||
.icon { |
|
||||
&.active { |
|
||||
color: #e49a3d; |
|
||||
} |
|
||||
|
|
||||
&.up { |
|
||||
margin-bottom: -16rpx; |
|
||||
} |
|
||||
|
|
||||
&.down { |
|
||||
margin-top: -16rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 商品列表 |
|
||||
.goods-list { |
|
||||
padding: 4rpx; |
|
||||
box-sizing: border-box; |
|
||||
} |
|
||||
|
|
||||
// 单列显示 |
|
||||
.goods-list.column-1 { |
|
||||
.goods-item { |
|
||||
width: 100%; |
|
||||
height: 280rpx; |
|
||||
margin-bottom: 12rpx; |
|
||||
padding: 20rpx; |
|
||||
box-sizing: border-box; |
|
||||
background: #fff; |
|
||||
line-height: 1.6; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-item_left { |
|
||||
display: flex; |
|
||||
width: 300rpx; |
|
||||
background: #fff; |
|
||||
align-items: center; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 240rpx; |
|
||||
height: 240rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-item_right { |
|
||||
position: relative; |
|
||||
// width: 450rpx; |
|
||||
flex: 1; |
|
||||
|
|
||||
.goods-name { |
|
||||
margin-top: 10rpx; |
|
||||
min-height: 68rpx; |
|
||||
line-height: 1.3; |
|
||||
white-space: normal; |
|
||||
color: #484848; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-item_desc { |
|
||||
margin-top: 8rpx; |
|
||||
} |
|
||||
|
|
||||
.desc-selling_point { |
|
||||
width: 400rpx; |
|
||||
font-size: 24rpx; |
|
||||
color: #e49a3d; |
|
||||
} |
|
||||
|
|
||||
.desc-goods_sales { |
|
||||
color: #999; |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
|
|
||||
.desc_footer { |
|
||||
font-size: 24rpx; |
|
||||
|
|
||||
.price_x { |
|
||||
margin-right: 16rpx; |
|
||||
color: #f03c3c; |
|
||||
font-size: 30rpx; |
|
||||
} |
|
||||
|
|
||||
.price_y { |
|
||||
text-decoration: line-through; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 平铺显示 |
|
||||
.goods-list.column-2 { |
|
||||
.goods-item { |
|
||||
width: 50%; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-item { |
|
||||
float: left; |
|
||||
box-sizing: border-box; |
|
||||
padding: 6rpx; |
|
||||
|
|
||||
.goods-image { |
|
||||
position: relative; |
|
||||
width: 100%; |
|
||||
height: 0; |
|
||||
padding-bottom: 100%; |
|
||||
overflow: hidden; |
|
||||
background: #fff; |
|
||||
|
|
||||
&:after { |
|
||||
content: ''; |
|
||||
display: block; |
|
||||
margin-top: 100%; |
|
||||
} |
|
||||
|
|
||||
.image { |
|
||||
position: absolute; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
-o-object-fit: cover; |
|
||||
object-fit: cover; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.detail { |
|
||||
padding: 8rpx; |
|
||||
background: #fff; |
|
||||
|
|
||||
.goods-name { |
|
||||
min-height: 68rpx; |
|
||||
line-height: 32rpx; |
|
||||
white-space: normal; |
|
||||
color: #484848; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
|
|
||||
.detail-price { |
|
||||
.goods-price { |
|
||||
margin-right: 8rpx; |
|
||||
} |
|
||||
|
|
||||
.line-price { |
|
||||
text-decoration: line-through; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,306 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption" |
|
||||
@up="upCallback"> |
|
||||
|
|
||||
<!-- tab栏 --> |
|
||||
<u-tabs :list="tabs" :is-scroll="false" :current="curTab" active-color="#FA2209" :duration="0.2" |
|
||||
@change="onChangeTab" /> |
|
||||
|
|
||||
<!-- 优惠券列表 --> |
|
||||
<view class="coupon-list"> |
|
||||
<view class="coupon-item" v-for="(item, index) in list.data" :key="index"> |
|
||||
<view class="item-wrapper" :class="['color-' + (item.state.value ? color[index % color.length] : 'gray')]"> |
|
||||
<view class="coupon-type">{{ CouponTypeEnum[item.coupon_type].name }}</view> |
|
||||
<view class="tip dis-flex flex-dir-column flex-x-center"> |
|
||||
<view v-if="item.coupon_type == CouponTypeEnum.FULL_DISCOUNT.value"> |
|
||||
<text class="f-30">¥</text> |
|
||||
<text class="money">{{ item.reduce_price }}</text> |
|
||||
</view> |
|
||||
<text class="money" v-if="item.coupon_type == CouponTypeEnum.DISCOUNT.value">{{ item.discount }}折</text> |
|
||||
<text class="pay-line">满{{ item.min_price }}元可用</text> |
|
||||
</view> |
|
||||
<view class="split-line"></view> |
|
||||
<view class="content dis-flex flex-dir-column flex-x-between"> |
|
||||
<view class="title">{{ item.name }}</view> |
|
||||
<view class="bottom dis-flex flex-y-center"> |
|
||||
<view class="time flex-box"> |
|
||||
<block v-if="item.start_time === item.end_time">{{ item.start_time }} 当天有效</block> |
|
||||
<block v-else>{{ item.start_time }}~{{ item.end_time }}</block> |
|
||||
</view> |
|
||||
<view class="receive state"> |
|
||||
<text>{{ item.state.text }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</mescroll-body> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import { getEmptyPaginateObj, getMoreListData } from '@/core/app' |
|
||||
import * as MyCouponApi from '@/api/myCoupon' |
|
||||
import { CouponTypeEnum } from '@/common/enum/coupon' |
|
||||
|
|
||||
const color = ['red', 'blue', 'violet', 'yellow'] |
|
||||
const pageSize = 15 |
|
||||
const tabs = [{ |
|
||||
name: `未使用`, |
|
||||
value: 'isUnused' |
|
||||
}, { |
|
||||
name: `已使用`, |
|
||||
value: 'isUse' |
|
||||
}, { |
|
||||
name: `已过期`, |
|
||||
value: 'isExpire' |
|
||||
}] |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody |
|
||||
}, |
|
||||
mixins: [MescrollMixin], |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
CouponTypeEnum, |
|
||||
// 颜色组 |
|
||||
color, |
|
||||
// 标签栏数据 |
|
||||
tabs, |
|
||||
// 当前标签索引 |
|
||||
curTab: 0, |
|
||||
// 优惠券列表数据 |
|
||||
list: getEmptyPaginateObj(), |
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于4条才显示无更多数据 |
|
||||
noMoreSize: 4, |
|
||||
// 空布局 |
|
||||
empty: { |
|
||||
tip: '亲,暂无相关优惠券' |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getCouponList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 获取优惠券列表 |
|
||||
*/ |
|
||||
getCouponList(pageNo = 1) { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
MyCouponApi.list({ dataType: app.getTabValue(), page: pageNo }, { load: false }) |
|
||||
.then(result => { |
|
||||
// 合并新数据 |
|
||||
const newList = result.data.list |
|
||||
app.list.data = getMoreListData(newList, app.list, pageNo) |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 评分类型 |
|
||||
getTabValue() { |
|
||||
return this.tabs[this.curTab].value |
|
||||
}, |
|
||||
|
|
||||
// 切换标签项 |
|
||||
onChangeTab(index) { |
|
||||
const app = this |
|
||||
// 设置当前选中的标签 |
|
||||
app.curTab = index |
|
||||
// 刷新优惠券列表 |
|
||||
app.onRefreshList() |
|
||||
}, |
|
||||
|
|
||||
// 刷新优惠券列表 |
|
||||
onRefreshList() { |
|
||||
this.list = getEmptyPaginateObj() |
|
||||
setTimeout(() => { |
|
||||
this.mescroll.resetUpScroll() |
|
||||
}, 120) |
|
||||
}, |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.coupon-list { |
|
||||
padding: 20rpx; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.coupon-item { |
|
||||
position: relative; |
|
||||
overflow: hidden; |
|
||||
margin-bottom: 22rpx; |
|
||||
} |
|
||||
|
|
||||
.item-wrapper { |
|
||||
width: 100%; |
|
||||
display: flex; |
|
||||
background: #fff; |
|
||||
border-radius: 8rpx; |
|
||||
color: #fff; |
|
||||
height: 180rpx; |
|
||||
|
|
||||
.coupon-type { |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
z-index: 10; |
|
||||
width: 128rpx; |
|
||||
padding: 6rpx 0; |
|
||||
background: #a771ff; |
|
||||
font-size: 20rpx; |
|
||||
text-align: center; |
|
||||
color: #ffffff; |
|
||||
transform: rotate(45deg); |
|
||||
transform-origin: 64rpx 64rpx; |
|
||||
} |
|
||||
|
|
||||
&.color-blue { |
|
||||
background: linear-gradient(-125deg, #57bdbf, #2f9de2); |
|
||||
} |
|
||||
|
|
||||
&.color-red { |
|
||||
background: linear-gradient(-128deg, #ff6d6d, #ff3636); |
|
||||
} |
|
||||
|
|
||||
&.color-violet { |
|
||||
background: linear-gradient(-113deg, #ef86ff, #b66ff5); |
|
||||
|
|
||||
.coupon-type { |
|
||||
background: #55b5ff; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&.color-yellow { |
|
||||
background: linear-gradient(-141deg, #f7d059, #fdb054); |
|
||||
} |
|
||||
|
|
||||
&.color-gray { |
|
||||
background: linear-gradient(-113deg, #bdbdbd, #a2a1a2); |
|
||||
|
|
||||
.coupon-type { |
|
||||
background: #9e9e9e; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.content { |
|
||||
flex: 1; |
|
||||
padding: 30rpx 20rpx; |
|
||||
border-radius: 16rpx 0 0 16rpx; |
|
||||
|
|
||||
.title { |
|
||||
font-size: 32rpx; |
|
||||
} |
|
||||
|
|
||||
.bottom { |
|
||||
.time { |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
|
|
||||
.receive { |
|
||||
height: 46rpx; |
|
||||
width: 122rpx; |
|
||||
line-height: 46rpx; |
|
||||
text-align: center; |
|
||||
border: 1rpx solid #fff; |
|
||||
border-radius: 30rpx; |
|
||||
color: #fff; |
|
||||
font-size: 24rpx; |
|
||||
|
|
||||
&.state { |
|
||||
border: none; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.tip { |
|
||||
position: relative; |
|
||||
flex: 0 0 32%; |
|
||||
text-align: center; |
|
||||
border-radius: 0 16rpx 16rpx 0; |
|
||||
|
|
||||
.money { |
|
||||
font-weight: bold; |
|
||||
font-size: 52rpx; |
|
||||
} |
|
||||
|
|
||||
.pay-line { |
|
||||
font-size: 22rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.split-line { |
|
||||
position: relative; |
|
||||
flex: 0 0 0; |
|
||||
border-left: 4rpx solid #fff; |
|
||||
margin: 0 10rpx 0 6rpx; |
|
||||
background: #fff; |
|
||||
|
|
||||
&:before, |
|
||||
{ |
|
||||
border-radius: 0 0 16rpx 16rpx; |
|
||||
top: 0; |
|
||||
} |
|
||||
|
|
||||
&:after { |
|
||||
border-radius: 16rpx 16rpx 0 0; |
|
||||
bottom: 0; |
|
||||
} |
|
||||
|
|
||||
&:before, |
|
||||
&:after { |
|
||||
content: ''; |
|
||||
position: absolute; |
|
||||
width: 24rpx; |
|
||||
height: 12rpx; |
|
||||
background: #f7f7f7; |
|
||||
left: -14rpx; |
|
||||
z-index: 1; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,136 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<!-- 订单页列表 --> |
|
||||
<view class="order-list"> |
|
||||
<view class="order-item" v-for="(item, index) in orderList" :key="index" @click="$navTo(item.path)"> |
|
||||
<view class="order-item-icon" :style="{ color: item.color }"> |
|
||||
<text class="iconfont" :class="item.icon"></text> |
|
||||
</view> |
|
||||
<view class="order-item-name">{{ item.name }}</view> |
|
||||
<view class="icon-arrow"> |
|
||||
<text class="iconfont icon-arrow-right"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 操作按钮 --> |
|
||||
<view class="footer"> |
|
||||
<view class="btn-wrapper"> |
|
||||
<view class="btn-item btn-item-main" @click="$navTo('pages/index/index')"> |
|
||||
<view class="btn-item-icon"> |
|
||||
<text class="iconfont icon-shouye2"></text> |
|
||||
</view> |
|
||||
<view class="btn-item-name"> |
|
||||
<text>返回首页</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as UserApi from '@/api/user' |
|
||||
|
|
||||
// 订单页数据 |
|
||||
const orderList = [{ |
|
||||
name: '商城订单', |
|
||||
icon: 'icon-qpdingdan', |
|
||||
color: 'rgb(253 65 0)', |
|
||||
path: 'pages/order/index' |
|
||||
}, |
|
||||
{ |
|
||||
name: '充值订单', |
|
||||
icon: 'icon-jifen', |
|
||||
color: 'rgb(191, 150, 7)', |
|
||||
path: 'pages/wallet/recharge/order' |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
orderList |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 获取当前用户信息 |
|
||||
this.getUserInfo() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取当前用户信息(验证是否登录) |
|
||||
getUserInfo() { |
|
||||
const app = this |
|
||||
UserApi.info() |
|
||||
}, |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.order-list { |
|
||||
padding: 0 25rpx; |
|
||||
background-color: #fff; |
|
||||
|
|
||||
.order-item { |
|
||||
position: relative; |
|
||||
padding: 26rpx 16rpx; |
|
||||
border-bottom: 1rpx solid #eee; |
|
||||
display: flex; |
|
||||
justify-content: flex-start; |
|
||||
align-items: center; |
|
||||
font-size: 30rpx; |
|
||||
|
|
||||
&:last-child { |
|
||||
border-bottom: none; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.order-item-icon { |
|
||||
font-size: 34rpx; |
|
||||
margin-right: 18rpx; |
|
||||
} |
|
||||
|
|
||||
.icon-arrow { |
|
||||
position: absolute; |
|
||||
top: 26rpx; |
|
||||
right: 6rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 底部操作栏 |
|
||||
.footer { |
|
||||
position: fixed; |
|
||||
bottom: var(--window-bottom); |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
z-index: 11; |
|
||||
box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24); |
|
||||
background: #fff; |
|
||||
|
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: constant(safe-area-inset-bottom); |
|
||||
padding-bottom: env(safe-area-inset-bottom); |
|
||||
|
|
||||
.btn-item { |
|
||||
font-size: 30rpx; |
|
||||
height: 90rpx; |
|
||||
border-radius: 50rpx; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.btn-item-icon { |
|
||||
font-size: 34rpx; |
|
||||
margin-right: 18rpx; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</style> |
|
||||
@ -1,571 +0,0 @@ |
|||||
<template> |
|
||||
<view v-if="!isLoading" class="container"> |
|
||||
<view class="goods-list"> |
|
||||
<view class="goods-item" v-for="(item, index) in goodsList" :key="index"> |
|
||||
<!-- 商品详情 --> |
|
||||
<view class="goods-main"> |
|
||||
<!-- 商品图片 --> |
|
||||
<view class="goods-image"> |
|
||||
<image class="image" :src="item.goods_image" mode="scaleToFill"></image> |
|
||||
</view> |
|
||||
<!-- 商品信息 --> |
|
||||
<view class="goods-content"> |
|
||||
<view class="goods-title"><text class="twoline-hide">{{ item.goods_name }}</text></view> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in item.goods_props" :key="idx"> |
|
||||
<text>{{ props.value.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 交易信息 --> |
|
||||
<view class="goods-trade"> |
|
||||
<view class="goods-price"> |
|
||||
<text class="unit">¥</text> |
|
||||
<text class="value">{{ item.goods_price }}</text> |
|
||||
</view> |
|
||||
<view class="goods-num"> |
|
||||
<text>×{{ item.total_num }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 选择评价 --> |
|
||||
<view class="score-row"> |
|
||||
<view class="score-item score-praise" :class="{ active: formData[index].score == 10 }" |
|
||||
@click="setScore(index, 10)"> |
|
||||
<view class="score"> |
|
||||
<text class="score-icon iconfont icon-haoping"></text> |
|
||||
<text class="score-text">好评</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="score-item score-review" :class="{ active: formData[index].score == 20 }" |
|
||||
@click="setScore(index, 20)"> |
|
||||
<view class="score"> |
|
||||
<text class="score-icon iconfont icon-zhongping"></text> |
|
||||
<text class="score-text">中评</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="score-item score-negative" :class="{ active: formData[index].score == 30 }" |
|
||||
@click="setScore(index, 30)"> |
|
||||
<view class="score"> |
|
||||
<text class="score-icon iconfont icon-chaping"></text> |
|
||||
<text class="score-text">差评</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 评价内容 --> |
|
||||
<view class="form-content"> |
|
||||
<textarea class="textarea" v-model="formData[index].content" maxlength="500" |
|
||||
placeholder="请输入评价内容 (留空则不评价)"></textarea> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 图片列表 --> |
|
||||
<view class="image-list"> |
|
||||
<view class="image-preview" v-for="(image, imageIndex) in formData[index].imageList" :key="imageIndex"> |
|
||||
<text class="image-delete iconfont icon-shanchu" @click="deleteImage(index, imageIndex)"></text> |
|
||||
<image class="image" mode="aspectFill" :src="image.path"></image> |
|
||||
</view> |
|
||||
<view v-if="!formData[index].imageList || formData[index].imageList.length < maxImageLength" |
|
||||
class="image-picker" @click="chooseImage(index)"> |
|
||||
<text class="choose-icon iconfont icon-camera"></text> |
|
||||
<text class="choose-text">上传图片</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 底部操作按钮 --> |
|
||||
<view class="footer-fixed"> |
|
||||
<view class="btn-wrapper"> |
|
||||
<view class="btn-item btn-item-main" :class="{ disabled }" @click="handleSubmit()">确认提交</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as UploadApi from '@/api/upload' |
|
||||
import * as OrderCommentApi from '@/api/order/comment' |
|
||||
|
|
||||
const maxImageLength = 6 |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 当前订单ID |
|
||||
orderId: null, |
|
||||
// 待评价商品列表 |
|
||||
goodsList: [], |
|
||||
// 表单数据 |
|
||||
formData: [], |
|
||||
// 最大图片数量 |
|
||||
maxImageLength, |
|
||||
// 按钮禁用 |
|
||||
disabled: false |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad({ orderId }) { |
|
||||
this.orderId = orderId |
|
||||
// 获取待评价商品列表 |
|
||||
this.getGoodsList() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取待评价商品列表 |
|
||||
getGoodsList() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
OrderCommentApi.list(app.orderId) |
|
||||
.then(result => { |
|
||||
app.goodsList = result.data.goodsList |
|
||||
app.initFormData() |
|
||||
app.isLoading = false |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 初始化form数据 |
|
||||
initFormData() { |
|
||||
const { goodsList } = this |
|
||||
const formData = goodsList.map(item => { |
|
||||
return { |
|
||||
goods_id: item.goods_id, |
|
||||
order_goods_id: item.order_goods_id, |
|
||||
score: 10, |
|
||||
content: '', |
|
||||
imageList: [], |
|
||||
uploaded: [] |
|
||||
} |
|
||||
}) |
|
||||
this.formData = formData |
|
||||
}, |
|
||||
|
|
||||
// 设置评分 |
|
||||
setScore(index, score) { |
|
||||
this.formData[index].score = score |
|
||||
}, |
|
||||
|
|
||||
// 选择图片 |
|
||||
chooseImage(index) { |
|
||||
const app = this |
|
||||
const oldImageList = app.formData[index].imageList |
|
||||
// 选择图片 |
|
||||
uni.chooseImage({ |
|
||||
count: maxImageLength - oldImageList.length, |
|
||||
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 |
|
||||
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 |
|
||||
success({ tempFiles }) { |
|
||||
// tempFiles = [{path:'xxx', size:100}] |
|
||||
app.formData[index].imageList = oldImageList.concat(tempFiles) |
|
||||
} |
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
// 删除图片 |
|
||||
deleteImage(index, imageIndex) { |
|
||||
this.formData[index].imageList.splice(imageIndex, 1) |
|
||||
}, |
|
||||
|
|
||||
// 表单提交 |
|
||||
handleSubmit() { |
|
||||
const app = this |
|
||||
// 判断是否重复提交 |
|
||||
if (app.disabled === true) return false |
|
||||
// 按钮禁用 |
|
||||
app.disabled = true |
|
||||
// 判断是否需要上传图片 |
|
||||
const imagesLength = app.getImagesLength() |
|
||||
if (imagesLength > 0) { |
|
||||
app.uploadFile() |
|
||||
.then(() => { |
|
||||
console.log('then') |
|
||||
app.onSubmit() |
|
||||
}) |
|
||||
.catch(err => { |
|
||||
console.log('catch') |
|
||||
app.disabled = false |
|
||||
if (err.statusCode !== 0) { |
|
||||
app.$toast(err.errMsg) |
|
||||
} |
|
||||
console.log('err', err) |
|
||||
}) |
|
||||
} else { |
|
||||
app.onSubmit() |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 统计图片数量 |
|
||||
getImagesLength() { |
|
||||
const { formData } = this |
|
||||
let imagesLength = 0 |
|
||||
formData.forEach(item => { |
|
||||
if (item.content.trim()) { |
|
||||
imagesLength += item.imageList.length |
|
||||
} |
|
||||
}) |
|
||||
return imagesLength |
|
||||
}, |
|
||||
|
|
||||
// 提交到后端 |
|
||||
onSubmit() { |
|
||||
const app = this |
|
||||
OrderCommentApi.submit(app.orderId, app.formData) |
|
||||
.then(result => { |
|
||||
app.$toast(result.message) |
|
||||
setTimeout(() => { |
|
||||
app.disabled = false |
|
||||
uni.navigateBack() |
|
||||
}, 1500) |
|
||||
}) |
|
||||
.catch(err => app.disabled = false) |
|
||||
}, |
|
||||
|
|
||||
// 上传图片 |
|
||||
uploadFile() { |
|
||||
const app = this |
|
||||
const { formData } = app |
|
||||
// 整理上传文件路径 |
|
||||
const files = [] |
|
||||
formData.forEach((item, index) => { |
|
||||
if (item.content.trim() && item.imageList.length) { |
|
||||
const images = item.imageList.map(image => image) |
|
||||
files.push({ formDataIndex: index, images }) |
|
||||
} |
|
||||
}) |
|
||||
// 批量上传 |
|
||||
return new Promise((resolve, reject) => { |
|
||||
Promise.all(files.map((file, index) => { |
|
||||
return new Promise((resolve, reject) => { |
|
||||
UploadApi.image(file.images) |
|
||||
.then(fileIds => { |
|
||||
app.formData[index].uploaded = fileIds |
|
||||
resolve(fileIds) |
|
||||
}) |
|
||||
.catch(reject) |
|
||||
}) |
|
||||
})) |
|
||||
.then(resolve, reject) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.container { |
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: constant(env(safe-area-inset-bottom) + 140rpx); |
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 140rpx); |
|
||||
} |
|
||||
|
|
||||
.goods-list { |
|
||||
font-size: 28rpx; |
|
||||
padding-top: 30rpx; |
|
||||
} |
|
||||
|
|
||||
.goods-item { |
|
||||
width: 94%; |
|
||||
background: #fff; |
|
||||
padding: 24rpx 24rpx; |
|
||||
box-shadow: 0 1rpx 5rpx 0px rgba(0, 0, 0, 0.05); |
|
||||
margin: 0 auto 30rpx auto; |
|
||||
border-radius: 20rpx; |
|
||||
|
|
||||
.goods-detail { |
|
||||
padding: 24rpx 20rpx; |
|
||||
|
|
||||
.left { |
|
||||
.goods-image { |
|
||||
display: block; |
|
||||
width: 150rpx; |
|
||||
height: 150rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.right { |
|
||||
padding-left: 20rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.score-row { |
|
||||
display: flex; |
|
||||
justify-content: space-around; |
|
||||
padding: 24rpx 20rpx; |
|
||||
|
|
||||
.score-item { |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
|
|
||||
&.score-praise { |
|
||||
color: #ff4544; |
|
||||
|
|
||||
.score-icon { |
|
||||
background: #ff4544; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&.score-review { |
|
||||
color: #fcb500; |
|
||||
|
|
||||
.score-icon { |
|
||||
background: #fcb500; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&.score-negative { |
|
||||
color: #9b9b9b; |
|
||||
|
|
||||
.score-icon { |
|
||||
background: #9b9b9b; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.score { |
|
||||
padding: 10rpx 20rpx 10rpx 10rpx; |
|
||||
border-radius: 30rpx; |
|
||||
|
|
||||
.score-icon { |
|
||||
margin-right: 10rpx; |
|
||||
padding: 10rpx; |
|
||||
border-radius: 50%; |
|
||||
font-size: 30rpx; |
|
||||
color: #fff; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&.active { |
|
||||
.score { |
|
||||
color: #fff; |
|
||||
} |
|
||||
|
|
||||
&.score-praise { |
|
||||
.score { |
|
||||
background: #ff4544; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&.score-review { |
|
||||
.score { |
|
||||
background: #fcb500; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&.score-negative { |
|
||||
.score { |
|
||||
background: #9b9b9b; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 评价内容 |
|
||||
.form-content { |
|
||||
padding: 14rpx 10rpx; |
|
||||
|
|
||||
.textarea { |
|
||||
width: 100%; |
|
||||
height: 220rpx; |
|
||||
padding: 12rpx; |
|
||||
border: 1rpx solid #e8e8e8; |
|
||||
border-radius: 5rpx; |
|
||||
box-sizing: border-box; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.image-list { |
|
||||
padding: 0 20rpx; |
|
||||
margin-top: 20rpx; |
|
||||
margin-bottom: -20rpx; |
|
||||
|
|
||||
&:after { |
|
||||
clear: both; |
|
||||
content: " "; |
|
||||
display: table; |
|
||||
} |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
} |
|
||||
|
|
||||
.image-picker, |
|
||||
.image-preview { |
|
||||
width: 184rpx; |
|
||||
height: 184rpx; |
|
||||
margin-right: 30rpx; |
|
||||
margin-bottom: 30rpx; |
|
||||
float: left; |
|
||||
|
|
||||
&:nth-child(3n+0) { |
|
||||
margin-right: 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.image-picker { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
border: 1rpx dashed #ccc; |
|
||||
color: #ccc; |
|
||||
|
|
||||
.choose-icon { |
|
||||
font-size: 48rpx; |
|
||||
margin-bottom: 6rpx; |
|
||||
} |
|
||||
|
|
||||
.choose-text { |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.image-preview { |
|
||||
position: relative; |
|
||||
|
|
||||
.image-delete { |
|
||||
position: absolute; |
|
||||
top: -15rpx; |
|
||||
right: -15rpx; |
|
||||
height: 42rpx; |
|
||||
width: 42rpx; |
|
||||
line-height: 42rpx; |
|
||||
background: rgba(0, 0, 0, 0.64); |
|
||||
border-radius: 50%; |
|
||||
color: #fff; |
|
||||
font-weight: bolder; |
|
||||
font-size: 22rpx; |
|
||||
z-index: 10; |
|
||||
text-align: center; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
// 商品项 |
|
||||
.goods-main { |
|
||||
display: flex; |
|
||||
margin-bottom: 20rpx; |
|
||||
|
|
||||
// 商品图片 |
|
||||
.goods-image { |
|
||||
width: 180rpx; |
|
||||
height: 180rpx; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
border-radius: 8rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品内容 |
|
||||
.goods-content { |
|
||||
flex: 1; |
|
||||
padding-left: 16rpx; |
|
||||
padding-top: 16rpx; |
|
||||
|
|
||||
.goods-title { |
|
||||
font-size: 26rpx; |
|
||||
max-height: 76rpx; |
|
||||
} |
|
||||
|
|
||||
.goods-props { |
|
||||
margin-top: 14rpx; |
|
||||
height: 40rpx; |
|
||||
color: #ababab; |
|
||||
font-size: 24rpx; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
display: inline-block; |
|
||||
margin-right: 14rpx; |
|
||||
padding: 4rpx 16rpx; |
|
||||
border-radius: 12rpx; |
|
||||
background-color: #F5F5F5; |
|
||||
width: auto; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 交易信息 |
|
||||
.goods-trade { |
|
||||
padding-top: 16rpx; |
|
||||
width: 150rpx; |
|
||||
text-align: right; |
|
||||
color: $uni-text-color-grey; |
|
||||
font-size: 26rpx; |
|
||||
|
|
||||
.goods-price { |
|
||||
vertical-align: bottom; |
|
||||
margin-bottom: 16rpx; |
|
||||
|
|
||||
.unit { |
|
||||
margin-right: -2rpx; |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 底部操作栏 |
|
||||
.footer-fixed { |
|
||||
position: fixed; |
|
||||
bottom: var(--window-bottom); |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
height: 96rpx; |
|
||||
z-index: 11; |
|
||||
box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24); |
|
||||
background: #fff; |
|
||||
|
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: constant(safe-area-inset-bottom); |
|
||||
padding-bottom: env(safe-area-inset-bottom); |
|
||||
|
|
||||
.btn-wrapper { |
|
||||
height: 100%; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
padding: 0 20rpx; |
|
||||
} |
|
||||
|
|
||||
.btn-item { |
|
||||
flex: 1; |
|
||||
font-size: 28rpx; |
|
||||
height: 80rpx; |
|
||||
line-height: 80rpx; |
|
||||
text-align: center; |
|
||||
color: #fff; |
|
||||
border-radius: 50rpx; |
|
||||
} |
|
||||
|
|
||||
.btn-item-main { |
|
||||
background: linear-gradient(to right, #f9211c, #ff6335); |
|
||||
|
|
||||
// 禁用按钮 |
|
||||
&.disabled { |
|
||||
background: #ff9779; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</style> |
|
||||
@ -1,866 +0,0 @@ |
|||||
<template> |
|
||||
<view v-if="!isLoading" class="container"> |
|
||||
|
|
||||
<view class="header"> |
|
||||
<!-- 订单状态 --> |
|
||||
<view class="order-status"> |
|
||||
<view class="status-icon"> |
|
||||
<!-- 进行中的订单 --> |
|
||||
<block v-if="order.order_status == OrderStatusEnum.NORMAL.value"> |
|
||||
<!-- 待支付 --> |
|
||||
<block v-if="order.pay_status == PayStatusEnum.PENDING.value"> |
|
||||
<image class="image" src="/static/order/status/wait_pay.png" mode="aspectFit"></image> |
|
||||
</block> |
|
||||
<!-- 待发货 --> |
|
||||
<block v-else-if="order.delivery_status == DeliveryStatusEnum.NOT_DELIVERED.value"> |
|
||||
<image class="image" src="/static/order/status/wait_deliver.png" mode="aspectFit"></image> |
|
||||
</block> |
|
||||
<!-- 待收货 --> |
|
||||
<block v-else-if="order.receipt_status == ReceiptStatusEnum.NOT_RECEIVED.value"> |
|
||||
<image class="image" src="/static/order/status/wait_receipt.png" mode="aspectFit"></image> |
|
||||
</block> |
|
||||
</block> |
|
||||
<!-- 已完成 --> |
|
||||
<block v-if="order.order_status == OrderStatusEnum.COMPLETED.value"> |
|
||||
<image class="image" src="/static/order/status/received.png" mode="aspectFit"></image> |
|
||||
</block> |
|
||||
<!-- 已取消/待取消 --> |
|
||||
<block v-if="order.order_status == OrderStatusEnum.CANCELLED.value || order.order_status == OrderStatusEnum.APPLY_CANCEL.value"> |
|
||||
<image class="image" src="/static/order/status/close.png" mode="aspectFit"></image> |
|
||||
</block> |
|
||||
</view> |
|
||||
<view class="status-text"> |
|
||||
<text>{{ order.state_text }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 下一步操作 --> |
|
||||
<view class="next-action" v-if="order.order_status == OrderStatusEnum.NORMAL.value"> |
|
||||
<view v-if="order.pay_status == PayStatusEnum.PENDING.value" class="action-btn" @click="onPay()">去支付</view> |
|
||||
<view v-if="order.delivery_status == DeliveryStatusEnum.DELIVERED.value && order.receipt_status == ReceiptStatusEnum.NOT_RECEIVED.value" class="action-btn" @click="onReceipt(order.order_id)">确认收货</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 快递配送:配送地址 --> |
|
||||
<view class="delivery-address i-card"> |
|
||||
<view class="link-man"> |
|
||||
<text class="name">{{ order.address.name }}</text> |
|
||||
<text class="phone">{{ order.address.phone }}</text> |
|
||||
</view> |
|
||||
<view class="address"> |
|
||||
<text class="region" v-for="(region, idx) in order.address.region" :key="idx">{{ region }}</text> |
|
||||
<text class="detail">{{ order.address.detail }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 物流信息 --> |
|
||||
<view v-if="order.delivery_type == DeliveryTypeEnum.EXPRESS.value && order.delivery_status == DeliveryStatusEnum.DELIVERED.value && order.express" class="express i-card" @click="handleTargetExpress()"> |
|
||||
<view class="main"> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">物流公司</view> |
|
||||
<view class="item-content"> |
|
||||
<text>{{ order.express.express_name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">物流单号</view> |
|
||||
<view class="item-content"> |
|
||||
<text>{{ order.express_no }}</text> |
|
||||
<view class="act-copy" @click.stop="handleCopy(order.express_no)"> |
|
||||
<text>复制</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="right-arrow"> |
|
||||
<text class="iconfont icon-arrow-right"></text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商品列表 --> |
|
||||
<view class="goods-list i-card"> |
|
||||
<view class="goods-item" v-for="(goods, idx) in order.goods" :key="idx"> |
|
||||
<view class="goods-main" @click="handleTargetGoods(goods.goods_id)"> |
|
||||
<!-- 商品图片 --> |
|
||||
<view class="goods-image"> |
|
||||
<image class="image" :src="goods.goods_image" mode="scaleToFill"></image> |
|
||||
</view> |
|
||||
<!-- 商品信息 --> |
|
||||
<view class="goods-content"> |
|
||||
<view class="goods-title"><text class="twoline-hide">{{ goods.goods_name }}</text></view> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in goods.goods_props" :key="idx"> |
|
||||
<text>{{ props.value.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 交易信息 --> |
|
||||
<view class="goods-trade"> |
|
||||
<view class="goods-price"> |
|
||||
<text class="unit">¥</text> |
|
||||
<text class="value">{{ goods.is_user_grade ? goods.grade_goods_price : goods.goods_price }}</text> |
|
||||
</view> |
|
||||
<view class="goods-num"> |
|
||||
<text>×{{ goods.total_num }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 商品售后 --> |
|
||||
<view class="goods-refund"> |
|
||||
<text v-if="goods.refund" class="stata-text">已申请售后</text> |
|
||||
<view v-else-if="order.isAllowRefund" class="action-btn" @click.stop="handleApplyRefund(goods.order_goods_id)">申请售后</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 订单信息 --> |
|
||||
<view class="order-info i-card"> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">订单编号</view> |
|
||||
<view class="item-content"> |
|
||||
<text>{{ order.order_no }}</text> |
|
||||
<view class="act-copy" @click="handleCopy(order.order_no)"> |
|
||||
<text>复制</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">下单时间</view> |
|
||||
<view class="item-content"> |
|
||||
<text>{{ order.create_time }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">买家留言</view> |
|
||||
<view class="item-content"> |
|
||||
<text>{{ order.buyer_remark ? order.buyer_remark : '--' }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 结算信息 --> |
|
||||
<view class="trade-info i-card"> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">订单金额</view> |
|
||||
<view class="item-content"> |
|
||||
<text>¥{{ order.total_price }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view v-if="order.coupon_money > 0" class="info-item"> |
|
||||
<view class="item-lable">优惠券抵扣</view> |
|
||||
<view class="item-content"> |
|
||||
<text>-¥{{ order.coupon_money }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view v-if="order.points_money > 0" class="info-item"> |
|
||||
<view class="item-lable">{{ setting.points_name }}抵扣</view> |
|
||||
<view class="item-content"> |
|
||||
<text>-¥{{ order.points_money }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">运费</view> |
|
||||
<view class="item-content"> |
|
||||
<text>+¥{{ order.express_price }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view v-if="order.update_price.value != '0.00'" class="info-item"> |
|
||||
<view class="item-lable">后台改价</view> |
|
||||
<view class="item-content"> |
|
||||
<text>{{ order.update_price.symbol }}</text> |
|
||||
<text>¥{{ order.update_price.value }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="divider"></view> |
|
||||
<view class="trade-total"> |
|
||||
<text class="lable">实付款</text> |
|
||||
<view class="goods-price"> |
|
||||
<text class="unit">¥</text> |
|
||||
<text class="value">{{ order.pay_price }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 底部操作按钮 --> |
|
||||
<view v-if="order.order_status != OrderStatusEnum.CANCELLED.value" class="footer-fixed"> |
|
||||
<view class="btn-wrapper"> |
|
||||
<!-- 未支付取消订单 --> |
|
||||
<block v-if="order.pay_status == PayStatusEnum.PENDING.value"> |
|
||||
<view class="btn-item" @click="onCancel(order.order_id)">取消</view> |
|
||||
</block> |
|
||||
<!-- 已支付进行中的订单 --> |
|
||||
<block v-if="order.order_status != OrderStatusEnum.APPLY_CANCEL.value"> |
|
||||
<block v-if="order.pay_status == PayStatusEnum.SUCCESS.value && order.delivery_status == DeliveryStatusEnum.NOT_DELIVERED.value"> |
|
||||
<view class="btn-item" @click="onCancel(order.order_id)">申请取消</view> |
|
||||
</block> |
|
||||
</block> |
|
||||
<!-- 已申请取消 --> |
|
||||
<view v-else class="f-28 col-8">取消申请中</view> |
|
||||
<!-- 未支付的订单 --> |
|
||||
<block v-if="order.pay_status == PayStatusEnum.PENDING.value"> |
|
||||
<view class="btn-item active" @click="onPay()">去支付</view> |
|
||||
</block> |
|
||||
<!-- 确认收货 --> |
|
||||
<block v-if="order.delivery_status == DeliveryStatusEnum.DELIVERED.value && order.receipt_status == ReceiptStatusEnum.NOT_RECEIVED.value"> |
|
||||
<view class="btn-item active" @click="onReceipt(order.order_id)">确认收货</view> |
|
||||
</block> |
|
||||
<!-- 订单评价 --> |
|
||||
<block v-if="order.order_status == OrderStatusEnum.COMPLETED.value && order.is_comment == 0"> |
|
||||
<view class="btn-item" @click="handleTargetComment(order.order_id)">评价</view> |
|
||||
</block> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 支付方式弹窗 --> |
|
||||
<u-popup v-model="showPayPopup" mode="bottom" border-radius="26" :closeable="true"> |
|
||||
<view class="pay-popup"> |
|
||||
<view class="title">请选择支付方式</view> |
|
||||
<view class="pop-content"> |
|
||||
<!-- 微信支付 --> |
|
||||
<!-- #ifdef MP-WEIXIN --> |
|
||||
<view class="pay-item dis-flex flex-x-between" @click="onSelectPayType(PayTypeEnum.WECHAT.value)"> |
|
||||
<view class="item-left dis-flex flex-y-center"> |
|
||||
<view class="item-left_icon wechat"> |
|
||||
<text class="iconfont icon-wechat-pay"></text> |
|
||||
</view> |
|
||||
<view class="item-left_text"> |
|
||||
<text>{{ PayTypeEnum.WECHAT.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- #endif --> |
|
||||
<!-- 余额支付 --> |
|
||||
<view class="pay-item dis-flex flex-x-between" @click="onSelectPayType(PayTypeEnum.BALANCE.value)"> |
|
||||
<view class="item-left dis-flex flex-y-center"> |
|
||||
<view class="item-left_icon balance"> |
|
||||
<text class="iconfont icon-balance-pay"></text> |
|
||||
</view> |
|
||||
<view class="item-left_text"> |
|
||||
<text>{{ PayTypeEnum.BALANCE.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</u-popup> |
|
||||
|
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { |
|
||||
DeliveryStatusEnum, |
|
||||
DeliveryTypeEnum, |
|
||||
OrderStatusEnum, |
|
||||
PayStatusEnum, |
|
||||
PayTypeEnum, |
|
||||
ReceiptStatusEnum |
|
||||
} from '@/common/enum/order' |
|
||||
import * as OrderApi from '@/api/order' |
|
||||
import { wxPayment } from '@/core/app' |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
DeliveryStatusEnum, |
|
||||
DeliveryTypeEnum, |
|
||||
OrderStatusEnum, |
|
||||
PayStatusEnum, |
|
||||
PayTypeEnum, |
|
||||
ReceiptStatusEnum, |
|
||||
// 当前订单ID |
|
||||
orderId: null, |
|
||||
// 加载中 |
|
||||
isLoading: true, |
|
||||
// 当前订单详情 |
|
||||
order: {}, |
|
||||
// 当前设置 |
|
||||
setting: {}, |
|
||||
// 支付方式弹窗 |
|
||||
showPayPopup: false, |
|
||||
// 控制onShow事件是否刷新订单信息 |
|
||||
canReset: false, |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad({ orderId }) { |
|
||||
// 当前订单ID |
|
||||
this.orderId = orderId |
|
||||
// 获取当前订单信息 |
|
||||
this.getOrderDetail() |
|
||||
// 注册全局事件订阅: 是否刷新当前订单数据 |
|
||||
uni.$on('syncRefresh', (val, isCur) => { |
|
||||
if (!isCur) { |
|
||||
this.canReset = val |
|
||||
} |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面显示 |
|
||||
*/ |
|
||||
onShow() { |
|
||||
this.canReset && this.getOrderDetail() |
|
||||
this.canReset = false |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取当前订单信息 |
|
||||
getOrderDetail(canReset = false) { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
OrderApi.detail(app.orderId) |
|
||||
.then(result => { |
|
||||
app.order = result.data.order |
|
||||
app.setting = result.data.setting |
|
||||
app.isLoading = false |
|
||||
}) |
|
||||
// 相应全局事件订阅: 刷新上级页面数据 |
|
||||
canReset && uni.$emit('syncRefresh', true, true) |
|
||||
}, |
|
||||
|
|
||||
// 复制指定内容 |
|
||||
handleCopy(value) { |
|
||||
const app = this |
|
||||
uni.setClipboardData({ |
|
||||
data: value, |
|
||||
success() { |
|
||||
app.$toast('复制成功') |
|
||||
} |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 跳转到物流跟踪页面 |
|
||||
handleTargetExpress() { |
|
||||
this.$navTo('pages/order/express/index', { orderId: this.orderId }) |
|
||||
}, |
|
||||
|
|
||||
// 跳转到商品详情页面 |
|
||||
handleTargetGoods(goodsId) { |
|
||||
this.$navTo('pages/goods/detail', { goodsId }) |
|
||||
}, |
|
||||
|
|
||||
// 跳转到申请售后页面 |
|
||||
handleApplyRefund(orderGoodsId) { |
|
||||
this.$navTo('pages/refund/apply', { orderGoodsId }) |
|
||||
}, |
|
||||
|
|
||||
// 取消订单 |
|
||||
onCancel(orderId) { |
|
||||
const app = this |
|
||||
uni.showModal({ |
|
||||
title: '友情提示', |
|
||||
content: '确认要取消该订单吗?', |
|
||||
success(o) { |
|
||||
if (o.confirm) { |
|
||||
OrderApi.cancel(orderId) |
|
||||
.then(result => { |
|
||||
// 显示成功信息 |
|
||||
app.$toast(result.message) |
|
||||
// 刷新当前订单数据 |
|
||||
app.getOrderDetail(true) |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
// 确认收货 |
|
||||
onReceipt(orderId) { |
|
||||
const app = this |
|
||||
uni.showModal({ |
|
||||
title: '友情提示', |
|
||||
content: '确认收到商品了吗?', |
|
||||
success(o) { |
|
||||
if (o.confirm) { |
|
||||
OrderApi.receipt(orderId) |
|
||||
.then(result => { |
|
||||
// 显示成功信息 |
|
||||
app.$success(result.message) |
|
||||
// 刷新当前订单数据 |
|
||||
app.getOrderDetail(true) |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
// 点击去支付 |
|
||||
onPay() { |
|
||||
// 显示支付方式弹窗 |
|
||||
this.showPayPopup = true |
|
||||
}, |
|
||||
|
|
||||
// 选择支付方式 |
|
||||
onSelectPayType(payType) { |
|
||||
const app = this |
|
||||
// 隐藏支付方式弹窗 |
|
||||
this.showPayPopup = false |
|
||||
// 发起支付请求 |
|
||||
OrderApi.pay(app.orderId, payType) |
|
||||
.then(result => app.onSubmitCallback(result)) |
|
||||
.catch(err => err) |
|
||||
}, |
|
||||
|
|
||||
// 订单提交成功后回调 |
|
||||
onSubmitCallback(result) { |
|
||||
const app = this |
|
||||
// 发起微信支付 |
|
||||
if (result.data.pay_type == PayTypeEnum.WECHAT.value) { |
|
||||
wxPayment(result.data.payment) |
|
||||
.then(() => { |
|
||||
app.$success('支付成功') |
|
||||
setTimeout(() => app.getOrderDetail(true), 1500) |
|
||||
}) |
|
||||
.catch(err => app.$error('订单未支付')) |
|
||||
.finally(() => app.disabled = false) |
|
||||
} |
|
||||
// 余额支付 |
|
||||
if (result.data.pay_type == PayTypeEnum.BALANCE.value) { |
|
||||
app.$success('支付成功') |
|
||||
app.disabled = false |
|
||||
// 刷新当前订单数据 |
|
||||
setTimeout(() => app.getOrderDetail(true), 1500) |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 跳转到订单评价页 |
|
||||
handleTargetComment(orderId) { |
|
||||
this.$navTo('pages/order/comment/index', { orderId }) |
|
||||
}, |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style> |
|
||||
page { |
|
||||
background: #f4f4f4; |
|
||||
} |
|
||||
</style> |
|
||||
<style lang="scss" scoped> |
|
||||
.container { |
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: constant(env(safe-area-inset-bottom) + 106rpx + 6rpx); |
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 106rpx + 6rpx); |
|
||||
} |
|
||||
|
|
||||
// 页面顶部 |
|
||||
.header { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
background-color: #e8c269; |
|
||||
height: 280rpx; |
|
||||
padding: 56rpx 30rpx 0 30rpx; |
|
||||
|
|
||||
.order-status { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
height: 128rpx; |
|
||||
|
|
||||
.status-icon { |
|
||||
width: 128rpx; |
|
||||
height: 128rpx; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.status-text { |
|
||||
padding-left: 20rpx; |
|
||||
color: #fff; |
|
||||
font-size: 38rpx; |
|
||||
font-weight: bold; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.next-action { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
height: 128rpx; |
|
||||
|
|
||||
.action-btn { |
|
||||
min-width: 152rpx; |
|
||||
height: 56rpx; |
|
||||
padding: 0 30rpx; |
|
||||
line-height: 56rpx; |
|
||||
background-color: #fff; |
|
||||
text-align: center; |
|
||||
border-radius: 28rpx; |
|
||||
border-color: rgb(102, 102, 102); |
|
||||
cursor: pointer; |
|
||||
user-select: none; |
|
||||
color: #c7a157; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 通栏卡片 |
|
||||
.i-card { |
|
||||
background: #fff; |
|
||||
padding: 24rpx 24rpx; |
|
||||
width: 94%; |
|
||||
box-shadow: 0 1rpx 5rpx 0px rgba(0, 0, 0, 0.05); |
|
||||
margin: 0 auto 20rpx auto; |
|
||||
border-radius: 20rpx; |
|
||||
} |
|
||||
|
|
||||
// 收货地址 |
|
||||
.delivery-address { |
|
||||
margin-top: -50rpx; |
|
||||
|
|
||||
.link-man { |
|
||||
line-height: 46rpx; |
|
||||
color: #333; |
|
||||
|
|
||||
.name { |
|
||||
margin-right: 10rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.address { |
|
||||
margin-top: 12rpx; |
|
||||
color: #999; |
|
||||
font-size: 24rpx; |
|
||||
|
|
||||
.detail { |
|
||||
margin-left: 6rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 物流公司 |
|
||||
.express { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
|
|
||||
.main { |
|
||||
flex: 1; |
|
||||
} |
|
||||
|
|
||||
.info-item { |
|
||||
display: flex; |
|
||||
margin-bottom: 24rpx; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
|
|
||||
.item-lable { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
margin-right: 30rpx; |
|
||||
} |
|
||||
|
|
||||
.item-content { |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
font-size: 26rpx; |
|
||||
color: #333; |
|
||||
|
|
||||
.act-copy { |
|
||||
margin-left: 20rpx; |
|
||||
padding: 2rpx 20rpx; |
|
||||
font-size: 22rpx; |
|
||||
color: #666; |
|
||||
border: 1rpx solid #c1c1c1; |
|
||||
border-radius: 16rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 右侧箭头 |
|
||||
.right-arrow { |
|
||||
margin-left: 16rpx; |
|
||||
// color: #777; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 商品列表 |
|
||||
.goods-list { |
|
||||
|
|
||||
// 商品项 |
|
||||
.goods-item { |
|
||||
margin-bottom: 40rpx; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
|
|
||||
// 商品信息 |
|
||||
.goods-main { |
|
||||
display: flex; |
|
||||
} |
|
||||
|
|
||||
// 商品图片 |
|
||||
.goods-image { |
|
||||
width: 180rpx; |
|
||||
height: 180rpx; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
border-radius: 8rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品内容 |
|
||||
.goods-content { |
|
||||
flex: 1; |
|
||||
padding-left: 16rpx; |
|
||||
padding-top: 16rpx; |
|
||||
|
|
||||
.goods-title { |
|
||||
font-size: 26rpx; |
|
||||
max-height: 76rpx; |
|
||||
} |
|
||||
|
|
||||
.goods-props { |
|
||||
margin-top: 14rpx; |
|
||||
height: 40rpx; |
|
||||
color: #ababab; |
|
||||
font-size: 24rpx; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
display: inline-block; |
|
||||
margin-right: 14rpx; |
|
||||
padding: 4rpx 16rpx; |
|
||||
border-radius: 12rpx; |
|
||||
background-color: #F5F5F5; |
|
||||
width: auto; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 交易信息 |
|
||||
.goods-trade { |
|
||||
padding-top: 16rpx; |
|
||||
width: 150rpx; |
|
||||
text-align: right; |
|
||||
color: $uni-text-color-grey; |
|
||||
font-size: 26rpx; |
|
||||
|
|
||||
.goods-price { |
|
||||
vertical-align: bottom; |
|
||||
margin-bottom: 16rpx; |
|
||||
|
|
||||
.unit { |
|
||||
margin-right: -2rpx; |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品售后 |
|
||||
.goods-refund { |
|
||||
display: flex; |
|
||||
justify-content: flex-end; |
|
||||
|
|
||||
.stata-text { |
|
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
} |
|
||||
|
|
||||
.action-btn { |
|
||||
border-radius: 28rpx; |
|
||||
padding: 8rpx 26rpx; |
|
||||
font-size: 24rpx; |
|
||||
color: #383838; |
|
||||
border: 1rpx solid #a8a8a8; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 订单信息 |
|
||||
.order-info { |
|
||||
|
|
||||
.info-item { |
|
||||
display: flex; |
|
||||
margin-bottom: 24rpx; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
|
|
||||
.item-lable { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
margin-right: 30rpx; |
|
||||
} |
|
||||
|
|
||||
.item-content { |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
font-size: 26rpx; |
|
||||
color: #333; |
|
||||
|
|
||||
.act-copy { |
|
||||
margin-left: 20rpx; |
|
||||
padding: 2rpx 20rpx; |
|
||||
font-size: 22rpx; |
|
||||
color: #666; |
|
||||
border: 1rpx solid #c1c1c1; |
|
||||
border-radius: 16rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 交易信息 |
|
||||
.trade-info { |
|
||||
|
|
||||
.info-item { |
|
||||
display: flex; |
|
||||
margin-bottom: 24rpx; |
|
||||
|
|
||||
.item-lable { |
|
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
margin-right: 24rpx; |
|
||||
} |
|
||||
|
|
||||
.item-content { |
|
||||
flex: 1; |
|
||||
font-size: 26rpx; |
|
||||
color: #333; |
|
||||
text-align: right; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.divider { |
|
||||
height: 1rpx; |
|
||||
background: #f1f1f1; |
|
||||
margin-bottom: 24rpx; |
|
||||
} |
|
||||
|
|
||||
.trade-total { |
|
||||
display: flex; |
|
||||
justify-content: flex-end; |
|
||||
|
|
||||
.goods-price { |
|
||||
margin-left: 12rpx; |
|
||||
vertical-align: bottom; |
|
||||
color: $uni-text-color-active; |
|
||||
|
|
||||
.unit { |
|
||||
margin-right: -2rpx; |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
/* 底部操作栏 */ |
|
||||
|
|
||||
.footer-fixed { |
|
||||
position: fixed; |
|
||||
bottom: var(--window-bottom); |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
z-index: 11; |
|
||||
box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24); |
|
||||
background: #fff; |
|
||||
|
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: constant(safe-area-inset-bottom); |
|
||||
padding-bottom: env(safe-area-inset-bottom); |
|
||||
|
|
||||
.btn-wrapper { |
|
||||
height: 106rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: flex-end; |
|
||||
padding: 0 30rpx; |
|
||||
} |
|
||||
|
|
||||
.btn-item { |
|
||||
min-width: 164rpx; |
|
||||
border-radius: 28rpx; |
|
||||
padding: 10rpx 24rpx; |
|
||||
font-size: 28rpx; |
|
||||
color: #383838; |
|
||||
text-align: center; |
|
||||
border: 1rpx solid #a8a8a8; |
|
||||
margin-left: 24rpx; |
|
||||
|
|
||||
&.active { |
|
||||
color: #fff; |
|
||||
border: none; |
|
||||
background: linear-gradient(to right, #f9211c, #ff6335); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 弹出层-支付方式 |
|
||||
.pay-popup { |
|
||||
padding: 24rpx; |
|
||||
|
|
||||
.title { |
|
||||
font-size: 30rpx; |
|
||||
margin-bottom: 50rpx; |
|
||||
font-weight: bold; |
|
||||
text-align: center; |
|
||||
} |
|
||||
|
|
||||
.pop-content { |
|
||||
min-height: 260rpx; |
|
||||
padding: 0 10rpx; |
|
||||
|
|
||||
.pay-item { |
|
||||
padding: 20rpx 35rpx; |
|
||||
font-size: 28rpx; |
|
||||
border-bottom: 1rpx solid #f1f1f1; |
|
||||
|
|
||||
&:last-child { |
|
||||
border-bottom: none; |
|
||||
} |
|
||||
|
|
||||
.item-left_icon { |
|
||||
margin-right: 20rpx; |
|
||||
font-size: 32rpx; |
|
||||
|
|
||||
&.wechat { |
|
||||
color: #00c800; |
|
||||
} |
|
||||
|
|
||||
&.balance { |
|
||||
color: #ff9700; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// |
|
||||
</style> |
|
||||
@ -1,202 +0,0 @@ |
|||||
<template> |
|
||||
<view v-if="!isLoading" class="container"> |
|
||||
<!-- 物流信息 --> |
|
||||
<view class="express i-card"> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">物流公司</view> |
|
||||
<view class="item-content"> |
|
||||
<text>{{ express.express_name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="info-item"> |
|
||||
<view class="item-lable">物流单号</view> |
|
||||
<view class="item-content"> |
|
||||
<text>{{ express.express_no }}</text> |
|
||||
<view class="act-copy" @click.stop="handleCopy(express.express_no)"> |
|
||||
<text>复制</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 物流动态 --> |
|
||||
<view class="logis-detail"> |
|
||||
<view class="logis-item" :class="{ first: index === 0 }" v-for="(item, index) in express.list" :key="index"> |
|
||||
<view class="logis-item-content"> |
|
||||
<view class="logis-item-content__describe"> |
|
||||
<text class="f-26">{{ item.context }}</text> |
|
||||
</view> |
|
||||
<view class="logis-item-content__time"> |
|
||||
<text class="f-22">{{ item.ftime }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as OrderApi from '@/api/order' |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 当前订单ID |
|
||||
orderId: null, |
|
||||
// 物流信息 |
|
||||
express: {} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad({ orderId }) { |
|
||||
this.orderId = orderId |
|
||||
// 获取当前订单的物流信息 |
|
||||
this.getExpress() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取当前订单的物流信息 |
|
||||
getExpress() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
OrderApi.express(app.orderId) |
|
||||
.then(result => { |
|
||||
app.express = result.data.express |
|
||||
app.isLoading = false |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 复制指定内容 |
|
||||
handleCopy(value) { |
|
||||
const app = this |
|
||||
uni.setClipboardData({ |
|
||||
data: value, |
|
||||
success() { |
|
||||
app.$toast('复制成功') |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
// 通栏卡片 |
|
||||
.i-card { |
|
||||
background: #fff; |
|
||||
padding: 24rpx 24rpx; |
|
||||
// width: 94%; |
|
||||
box-shadow: 0 1rpx 5rpx 0px rgba(0, 0, 0, 0.05); |
|
||||
// margin: 0 auto 20rpx auto; |
|
||||
// border-radius: 20rpx; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 物流公司 |
|
||||
.express { |
|
||||
|
|
||||
// margin-top: 24rpx; |
|
||||
|
|
||||
.info-item { |
|
||||
display: flex; |
|
||||
margin-bottom: 24rpx; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
|
|
||||
.item-lable { |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
font-size: 24rpx; |
|
||||
color: #999; |
|
||||
margin-right: 30rpx; |
|
||||
} |
|
||||
|
|
||||
.item-content { |
|
||||
flex: 1; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
font-size: 26rpx; |
|
||||
color: #333; |
|
||||
|
|
||||
.act-copy { |
|
||||
margin-left: 20rpx; |
|
||||
padding: 2rpx 20rpx; |
|
||||
font-size: 22rpx; |
|
||||
color: #666; |
|
||||
border: 1rpx solid #c1c1c1; |
|
||||
border-radius: 16rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
.logis-detail { |
|
||||
padding: 30rpx; |
|
||||
background-color: #fff; |
|
||||
|
|
||||
.logis-item { |
|
||||
position: relative; |
|
||||
padding: 10px 0 10px 25px; |
|
||||
box-sizing: border-box; |
|
||||
border-left: 2px solid #ccc; |
|
||||
|
|
||||
&.first { |
|
||||
border-left: 2px solid #f40; |
|
||||
|
|
||||
&:after { |
|
||||
background: #f40; |
|
||||
} |
|
||||
|
|
||||
.logis-item-content { |
|
||||
background: #ff6e39; |
|
||||
color: #fff; |
|
||||
|
|
||||
&:after { |
|
||||
border-bottom-color: #ff6e39; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
&:after { |
|
||||
content: ' '; |
|
||||
display: inline-block; |
|
||||
position: absolute; |
|
||||
left: -6px; |
|
||||
top: 30px; |
|
||||
width: 6px; |
|
||||
height: 6px; |
|
||||
border-radius: 10px; |
|
||||
background: #bdbdbd; |
|
||||
border: 2px solid #fff; |
|
||||
} |
|
||||
|
|
||||
.logis-item-content { |
|
||||
position: relative; |
|
||||
background: #f9f9f9; |
|
||||
padding: 10rpx 20rpx; |
|
||||
box-sizing: border-box; |
|
||||
color: #666; |
|
||||
|
|
||||
&:after { |
|
||||
content: ''; |
|
||||
display: inline-block; |
|
||||
position: absolute; |
|
||||
left: -10px; |
|
||||
top: 18px; |
|
||||
border-left: 10px solid #fff; |
|
||||
border-bottom: 10px solid #f3f3f3; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,596 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ native: true }" @down="downCallback" :up="upOption" @up="upCallback"> |
|
||||
|
|
||||
<!-- tab栏 --> |
|
||||
<u-tabs :list="tabs" :is-scroll="false" :current="curTab" active-color="#FA2209" :duration="0.2" @change="onChangeTab" /> |
|
||||
|
|
||||
<!-- 订单列表 --> |
|
||||
<view class="order-list"> |
|
||||
<view class="order-item" v-for="(item, index) in list.data" :key="index"> |
|
||||
<view class="item-top"> |
|
||||
<view class="item-top-left"> |
|
||||
<text class="order-time">{{ item.create_time }}</text> |
|
||||
</view> |
|
||||
<view class="item-top-right"> |
|
||||
<text class="state-text">{{ item.state_text }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 商品列表 --> |
|
||||
<view class="goods-list" @click="handleTargetDetail(item.order_id)"> |
|
||||
<view class="goods-item" v-for="(goods, idx) in item.goods" :key="idx"> |
|
||||
<!-- 商品图片 --> |
|
||||
<view class="goods-image"> |
|
||||
<image class="image" :src="goods.goods_image" mode="scaleToFill"></image> |
|
||||
</view> |
|
||||
<!-- 商品信息 --> |
|
||||
<view class="goods-content"> |
|
||||
<view class="goods-title"><text class="twoline-hide">{{ goods.goods_name }}</text></view> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in goods.goods_props" :key="idx"> |
|
||||
<text>{{ props.value.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 交易信息 --> |
|
||||
<view class="goods-trade"> |
|
||||
<view class="goods-price"> |
|
||||
<text class="unit">¥</text> |
|
||||
<text class="value">{{ goods.is_user_grade ? goods.grade_goods_price : goods.goods_price }}</text> |
|
||||
</view> |
|
||||
<view class="goods-num"> |
|
||||
<text>×{{ goods.total_num }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 订单合计 --> |
|
||||
<view class="order-total"> |
|
||||
<text>共{{ item.total_num }}件商品,总金额</text> |
|
||||
<text class="unit">¥</text> |
|
||||
<text class="money">{{ item.pay_price }}</text> |
|
||||
</view> |
|
||||
<!-- 订单操作 --> |
|
||||
<view v-if="item.order_status != OrderStatusEnum.CANCELLED.value" class="order-handle"> |
|
||||
<view class="btn-group clearfix"> |
|
||||
<!-- 未支付取消订单 --> |
|
||||
<block v-if="item.pay_status == PayStatusEnum.PENDING.value"> |
|
||||
<view class="btn-item" @click="onCancel(item.order_id)">取消</view> |
|
||||
</block> |
|
||||
<!-- 已支付进行中的订单 --> |
|
||||
<block v-if="item.order_status != OrderStatusEnum.APPLY_CANCEL.value"> |
|
||||
<block v-if="item.pay_status == PayStatusEnum.SUCCESS.value && item.delivery_status == DeliveryStatusEnum.NOT_DELIVERED.value"> |
|
||||
<view class="btn-item" @click="onCancel(item.order_id)">申请取消</view> |
|
||||
</block> |
|
||||
</block> |
|
||||
<!-- 已申请取消 --> |
|
||||
<view v-else class="f-28 col-8">取消申请中</view> |
|
||||
<!-- 未支付的订单 --> |
|
||||
<block v-if="item.pay_status == PayStatusEnum.PENDING.value"> |
|
||||
<view class="btn-item active" @click="onPay(item.order_id)">去支付</view> |
|
||||
</block> |
|
||||
<!-- 确认收货 --> |
|
||||
<block v-if="item.delivery_status == DeliveryStatusEnum.DELIVERED.value && item.receipt_status == ReceiptStatusEnum.NOT_RECEIVED.value"> |
|
||||
<view class="btn-item active" @click="onReceipt(item.order_id)">确认收货</view> |
|
||||
</block> |
|
||||
<!-- 订单评价 --> |
|
||||
<block v-if="item.order_status == OrderStatusEnum.COMPLETED.value && item.is_comment == 0"> |
|
||||
<view class="btn-item" @click="handleTargetComment(item.order_id)">评价</view> |
|
||||
</block> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
</view> |
|
||||
</view> |
|
||||
</mescroll-body> |
|
||||
|
|
||||
<!-- 支付方式弹窗 --> |
|
||||
<u-popup v-model="showPayPopup" mode="bottom" border-radius="26" :closeable="true"> |
|
||||
<view class="pay-popup"> |
|
||||
<view class="title">请选择支付方式</view> |
|
||||
<view class="pop-content"> |
|
||||
<!-- 微信支付 --> |
|
||||
<!-- #ifdef MP-WEIXIN --> |
|
||||
<view class="pay-item dis-flex flex-x-between" @click="onSelectPayType(PayTypeEnum.WECHAT.value)"> |
|
||||
<view class="item-left dis-flex flex-y-center"> |
|
||||
<view class="item-left_icon wechat"> |
|
||||
<text class="iconfont icon-wechat-pay"></text> |
|
||||
</view> |
|
||||
<view class="item-left_text"> |
|
||||
<text>{{ PayTypeEnum.WECHAT.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- #endif --> |
|
||||
<!-- 余额支付 --> |
|
||||
<view class="pay-item dis-flex flex-x-between" @click="onSelectPayType(PayTypeEnum.BALANCE.value)"> |
|
||||
<view class="item-left dis-flex flex-y-center"> |
|
||||
<view class="item-left_icon balance"> |
|
||||
<text class="iconfont icon-balance-pay"></text> |
|
||||
</view> |
|
||||
<view class="item-left_text"> |
|
||||
<text>{{ PayTypeEnum.BALANCE.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</u-popup> |
|
||||
|
|
||||
</view> |
|
||||
|
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { |
|
||||
DeliveryStatusEnum, |
|
||||
DeliveryTypeEnum, |
|
||||
OrderStatusEnum, |
|
||||
PayStatusEnum, |
|
||||
PayTypeEnum, |
|
||||
ReceiptStatusEnum |
|
||||
} from '@/common/enum/order' |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import { getEmptyPaginateObj, getMoreListData } from '@/core/app' |
|
||||
import * as OrderApi from '@/api/order' |
|
||||
import { wxPayment } from '@/core/app' |
|
||||
|
|
||||
// 每页记录数量 |
|
||||
const pageSize = 15 |
|
||||
|
|
||||
// tab栏数据 |
|
||||
const tabs = [{ |
|
||||
name: `全部`, |
|
||||
value: 'all' |
|
||||
}, { |
|
||||
name: `待支付`, |
|
||||
value: 'payment' |
|
||||
}, { |
|
||||
name: `待发货`, |
|
||||
value: 'delivery' |
|
||||
}, { |
|
||||
name: `待收货`, |
|
||||
value: 'received' |
|
||||
}, { |
|
||||
name: `待评价`, |
|
||||
value: 'comment' |
|
||||
}] |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody |
|
||||
}, |
|
||||
mixins: [MescrollMixin], |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
DeliveryStatusEnum, |
|
||||
DeliveryTypeEnum, |
|
||||
OrderStatusEnum, |
|
||||
PayStatusEnum, |
|
||||
PayTypeEnum, |
|
||||
ReceiptStatusEnum, |
|
||||
|
|
||||
// 当前页面参数 |
|
||||
options: { dataType: 'all' }, |
|
||||
// tab栏数据 |
|
||||
tabs, |
|
||||
// 当前标签索引 |
|
||||
curTab: 0, |
|
||||
// 订单列表数据 |
|
||||
list: getEmptyPaginateObj(), |
|
||||
|
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于4条才显示无更多数据 |
|
||||
noMoreSize: 4, |
|
||||
// 空布局 |
|
||||
empty: { |
|
||||
tip: '亲,暂无订单记录' |
|
||||
} |
|
||||
}, |
|
||||
// 控制onShow事件是否刷新订单列表 |
|
||||
canReset: false, |
|
||||
// 支付方式弹窗 |
|
||||
showPayPopup: false |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 初始化当前选中的标签 |
|
||||
this.initCurTab(options) |
|
||||
// 注册全局事件订阅: 是否刷新订单列表 |
|
||||
uni.$on('syncRefresh', canReset => { |
|
||||
this.canReset = canReset |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面显示 |
|
||||
*/ |
|
||||
onShow() { |
|
||||
this.canReset && this.onRefreshList() |
|
||||
this.canReset = false |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面的卸载 |
|
||||
*/ |
|
||||
onUnload() { |
|
||||
// 卸载全局事件订阅 |
|
||||
uni.$off('syncRefresh') |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 初始化当前选中的标签 |
|
||||
initCurTab(options) { |
|
||||
const app = this |
|
||||
if (options.dataType) { |
|
||||
const index = app.tabs.findIndex(item => item.value == options.dataType) |
|
||||
app.curTab = index > -1 ? index : 0 |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getOrderList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
// 获取订单列表 |
|
||||
getOrderList(pageNo = 1) { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
OrderApi.list({ dataType: app.getTabValue(), page: pageNo }, { load: false }) |
|
||||
.then(result => { |
|
||||
// 合并新数据 |
|
||||
const newList = app.initList(result.data.list) |
|
||||
app.list.data = getMoreListData(newList, app.list, pageNo) |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 初始化订单列表数据 |
|
||||
initList(newList) { |
|
||||
newList.data.forEach(item => { |
|
||||
item.total_num = 0 |
|
||||
item.goods.forEach(goods => { |
|
||||
item.total_num += goods.total_num |
|
||||
}) |
|
||||
}) |
|
||||
return newList |
|
||||
}, |
|
||||
|
|
||||
// 获取当前标签项的值 |
|
||||
getTabValue() { |
|
||||
return this.tabs[this.curTab].value |
|
||||
}, |
|
||||
|
|
||||
// 切换标签项 |
|
||||
onChangeTab(index) { |
|
||||
const app = this |
|
||||
// 设置当前选中的标签 |
|
||||
app.curTab = index |
|
||||
// 刷新订单列表 |
|
||||
app.onRefreshList() |
|
||||
}, |
|
||||
|
|
||||
// 刷新订单列表 |
|
||||
onRefreshList() { |
|
||||
this.list = getEmptyPaginateObj() |
|
||||
setTimeout(() => { |
|
||||
this.mescroll.resetUpScroll() |
|
||||
}, 120) |
|
||||
}, |
|
||||
|
|
||||
// 取消订单 |
|
||||
onCancel(orderId) { |
|
||||
const app = this |
|
||||
uni.showModal({ |
|
||||
title: '友情提示', |
|
||||
content: '确认要取消该订单吗?', |
|
||||
success(o) { |
|
||||
if (o.confirm) { |
|
||||
OrderApi.cancel(orderId) |
|
||||
.then(result => { |
|
||||
// 显示成功信息 |
|
||||
app.$toast(result.message) |
|
||||
// 刷新订单列表 |
|
||||
app.onRefreshList() |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
// 确认收货 |
|
||||
onReceipt(orderId) { |
|
||||
const app = this |
|
||||
uni.showModal({ |
|
||||
title: '友情提示', |
|
||||
content: '确认收到商品了吗?', |
|
||||
success(o) { |
|
||||
if (o.confirm) { |
|
||||
OrderApi.receipt(orderId) |
|
||||
.then(result => { |
|
||||
// 显示成功信息 |
|
||||
app.$success(result.message) |
|
||||
// 刷新订单列表 |
|
||||
app.onRefreshList() |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
// 点击去支付 |
|
||||
onPay(orderId) { |
|
||||
// 记录订单id |
|
||||
this.payOrderId = orderId |
|
||||
// 显示支付方式弹窗 |
|
||||
this.showPayPopup = true |
|
||||
}, |
|
||||
|
|
||||
// 选择支付方式 |
|
||||
onSelectPayType(payType) { |
|
||||
const app = this |
|
||||
// 隐藏支付方式弹窗 |
|
||||
this.showPayPopup = false |
|
||||
// 发起支付请求 |
|
||||
OrderApi.pay(app.payOrderId, payType) |
|
||||
.then(result => app.onSubmitCallback(result)) |
|
||||
}, |
|
||||
|
|
||||
// 订单提交成功后回调 |
|
||||
onSubmitCallback(result) { |
|
||||
const app = this |
|
||||
// 发起微信支付 |
|
||||
if (result.data.pay_type == PayTypeEnum.WECHAT.value) { |
|
||||
wxPayment(result.data.payment) |
|
||||
.then(() => { |
|
||||
app.$success('支付成功') |
|
||||
setTimeout(() => { |
|
||||
app.onRefreshList() |
|
||||
}, 1500) |
|
||||
}) |
|
||||
.catch(err => { |
|
||||
app.$error('订单未支付') |
|
||||
}) |
|
||||
.finally(() => { |
|
||||
app.disabled = false |
|
||||
}) |
|
||||
} |
|
||||
// 余额支付 |
|
||||
if (result.data.pay_type == PayTypeEnum.BALANCE.value) { |
|
||||
app.$success('支付成功') |
|
||||
app.disabled = false |
|
||||
setTimeout(() => { |
|
||||
app.onRefreshList() |
|
||||
}, 1500) |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 跳转到订单详情页 |
|
||||
handleTargetDetail(orderId) { |
|
||||
this.$navTo('pages/order/detail', { orderId }) |
|
||||
}, |
|
||||
|
|
||||
// 跳转到订单评价页 |
|
||||
handleTargetComment(orderId) { |
|
||||
this.$navTo('pages/order/comment/index', { orderId }) |
|
||||
} |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
// 项目内容 |
|
||||
.order-item { |
|
||||
margin: 20rpx auto 20rpx auto; |
|
||||
padding: 30rpx 30rpx; |
|
||||
width: 94%; |
|
||||
box-shadow: 0 1rpx 5rpx 0px rgba(0, 0, 0, 0.05); |
|
||||
border-radius: 16rpx; |
|
||||
background: #fff; |
|
||||
} |
|
||||
|
|
||||
// 项目顶部 |
|
||||
.item-top { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
font-size: 26rpx; |
|
||||
margin-bottom: 40rpx; |
|
||||
|
|
||||
.order-time { |
|
||||
color: #777; |
|
||||
} |
|
||||
|
|
||||
.state-text { |
|
||||
color: $uni-text-color-active; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品列表 |
|
||||
.goods-list { |
|
||||
|
|
||||
// 商品项 |
|
||||
.goods-item { |
|
||||
display: flex; |
|
||||
margin-bottom: 40rpx; |
|
||||
|
|
||||
// 商品图片 |
|
||||
.goods-image { |
|
||||
width: 180rpx; |
|
||||
height: 180rpx; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
border-radius: 8rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 商品内容 |
|
||||
.goods-content { |
|
||||
flex: 1; |
|
||||
padding-left: 16rpx; |
|
||||
padding-top: 16rpx; |
|
||||
|
|
||||
.goods-title { |
|
||||
font-size: 26rpx; |
|
||||
max-height: 76rpx; |
|
||||
} |
|
||||
|
|
||||
.goods-props { |
|
||||
margin-top: 14rpx; |
|
||||
height: 40rpx; |
|
||||
color: #ababab; |
|
||||
font-size: 24rpx; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
display: inline-block; |
|
||||
margin-right: 14rpx; |
|
||||
padding: 4rpx 16rpx; |
|
||||
border-radius: 12rpx; |
|
||||
background-color: #F5F5F5; |
|
||||
width: auto; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 交易信息 |
|
||||
.goods-trade { |
|
||||
padding-top: 16rpx; |
|
||||
width: 150rpx; |
|
||||
text-align: right; |
|
||||
color: $uni-text-color-grey; |
|
||||
font-size: 26rpx; |
|
||||
|
|
||||
.goods-price { |
|
||||
vertical-align: bottom; |
|
||||
margin-bottom: 16rpx; |
|
||||
|
|
||||
.unit { |
|
||||
margin-right: -2rpx; |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 订单合计 |
|
||||
.order-total { |
|
||||
font-size: 26rpx; |
|
||||
vertical-align: bottom; |
|
||||
text-align: right; |
|
||||
height: 40rpx; |
|
||||
margin-bottom: 30rpx; |
|
||||
|
|
||||
.unit { |
|
||||
margin-left: 8rpx; |
|
||||
margin-right: -2rpx; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
|
|
||||
.money { |
|
||||
font-size: 28rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 订单操作 |
|
||||
.order-handle { |
|
||||
.btn-group { |
|
||||
|
|
||||
.btn-item { |
|
||||
border-radius: 10rpx; |
|
||||
padding: 6rpx 20rpx; |
|
||||
margin-left: 15rpx; |
|
||||
font-size: 28rpx; |
|
||||
float: right; |
|
||||
color: #383838; |
|
||||
border: 1rpx solid #a8a8a8; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-left: 0; |
|
||||
} |
|
||||
|
|
||||
&.active { |
|
||||
color: $uni-text-color-active; |
|
||||
border: 1rpx solid $uni-text-color-active; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
// 弹出层-支付方式 |
|
||||
.pay-popup { |
|
||||
padding: 24rpx; |
|
||||
|
|
||||
.title { |
|
||||
font-size: 30rpx; |
|
||||
margin-bottom: 40rpx; |
|
||||
font-weight: bold; |
|
||||
text-align: center; |
|
||||
} |
|
||||
|
|
||||
.pop-content { |
|
||||
min-height: 260rpx; |
|
||||
padding: 0 10rpx; |
|
||||
|
|
||||
.pay-item { |
|
||||
padding: 24rpx 35rpx; |
|
||||
font-size: 28rpx; |
|
||||
border-bottom: 1rpx solid #f1f1f1; |
|
||||
|
|
||||
&:last-child { |
|
||||
border-bottom: none; |
|
||||
} |
|
||||
|
|
||||
.item-left_icon { |
|
||||
margin-right: 20rpx; |
|
||||
font-size: 32rpx; |
|
||||
|
|
||||
&.wechat { |
|
||||
color: #00c800; |
|
||||
} |
|
||||
|
|
||||
&.balance { |
|
||||
color: #ff9700; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,127 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption" |
|
||||
@up="upCallback"> |
|
||||
<view class="log-list"> |
|
||||
<view v-for="(item, index) in list.data" :key="index" class="log-item"> |
|
||||
<view class="item-left flex-box"> |
|
||||
<view class="rec-status"> |
|
||||
<text>{{ item.describe }}</text> |
|
||||
</view> |
|
||||
<view class="rec-time"> |
|
||||
<text>{{ item.create_time }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="item-right" :class="[item.value > 0 ? 'col-green' : 'col-6']"> |
|
||||
<text>{{ item.value > 0 ? '+' : '' }}{{ item.value }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</mescroll-body> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import * as LogApi from '@/api/points/log' |
|
||||
import { getEmptyPaginateObj, getMoreListData } from '@/core/app' |
|
||||
|
|
||||
const pageSize = 15 |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody |
|
||||
}, |
|
||||
mixins: [MescrollMixin], |
|
||||
data() { |
|
||||
return { |
|
||||
// 充值记录 |
|
||||
list: getEmptyPaginateObj(), |
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于12条才显示无更多数据 |
|
||||
noMoreSize: 12, |
|
||||
// 空布局 |
|
||||
empty: { |
|
||||
tip: '亲,暂无相关数据' |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) {}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getLogList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
// 获取积分明细列表 |
|
||||
getLogList(pageNo = 1) { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
LogApi.list({ page: pageNo }) |
|
||||
.then(result => { |
|
||||
// 合并新数据 |
|
||||
const newList = result.data.list |
|
||||
app.list.data = getMoreListData(newList, app.list, pageNo) |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
page, |
|
||||
.container { |
|
||||
background: #fff; |
|
||||
} |
|
||||
|
|
||||
.log-list { |
|
||||
padding: 0 30rpx; |
|
||||
} |
|
||||
|
|
||||
.log-item { |
|
||||
font-size: 28rpx; |
|
||||
padding: 20rpx 20rpx; |
|
||||
line-height: 1.8; |
|
||||
border-bottom: 1rpx solid rgb(238, 238, 238); |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.rec-status { |
|
||||
color: #333; |
|
||||
|
|
||||
.rec-time { |
|
||||
color: rgb(160, 160, 160); |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,429 +0,0 @@ |
|||||
<template> |
|
||||
<view v-if="!isLoading" class="container"> |
|
||||
|
|
||||
<!-- 商品详情 --> |
|
||||
<view class="goods-detail b-f dis-flex flex-dir-row"> |
|
||||
<view class="left"> |
|
||||
<image class="goods-image" :src="goods.goods_image"></image> |
|
||||
</view> |
|
||||
<view class="right dis-flex flex-box flex-dir-column flex-x-around"> |
|
||||
<view class="goods-name"> |
|
||||
<text class="twoline-hide">{{ goods.goods_name }}</text> |
|
||||
</view> |
|
||||
<view class="dis-flex col-9 f-24"> |
|
||||
<view class="flex-box"> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in goods.goods_props" :key="idx"> |
|
||||
<text>{{ props.value.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<text class="t-r">×{{ goods.total_num }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 服务类型 --> |
|
||||
<view class="row-service b-f m-top20"> |
|
||||
<view class="row-title">服务类型</view> |
|
||||
<view class="service-switch dis-flex"> |
|
||||
<view class="switch-item" v-for="(item, index) in RefundTypeEnum.data" :key="index" :class="{ active: formData.type == item.value }" |
|
||||
@click="onSwitchService(item.value)">{{ item.name }}</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 申请原因 --> |
|
||||
<view class="row-textarea b-f m-top20"> |
|
||||
<view class="row-title">申请原因</view> |
|
||||
<view class="content"> |
|
||||
<textarea class="textarea" v-model="formData.content" maxlength="2000" placeholder="请详细填写申请原因,注意保持商品的完好,建议您先与卖家沟通" |
|
||||
placeholderStyle="color:#ccc"></textarea> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 退款金额 --> |
|
||||
<view v-if="formData.type == RefundTypeEnum.RETURN.value" class="row-money b-f m-top20 dis-flex"> |
|
||||
<view class="row-title">退款金额</view> |
|
||||
<view class="money col-m">¥{{ goods.total_pay_price }}</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 上传凭证 --> |
|
||||
<view class="row-voucher b-f m-top20"> |
|
||||
<view class="row-title">上传凭证 (最多6张)</view> |
|
||||
<view class="image-list"> |
|
||||
<!-- 图片列表 --> |
|
||||
<view class="image-preview" v-for="(image, imageIndex) in imageList" :key="imageIndex"> |
|
||||
<text class="image-delete iconfont icon-shanchu" @click="deleteImage(imageIndex)"></text> |
|
||||
<image class="image" mode="aspectFill" :src="image.path"></image> |
|
||||
</view> |
|
||||
<!-- 上传图片 --> |
|
||||
<view v-if="imageList.length < maxImageLength" class="image-picker" @click="chooseImage()"> |
|
||||
<text class="choose-icon iconfont icon-camera"></text> |
|
||||
<text class="choose-text">上传图片</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 底部操作按钮 --> |
|
||||
<view class="footer-fixed"> |
|
||||
<view class="btn-wrapper"> |
|
||||
<view class="btn-item btn-item-main" :class="{ disabled }" @click="handleSubmit()">确认提交</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { RefundTypeEnum } from '@/common/enum/order/refund' |
|
||||
import * as UploadApi from '@/api/upload' |
|
||||
import * as RefundApi from '@/api/refund' |
|
||||
|
|
||||
const maxImageLength = 6 |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
RefundTypeEnum, |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 订单商品id |
|
||||
orderGoodsId: null, |
|
||||
// 订单商品详情 |
|
||||
goods: {}, |
|
||||
// 表单数据 |
|
||||
formData: { |
|
||||
// 图片上传成功的文件ID集 |
|
||||
images: [], |
|
||||
// 服务类型 |
|
||||
type: 10, |
|
||||
// 申请原因 |
|
||||
content: '' |
|
||||
}, |
|
||||
// 用户选择的图片列表 |
|
||||
imageList: [], |
|
||||
// 最大图片数量 |
|
||||
maxImageLength, |
|
||||
// 按钮禁用 |
|
||||
disabled: false |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad({ orderGoodsId }) { |
|
||||
this.orderGoodsId = orderGoodsId |
|
||||
// 获取订单商品详情 |
|
||||
this.getGoodsDetail() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取订单商品详情 |
|
||||
getGoodsDetail() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
RefundApi.goods(app.orderGoodsId) |
|
||||
.then(result => { |
|
||||
app.goods = result.data.goods |
|
||||
app.isLoading = false |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 切换类型 |
|
||||
onSwitchService(value) { |
|
||||
this.formData.type = value |
|
||||
}, |
|
||||
|
|
||||
// 选择图片 |
|
||||
chooseImage() { |
|
||||
const app = this |
|
||||
const oldImageList = app.imageList |
|
||||
// 选择图片 |
|
||||
uni.chooseImage({ |
|
||||
count: maxImageLength - oldImageList.length, |
|
||||
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 |
|
||||
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 |
|
||||
success({ tempFiles }) { |
|
||||
// tempFiles = [{path:'xxx', size:100}] |
|
||||
app.imageList = oldImageList.concat(tempFiles) |
|
||||
} |
|
||||
}); |
|
||||
}, |
|
||||
|
|
||||
// 删除图片 |
|
||||
deleteImage(imageIndex) { |
|
||||
this.imageList.splice(imageIndex, 1) |
|
||||
}, |
|
||||
|
|
||||
// 表单提交 |
|
||||
handleSubmit() { |
|
||||
const app = this |
|
||||
const { imageList } = app |
|
||||
// 判断是否重复提交 |
|
||||
if (app.disabled === true) return false |
|
||||
// 按钮禁用 |
|
||||
app.disabled = true |
|
||||
// 判断是否需要上传图片 |
|
||||
if (imageList.length > 0) { |
|
||||
app.uploadFile() |
|
||||
.then(() => app.onSubmit()) |
|
||||
.catch(err => { |
|
||||
app.disabled = false |
|
||||
if (err.statusCode !== 0) { |
|
||||
app.$toast(err.errMsg) |
|
||||
} |
|
||||
console.log('err', err) |
|
||||
}) |
|
||||
} else { |
|
||||
app.onSubmit() |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// 提交到后端 |
|
||||
onSubmit() { |
|
||||
const app = this |
|
||||
RefundApi.apply(app.orderGoodsId, app.formData) |
|
||||
.then(result => { |
|
||||
app.$toast(result.message) |
|
||||
setTimeout(() => { |
|
||||
app.disabled = false |
|
||||
uni.navigateBack() |
|
||||
}, 1500) |
|
||||
}) |
|
||||
.catch(err => app.disabled = false) |
|
||||
}, |
|
||||
|
|
||||
// 上传图片 |
|
||||
uploadFile() { |
|
||||
const app = this |
|
||||
const { imageList } = app |
|
||||
// 批量上传 |
|
||||
return new Promise((resolve, reject) => { |
|
||||
if (imageList.length > 0) { |
|
||||
UploadApi.image(imageList) |
|
||||
.then(fileIds => { |
|
||||
app.formData.images = fileIds |
|
||||
resolve(fileIds) |
|
||||
}) |
|
||||
.catch(reject) |
|
||||
} else { |
|
||||
resolve() |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.container { |
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: calc(constant(safe-area-inset-bottom) + 140rpx); |
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 140rpx); |
|
||||
} |
|
||||
|
|
||||
.row-title { |
|
||||
color: #888; |
|
||||
margin-bottom: 20rpx; |
|
||||
} |
|
||||
|
|
||||
// 商品信息 |
|
||||
.goods-detail { |
|
||||
padding: 24rpx 20rpx; |
|
||||
|
|
||||
.left { |
|
||||
.goods-image { |
|
||||
display: block; |
|
||||
width: 150rpx; |
|
||||
height: 150rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.right { |
|
||||
padding-left: 20rpx; |
|
||||
} |
|
||||
|
|
||||
.goods-props { |
|
||||
margin-top: 14rpx; |
|
||||
height: 40rpx; |
|
||||
color: #ababab; |
|
||||
font-size: 24rpx; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
display: inline-block; |
|
||||
margin-right: 14rpx; |
|
||||
padding: 4rpx 16rpx; |
|
||||
border-radius: 12rpx; |
|
||||
background-color: #F5F5F5; |
|
||||
width: auto; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* 服务类型 */ |
|
||||
.row-service { |
|
||||
padding: 24rpx 20rpx; |
|
||||
} |
|
||||
|
|
||||
.service-switch { |
|
||||
.switch-item { |
|
||||
padding: 6rpx 30rpx; |
|
||||
margin-right: 25rpx; |
|
||||
border-radius: 10rpx; |
|
||||
border: 1px solid rgb(177, 177, 177); |
|
||||
color: #888; |
|
||||
|
|
||||
&.active { |
|
||||
color: #fc1e56; |
|
||||
border: 1px solid #fc1e56; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* 申请原因 */ |
|
||||
.row-textarea { |
|
||||
padding: 24rpx 20rpx; |
|
||||
|
|
||||
.textarea { |
|
||||
width: 100%; |
|
||||
height: 220rpx; |
|
||||
padding: 12rpx; |
|
||||
border: 1rpx solid #e8e8e8; |
|
||||
border-radius: 5rpx; |
|
||||
box-sizing: border-box; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* 退款金额 */ |
|
||||
.row-money { |
|
||||
padding: 24rpx 20rpx; |
|
||||
|
|
||||
.row-title { |
|
||||
margin-bottom: 0; |
|
||||
margin-right: 30rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 上传凭证 |
|
||||
.row-voucher { |
|
||||
padding: 24rpx 20rpx; |
|
||||
|
|
||||
.image-list { |
|
||||
padding: 0 20rpx; |
|
||||
margin-top: 20rpx; |
|
||||
margin-bottom: -20rpx; |
|
||||
|
|
||||
&:after { |
|
||||
clear: both; |
|
||||
content: " "; |
|
||||
display: table; |
|
||||
} |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
} |
|
||||
|
|
||||
.image-picker, |
|
||||
.image-preview { |
|
||||
width: 184rpx; |
|
||||
height: 184rpx; |
|
||||
margin-right: 30rpx; |
|
||||
margin-bottom: 30rpx; |
|
||||
float: left; |
|
||||
|
|
||||
&:nth-child(3n+0) { |
|
||||
margin-right: 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.image-picker { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
border: 1rpx dashed #ccc; |
|
||||
color: #ccc; |
|
||||
|
|
||||
.choose-icon { |
|
||||
font-size: 48rpx; |
|
||||
margin-bottom: 6rpx; |
|
||||
} |
|
||||
|
|
||||
.choose-text { |
|
||||
font-size: 24rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.image-preview { |
|
||||
position: relative; |
|
||||
|
|
||||
.image-delete { |
|
||||
position: absolute; |
|
||||
top: -15rpx; |
|
||||
right: -15rpx; |
|
||||
height: 42rpx; |
|
||||
width: 42rpx; |
|
||||
line-height: 42rpx; |
|
||||
background: rgba(0, 0, 0, 0.64); |
|
||||
border-radius: 50%; |
|
||||
color: #fff; |
|
||||
font-weight: bolder; |
|
||||
font-size: 22rpx; |
|
||||
z-index: 10; |
|
||||
text-align: center; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 底部操作栏 |
|
||||
.footer-fixed { |
|
||||
position: fixed; |
|
||||
bottom: var(--window-bottom); |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
z-index: 11; |
|
||||
box-shadow: 0 -4rpx 40rpx 0 rgba(151, 151, 151, 0.24); |
|
||||
background: #fff; |
|
||||
|
|
||||
// 设置ios刘海屏底部横线安全区域 |
|
||||
padding-bottom: constant(safe-area-inset-bottom); |
|
||||
padding-bottom: env(safe-area-inset-bottom); |
|
||||
|
|
||||
.btn-wrapper { |
|
||||
height: 120rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
padding: 0 20rpx; |
|
||||
} |
|
||||
|
|
||||
.btn-item { |
|
||||
flex: 1; |
|
||||
font-size: 28rpx; |
|
||||
height: 80rpx; |
|
||||
line-height: 80rpx; |
|
||||
text-align: center; |
|
||||
color: #fff; |
|
||||
border-radius: 50rpx; |
|
||||
} |
|
||||
|
|
||||
.btn-item-main { |
|
||||
background: linear-gradient(to right, #f9211c, #ff6335); |
|
||||
|
|
||||
// 禁用按钮 |
|
||||
&.disabled { |
|
||||
background: #ff9779; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</style> |
|
||||
@ -1,483 +0,0 @@ |
|||||
<template> |
|
||||
<view v-if="!isLoading" class="container p-bottom"> |
|
||||
|
|
||||
<!-- 顶部状态栏 --> |
|
||||
<view class="detail-header dis-flex flex-y-center"> |
|
||||
<view class="header-backdrop"> |
|
||||
<image class="image" src="/static/order/refund-bg.png"></image> |
|
||||
</view> |
|
||||
<view class="header-state"> |
|
||||
<text class="f-32 col-f">{{ detail.state_text }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商品详情 --> |
|
||||
<view class="detail-goods b-f m-top20 dis-flex flex-dir-row" @click="onGoodsDetail(detail.orderGoods.goods_id)"> |
|
||||
<view class="left"> |
|
||||
<image class="goods-image" :src="detail.orderGoods.goods_image"></image> |
|
||||
</view> |
|
||||
<view class="right dis-flex flex-box flex-dir-column flex-x-around"> |
|
||||
<view class="goods-name"> |
|
||||
<text class="twoline-hide">{{ detail.orderGoods.goods_name }}</text> |
|
||||
</view> |
|
||||
<view class="dis-flex col-9 f-24"> |
|
||||
<view class="flex-box"> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in detail.orderGoods.goods_props" :key="idx"> |
|
||||
<text>{{ props.value.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<text class="t-r">×{{ detail.orderGoods.total_num }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商品金额 --> |
|
||||
<view class="detail-order b-f row-block"> |
|
||||
<view class="item dis-flex flex-x-end flex-y-center"> |
|
||||
<text class="">商品金额:</text> |
|
||||
<text class="col-m">¥{{ detail.orderGoods.total_pay_price }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 已退款金额 --> |
|
||||
<view v-if="detail.status == RefundStatusEnum.COMPLETED.value && detail.type == 10" |
|
||||
class="detail-order b-f row-block dis-flex flex-x-end flex-y-center"> |
|
||||
<text class="">已退款金额:</text> |
|
||||
<text class="col-m">¥{{ detail.refund_money }}</text> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 售后信息 --> |
|
||||
<view v-if="detail.status == RefundStatusEnum.REJECTED.value" class="detail-refund b-f m-top20"> |
|
||||
<view class="detail-refund__row dis-flex"> |
|
||||
<view class="text"> |
|
||||
<text>售后类型:</text> |
|
||||
</view> |
|
||||
<view class="flex-box"> |
|
||||
<text>{{ RefundTypeEnum[detail.type].name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="detail-refund__row dis-flex"> |
|
||||
<view class="text"> |
|
||||
<text>申请原因:</text> |
|
||||
</view> |
|
||||
<view class="flex-box"> |
|
||||
<text>{{ detail.apply_desc }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view v-if="detail.images.length > 0" class="detail-refund__row dis-flex"> |
|
||||
<view class="text"> |
|
||||
<text>申请凭证:</text> |
|
||||
</view> |
|
||||
<view class="image-list flex-box"> |
|
||||
<view class="image-preview" v-for="(item, index) in detail.images" :key="index"> |
|
||||
<image class="image" mode="aspectFill" :src="item.image_url" @click="handlePreviewImages(index)"></image> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 售后信息 --> |
|
||||
<view v-if="detail.status.value == RefundStatusEnum.REJECTED.value" class="detail-refund b-f m-top20"> |
|
||||
<view class="detail-refund__row dis-flex"> |
|
||||
<view class="text"> |
|
||||
<text class="col-m">拒绝原因:</text> |
|
||||
</view> |
|
||||
<view class="flex-box"> |
|
||||
<text>{{ detail.refuse_desc }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 退货物流信息 --> |
|
||||
<view v-if="detail.audit_status == AuditStatusEnum.REVIEWED.value && detail.is_user_send" |
|
||||
class="detail-address b-f m-top20"> |
|
||||
<view class="detail-address__row address-title"> |
|
||||
<text class="col-m">退货物流信息</text> |
|
||||
</view> |
|
||||
<view class="detail-address__row address-details"> |
|
||||
<view class="address-details__row"> |
|
||||
<text>物流公司:{{ detail.express.express_name }}</text> |
|
||||
</view> |
|
||||
<view class="address-details__row"> |
|
||||
<text>物流单号:{{ detail.express_no }}</text> |
|
||||
</view> |
|
||||
<!-- <view class="address-details__row"> |
|
||||
<text>发货状态:{{ detail.is_user_send ? '已发货' : '未发货' }}</text> |
|
||||
</view> --> |
|
||||
<view class="address-details__row"> |
|
||||
<text>发货时间:{{ detail.send_time }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 商家收货地址 --> |
|
||||
<view v-if="detail.audit_status == AuditStatusEnum.REVIEWED.value" class="detail-address b-f m-top20"> |
|
||||
<view class="detail-address__row address-title"> |
|
||||
<text class="col-m">商家退货地址</text> |
|
||||
</view> |
|
||||
<view class="detail-address__row address-details"> |
|
||||
<view class="address-details__row"> |
|
||||
<text>收货人:{{ detail.address.name }}</text> |
|
||||
</view> |
|
||||
<view class="address-details__row"> |
|
||||
<text>联系电话:{{ detail.address.phone }}</text> |
|
||||
</view> |
|
||||
<view class="address-details__row dis-flex"> |
|
||||
<view class="text"> |
|
||||
<text>详细地址:</text> |
|
||||
</view> |
|
||||
<view class="address flex-box"> |
|
||||
<text class="region" v-for="(region, idx) in detail.address.region" :key="idx">{{ region }}</text> |
|
||||
<text class="detail">{{ detail.address.detail }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="detail-address__row address-tips"> |
|
||||
<view class="f-26 col-9"> |
|
||||
<text>· 未与卖家协商一致情况下,请勿寄到付或平邮</text> |
|
||||
</view> |
|
||||
<view class="f-26 col-9"> |
|
||||
<text>· 请填写真实有效物流信息</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
<!-- 填写物流信息 --> |
|
||||
<form |
|
||||
v-if="detail.type == RefundTypeEnum.RETURN.value && detail.audit_status == AuditStatusEnum.REVIEWED.value && !detail.is_user_send" |
|
||||
@submit="onSubmit()"> |
|
||||
<view class="detail-express b-f m-top20"> |
|
||||
<view class="form-group dis-flex flex-y-center"> |
|
||||
<view class="field">物流公司:</view> |
|
||||
<view class="flex-box"> |
|
||||
<picker mode="selector" :range="expressList" range-key="express_name" :value="expressIndex" |
|
||||
@change="onChangeExpress"> |
|
||||
<text v-if="expressIndex > -1">{{ expressList[expressIndex].express_name }}</text> |
|
||||
<text v-else class="col-80">请选择物流公司</text> |
|
||||
</picker> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="form-group dis-flex flex-y-center"> |
|
||||
<view class="field">物流单号:</view> |
|
||||
<view class="flex-box"> |
|
||||
<input class="input" v-model="formData.expressNo" placeholder="请填写物流单号"></input> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 操作按钮 --> |
|
||||
<view class="footer"> |
|
||||
<view class="btn-wrapper"> |
|
||||
<button class="btn-item btn-item-main btn-normal" :class="{ disabled }" formType="submit">确认发货</button> |
|
||||
</view> |
|
||||
</view> |
|
||||
</form> |
|
||||
|
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import { AuditStatusEnum, RefundStatusEnum, RefundTypeEnum } from '@/common/enum/order/refund' |
|
||||
import * as RefundApi from '@/api/refund' |
|
||||
import * as ExpressApi from '@/api/express' |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
// 枚举类 |
|
||||
AuditStatusEnum, |
|
||||
RefundStatusEnum, |
|
||||
RefundTypeEnum, |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 售后单ID |
|
||||
orderRefundId: null, |
|
||||
// 售后单详情 |
|
||||
detail: {}, |
|
||||
// 物流公司列表 |
|
||||
expressList: [], |
|
||||
// 表单数据 |
|
||||
formData: { |
|
||||
// 物流公司ID |
|
||||
expressId: null, |
|
||||
// 物流单号 |
|
||||
expressNo: '' |
|
||||
}, |
|
||||
// 选择的物流公司索引 |
|
||||
expressIndex: -1, |
|
||||
// 按钮禁用 |
|
||||
disabled: false |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad({ orderRefundId }) { |
|
||||
// 售后单ID |
|
||||
this.orderRefundId = orderRefundId |
|
||||
// 获取页面数据 |
|
||||
this.getPageData() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取页面数据 |
|
||||
getPageData() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
Promise.all([app.getRefundDetail(), app.getExpressList()]) |
|
||||
.then(result => { |
|
||||
app.isLoading = false |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 获取售后单详情 |
|
||||
getRefundDetail() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
RefundApi.detail(app.orderRefundId) |
|
||||
.then(result => { |
|
||||
app.detail = result.data.detail |
|
||||
resolve() |
|
||||
}) |
|
||||
.catch(reject) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 获取物流公司列表 |
|
||||
getExpressList() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
ExpressApi.list() |
|
||||
.then(result => { |
|
||||
app.expressList = result.data.list |
|
||||
resolve() |
|
||||
}) |
|
||||
.catch(reject) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 跳转商品详情页 |
|
||||
onGoodsDetail(goodsId) { |
|
||||
this.$navTo('pages/goods/detail', { goodsId }) |
|
||||
}, |
|
||||
|
|
||||
// 凭证图片预览 |
|
||||
handlePreviewImages(index) { |
|
||||
const { detail: { images } } = this |
|
||||
const imageUrls = images.map(item => item.image_url) |
|
||||
uni.previewImage({ |
|
||||
current: imageUrls[index], |
|
||||
urls: imageUrls |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 选择物流公司 |
|
||||
onChangeExpress(e) { |
|
||||
const expressIndex = e.detail.value |
|
||||
const { expressList } = this |
|
||||
this.expressIndex = expressIndex |
|
||||
this.formData.expressId = expressList[expressIndex].express_id |
|
||||
}, |
|
||||
|
|
||||
// 表单提交 |
|
||||
onSubmit() { |
|
||||
const app = this |
|
||||
// 判断是否重复提交 |
|
||||
if (app.disabled === true) return false |
|
||||
// 按钮禁用 |
|
||||
app.disabled = true |
|
||||
// 提交到后端 |
|
||||
RefundApi.delivery(app.orderRefundId, app.formData) |
|
||||
.then(result => { |
|
||||
app.$toast(result.message) |
|
||||
setTimeout(() => { |
|
||||
app.disabled = false |
|
||||
uni.navigateBack() |
|
||||
}, 1500) |
|
||||
}) |
|
||||
.catch(err => app.disabled = false) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
// 顶部状态栏 |
|
||||
.detail-header { |
|
||||
position: relative; |
|
||||
width: 100%; |
|
||||
height: 140rpx; |
|
||||
|
|
||||
.header-backdrop { |
|
||||
width: 100%; |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
z-index: 0; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 100%; |
|
||||
height: 140rpx; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.header-state { |
|
||||
z-index: 1; |
|
||||
padding: 0 50rpx; |
|
||||
} |
|
||||
|
|
||||
/* 商品详情 */ |
|
||||
.detail-goods { |
|
||||
padding: 24rpx 20rpx; |
|
||||
|
|
||||
.left { |
|
||||
.goods-image { |
|
||||
display: block; |
|
||||
width: 150rpx; |
|
||||
height: 150rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.right { |
|
||||
padding-left: 20rpx; |
|
||||
} |
|
||||
|
|
||||
.goods-props { |
|
||||
margin-top: 14rpx; |
|
||||
height: 40rpx; |
|
||||
color: #ababab; |
|
||||
font-size: 24rpx; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
display: inline-block; |
|
||||
margin-right: 14rpx; |
|
||||
padding: 4rpx 16rpx; |
|
||||
border-radius: 12rpx; |
|
||||
background-color: #F5F5F5; |
|
||||
width: auto; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.detail-order { |
|
||||
padding: 15rpx 20rpx; |
|
||||
font-size: 26rpx; |
|
||||
|
|
||||
.item { |
|
||||
margin-bottom: 10rpx; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* 售后详情 */ |
|
||||
.detail-refund { |
|
||||
padding: 15rpx 20rpx; |
|
||||
} |
|
||||
|
|
||||
.detail-refund__row { |
|
||||
margin: 20rpx 0; |
|
||||
} |
|
||||
|
|
||||
/* 申请凭证 */ |
|
||||
.image-list { |
|
||||
margin-bottom: -15rpx; |
|
||||
|
|
||||
.image-preview { |
|
||||
margin: 0 15rpx 15rpx 0; |
|
||||
float: left; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 180rpx; |
|
||||
height: 180rpx; |
|
||||
} |
|
||||
|
|
||||
&:nth-child(3n+0) { |
|
||||
margin-right: 0; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* 商家收货地址 */ |
|
||||
.detail-address { |
|
||||
padding: 20rpx 34rpx; |
|
||||
} |
|
||||
|
|
||||
.address-details { |
|
||||
padding: 8rpx 0; |
|
||||
border-bottom: 1px solid #eee; |
|
||||
|
|
||||
.address-details__row { |
|
||||
margin: 14rpx 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.address-tips { |
|
||||
margin-top: 16rpx; |
|
||||
line-height: 46rpx; |
|
||||
} |
|
||||
|
|
||||
.detail-address__row { |
|
||||
// margin: 18rpx 0; |
|
||||
} |
|
||||
|
|
||||
/* 填写物流信息 */ |
|
||||
.detail-express { |
|
||||
padding: 10rpx 30rpx; |
|
||||
} |
|
||||
|
|
||||
.form-group { |
|
||||
height: 60rpx; |
|
||||
margin: 14rpx 0; |
|
||||
|
|
||||
.input { |
|
||||
height: 100%; |
|
||||
font-size: 28rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
/* 底部操作栏 */ |
|
||||
|
|
||||
.footer { |
|
||||
margin-top: 60rpx; |
|
||||
|
|
||||
.btn-wrapper { |
|
||||
height: 100%; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
padding: 0 20rpx; |
|
||||
} |
|
||||
|
|
||||
.btn-item { |
|
||||
flex: 1; |
|
||||
font-size: 28rpx; |
|
||||
height: 80rpx; |
|
||||
color: #fff; |
|
||||
border-radius: 50rpx; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.btn-item-main { |
|
||||
background: linear-gradient(to right, #f9211c, #ff6335); |
|
||||
|
|
||||
// 禁用按钮 |
|
||||
&.disabled { |
|
||||
background: #ff9779; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
</style> |
|
||||
@ -1,263 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ native: true }" @down="downCallback" |
|
||||
:up="upOption" @up="upCallback"> |
|
||||
|
|
||||
<!-- tab栏 --> |
|
||||
<u-tabs :list="tabs" :is-scroll="false" :current="curTab" active-color="#FA2209" :duration="0.2" |
|
||||
@change="onChangeTab" /> |
|
||||
|
|
||||
<!-- 退款/售后单 --> |
|
||||
<view class="widget-list"> |
|
||||
<view class="widget-detail" v-for="(item, index) in list.data" :key="index"> |
|
||||
<view class="row-block dis-flex flex-y-center"> |
|
||||
<view class="flex-box">{{ item.create_time }}</view> |
|
||||
<view class="flex-box t-r"> |
|
||||
<text class="col-m">{{ item.state_text }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="detail-goods row-block dis-flex" @click.stop="handleTargetDetail(item.order_refund_id)"> |
|
||||
<view class="goods-image"> |
|
||||
<image class="image" :src="item.orderGoods.goods_image" mode="aspectFit"></image> |
|
||||
</view> |
|
||||
<view class="goods-right flex-box"> |
|
||||
<view class="goods-name"> |
|
||||
<text class="twoline-hide">{{ item.orderGoods.goods_name }}</text> |
|
||||
</view> |
|
||||
<view class="goods-props clearfix"> |
|
||||
<view class="goods-props-item" v-for="(props, idx) in item.orderGoods.goods_props" :key="idx"> |
|
||||
<text>{{ props.value.name }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="goods-num t-r"> |
|
||||
<text class="f-26 col-8">×{{ item.orderGoods.total_num }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="detail-order row-block"> |
|
||||
<view class="item dis-flex flex-x-end flex-y-center"> |
|
||||
<text class="">付款金额:</text> |
|
||||
<text class="col-m">¥{{ item.orderGoods.total_pay_price }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="detail-operate row-block dis-flex flex-x-end flex-y-center"> |
|
||||
<view class="detail-btn btn-detail" @click.stop="handleTargetDetail(item.order_refund_id)">查看详情</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
|
|
||||
</mescroll-body> |
|
||||
|
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import { getEmptyPaginateObj, getMoreListData } from '@/core/app' |
|
||||
import * as RefundApi from '@/api/refund' |
|
||||
|
|
||||
// 每页记录数量 |
|
||||
const pageSize = 15 |
|
||||
|
|
||||
// tab栏数据 |
|
||||
const tabs = [{ |
|
||||
name: '全部', |
|
||||
value: -1 |
|
||||
}, { |
|
||||
name: '待处理', |
|
||||
value: 0 |
|
||||
}] |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody |
|
||||
}, |
|
||||
mixins: [MescrollMixin], |
|
||||
data() { |
|
||||
return { |
|
||||
// 订单列表数据 |
|
||||
list: getEmptyPaginateObj(), |
|
||||
// tabs栏数据 |
|
||||
tabs, |
|
||||
// 当前标签索引 |
|
||||
curTab: 0, |
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于2条才显示无更多数据 |
|
||||
noMoreSize: 2, |
|
||||
// 空布局 |
|
||||
empty: { |
|
||||
tip: '亲,暂无售后单记录' |
|
||||
} |
|
||||
}, |
|
||||
// 控制首次触发onShow事件时不刷新列表 |
|
||||
canReset: false, |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
|
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面显示 |
|
||||
*/ |
|
||||
onShow() { |
|
||||
this.canReset && this.onRefreshList() |
|
||||
// this.canReset = true |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getRefundList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
// 获取退款/售后单列表 |
|
||||
getRefundList(pageNo = 1) { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
RefundApi.list({ state: app.getTabValue(), page: pageNo }, { load: false }) |
|
||||
.then(result => { |
|
||||
// 合并新数据 |
|
||||
const newList = result.data.list |
|
||||
app.list.data = getMoreListData(newList, app.list, pageNo) |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 切换标签项 |
|
||||
onChangeTab(index) { |
|
||||
const app = this |
|
||||
// 设置当前选中的标签 |
|
||||
app.curTab = index |
|
||||
// 刷新售后单列表 |
|
||||
app.onRefreshList() |
|
||||
}, |
|
||||
|
|
||||
// 刷新订单列表 |
|
||||
onRefreshList() { |
|
||||
this.list = getEmptyPaginateObj() |
|
||||
setTimeout(() => { |
|
||||
this.mescroll.resetUpScroll() |
|
||||
}, 120) |
|
||||
}, |
|
||||
|
|
||||
// 获取当前标签项的值 |
|
||||
getTabValue() { |
|
||||
return this.tabs[this.curTab].value |
|
||||
}, |
|
||||
|
|
||||
// 跳转到售后单详情页 |
|
||||
handleTargetDetail(orderRefundId) { |
|
||||
this.$navTo('pages/refund/detail', { orderRefundId }) |
|
||||
}, |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.widget-detail { |
|
||||
box-sizing: border-box; |
|
||||
background: #fff; |
|
||||
margin-bottom: 20rpx; |
|
||||
|
|
||||
.row-block { |
|
||||
padding: 0 20rpx; |
|
||||
min-height: 70rpx; |
|
||||
} |
|
||||
|
|
||||
.detail-goods { |
|
||||
padding: 20rpx; |
|
||||
background: #f9f9f9; |
|
||||
|
|
||||
.goods-image { |
|
||||
margin-right: 20rpx; |
|
||||
|
|
||||
.image { |
|
||||
display: block; |
|
||||
width: 200rpx; |
|
||||
height: 200rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.goods-right { |
|
||||
padding: 15rpx 0; |
|
||||
} |
|
||||
|
|
||||
.goods-name { |
|
||||
margin-bottom: 10rpx; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
.goods-props { |
|
||||
margin-top: 14rpx; |
|
||||
height: 40rpx; |
|
||||
color: #ababab; |
|
||||
font-size: 24rpx; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.goods-props-item { |
|
||||
display: inline-block; |
|
||||
margin-right: 14rpx; |
|
||||
padding: 4rpx 16rpx; |
|
||||
border-radius: 12rpx; |
|
||||
background-color: #F5F5F5; |
|
||||
width: auto; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.detail-operate { |
|
||||
padding-bottom: 20rpx; |
|
||||
|
|
||||
.detail-btn { |
|
||||
border-radius: 4px; |
|
||||
border: 1rpx solid #ccc; |
|
||||
padding: 8rpx 20rpx; |
|
||||
font-size: 28rpx; |
|
||||
color: #555; |
|
||||
margin-left: 10rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.detail-order { |
|
||||
padding: 10rpx 20rpx; |
|
||||
font-size: 26rpx; |
|
||||
line-height: 50rpx; |
|
||||
height: 50rpx; |
|
||||
|
|
||||
.item { |
|
||||
margin-bottom: 10rpx; |
|
||||
|
|
||||
&:last-child { |
|
||||
margin-bottom: 0; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,227 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<view class="search-wrapper"> |
|
||||
<view class="search-input"> |
|
||||
<view class="search-input-wrapper"> |
|
||||
<view class="left"> |
|
||||
<text class="search-icon iconfont icon-search"></text> |
|
||||
</view> |
|
||||
<view class="right"> |
|
||||
<input v-model="searchValue" class="input" focus="true" placeholder="请输入您搜索的商品" type="text"></input> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="search-button"> |
|
||||
<view class="button" @click="onSearch">搜索</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="history" v-if="historySearch.length"> |
|
||||
<view class="his-head"> |
|
||||
<text class="title">最近搜索</text> |
|
||||
<text class="icon iconfont icon-delete" @click="clearSearch"></text> |
|
||||
</view> |
|
||||
<view class="his-list"> |
|
||||
<view class="his-item" v-for="(val, index) in historySearch" :key="index"> |
|
||||
<view class="history-button" @click="handleQuick(val)">{{ val }}</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- </view> --> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
const HISTORY_SEARCH = 'historySearch' |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
historySearch: [], |
|
||||
searchValue: '' |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 获取历史搜索 |
|
||||
this.historySearch = this.getHistorySearch() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 获取历史搜索 |
|
||||
*/ |
|
||||
getHistorySearch() { |
|
||||
return uni.getStorageSync(HISTORY_SEARCH) || [] |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 搜索提交 |
|
||||
*/ |
|
||||
onSearch() { |
|
||||
const { searchValue } = this |
|
||||
if (searchValue) { |
|
||||
// 记录历史搜索 |
|
||||
this.setHistory(searchValue) |
|
||||
// 跳转到商品列表页 |
|
||||
this.$navTo('pages/goods/list', { search: searchValue }) |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 记录历史搜索 |
|
||||
*/ |
|
||||
setHistory(searchValue) { |
|
||||
const data = this.getHistorySearch() |
|
||||
const index = data.indexOf(searchValue) |
|
||||
index > -1 && data.splice(index, 1) |
|
||||
data.unshift(searchValue) |
|
||||
this.historySearch = data |
|
||||
this.onUpdateStorage() |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 清空最近搜索记录 |
|
||||
*/ |
|
||||
clearSearch() { |
|
||||
this.historySearch = [] |
|
||||
this.onUpdateStorage() |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 更新历史搜索缓存 |
|
||||
* @param {Object} data |
|
||||
*/ |
|
||||
onUpdateStorage(data) { |
|
||||
uni.setStorageSync(HISTORY_SEARCH, this.historySearch) |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 跳转到最近搜索 |
|
||||
*/ |
|
||||
handleQuick(search) { |
|
||||
this.$navTo('pages/goods/list', { search }) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
.container { |
|
||||
padding: 20rpx; |
|
||||
min-height: 100vh; |
|
||||
background: #f7f7f7; |
|
||||
} |
|
||||
|
|
||||
.search-wrapper { |
|
||||
display: flex; |
|
||||
height: 64rpx; |
|
||||
} |
|
||||
|
|
||||
// 搜索输入框 |
|
||||
.search-input { |
|
||||
width: 80%; |
|
||||
background: #fff; |
|
||||
border-radius: 10rpx 0 0 10rpx; |
|
||||
box-sizing: border-box; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.search-input-wrapper { |
|
||||
display: flex; |
|
||||
|
|
||||
.left { |
|
||||
display: flex; |
|
||||
width: 60rpx; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
|
|
||||
.search-icon { |
|
||||
display: block; |
|
||||
color: #b4b4b4; |
|
||||
font-size: 28rpx; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.right { |
|
||||
flex: 1; |
|
||||
|
|
||||
input { |
|
||||
font-size: 28rpx; |
|
||||
height: 64rpx; |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
|
|
||||
.input-placeholder { |
|
||||
color: #aba9a9; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// 搜索按钮 |
|
||||
.search-button { |
|
||||
width: 20%; |
|
||||
box-sizing: border-box; |
|
||||
|
|
||||
.button { |
|
||||
height: 64rpx; |
|
||||
font-size: 28rpx; |
|
||||
border-radius: 0 10rpx 10rpx 0; |
|
||||
background: #fa2209; |
|
||||
color: #fff; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
// 最近搜索 |
|
||||
.history { |
|
||||
|
|
||||
.his-head { |
|
||||
font-size: 28rpx; |
|
||||
padding: 50rpx 0 0 0; |
|
||||
color: #777; |
|
||||
|
|
||||
.icon { |
|
||||
float: right; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.his-list { |
|
||||
padding: 20rpx 0; |
|
||||
overflow: hidden; |
|
||||
|
|
||||
.his-item { |
|
||||
width: 33.3%; |
|
||||
float: left; |
|
||||
padding: 10rpx; |
|
||||
box-sizing: border-box; |
|
||||
|
|
||||
.history-button { |
|
||||
text-align: center; |
|
||||
padding: 14rpx; |
|
||||
line-height: 30rpx; |
|
||||
border-radius: 100rpx; |
|
||||
background: #fff; |
|
||||
font-size: 26rpx; |
|
||||
border: 1rpx solid #efefef; |
|
||||
overflow: hidden; |
|
||||
white-space: nowrap; |
|
||||
text-overflow: ellipsis; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,127 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption" |
|
||||
@up="upCallback"> |
|
||||
<view class="log-list"> |
|
||||
<view v-for="(item, index) in list.data" :key="index" class="log-item"> |
|
||||
<view class="item-left flex-box"> |
|
||||
<view class="rec-status"> |
|
||||
<text>{{ item.describe }}</text> |
|
||||
</view> |
|
||||
<view class="rec-time"> |
|
||||
<text>{{ item.create_time }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="item-right"> |
|
||||
<text>{{ item.money > 0 ? '+' : '' }}{{ item.money }}元</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</mescroll-body> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import * as LogApi from '@/api/balance/log' |
|
||||
import { getEmptyPaginateObj, getMoreListData } from '@/core/app' |
|
||||
|
|
||||
const pageSize = 15 |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody |
|
||||
}, |
|
||||
mixins: [MescrollMixin], |
|
||||
data() { |
|
||||
return { |
|
||||
// 余额账单明细列表 |
|
||||
list: getEmptyPaginateObj(), |
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于12条才显示无更多数据 |
|
||||
noMoreSize: 12, |
|
||||
// 空布局 |
|
||||
empty: { |
|
||||
tip: '亲,暂无账单明细' |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) {}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getLogList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
// 获取余额账单明细列表 |
|
||||
getLogList(pageNo = 1) { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
LogApi.list({ page: pageNo }) |
|
||||
.then(result => { |
|
||||
// 合并新数据 |
|
||||
const newList = result.data.list |
|
||||
app.list.data = getMoreListData(newList, app.list, pageNo) |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
page, |
|
||||
.container { |
|
||||
background: #fff; |
|
||||
} |
|
||||
|
|
||||
.log-list { |
|
||||
padding: 0 30rpx; |
|
||||
} |
|
||||
|
|
||||
.log-item { |
|
||||
font-size: 28rpx; |
|
||||
padding: 20rpx 20rpx; |
|
||||
line-height: 1.8; |
|
||||
border-bottom: 1rpx solid rgb(238, 238, 238); |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.rec-status { |
|
||||
color: #333; |
|
||||
|
|
||||
.rec-time { |
|
||||
color: rgb(160, 160, 160); |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,167 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container" v-if="!isLoading"> |
|
||||
<view class="space-upper"> |
|
||||
<view class="wallet-image"> |
|
||||
<image src="/static/wallet.png" mode="widthFix"></image> |
|
||||
</view> |
|
||||
<view class="wallet-account"> |
|
||||
<view class="wallet-account_balance"> |
|
||||
<text>{{ userInfo.balance }}</text> |
|
||||
</view> |
|
||||
<view class="wallet-account_lable"> |
|
||||
<text>账户余额(元)</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="space-lower"> |
|
||||
<view v-if="setting.is_entrance" class="space-lower_item btn-recharge"> |
|
||||
<view class="btn-submit" @click="onTargetRecharge()">充 值</view> |
|
||||
</view> |
|
||||
<view class="space-lower_item item-lable dis-flex flex-x-around"> |
|
||||
<view class="lable-text" @click="onTargetRechargeOrder()"> |
|
||||
<text>充值记录</text> |
|
||||
</view> |
|
||||
<view class="lable-text" @click="onTargetBalanceLog()"> |
|
||||
<text>账单详情</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as UserApi from '@/api/user' |
|
||||
import SettingModel from '@/common/model/Setting' |
|
||||
import SettingKeyEnum from '@/common/enum/setting/Key' |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 会员信息 |
|
||||
userInfo: {}, |
|
||||
// 充值设置 |
|
||||
setting: {}, |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onShow(options) { |
|
||||
// 获取页面数据 |
|
||||
this.getPageData() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
// 获取页面数据 |
|
||||
getPageData() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
Promise.all([app.getUserInfo(), app.getSetting()]) |
|
||||
.then(() => app.isLoading = false) |
|
||||
}, |
|
||||
|
|
||||
// 获取会员信息 |
|
||||
getUserInfo() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
UserApi.info() |
|
||||
.then(result => { |
|
||||
app.userInfo = result.data.userInfo |
|
||||
resolve(app.userInfo) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 获取充值设置 |
|
||||
getSetting() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
SettingModel.item(SettingKeyEnum.RECHARGE.value, false) |
|
||||
.then(data => { |
|
||||
app.setting = data |
|
||||
resolve(data) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 跳转充值页面 |
|
||||
onTargetRecharge() { |
|
||||
this.$navTo('pages/wallet/recharge/index') |
|
||||
}, |
|
||||
|
|
||||
// 跳转充值记录页面 |
|
||||
onTargetRechargeOrder() { |
|
||||
this.$navTo('pages/wallet/recharge/order') |
|
||||
}, |
|
||||
|
|
||||
// 跳转账单详情页面 |
|
||||
onTargetBalanceLog() { |
|
||||
this.$navTo('pages/wallet/balance/log') |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
<style> |
|
||||
page { |
|
||||
background: #fff; |
|
||||
} |
|
||||
</style> |
|
||||
<style lang="scss" scoped> |
|
||||
.container { |
|
||||
background: #fff; |
|
||||
} |
|
||||
|
|
||||
.space-upper { |
|
||||
padding: 150rpx 0; |
|
||||
text-align: center; |
|
||||
} |
|
||||
|
|
||||
.wallet-image image { |
|
||||
width: 360rpx; |
|
||||
height: 261.72rpx; |
|
||||
} |
|
||||
|
|
||||
.wallet-account { |
|
||||
margin-top: 20rpx; |
|
||||
} |
|
||||
|
|
||||
.wallet-account_balance { |
|
||||
font-size: 56rpx; |
|
||||
} |
|
||||
|
|
||||
.wallet-account_lable { |
|
||||
margin-top: 14rpx; |
|
||||
color: #cec1c1; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
|
|
||||
.space-lower { |
|
||||
margin-top: 30rpx; |
|
||||
padding: 0 110rpx; |
|
||||
} |
|
||||
|
|
||||
.btn-recharge .btn-submit { |
|
||||
width: 460rpx; |
|
||||
height: 84rpx; |
|
||||
margin: 0 auto; |
|
||||
border-radius: 50rpx; |
|
||||
background: #786cff; |
|
||||
color: white; |
|
||||
font-size: 30rpx; |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.item-lable { |
|
||||
margin-top: 80rpx; |
|
||||
font-size: 28rpx; |
|
||||
color: rgb(94, 94, 94); |
|
||||
padding: 0 100rpx; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,300 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container" v-if="userInfo.user_id"> |
|
||||
<view class="account-panel dis-flex flex-y-center"> |
|
||||
<view class="panel-lable"> |
|
||||
<text>账户余额</text> |
|
||||
</view> |
|
||||
<view class="panel-balance flex-box"> |
|
||||
<text>¥{{ userInfo.balance }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="recharge-panel"> |
|
||||
<view class="recharge-label"> |
|
||||
<text>充值金额</text> |
|
||||
</view> |
|
||||
<view class="recharge-plan clearfix"> |
|
||||
<block v-for="(item, index) in planList" :key="index"> |
|
||||
<view class="recharge-plan_item" :class="{ active: selectedPlanId == item.plan_id }" @click="onSelectPlan(item.plan_id)"> |
|
||||
<view class="plan_money"> |
|
||||
<text>{{ item.money }}</text> |
|
||||
</view> |
|
||||
<view class="plan_gift" v-if="item.gift_money > 0"> |
|
||||
<text>送{{ item.gift_money }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</block> |
|
||||
</view> |
|
||||
<!-- 手动充值输入框 --> |
|
||||
<view class="recharge-input" v-if="setting.is_custom == 1"> |
|
||||
<input type="digit" placeholder="请输入充值金额" v-model="inputValue" @input="onChangeMoney" /> |
|
||||
</view> |
|
||||
<!-- 确认按钮 --> |
|
||||
<view class="recharge-submit btn-submit"> |
|
||||
<form @submit="onSubmit"> |
|
||||
<button class="button" formType="submit" :disabled="disabled">立即充值</button> |
|
||||
</form> |
|
||||
</view> |
|
||||
</view> |
|
||||
<!-- 充值描述 --> |
|
||||
<view class="recharge-describe"> |
|
||||
<view class="recharge-label"> |
|
||||
<text>充值说明</text> |
|
||||
</view> |
|
||||
<view class="content"> |
|
||||
<text space="ensp">{{ setting.describe }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import * as UserApi from '@/api/user' |
|
||||
import * as RechargeApi from '@/api/recharge' |
|
||||
import * as PlanApi from '@/api/recharge/plan' |
|
||||
import SettingModel from '@/common/model/Setting' |
|
||||
import SettingKeyEnum from '@/common/enum/setting/Key' |
|
||||
import { wxPayment } from '@/core/app' |
|
||||
|
|
||||
export default { |
|
||||
data() { |
|
||||
return { |
|
||||
// 正在加载 |
|
||||
isLoading: true, |
|
||||
// 会员信息 |
|
||||
userInfo: {}, |
|
||||
// 充值设置 |
|
||||
setting: {}, |
|
||||
// 充值方案列表 |
|
||||
planList: [], |
|
||||
// 按钮禁用 |
|
||||
disabled: false, |
|
||||
// 当前选中的套餐id |
|
||||
selectedPlanId: 0, |
|
||||
// 自定义金额 |
|
||||
inputValue: '', |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) { |
|
||||
// 获取页面数据 |
|
||||
this.getPageData() |
|
||||
}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 选择充值套餐 |
|
||||
*/ |
|
||||
onSelectPlan(planId) { |
|
||||
this.selectedPlanId = planId |
|
||||
this.inputValue = '' |
|
||||
}, |
|
||||
|
|
||||
// 金额输入框 |
|
||||
onChangeMoney(e) { |
|
||||
this.inputValue = e.target.value |
|
||||
this.selectedPlanId = 0 |
|
||||
}, |
|
||||
|
|
||||
// 获取页面数据 |
|
||||
getPageData() { |
|
||||
const app = this |
|
||||
app.isLoading = true |
|
||||
Promise.all([app.getUserInfo(), app.getSetting(), app.getPlanList()]) |
|
||||
.then(() => app.isLoading = false) |
|
||||
}, |
|
||||
|
|
||||
// 获取充值方案列表 |
|
||||
getPlanList() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
PlanApi.list() |
|
||||
.then(result => { |
|
||||
app.planList = result.data.list |
|
||||
resolve(app.planList) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 获取会员信息 |
|
||||
getUserInfo() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
UserApi.info() |
|
||||
.then(result => { |
|
||||
app.userInfo = result.data.userInfo |
|
||||
resolve(app.userInfo) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 获取充值设置 |
|
||||
getSetting() { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
SettingModel.item(SettingKeyEnum.RECHARGE.value, false) |
|
||||
.then(data => { |
|
||||
app.setting = data |
|
||||
resolve(data) |
|
||||
}) |
|
||||
}) |
|
||||
}, |
|
||||
|
|
||||
// 立即充值 |
|
||||
onSubmit(e) { |
|
||||
const app = this |
|
||||
// 按钮禁用 |
|
||||
app.disabled = true |
|
||||
// 提交到后端 |
|
||||
RechargeApi.submit({ planId: app.selectedPlanId, customMoney: app.inputValue }) |
|
||||
.then(result => app.wxPayment(result.data.payment)) |
|
||||
.finally(() => app.disabled = false) |
|
||||
}, |
|
||||
|
|
||||
// 发起微信支付 |
|
||||
wxPayment(option) { |
|
||||
const app = this |
|
||||
wxPayment(option) |
|
||||
.then(() => { |
|
||||
app.$success('支付成功') |
|
||||
setTimeout(() => { |
|
||||
// 获取页面数据 |
|
||||
app.getPageData() |
|
||||
}, 1500) |
|
||||
}) |
|
||||
.catch(err => app.$error('订单未支付')) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
page, |
|
||||
.container { |
|
||||
background: #fff; |
|
||||
} |
|
||||
|
|
||||
.container { |
|
||||
padding-bottom: 70rpx; |
|
||||
} |
|
||||
|
|
||||
/* 账户面板 */ |
|
||||
.account-panel { |
|
||||
width: 650rpx; |
|
||||
height: 180rpx; |
|
||||
margin: 50rpx auto; |
|
||||
padding: 0 60rpx; |
|
||||
box-sizing: border-box; |
|
||||
border-radius: 12rpx; |
|
||||
color: #fff; |
|
||||
background: linear-gradient(-125deg, #a46bff, #786cff); |
|
||||
box-shadow: 0 5px 22px 0 rgba(0, 0, 0, 0.26); |
|
||||
} |
|
||||
|
|
||||
.panel-lable { |
|
||||
font-size: 32rpx; |
|
||||
} |
|
||||
|
|
||||
.recharge-label { |
|
||||
color: rgb(51, 51, 51); |
|
||||
font-size: 28rpx; |
|
||||
margin-bottom: 25rpx; |
|
||||
} |
|
||||
|
|
||||
.panel-balance { |
|
||||
text-align: right; |
|
||||
font-size: 46rpx; |
|
||||
} |
|
||||
|
|
||||
.recharge-panel { |
|
||||
margin-top: 60rpx; |
|
||||
padding: 0 60rpx; |
|
||||
} |
|
||||
|
|
||||
/* 充值套餐 */ |
|
||||
.recharge-plan { |
|
||||
.recharge-plan_item { |
|
||||
width: 192rpx; |
|
||||
padding: 15rpx 0; |
|
||||
float: left; |
|
||||
text-align: center; |
|
||||
color: #888; |
|
||||
border: 1rpx solid rgb(228, 228, 228); |
|
||||
border-radius: 10rpx; |
|
||||
margin: 0 20rpx 20rpx 0; |
|
||||
|
|
||||
&:nth-child(3n + 0) { |
|
||||
margin-right: 0; |
|
||||
} |
|
||||
|
|
||||
&.active { |
|
||||
color: #786cff; |
|
||||
border: 1rpx solid #786cff; |
|
||||
|
|
||||
.plan_money { |
|
||||
color: #786cff; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
.plan_money { |
|
||||
font-size: 32rpx; |
|
||||
color: rgb(82, 82, 82); |
|
||||
} |
|
||||
|
|
||||
.plan_gift { |
|
||||
font-size: 25rpx; |
|
||||
} |
|
||||
|
|
||||
.recharge-input { |
|
||||
margin-top: 25rpx; |
|
||||
|
|
||||
input { |
|
||||
border: 1rpx solid rgb(228, 228, 228); |
|
||||
border-radius: 10rpx; |
|
||||
padding: 15rpx 16rpx; |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* 立即充值 */ |
|
||||
.recharge-submit { |
|
||||
margin-top: 70rpx; |
|
||||
} |
|
||||
|
|
||||
.btn-submit { |
|
||||
.button { |
|
||||
font-size: 30rpx; |
|
||||
background: #786cff; |
|
||||
border: none; |
|
||||
color: white; |
|
||||
border-radius: 50rpx; |
|
||||
padding: 0 120rpx; |
|
||||
line-height: 3; |
|
||||
} |
|
||||
|
|
||||
.button[disabled] { |
|
||||
background: #a098ff; |
|
||||
border-color: #a098ff; |
|
||||
color: white; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* 充值说明 */ |
|
||||
.recharge-describe { |
|
||||
margin-top: 50rpx; |
|
||||
padding: 0 60rpx; |
|
||||
|
|
||||
.content { |
|
||||
font-size: 26rpx; |
|
||||
line-height: 1.6; |
|
||||
color: #888; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,127 +0,0 @@ |
|||||
<template> |
|
||||
<view class="container"> |
|
||||
<mescroll-body ref="mescrollRef" :sticky="true" @init="mescrollInit" :down="{ use: false }" :up="upOption" |
|
||||
@up="upCallback"> |
|
||||
<view class="log-list"> |
|
||||
<view v-for="(item, index) in list.data" :key="index" class="log-item"> |
|
||||
<view class="item-left flex-box"> |
|
||||
<view class="rec-status"> |
|
||||
<text>{{ '充值成功' }}</text> |
|
||||
</view> |
|
||||
<view class="rec-time"> |
|
||||
<text>{{ item.pay_time }}</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
<view class="item-right"> |
|
||||
<text>+{{ item.actual_money }}元</text> |
|
||||
</view> |
|
||||
</view> |
|
||||
</view> |
|
||||
</mescroll-body> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script> |
|
||||
import MescrollBody from '@/components/mescroll-uni/mescroll-body.vue' |
|
||||
import MescrollMixin from '@/components/mescroll-uni/mescroll-mixins' |
|
||||
import * as OrderApi from '@/api/recharge/order' |
|
||||
import { getEmptyPaginateObj, getMoreListData } from '@/core/app' |
|
||||
|
|
||||
const pageSize = 15 |
|
||||
|
|
||||
export default { |
|
||||
components: { |
|
||||
MescrollBody |
|
||||
}, |
|
||||
mixins: [MescrollMixin], |
|
||||
data() { |
|
||||
return { |
|
||||
// 余额账单明细列表 |
|
||||
list: getEmptyPaginateObj(), |
|
||||
// 上拉加载配置 |
|
||||
upOption: { |
|
||||
// 首次自动执行 |
|
||||
auto: true, |
|
||||
// 每页数据的数量; 默认10 |
|
||||
page: { size: pageSize }, |
|
||||
// 数量要大于12条才显示无更多数据 |
|
||||
noMoreSize: 12, |
|
||||
// 空布局 |
|
||||
empty: { |
|
||||
tip: '亲,暂无充值记录' |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
/** |
|
||||
* 生命周期函数--监听页面加载 |
|
||||
*/ |
|
||||
onLoad(options) {}, |
|
||||
|
|
||||
methods: { |
|
||||
|
|
||||
/** |
|
||||
* 上拉加载的回调 (页面初始化时也会执行一次) |
|
||||
* 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 |
|
||||
* @param {Object} page |
|
||||
*/ |
|
||||
upCallback(page) { |
|
||||
const app = this |
|
||||
// 设置列表数据 |
|
||||
app.getLogList(page.num) |
|
||||
.then(list => { |
|
||||
const curPageLen = list.data.length |
|
||||
const totalSize = list.data.total |
|
||||
app.mescroll.endBySize(curPageLen, totalSize) |
|
||||
}) |
|
||||
.catch(() => app.mescroll.endErr()) |
|
||||
}, |
|
||||
|
|
||||
// 获取余额账单明细列表 |
|
||||
getLogList(pageNo = 1) { |
|
||||
const app = this |
|
||||
return new Promise((resolve, reject) => { |
|
||||
OrderApi.list({ page: pageNo }) |
|
||||
.then(result => { |
|
||||
// 合并新数据 |
|
||||
const newList = result.data.list |
|
||||
app.list.data = getMoreListData(newList, app.list, pageNo) |
|
||||
resolve(newList) |
|
||||
}) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="scss" scoped> |
|
||||
page, |
|
||||
.container { |
|
||||
background: #fff; |
|
||||
} |
|
||||
|
|
||||
.log-list { |
|
||||
padding: 0 30rpx; |
|
||||
} |
|
||||
|
|
||||
.log-item { |
|
||||
font-size: 28rpx; |
|
||||
padding: 20rpx 20rpx; |
|
||||
line-height: 1.8; |
|
||||
border-bottom: 1rpx solid rgb(238, 238, 238); |
|
||||
display: flex; |
|
||||
justify-content: center; |
|
||||
align-items: center; |
|
||||
} |
|
||||
|
|
||||
.rec-status { |
|
||||
color: #333; |
|
||||
|
|
||||
.rec-time { |
|
||||
color: rgb(160, 160, 160); |
|
||||
font-size: 26rpx; |
|
||||
} |
|
||||
} |
|
||||
</style> |
|
||||
Loading…
Reference in new issue